0% found this document useful (0 votes)
3 views

Lab Report4

This lab report details the communication protocols used in embedded devices, specifically focusing on a JPEG compression VGA camera module and an LCD display. It outlines the commands for interfacing with the camera and provides LabVIEW code for capturing images, as well as details on using the MPLAB XLCD library for the LCD display. The experiments were conducted primarily between 2021 and 2023.

Uploaded by

claude.baumann
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Lab Report4

This lab report details the communication protocols used in embedded devices, specifically focusing on a JPEG compression VGA camera module and an LCD display. It outlines the commands for interfacing with the camera and provides LabVIEW code for capturing images, as well as details on using the MPLAB XLCD library for the LCD display. The experiments were conducted primarily between 2021 and 2023.

Uploaded by

claude.baumann
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

Communication with various devices (Camera, LCD display, 4 digit

7-segment display, I2C-Slave)


Lab Report
Claude BAUMANN Computarium

last edited: Thursday 16th March, 2023 (09:47)

Abstract
This lab report will document the development of embedded device communication between PICs with a list
of devices using UART, SPI, etc. Experiments took place mostly during 2021-23.

I C328-7640 JPEG Compression VGA Camera Module


Reference: https://manualzz.com/doc/6891593/cj—cam-user-manual-ov528-protocol

This tiny camera is interesting for the study of bi-directional UART communication. It is capable of finding the
baud-rate through receiving a synchronizing command from the host. It uses a handshaking protocol with acknowl-
edge messages. Note that we use the 3.3.V supply circuit shown in Fig. 1.

Figure 1: Simple 3.3V supply using a 4.5V battery set.

Rload Idiode Uload


2k2 10µA 3.7V
680Ω 10µA 3.4V
470Ω 30µA 3.39V
100Ω 100µA 3.15V
87Ω 130µA 3.15V
82Ω 140µA 3.13V
10Ω 40mA !! 2V !!

Table 1: Behavior of the circuit shown in Fig. 1.

1
Since the camera module draws 60mA current, and has operation ranges from 3.0-3.6V, this circuitry should be
sufficient for test purpose. The camera will be addressed via UART from the PC. Level conversions are made with
1:3 resistor net.

ˆ Red: Power 3.3VDC

ˆ Yellow: TX (3.3V)

ˆ Green: RX (3.3.V)

ˆ Black: GND

A Command Set
Camera can support 11 commands for interfacing to host as following.

No. Command Comm. ID Parameter 1 Parameter 2 Parameter 3 Parameter 4


1 Initial AA01h 00h Color Setting Preview Resolution JPEG Resolution
2 Get Picture AA04h Get Setting 00h 00h 00h
3 Snapshot AA05h Snapshot Setting Skip Frame (low byte) Skip Frame (high byte) 00h
4 Set Package Size AA06h 08h Package Size (low byte) Package Size (high byte) 00h
5 Set Baud-rate AA07h 1st Divider 2nd Divider 00h 00h
6 Reset AA08h Reset Setting 00h 00h xxh*
7 Power Down AA09h 00h 00h 00h 00h
8 Data AA0Ah Date Type Length-byte 0 Length-byte 1 Length-byte 2
9 SNYC AA0Dh 00h 00h 00h 00h
10 ACK AA0Eh Command ID ACK counter Package ID Byte 0 Package ID Byte 1
11 NAK AA0Fh 00h NAK counter Error Number 00h

* If the parameter is FFh, firmware will respond immediately.

Interface Commands Details


1. Initial (AA01h)
The host issues this command to configure the preview image size and color type. After receiving this command, the
camera will send out an ACK command to the host if the configuration success. Otherwise, a NACK command will
be sent out.

Color Setting
2-bit Gray-Scale 01h
4-bit Gray-Scale 02h
8-bit Gray-Scale 03h
2-bit Color 05h
16-bit Color 06h
JPEG 07h

Preview Resolution
80*60 01h
160*120 03h

JPEG Resolution
80*64 01h
160*128 03h
320*240 05h
640*480 07h

2
2. Get Picture (AA04h)
Host issues this command to get a picture from camera.

Get Setting
Snapshot 01h
Preview Picture 02h
JPEG Preview Picture 03h

3. Snapshot (AA05h)
Camera keeps a single frame of JPEG still picture data in the buffer after receiving this command.

Snapshot Setting
Compressed Picture 00h
Uncompressed Picture 01h

Skip Frame: the number of dropped frames can be defined before compression occurs. 0 keeps the current frame, 1
captures the next frame etc.

4. Set Package Size (AA06h)


Host will send out the size of JPEG still picture after receiving this command issued by camera. Type of package is
as follows:

ID Date Size Image Data Verify Code


(2 bytes) (2 bytes) (Package Size-6 bytes) (2 bytes)

ID: Package ID, stars from zero for an image


Data Size: Size of image data in this package
Verify Code: Error detection code, equals to the lower byte of sum of the whole package data except the verify
code field. The higher byte of this code is always zero. i.e. verify code = lowbyte(sum(byte[0] to byte[N-2]).

Note: As the transmission of uncompressed image is not the package mode, it is not necessary to set the package
size for the uncompressed image.

5. Set Baud Rate (AA07h)


Host issues this command to set camera’s baud rate. Camera auto-detects the baud rate issued by host and keep the
baud rate to communicate with host, reconfiguration should be made if power off.The baud rates were supported by
camera as follows. Baud Rate=14.7456MHz/2 × (2nd divider +1)/2 × (1st divider+1)

Baud Rate 1st Divider 2nd Divider Baud Rate 1st Divider 2nd Divider
7200bps FFh 01h 28800bps 3Fh 01h
9600bps BFh 01h 38400bps 2Fh 01h
14400bps 7Fh 01h 57600bps 1Fh 01h
19200bps 5Fh 01h 115200bps 0Fh 01h

6. Reset (AA08h)
Reset Setting 00h resets the whole system. C328-7640 will reboot and reset all registers and state machines. 01h
resets state machines only.

7. Power down (AA09h)


Camera will go into sleep mode after receiving this command and get resumed after sending out an ACK against
SYNC command issued by host.

3
8. Data (AA0Ah)
The type and size of image data prepared for transmitting out to host would be advised to host when camera issuing
this command.

Data Type
Snapshot Picture 01h
Preview Picture 02h
JPEG Picture 05h

Data Length: these 3 bytes represent the length of Snapshot Picture, Preview Picture and JPEG Preview Picture.

9. SYNC (AA0Dh)
Either the host or the camera can issue this command to make connection. An ACK command must be sent out
after receiving this command.

10. ACK (AA0Eh)


This command indicates the success of the last operation. After receiving any valid command, ACK command must
be sent out except when getting preview data. The host can issue this command request image data package with
desired package ID after receiving Data command from camera, and send this command with package ID 0F0Fh
when finishing with receiving data package. Note: “Command ID” is 00h when host requesting image data package.
Command ID: The command with that ID is acknowledged by this command.
ACK Counter: Not in use
Package ID: For acknowledging Data Command, these two bytes represent the requested package ID. While for
acknowledging other commands, these two bytes are set to 00h.

11. NAK (AA0Fh)


This command shows corrupted transmission or unsupported features.
NAK Counter: Not in use
Error Number: (Please read the following chart)

Error Messages NAK code Error Messages NAK code


Picture Type Error 01h Parameter Error 0Bh
Picture Up Scale 02h Send Register Timeout 0Ch
Picture Scale Error 03h Command ID Error 0Dh
Unexpected Respond 04h Picture Not Ready 0Fh
Send Picture Timeout 05h Transfer Package Number Error 10h
Unexpected Command 06h Set Transfer Package Size Wrong 11h
ASRAM JPEG Type Error 07h Command Header Error F0h
ASRAM JPEG Size Error 08h Command Length Error F1h
Picture Format Error 09h Send Picture Error F5h
Picture Size Error 0Ah Send Command Error FFh

B LabVIEW program
Here the LabVIEW code for getting snapshots from the camera:

4
Figure 2: Main program front panel (test3.vi).

Figure 3: Main program diagram (test3.vi).

5
Figure 4: UART initialization.

Figure 5: Sending a command and waiting for the reply.

6
Figure 6: TRUE case in the former diagram.

Figure 7: TX command.

7
Figure 8: RX command.

Figure 9: Verify reply integrity.

8
Figure 10: C328-7640.

II LCD Display
We follow the advice by Dogan Ibrahim,1 and use the MPLAB XLCD library, by including xlcd.h in the C-programs.
This library has all the functions to use displays with incorporated HD44780 LCD controllers.
We currently use a device by Displaytech from the 161A series.2 The particularity of our part is that, although
showing a single 16 character line, this line is internally split into two 8-bit lines. So, the device must be configured
as multiline 5x7 dots. We will drive it in 4 bit mode, as recommended by Ibrahim.
# include < p18F452 .h >
# include < xlcd .h >
# include < delays .h >

/* We want to write to a standard LCD display ( Displaytech 161 A )


Author : Claude Baumann
Inspired by book : Dogan Ibrahim
4 - bit configuration of the display */

# pragma config OSC = HS


# pragma config PWRT = ON
# pragma config WDT = OFF
# pragma config BOR = OFF
# pragma config DEBUG = OFF
# pragma config LVP = OFF

# define _XTAL_FREQ 20000000 // Hz


# define CLR_LCD 1
# define HOME_LCD 2

void DelayFor18TCY ( void ){


Nop (); Nop (); Nop (); Nop (); //18 cycle delay
Nop (); Nop (); Nop (); Nop ();

1 D. Ibrahim, SD Card Projects Using the PIC Microcontroller, Elsevier, (2010), pp. 225-239
2 https://cdn.displaytech-us.com/sites/default/files/display-data-sheet/161A%20series-v21.pdf

9
Nop (); Nop (); Nop (); Nop ();
Nop (); Nop ();
return ;
}

void DelayPORXLCD ( void ){


Delay1KTCYx (75); //15 ms delay ( cf . page 229 Ibrahim )
}
void DelayXLCD ( void ){
Delay1KTCYx (25); //5 ms
}

/ * = = = == = = = = = = = = = = = = Main program = = = = = = = = = = = = = = = = * /

void main ( void ){


char msg1 []=" Hey Comp ";
char msg2 []=" utarium ";
PORTCbits . RC2 = 0; // Make PORTB zero
TRISCbits . RC2 = 0; // Make PORTB all output
OpenXLCD ( FOUR_BIT & LINES_5X7 ); // configure 4 bits , 5 x7 charcaters
Delay1KTCYx (10000); // settling time
WriteCmdXLCD ( CLR_LCD ); // Clear LCD
while ( BusyXLCD ()); // wait
WriteCmdXLCD ( HOME_LCD ); // Home cursor
while ( BusyXLCD ()); // wait
putsXLCD ( msg1 ); // write text
while ( BusyXLCD ()); // wait

WriteCmdXLCD (0 xC0 ); // set cursor to second row


while ( BusyXLCD ()); // wait
putsXLCD ( msg2 ); // write text
while ( BusyXLCD ()); // wait

while (1)
{
PORTCbits . RC2 = 1; // Make RC2 one
Delay1KTCYx (1000); // delay a bit

PORTCbits . RC2 = 0; // Make RC2 zero


Delay1KTCYx (1000); // delay a bit
}
}

Figure 11: C328-7640.

If numbers are being used, we can apply the MPLAB standard library number to string function (itoa).
# include < p18F452 .h >
# include < xlcd .h >
# include < delays .h >
# include < stdlib .h >

/* We want to write to a standard LCD display ( Displaytech 161 A )


Author : Claude Baumann

10
Inspired by book : Dogan Ibrahim
4 - bit configuration of the display */

# pragma config OSC = HS


# pragma config PWRT = ON
# pragma config WDT = OFF
# pragma config BOR = OFF
# pragma config DEBUG = OFF
# pragma config LVP = OFF

# define _XTAL_FREQ 20000000 // Hz


# define CLR_LCD 1
# define HOME_LCD 2
# define LCDCURSOR_OFF 12

void DelayFor18TCY ( void ){


Nop (); Nop (); Nop (); Nop (); //18 cycle delay
Nop (); Nop (); Nop (); Nop ();
Nop (); Nop (); Nop (); Nop ();
Nop (); Nop ();
return ;
}

void DelayPORXLCD ( void ){


Delay1KTCYx (75); //15 ms delay ( cf . page 229 Ibrahim )
}
void DelayXLCD ( void ){
Delay1KTCYx (25); //5 ms
}

/ * = = = == = = = = = = = = = = = = Main program = = = = = = = = = = = = = = = = * /

void main ( void ){


char msg1 []=" Hey ";
int i =0;

PORTCbits . RC2 = 0; // Make PORTB zero


TRISCbits . RC2 = 0; // Make PORTB all output
OpenXLCD ( FOUR_BIT & LINES_5X7 ); // configure 4 bits , 5 x7 charcaters
Delay10KTCYx (500); // settling time
WriteCmdXLCD ( LCDCURSOR_OFF ); // Cursor off
while ( BusyXLCD ());
while (1)
{
itoa (i , msg1 +4);
i ++; if (i >999) { i =0;}

WriteCmdXLCD ( CLR_LCD ); // Clear LCD


while ( BusyXLCD ()); // wait
WriteCmdXLCD ( HOME_LCD ); // Home cursor
while ( BusyXLCD ()); // wait
putsXLCD ( msg1 ); // write text
while ( BusyXLCD ()); // wait

PORTCbits . RC2 = 1; // Make RC2 one


Delay10KTCYx (100); // delay a bit

PORTCbits . RC2 = 0; // Make RC2 zero


Delay10KTCYx (100); // delay a bit
}
}

III 4-digit 7-segment display 3641AS with common cathode


This project will be made with the PIC16F876.

Figure 12: Pinout of the 3641AS display.

11
Figure 13: Schematics of the 3641AS display.

Reference: https://docs.sunfounder.com/projects/euler-kit/en/latest/pyproject/py 74hc595 4dig.html#py-74hc-4dig


The idea to drive the four digit display consists of using the principle of human visual persistence to
quickly display the characters of each 7-segment in a loop to form continuous strings.
For example, when “1234” is displayed on the display, “1” is displayed on the first 7-segment, and “234”
is not displayed. After a period of time, the second 7-segment shows “2”, the 1st 3th 4th of 7-segment
does not show, and so on, the four digital display show in turn. This process is very short (typically 5ms),
and because of the optical afterglow effect and the principle of visual residue, we can see four characters
at the same time.

Although the PIC16F876 has enough IO pins to allow the control of the display, we will stick to the method of
using additional shift-register 74HC595, which can save IO pins. It can replace 8 pins for digital signal output by
serially writing an 8-bit binary number using 3 pins only.

Reference: https://docs.sunfounder.com/projects/euler-kit/en/latest/component/component 74hc595.html

Pins of 74HC595 and their functions:

ˆ Q0-Q7: 8-bit parallel data output pins, able to control 8 LEDs or 8 pins of 7-segment display directly.
ˆ Q7’: Series output pin, connected to DS of another 74HC595 to connect multiple 74HC595s in series
ˆ MR: Reset pin, active at low level;
ˆ SHcp: Time sequence input of shift register. On the rising edge, the data in shift register moves
successively one bit, i.e. data in Q1 moves to Q2, and so forth. While on the falling edge, the data
in shift register remain unchanged.
ˆ STcp: Time sequence input of storage register. On the rising edge, data in the shift register moves
into memory register.
ˆ CE: Output enable pin, active at low level.
ˆ DS: Serial data input pin
ˆ VCC: Positive supply voltage.
ˆ GND: Ground.

12
Figure 14: Pinout of the 74hc395 shift register.

Further functionality:

ˆ When MR (pin10) is high level and OE (pin13) is low level, data is input in the rising edge of SHcp
and goes to the memory register through the rising edge of SHcp.
ˆ If the two clocks are connected together, the shift register is always one pulse earlier than the memory
register.
ˆ There is a serial shift input pin (Ds), a serial output pin (Q) and an asynchronous reset button (low
level) in the memory register.
ˆ The memory register outputs a Bus with a parallel 8-bit and in three states.
ˆ When OE is enabled (low level), the data in memory register is output to the bus (Q0 to Q7).

A schematics
The PIC16F876 is clocked at 20MHz. For further use, RA0-RA5 are configured as analog channels. (Note that
AN4 is internally wired to RA5! This is a particularity of the 16F87x series.) Therefore, RA5 must be manually
reconfigured as input and RA4 as output. PICLab doesn’t do this on its own. RB0-RB3 are used as digit selection.
RC0 is the data-line (SDI), RC1 (RCLK), RC2 (SRCLK) of the serial communication to the 74hc595.

Figure 15: Schematics.

13
B PIC16F876-main loop method

Figure 16: Main program (loop method).

This method is the easiest to implement, because the 74hc595 shifting is controlled in the main loop. Note that the
display needs to be cleared, before setting a new digit. If this is not preformed, the LEDs get intermediate states
producing imprecise appearance. Single digits are extracted from the number to show and subsequently converted
to the right 7-segment LED pattern displayed in a look-up table for figures 0-9, and letters A-F.

The program uses a ms-timer (in fact 0.9984ms) and configures a ms-interrupt. Counters incremented at each
interrupt event or after 1000 such events. The sec counter is shown on the display. Note that leading zeroes are not
shown.

Figure 17: 74hc595 subroutine.

14
Figure 18: Decimal digit subroutine.

Although the method is easy to implement, it must be considered as very inefficient, because most of the time the
main loop is kept in wait functions. These are simple loops, where the processor is occupied with unproductive
activity. Also the digit switching requires much computing time, because digit extraction must is done at the main
loop rate.

C PIC16F876-interrupt state machine method


A better method is by using a state machine. The 74hc595 updates are only briefly executed in a 100µs interrupt
service routine (ISR). The main loop can be used for other tasks. Such a program is more difficult to design, because
also the digit switching with display clearing must be performed in the ISR. A further gain of computing time results
from the fact that the single digits are only computed once every second. For this purpose the computed digit codes
are stored into a buffer, from which the 74hc595 ISR picks them for rapid display update. So, for short, there two
different update rates, one for the fast digit switching and the other for the number update. Note that in order to
avoid flickering, we reduced the pauses between display states to 100µs.

Figure 19: Main program (interrupt state machine method).

15
Figure 20: Interrupt state machine.

IV Running the I2C-Slave device on a PIC16F876: communication


with ESP8266 D1 Mini NodeMcu
References:
ˆ Microchip Application Notes 00734: http://ww1.microchip.com/downloads/en/appnotes/00000734c.pdf
ˆ Related asm code: https://ww1.microchip.com/downloads/en/AppNotes/Source code.zip
ˆ Tutorial (buggy): https://www.teachmemicro.com/pic16-i2c/
ˆ Tutorial (buggy): http://www.stefan-buchgeher.info/elektronik/i2c pic slave/i2c slave pic.html#Kap1
ˆ Book: H.-J. Berndt, Messen, Steuern und Regeln mit MicroPython und RP2040, Independently Published,
(2021), pp. 106-109.
ˆ Tutorial: http://staff.ltam.lu/feljc/electronics/uPython/ESP8266&uPython I2C.pdf

16
ˆ Level converters: https://www.digikey.be/htmldatasheets/production/1828278/0/0/1/bob-12009.html

A Hardware
Configuring a micro-controller as an I2C-master is a relatively easy and well documented task. Unfortunately, this is
not the case for the I2C-slave mode. For PICs, we were astonished to find few information only, and above all very
incomplete and buggy. The only valuable document was the original Microchip Application Note 00734, and –not
easy to find on the Internet, because of broken links– the related Assembly code.

Note that some authors complain that their code doesn’t always work as expected. Some do completely misunder-
stand the role of the Buffer Full status bit BF of the SSPSTAT register, which is Read-only. And through they
recommend clearing it by software. In fact, this bit is set and cleared by the PIC hardware only. Some authors
confuse methods of handling the I2C bus by mixing up polling with interrupt methods. They introduce unbreakable
while-loops within interrupt service routines that poll the BF bit. This is a very bad idea, because the system can
hang up, if the SSPBUF register isn’t correctly written or read. The program could hang up.

So, we decided to write our own well working code, which is presented here.

PIC16F876 uses RC3 and RC4 for the I2C module. ESP8266 uses GPO4 and GPIO5. Because the PIC is powered
at 5V and the ESP8266 at 3V3, we must use level converters between the two devices. We also add 1.5kΩ pull-up
resistors to the I2C bus (on the 3V3 side). We don’t add any resistor on the 5V side, because only one slave is being
used.

Figure 21: ESP8266 D1 Mini NodeMcu.

B PIC program
Functionality description:

ˆ Correctly initialize the I2C module in slave mode (7-bit address mode)
ˆ Define a special byte-array (=buffer) that is filled for test reasons with ASCII values 65..68 (letters A, B, C,
D).
ˆ Define the interrupt service routine that can handle read, write modes and also distinguish data from slave
address. (Note the I2C master sends the device address first, and then only one or more data bytes.)
ˆ This is test version for further use that should read data from the PIC’s buffer. The ISR is configured to
respond on both read and write commands. However, in this actual version the variable first is never cleared,
which means that the PIC is never allowed to write into the buffer from the ISR. The ESP8266 can only read
the buffer. Therefore the ESP8266 must first send the buffer location (index) that it wants to read and then

17
read the related data. Don’t confuse the slave address with the buffer location. (If writing to the buffer is
desired, first must be cleared after the reception of the data location.)

Important note: Because the 0-bit of the address must be cleared at the Slave side -otherwise the module wouldn’t
recognize it as an address–, the address used by the ESP8266 must be left-shifted one bit on the PIC side, i.e. PIC
address 0x48=dec72 corresponds to 0x24=dec36.

Figure 22: A well working test program. (READ-ONLY configuration: Variable first is never cleared!)

18
Figure 23: I2C slave configuration.

Figure 24: We use a buffer for the data that is going to travel on the I2C bus.

19
Figure 25: A bunch of subroutines. Note that the subroutines must be define in PICLab within the interrupt service
routine.

;========================================================================================
; Assembler code for te st _I 2 C_ sl av e 4 . vi created with PICLab
;========================================================================================

LIST p =16 F876

# include " P16F876 . INC " ; Include header file

__CONFIG ( _BODEN_OFF & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _HS_OSC )

; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Variable definitions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

TEMPPORT8 EQU 0 X20


TEMPX8 EQU 0 X21
TEMPY8 EQU 0 X22
RESULT8 EQU 0 X23
TEMPX16 EQU 0 X24
TEMPX16_H EQU 0 X25
TEMPY16 EQU 0 X26
TEMPY16_H EQU 0 X27
RESULT16 EQU 0 X28
RESULT16_H EQU 0 X29
IDX16 EQU 0 X2A
IDX16_H EQU 0 X2B
TEMPYY EQU 0 X2C
OP_SIGN8 EQU 0 X2D
ADHBYTE EQU 0 X2E
ADLBYTE EQU 0 X2F
AD_RESULT EQU 0 X30
AD_RESULT_H EQU 0 X31
ISR_TEMPPORT8 EQU 0 X32
ISR_TEMPX8 EQU 0 X33
ISR_TEMPY8 EQU 0 X34
ISR_RESULT8 EQU 0 X35
ISR_TEMPX16 EQU 0 X36
ISR_TEMPX16_H EQU 0 X37
ISR_TEMPY16 EQU 0 X38
ISR_TEMPY16_H EQU 0 X39
ISR_RESULT16 EQU 0 X3A
ISR_RESULT16_H EQU 0 X3B
ISR_IDX16 EQU 0 X3C
ISR_IDX16_H EQU 0 X3D
ISR_TEMPYY EQU 0 X3E
ISR_OP_SIGN8 EQU 0 X3F
ISR_STATUS EQU 0 X40
ISR_W EQU 0 X41
ISR_FSR EQU 0 X42

20
I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S EQU 0 X43
I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S _ H EQU 0 X44
I2C_CURRENT EQU 0 X45
SLAVE_ADDRESS EQU 0 X46
I 2 C _ B U F F E R _ S T A R T _ A D D R E S S EQU 0 X47
I 2 C _ B U F F E R _ S T A R T _ A D D R E S S _ H EQU 0 X48
LOCATION EQU 0 X49
I 2 C _ B U F F E R _ E N D _ A D D R E S S EQU 0 X4A
I 2 C _ B U F F E R _ E N D _ A D D R E S S _ H EQU 0 X4B
FIRST EQU 0 X4C
I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ I N EQU 0 X4D
I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ I N _ H EQU 0 X4E
I 2 C _ B U F F E R _ M A X _ B Y T E S EQU 0 X4F
DUMMY EQU 0 X50
ISR_TMPX8 EQU 0 X51

; * * * * * * * * * * * * * * * * * * * * * * * * * * Makro definitions and definitions of used operations * * * * * * * * * * * * * * * * * * * * * * * * * *

BANK0 MACRO
BCF STATUS , RP0
BCF STATUS , RP1
ENDM
BANK1 MACRO
BSF STATUS , RP0
BCF STATUS , RP1
ENDM
BANK2 MACRO
BCF STATUS , RP0
BSF STATUS , RP1
ENDM
BANK3 MACRO
BSF STATUS , RP0
BSF STATUS , RP1
ENDM

GOTO START
ORG 0 X4
GOTO LABEL_ISR

SUMV16
MOVF TEMPY16 , W
ADDWF TEMPX16
BTFSC STATUS , C
INCF TEMPX16_H
MOVF TEMPY16_H , W
ADDWF TEMPX16_H
RETURN

ISR_DIVV8
MOVF ISR_TEMPY8 , F
BTFSC STATUS , Z ; SKIP IF NON - ZERO
RETURN
CLRF ISR_RESULT8
MOVLW 1
MOVWF ISR_IDX16
ISR_SHIFT_IT8
BCF STATUS , C
RLF ISR_IDX16 , F
BCF STATUS , C
RLF ISR_TEMPY8 , F
BTFSS ISR_TEMPY8 ,7
GOTO ISR_SHIFT_IT8
ISR_DIVU8LOOP
MOVF ISR_TEMPY8 , W
SUBWF ISR_TEMPX8
BTFSC STATUS , C
GOTO ISR_COUNT8
ADDWF ISR_TEMPX8
GOTO ISR_FINAL8
ISR_COUNT8
MOVF ISR_IDX16 , W
ADDWF ISR_RESULT8
ISR_FINAL8
BCF STATUS , C
RRF ISR_TEMPY8 , F
BCF STATUS , C
RRF ISR_IDX16 , F
BTFSS STATUS , C
GOTO ISR_DIVU8LOOP
RETURN

ISR_SUMV16
MOVF ISR_TEMPY16 , W
ADDWF ISR_TEMPX16
BTFSC STATUS , C

21
INCF ISR_TEMPX16_H
MOVF ISR_TEMPY16_H , W
ADDWF ISR_TEMPX16_H
RETURN

ISR_GRU16U16
MOVF ISR_TEMPX16 , W
SUBWF ISR_TEMPY16
MOVF ISR_TEMPX16_H , W
BTFSS STATUS , C
INCFSZ ISR_TEMPX16_H , W
SUBWF ISR_TEMPY16_H
BTFSS STATUS , C
RETLW 0
RETLW 1

; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * BEGIN OF MAIN PROGRAM * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

START

; INITIALIZE PORT A
BANK0
CLRF PORTA
BANK1
MOVLW 0 X0
MOVWF TRISA

; INITIALIZE PORT B
BANK0
CLRF PORTB
BANK1
MOVWF TRISB

; INITIALIZE PORT C
BANK0
CLRF PORTC
BANK1
MOVWF TRISC

; SET VARIABLE U8 WITH CONSTANT


MOVLW 0 X4
BANK0
MOVWF I 2 C _ B U F F E R _ M A X _ B Y T E S

; SET VARIABLE U16 WITH CONSTANT


MOVLW 0 X10
MOVWF I 2 C _ B U F F E R _ S T A R T _ A D D R E S S
MOVLW 0 X1
MOVWF I 2 C _ B U F F E R _ S T A R T _ A D D R E S S _ H

; SET VARIABLE U16 WITH VARIABLE U16


MOVF I2C_BUFFER_START_ADDRESS , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S
MOVF I2C_BUFFER_START_ADDRESS_H , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S _ H

; SET VARIABLE U16 WITH VARIABLE U16


MOVF I2C_BUFFER_START_ADDRESS , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ I N
MOVF I2C_BUFFER_START_ADDRESS_H , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ I N _ H

; SET VARIABLE U16 WITH VARIABLE U16


MOVF I2C_BUFFER_START_ADDRESS , W
MOVWF I 2 C _ B U F F E R _ E N D _ A D D R E S S
MOVF I2C_BUFFER_START_ADDRESS_H , W
MOVWF I 2 C _ B U F F E R _ E N D _ A D D R E S S _ H

; OPERATION
; SET VARIABLE U16 WITH VARIABLE U16
MOVF I2C_BUFFER_END_ADDRESS , W
MOVWF TEMPX16
MOVF I2C_BUFFER_END_ADDRESS_H , W
MOVWF TEMPX16_H
; SET VARIABLE U16 WITH CONSTANT
MOVLW 0 X3
MOVWF TEMPY16
MOVLW 0 X0
MOVWF TEMPY16_H
CALL SUMV16
; SET VARIABLE U16 WITH VARIABLE U16
BANK0
MOVF TEMPX16 , W
MOVWF I 2 C _ B U F F E R _ E N D _ A D D R E S S

22
MOVF TEMPX16_H , W
MOVWF I 2 C _ B U F F E R _ E N D _ A D D R E S S _ H

; SET INDIRECT VARIABLE WITH CONSTANT


; SET U16 POINTER
BCF STATUS , IRP
BTFSC I2C_BUFFE R _ C U R R E N T _ A D DR E S S _ B U S _ H ,0
BSF STATUS , IRP
BANK0
MOVF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , W
MOVWF FSR
MOVLW 0 X41
MOVWF INDF

INCF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , F
BTFSC STATUS , Z
INCF I2C_BUFFER _ C U R R E N T _ A D D R E S S _ B US _ H , F

; SET INDIRECT VARIABLE WITH CONSTANT


; SET U16 POINTER
BCF STATUS , IRP
BANK0
BTFSC I2C_BUFFE R _ C U R R E N T _ A D DR E S S _ B U S _ H ,0
BSF STATUS , IRP
BANK0
MOVF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , W
MOVWF FSR
MOVLW 0 X42
MOVWF INDF

INCF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , F
BTFSC STATUS , Z
INCF I2C_BUFFER _ C U R R E N T _ A D D R E S S _ B US _ H , F

; SET INDIRECT VARIABLE WITH CONSTANT


; SET U16 POINTER
BCF STATUS , IRP
BANK0
BTFSC I2C_BUFFE R _ C U R R E N T _ A D DR E S S _ B U S _ H ,0
BSF STATUS , IRP
BANK0
MOVF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , W
MOVWF FSR
MOVLW 0 X43
MOVWF INDF

INCF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , F
BTFSC STATUS , Z
INCF I2C_BUFFER _ C U R R E N T _ A D D R E S S _ B US _ H , F

; SET INDIRECT VARIABLE WITH CONSTANT


; SET U16 POINTER
BCF STATUS , IRP
BANK0
BTFSC I2C_BUFFE R _ C U R R E N T _ A D DR E S S _ B U S _ H ,0
BSF STATUS , IRP
BANK0
MOVF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , W
MOVWF FSR
MOVLW 0 X44
MOVWF INDF

INCF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , F
BTFSC STATUS , Z
INCF I2C_BUFFER _ C U R R E N T _ A D D R E S S _ B US _ H , F

; CONFIGURE AD - CONVERTER
; CONFIGURE PORT INPUTS
BANK1
MOVF TRISA , W
IORLW 0 X1F
MOVWF TRISA
MOVLW 0 X82
MOVWF ADCON1
MOVLW 0 X81
BANK0
MOVWF ADCON0

; CONFIGURE PORT ALL


; SET SFR WITH CONSTANT
MOVLW 0 X2F
BANK1
MOVWF TRISA

; SET SFR WITH CONSTANT

23
MOVLW 0 XF
BANK0
MOVWF PORTB

; SET SFR WITH CONSTANT


MOVLW 0 X6
MOVWF PORTC

; WAIT
MOVLW 0 XAA
MOVWF TEMPYY
LABEL_1003
MOVLW 0 X1D
MOVWF IDX16
LABEL_1004
MOVLW 0 XA7
MOVWF IDX16_H
LABEL_1005
DECFSZ IDX16_H , F
GOTO LABEL_1005
DECFSZ IDX16 , F
GOTO LABEL_1004
DECFSZ TEMPYY , F
GOTO LABEL_1003
NOP
NOP
NOP
NOP
NOP
NOP
NOP

; CONFIGURE UART
BANK1
BSF TRISC ,7
BSF TRISC ,6
MOVLW 0 X20
MOVWF SPBRG
BCF TXSTA , BRGH
BCF TXSTA , SYNC
BANK0
BSF RCSTA , SPEN
BCF RCSTA , RX9
BSF RCSTA , CREN
BANK1
BCF TXSTA , TX9
BSF TXSTA , TXEN

; SET SFR WITH CONSTANT


MOVLW 0 X80
MOVWF SSPSTAT

; SET SFR WITH CONSTANT


MOVLW 0 X48
MOVWF SSPADD

; SET SFR WITH CONSTANT


MOVLW 0 X36
BANK0
MOVWF SSPCON

; SET SFR WITH CONSTANT


MOVLW 0 X1
BANK1
MOVWF SSPCON2

; CONFIGURE SINGLE PIN


BSF TRISC ,3

; CONFIGURE SINGLE PIN


BSF TRISC ,4

; START MONITORING INTERRUPTS


BANK0
BCF PIR1 , SSPIF
BANK1
BSF PIE1 , SSPIE
BSF INTCON , GIE
BSF INTCON , PEIE

LABEL_0

; WAIT
BANK0
MOVLW 0 XE9

24
MOVWF TEMPYY
LABEL_1021
MOVLW 0 X73
MOVWF IDX16
LABEL_1022
MOVLW 0 XB9
MOVWF IDX16_H
LABEL_1023
DECFSZ IDX16_H , F
GOTO LABEL_1023
DECFSZ IDX16 , F
GOTO LABEL_1022
DECFSZ TEMPYY , F
GOTO LABEL_1021
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP

; SET SINGLE OUPUT PIN


BANK0
BCF PORTB ,4

GOTO LABEL_0

LABEL_1024

GOTO LABEL_1024

; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SUBROUTINES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

L A BEL_AQUISITION

; WAIT
BANK0
MOVLW 0 X12
MOVWF TEMPYY
LABEL_1002
DECFSZ TEMPYY , F
GOTO LABEL_1002
NOP

RETURN

L A B E L_ IS R _O V ER FL O W

; BEGIN OF IF - STRUCTURE ( DEPENDING ON BIT / PIN )


BANK0
BTFSS SSPCON ,6
GOTO LABEL_1006

BANK0
BCF SSPCON ,6

; SET VARIABLE U8 WITH SFR


MOVF SSPBUF , W
MOVWF DUMMY

GOTO LABEL_1007
LABEL_1006

LABEL_1007
; END OF IF - STRUCTURE

RETURN

LABEL_ISR_WRITE_COLLISION

; BEGIN OF IF - STRUCTURE ( DEPENDING ON BIT / PIN )


BANK0
BTFSS SSPCON ,7
GOTO LABEL_1008

BANK0
BCF SSPCON ,7

; SET VARIABLE U8 WITH SFR

25
MOVF SSPBUF , W
MOVWF DUMMY

GOTO LABEL_1009
LABEL_1008

LABEL_1009
; END OF IF - STRUCTURE

RETURN

LABEL_ISR_SET_LOCATION_POINTER

; SET VARIABLE U8 WITH VARIABLE U8


BANK0
MOVF LOCATION , W
MOVWF ISR_TMPX8
; OPERATION
; SET VARIABLE U8 WITH VARIABLE U8
MOVF ISR_TMPX8 , W
MOVWF ISR_TEMPX8
; SET VARIABLE U8 WITH VARIABLE U8
MOVF I2C_BUFFER_MAX_BYTES , W
MOVWF ISR_TEMPY8
CALL ISR_DIVV8
; SET VARIABLE U8 WITH VARIABLE U8
BANK0
MOVF ISR_RESULT8 , W
MOVWF ISR_TMPX8

; SET VARIABLE U8 WITH VARIABLE U8


MOVF ISR_TEMPX8 , W
MOVWF LOCATION
; SET VARIABLE U16 WITH VARIABLE U16
MOVF I2C_BUFFER_START_ADDRESS , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S
MOVF I2C_BUFFER_START_ADDRESS_H , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S _ H

; OPERATION
; SET VARIABLE U16 WITH VARIABLE U16
MOVF I2C_BUFF ER _C U RR EN T_ A DD RE SS _ BU S , W
MOVWF ISR_TEMPX16
MOVF I2C_BUFFER _ C U R R E N T _ A D D R E S S _ B US _ H , W
MOVWF ISR_TEMPX16_H
; SET VARIABLE U16 WITH VARIABLE U8
MOVF LOCATION , W
MOVWF ISR_TEMPY16
CLRF ISR_TEMPY16_H
CALL ISR_SUMV16
; SET VARIABLE U16 WITH VARIABLE U16
BANK0
MOVF ISR_TEMPX16 , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S
MOVF ISR_TEMPX16_H , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S _ H

RETURN

LABEL_ISR_INCREMENT_POINTER

BANK0
INCF I2C_BUFFER _C UR R EN T_ A DD RE SS _ BU S , F
BTFSC STATUS , Z
INCF I2C_BUFFER _ C U R R E N T _ A D D R E S S _ B US _ H , F

; BEGIN OF IF - STRUCTURE
; COMPARE - OPERATION
; SET VARIABLE U16 WITH VARIABLE U16
BANK0
MOVF I2C_BUFF ER _C U RR EN T_ A DD RE SS _ BU S , W
MOVWF ISR_TEMPX16
MOVF I2C_BUFFER _ C U R R E N T _ A D D R E S S _ B US _ H , W
MOVWF ISR_TEMPX16_H
; SET VARIABLE U16 WITH VARIABLE U16
MOVF I2C_BUFFER_END_ADDRESS , W
MOVWF ISR_TEMPY16
MOVF I2C_BUFFER_END_ADDRESS_H , W
MOVWF ISR_TEMPY16_H
CALL ISR_GRU16U16
BANK0
MOVWF ISR_RESULT8
BTFSC ISR_RESULT8 ,0
GOTO LABEL_1010

26
; SET VARIABLE U16 WITH VARIABLE U16
BANK0
MOVF I2C_BUFFER_START_ADDRESS , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S
MOVF I2C_BUFFER_START_ADDRESS_H , W
MOVWF I 2 C _ B U F F E R _ C U R R E N T _ A D D R E S S _ B U S _ H

GOTO LABEL_1011
LABEL_1010

LABEL_1011
; END OF IF - STRUCTURE

RETURN

; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INTERRUPT SERVICE ROUTINE * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

LABEL_ISR
MOVWF 0 X7F
SWAPF STATUS , W
BANK0
MOVWF ISR_STATUS
MOVF 0 X7F , W
MOVWF ISR_W
MOVF TEMPPORT8 , W
MOVWF ISR_TEMPPORT8
MOVF FSR , W
MOVWF ISR_FSR
BANK1
BTFSS PIE1 , SSPIE
GOTO LABEL_1025
BANK0
BTFSS PIR1 , SSPIF
GOTO LABEL_1025
CALL LABEL_EVENT0
BANK0
BCF PIR1 , SSPIF
LABEL_1025
BANK0
MOVF ISR_FSR , W
MOVWF FSR
MOVF ISR_TEMPPORT8 , W
MOVWF TEMPPORT8
MOVF ISR_W , W
MOVWF 0 X7F
SWAPF ISR_STATUS , W
MOVWF STATUS
SWAPF 0 X7F , F
SWAPF 0 X7F , W
RETFIE

; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * EVENT - ROUTINES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

LABEL_EVENT0

BANK0
BCF SSPCON ,4

; SET SINGLE OUPUT PIN


BSF PORTB ,4

; BEGIN OF IF - STRUCTURE ( DEPENDING ON BIT / PIN )


BANK1
BTFSS SSPSTAT ,2
GOTO LABEL_1012

; BEGIN OF IF - STRUCTURE ( DEPENDING ON BIT / PIN )


BANK1
BTFSS SSPSTAT ,5
GOTO LABEL_1013

GOTO LABEL_1014
LABEL_1013

LABEL_1014
; END OF IF - STRUCTURE

; SET SFR WITH INDIRECT VARIABLE


; SET U16 POINTER
BCF STATUS , IRP
BANK0
BTFSC I 2 C _ B U F F E R _ C U R R E N T _ A DD R E S S _ B U S _ H ,0
BSF STATUS , IRP
BANK0
MOVF I 2C _B UF F ER _C UR R EN T_ A DD RE SS _ BU S , W

27
MOVWF FSR
MOVF INDF , W
MOVWF SSPBUF

CALL L A B E L _ I S R _ I N C R E M E N T _ P O I N T E R

BANK0
BSF FIRST ,0

GOTO LABEL_1020
LABEL_1012

; SET VARIABLE U8 WITH SFR


BANK0
MOVF SSPBUF , W
MOVWF I2C_CURRENT

; BEGIN OF IF - STRUCTURE ( DEPENDING ON BIT / PIN )


BANK1
BTFSS SSPSTAT ,5
GOTO LABEL_1015

; BEGIN OF IF - STRUCTURE ( DEPENDING ON BIT / PIN )


BANK0
BTFSS FIRST ,0
GOTO LABEL_1016

; SET VARIABLE U8 WITH VARIABLE U8


BANK0
MOVF I2C_CURRENT , W
MOVWF LOCATION

CALL L A B E L _ I S R _ S E T _ L O C A T I O N _ P O I N T E R

BANK0
BCF FIRST ,0

GOTO LABEL_1017
LABEL_1016

; SET INDIRECT VARIABLE WITH VARIABLE U8


; SET U16 POINTER
BCF STATUS , IRP
BANK0
BTFSC I 2 C _ B U F F E R _ C U R R E N T _ A D DR E S S _ B U S _ H ,0
BSF STATUS , IRP
BANK0
MOVF I 2C _B UF F ER _C UR R EN T_ A DD RE SS _ BU S , W
MOVWF FSR
MOVF I2C_CURRENT , W
MOVWF INDF

CALL L A B E L _ I S R _ I N C R E M E N T _ P O I N T E R

LABEL_1017
; END OF IF - STRUCTURE

GOTO LABEL_1018
LABEL_1015

; SET VARIABLE U8 WITH VARIABLE U8


BANK0
MOVF I2C_CURRENT , W
MOVWF SLAVE_ADDRESS

BSF FIRST ,0

LABEL_1018
; END OF IF - STRUCTURE

; SEND MAIL
BANK0
LABEL_1019
BTFSS PIR1 , TXIF
GOTO LABEL_1019
; SET SFR WITH VARIABLE U8
BANK0
MOVF I2C_CURRENT , W
MOVWF TXREG

LABEL_1020
; END OF IF - STRUCTURE

CALL L A B E L _ I S R _ W R I T E _ C O L L I S I O N

28
CALL L AB E L_ IS R _ O V E R F L O W

BANK0
BSF SSPCON ,4

RETURN

END

C ESP8266 Micropython program

Figure 26: A very simple Micopython code to read from the I2C slave as desired.

29

You might also like