Digital SM Part II: I2C PIC18F4550 Slave and PIC18F4550 continued
In
part I , I wrote about the problem with receiving multiple bytes from slave. I rewrote both master and slave and discovered that after the first read, the next reads commands just aren't received by the slave. So I altered both the master and slave code in order to read all PIC18F4550 ports.
I changed the code for the slave. It now uses interrupts. When it receives the 'command byte' F6 from the master, it collects data from PORT A-E and stores it in an internal buffer and it calculates a checksum of 2 bytes. Now each time the master asks to read a byte, it will return a byte from this buffer: PORT A, ... PORT E, checksum high byte, checksum low byte.
#include <p18f4550.h>
#include <stdio.h>
#include <stdlib.h>
#include <i2c.h>
#pragma config PLLDIV = 5 // 20 MHz Oscillator
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // 48 MHz CPU-CLK
#pragma config FOSC = HSPLL_HS // Highspeed with phase locked loop
//#pragma config FOSC = HS // Highspeed, no phase locked loop
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config DEBUG = OFF
//#ifdef __DEBUG
#pragma config PWRT = OFF
#pragma config WDT = OFF, WDTPS = 1024
//#else
// #pragma config PWRT = ON
// #pragma config WDT = ON, WDTPS = 32768
//#endif
#pragma config BOR = OFF, BORV = 0
#pragma config VREGEN = ON
#pragma config MCLRE = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config CCP2MX = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF
#pragma config ICPRT = ON//OFF
#pragma config XINST = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTRB = OFF
#define _XTAL_FREQ 20000000
//void low_isr (void);
void high_isr(void);
unsigned char databyte;
unsigned char status = 0;
unsigned char readIndex = 0;
unsigned char writeIndex = 0;
unsigned char R_CNT = 0;
void delay_sec(unsigned char sec);
void delay_msec(unsigned char msec);
void leds_test(void);
void writeByte(void);
unsigned char I2C_Send[7];
unsigned char I2C_Recv[21];
#pragma code low_vector=0x08 //High interrupt priority starts at 0x08
void high_interrupt(void) {
_asm GOTO high_isr _endasm
}
#pragma code
#pragma interrupt high_isr
void high_isr(void) {
unsigned int checksum = 0;
unsigned char data = 0;
if (PIR1bits.SSPIF) {
if (SSPSTATbits.S) // start bit has been detected last
{
status = 0;
if (SSPSTATbits.R_W == 0) // master write operation
{
if (SSPSTATbits.BF) {
data = SSPBUF;
if (SSPSTATbits.D_A == 0) //last byte was an address byte
{
//PORTD = 1;
status = 1;
readIndex = 0;
writeIndex = 0;
} else {
if (data == 0xF6)
{
checksum = 0;
writeIndex = 0;
I2C_Send[0] = 0b11000011; // test data, can be replaced by PORTA;
I2C_Send[1] = 0b10011001; // test data, can be replaced by PORTB;
I2C_Send[2] = 0b00001111; // test data, can be replaced by PORTB;
I2C_Send[3] = 0b11110000; // test data, can be replaced by PORTD;
I2C_Send[4] = 0b11100111; // test data, can be replaced by PORTE;
checksum += I2C_Send[0];
checksum += I2C_Send[1];
checksum += I2C_Send[2];
checksum += I2C_Send[3];
checksum += I2C_Send[4];
I2C_Send[5] = checksum >> 8; // high byte
I2C_Send[6] = (checksum << 8) >> 8; // low byte
writeIndex = 0;
R_CNT++;
}
status = 2;
//PORTD = 2;
if (readIndex < 20) {
I2C_Recv[readIndex] = data;
//PORTD = I2C_Recv[readIndex];
readIndex++;
}
}
SSPCON1bits.CKP = 1;
}
} else // master read operation
{
if (SSPSTATbits.D_A == 0)//last byte was an address byte
{
if (SSPSTATbits.BF) {
data = SSPBUF;
}
SSPBUF = I2C_Send[writeIndex++];
if(writeIndex >= 7)
{
writeIndex =0;
}
//PORTD = 0b11000011;
status = 3;
SSPCON1bits.CKP = 1;
} else if (SSPSTATbits.BF) {
data = SSPBUF;
status = 4;
writeByte();
writeIndex++;
SSPCON1bits.CKP = 1;
}
else if(!SSPCON1bits.CKP){
writeByte();
writeIndex++;
SSPCON1bits.CKP = 1;
}
}
}
PORTD = R_CNT;
PIR1bits.SSPIF = 0;
}
}
void writeByte(void) {
PORTD = 0b11110000;
SSPCON1bits.WCOL = 0;
SSPBUF = 0b11000011;
while (SSPCON1bits.WCOL) {
SSPCON1bits.WCOL = 0;
SSPBUF = 0b10000011;
PORTD = 0b11001101;
}
PORTD = 0b11110011;
}
/*
#pragma code low_vector=0x18 //Low interrupt priority starts at 0x18
void low_interrupt(void)
{
_asm GOTO low_isr _endasm
}
#pragma code
#pragma interrupt low_isr
void low_isr (void)
{
PORTD = 3;
if(PIR1bits.SSPIF) //Timer0 interrupt
{
PIR1bits.SSPIF = 0;
PORTD = 4;
}
}
*/
void main(void) {
unsigned char sync_mode = 0, slew = 0, add1, status, temp, w, length = 0;
unsigned char slaveEvenAddress = 0xA2;
unsigned char slaveOddAddress = 0xA2 | 0x01;
unsigned char command = 0x00;
unsigned char counter = 0x00;
unsigned char counter2 = 0x00;
unsigned char slaveData = 0x00;
unsigned char mask = 0x00;
PORTA = 0;
TRISA = 0b00000000; // PORTD all outputs
PORTA = 0b11111111;
/*
Two pins are used for data transfer:
? Serial clock (I2C_SCL) ? RB1/AN10/INT1/SCK/I2C_SCL
? Serial data (I2C_SDA) ? RB0/AN12/INT0/FLT0/SDI/I2C_SDA
The user must configure these pins as inputs by setting
the associated TRIS bits.
*/
ADCON1 = 0b00001111; //AN0...AN12 as digital I/O
TRISB = 0b00000011; //RB0...RB1 as digital inputs, others output
PORTB = 0;
PORTB = 0b11111100;
PORTC = 0;
TRISC = 0b00000000; // PORTD all outputs
PORTC = 0b11111111;
PORTD = 0;
TRISD = 0b00000000; // PORTD all outputs
PORTD = 0b11111111;
PORTE = 0;
TRISE = 0b00000000; // PORTD all outputs
PORTE = 0b11111111;
leds_test();
for (w = 0; w < 20; w++) {
I2C_Recv[w] = 0;
I2C_Send[w] = 0b11000011;
}
CloseI2C(); //close i2c if was operating earlier
//------------------------INITIALISE THE I2C MODULE FOR MASTER MODE WITH 100KHz ---------------------------
SSPCON1 = 0;
SSPCON2 = 0;
SSPSTAT = 0;
SSPSTATbits.SMP = 1; // slew rate is disabled
SSPSTATbits.CKE = 1; // enable SM
SSPCON1bits.CKP = 1; // Release clock
SSPCON2bits.SEN = 1; // 0 =Clock stretching is disabled
//SSPCON1 = 0b00101110;// I2C Slave mode, 7-bit address with Start and Stop bit interrupts enabled(2)
SSPCON1 = 0b00100110; // I2C Slave mode, 7-bit address
SSPSTATbits.SMP = 1; // slew rate is disabled
SSPADD = slaveEvenAddress; //initialze slave address
PORTD = 1;
PIE1bits.SSPIE = 1; //SSPIE: Master Synchronous Serial Port Interrupt Enable bit
INTCONbits.PEIE = 1; //Enable all peripheral interrupts
INTCONbits.GIE = 1; //Enable global interrupts
PORTD = 2;
while (1) {
}
while (1) {
PORTD = 2;
while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master
temp = ReadI2C();
if (temp == slaveEvenAddress) {
PORTD = 3;
//********************* Data reception from master by slave *********************
do {
while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master
I2C_Recv[length++] = getcI2C(); // save byte received
PORTD = PORTD + 1;
} while (length != 20);
PORTD = 4;
//******************** write sequence from slave *******************************
while (SSPSTATbits.S != 1); //wait untill STOP CONDITION
PORTD = 5;
//********************* Read the address sent by master from buffer **************
while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master
temp = ReadI2C();
if (temp == slaveEvenAddress) {
PORTD = 6;
command = ReadI2C();
PORTD = command;
slaveData++;
}
while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master
PORTD = 7;
temp = ReadI2C();
if (temp == slaveOddAddress) {
PORTD = 8;
} else {
PORTD = temp;
while (1) {
}
}
PORTD = 10;
temp = SSPBUF;
slaveData = 0b11000011;
/*
bit 7 SMP: Slew Rate Control bit
In Master or Slave mode:
1 = Slew rate control disabled for Standard Speed mode (100 kHz and 1 MHz)
0 = Slew rate control enabled for High-Speed mode (400 kHz)
bit 6 CKE: SMBus Select bit
In Master or Slave mode:
1 = Enable SMBus specific inputs
0 = Disable SMBus specific inputs
bit 5 D/A: Data/Address bit
In Master mode:
Reserved.
In Slave mode:
1 = Indicates that the last byte received or transmitted was data
0 = Indicates that the last byte received or transmitted was address
bit 4 P: Stop bit(1)
1 = Indicates that a Stop bit has been detected last
0 = Stop bit was not detected last
bit 3 S: Start bit(1)
1 = Indicates that a Start bit has been detected last
0 = Start bit was not detected last
bit 2 R/W: Read/Write Information bit(2,3)
In Slave mode:
1 = Read
0 = Write
In Master mode:
1 = Transmit is in progress
0 = Transmit is not in progress
bit 1 UA: Update Address bit (10-Bit Slave mode only)
1 = Indicates that the user needs to update the address in the SSPADD register
0 = Address does not need to be updated
bit 0 BF: Buffer Full Status bit
In Transmit mode:
1 = SSPBUF is full
0 = SSPBUF is empty
In Receive mode:
1 = SSPBUF is full (does not include the ACK and Stop bits)
0 = SSPBUF is empty (does not include the ACK and Stop bits)
*/
//movf Temp,W ;
//andlw b'00101100' ; Mask BF bit in SSPSTAT
//xorlw b'00001100'
mask = 0b00001100;
status = SSPSTAT;
while (status) {
PORTD = status;
status = SSPSTAT & 0b00101100; // Mask BF bit in SSPSTAT
status = status ^ mask; // mask sspstat
}
SSPBUF = 0b11000011;
while (SSPCON1bits.WCOL) {
SSPCON1bits.WCOL = 0;
PORTD = 0b11010011;
SSPBUF = 0b11000011;
}
for (counter = 1; counter < 20; counter++) {
mask = 0b00101100;
status = SSPSTAT;
//S = 1, D_A = 1, R_W = 1, BF = 0
while (status) {
PORTD = status;
status = SSPSTAT & 0b00101100; // Mask BF bit in SSPSTAT
status = status ^ mask; // mask sspstat
}
SSPBUF = 0b11000011;
while (SSPCON1bits.WCOL) {
SSPCON1bits.WCOL = 0;
PORTD = 0b11010011;
SSPBUF = 0b11000011;
}
}
//if (SSPSTAT & 0x04) //check if master is ready for reception
// while (putsI2C(I2C_Send)); // send the data to master
PORTD = 0b01010101;
while (1) {
}
} else {
PORTD = temp;
}
}
//-------------TERMINATE COMMUNICATION FROM MASTER SIDE---------------
CloseI2C(); //close I2C module
}
void delay_sec(unsigned char sec) {
unsigned char counter1 = 0;
unsigned char counter2 = 0;
unsigned char counter3 = 0;
unsigned char counter4 = 0;
for (counter1 = 0; counter1 < sec; counter1++) {
for (counter2 = 0; counter2 < 50; counter2++) {
for (counter3 = 0; counter3 < 100; counter3++) {
for (counter4 = 0; counter4 < 100; counter4++) {
Nop();
// (5 * 2) * 100 * 100 * 100
}
}
}
}
}
void delay_msec(unsigned char msec) {
unsigned char counter1 = 0;
unsigned char counter2 = 0;
unsigned char counter3 = 0;
for (counter1 = 0; counter1 < msec; counter1++) {
for (counter2 = 0; counter2 < 50; counter2++) {
for (counter3 = 0; counter3 < 10; counter3++) {
Nop();
// (5 * 2) * 100 * 100 * 100
}
}
}
}
void leds_test(void) {
PORTD = 0b11111111;
delay_msec(100);
PORTD = 0b00000001;
delay_msec(100);
PORTD = PORTD << 1;
delay_msec(100);
PORTD = PORTD << 1;
delay_msec(100);
PORTD = PORTD << 1;
delay_msec(100);
PORTD = PORTD << 1;
delay_msec(100);
PORTD = PORTD << 1;
delay_msec(100);
PORTD = PORTD << 1;
delay_msec(100);
PORTD = PORTD << 1;
delay_sec(1);
}
The master code had to be changed too. It sends the F6 command to the slave, then it sends repeated start sequences for every byte it wants to receive. After receiving all data, it calculates a checksum and compares it with the received checksum. If they don't match, the program halts and displays the received data (byte by byte): Port A-E, checksum high byte, checksum low byte. Otherwise it will just repeat the whole process.
/*
* File: main.c
* Author: erwin_000
*
* Created on December 30, 2013, 8:07 PM
*/
#include <p18f4550.h>
#include <stdio.h>
#include <stdlib.h>
#include <i2c.h>
#pragma config PLLDIV = 5 // 20 MHz Oscillator
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // 48 MHz CPU-CLK
#pragma config FOSC = HSPLL_HS // Highspeed with phase locked loop
//#pragma config FOSC = HS // Highspeed, no phase locked loop
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config DEBUG = OFF
//#ifdef __DEBUG
#pragma config PWRT = OFF
#pragma config WDT = OFF, WDTPS = 1024
//#else
// #pragma config PWRT = ON
// #pragma config WDT = ON, WDTPS = 32768
//#endif
#pragma config BOR = OFF, BORV = 0
#pragma config VREGEN = ON
#pragma config MCLRE = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config CCP2MX = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF
#pragma config ICPRT = ON//OFF
#pragma config XINST = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTRB = OFF
#define _XTAL_FREQ 20000000
#define SCL TRISBbits.TRISB1 // I2C bus
#define SDA TRISBbits.TRISB0
#define SCL_IN PORTBbits.RB1 //
#define SDA_IN PORTBbits.RB0 //
const unsigned char PORTA_DATA = 0;
const unsigned char PORTB_DATA = 1;
const unsigned char PORTC_DATA = 2;
const unsigned char PORTD_DATA = 3;
const unsigned char PORTE_DATA = 4;
const unsigned char CHECKSUM_LO = 5;
const unsigned char CHECKSUM_HI = 6;
void delay_sec(unsigned char sec);
void delay_msec(unsigned char msec);
void leds_test(void);
void sendStartSequence(void);
void sendStopSequence(void);
void sendRepeatedStartSequence(void);
void writeAddressOfSlave(unsigned char add1, unsigned char modus);
void sendReadAcknowledge(void);
void sendReadNotAcknowledge(void);
unsigned char sendReadCommand(void);
unsigned char I2C_Send[21] = "MICROCHIP:I2C_MASTER";
unsigned char I2C_Recv[7];
unsigned char status = 0;
unsigned char data = 0;
//************ I2C MASTER ****************************
void main(void) {
unsigned char add1, w;
unsigned char counter = 0;
unsigned char loopcounter = 0;
unsigned int received_checksum=0;
unsigned int calculated_checksum=0;
PORTA = 0;
TRISA = 0b00000000; // PORTD all outputs
PORTA = 0b11111111;
/*
Two pins are used for data transfer:
? Serial clock (I2C_SCL) ? RB1/AN10/INT1/SCK/I2C_SCL
? Serial data (I2C_SDA) ? RB0/AN12/INT0/FLT0/SDI/I2C_SDA
The user must configure these pins as inputs by setting
the associated TRIS bits.
*/
ADCON1 = 0b00001111; //AN0...AN12 as digital I/O
TRISB = 0b00000011; //RB0...RB1 as digital inputs, others output
PORTB = 0;
PORTB = 0b11111100;
PORTC = 0;
TRISC = 0b00000000; // PORTD all outputs
PORTC = 0b11111111;
PORTD = 0;
TRISD = 0b00000000; // PORTD all outputs
PORTD = 0b11111111;
PORTE = 0;
TRISE = 0b00000000; // PORTD all outputs
PORTE = 0b11111111;
leds_test();
for (w = 0; w < 7; w++) {
I2C_Recv[w] = 0;
}
status = 0;
add1 = 0xA2; //address of the device (slave) under communication
SSPCON1 = 0;
SSPCON2 = 0;
SSPADD = 0x63; // 0x63 = 100kHz Baud clock(9) @20MHz
SSPSTATbits.SMP = 1; // slew rate is disabled
SSPSTATbits.CKE = 1; // enable SM
SSPCON1bits.SSPM3 = 1; // 1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
SSPCON1bits.SSPM2 = 0;
SSPCON1bits.SSPM1 = 0;
SSPCON1bits.SSPM0 = 0;
SSPCON1bits.SSPEN = 1; // enable I2C
SSPCON2bits.SEN = 0; // Clock stretching is disabled
while (1) {
while (SSPCON1bits.SSPOV) {
SSPCON1bits.SSPOV = 0;
}
while (SSPCON1bits.WCOL) {
SSPCON1bits.WCOL = 0;
}
/*
1. Send a start sequence
2. Send the I2C address of the slave with the R/W bit low (even address)
3. Send the internal register number you want to write to
4. Send the data byte
5. [Optionally, send any further data bytes]
6. Send the stop sequence.
*/
sendStartSequence();
PORTD = 1;
writeAddressOfSlave(add1, 0x00);
PORTD = 2;
for (counter = 0; counter < 20; counter++) {
I2C_Send[counter] = 0b11100111;
}
while (putsI2C(I2C_Send) != 0); //write string of data to be transmitted to slave
PORTD = 3;
sendStopSequence();
PORTD = 4;
/*
1. Send a start sequence
2. Send the I2C address of the slave with the R/W bit low (even address)
3. Send 0xF6 command
4. Send a start sequence again (repeated start)
5. Send the I2C address of the slave with the R/W bit high (odd address)
6. Read data byte from slave
7. Send the stop sequence.
*/
while (1) {
sendStartSequence();
PORTD = 5;
IdleI2C();
writeAddressOfSlave(add1, 0x00);
PORTD = 6;
WriteI2C(0xF6);
SSPCON1bits.SSPOV = 0;
while (SSPSTATbits.BF) {
data = SSPBUF;
}
for (counter = 0; counter < 7; counter++) {
PORTD = 9;
sendRepeatedStartSequence();
writeAddressOfSlave(add1, 0x01);
data = sendReadCommand();
PORTD = data;
if (SSPCON2bits.ACKSTAT) {
PORTD = 0b11111111;
}
I2C_Recv[counter] = data;
if (counter < 6) {
PORTD = 13;
IdleI2C();
sendReadAcknowledge();
} else {
PORTD = 14;
IdleI2C();
sendReadNotAcknowledge();
}
}
PORTD = 14;
sendStopSequence();
PORTD = 0b10101010;
calculated_checksum = I2C_Recv[0];
calculated_checksum += I2C_Recv[1];
calculated_checksum += I2C_Recv[2];
calculated_checksum += I2C_Recv[3];
calculated_checksum += I2C_Recv[4];
received_checksum = I2C_Recv[5];
received_checksum <<= 8;
received_checksum += I2C_Recv[6];
if(I2C_Recv[0] != 0b11000011 || (calculated_checksum != received_checksum))
{
while(1){
PORTD = 0b10101010;
delay_sec(1);
for (counter = 0; counter < 7; counter++) {
PORTD = 0b11111111;
delay_sec(1);
PORTD = I2C_Recv[counter];
delay_sec(1);
}
}
}
for (counter = 0; counter < 7; counter++) {
delay_msec(25);
PORTD = I2C_Recv[counter];
}
if(loopcounter==255)
{
delay_sec(2);
}
loopcounter++;
}
}
}
void sendStartSequence(void) {
PORTD = 0b10000001;
data = SSPBUF; //read any previous stored content in buffer to clear buffer full status
SSPCON2bits.SEN = 1; // send a start sequence
while (SSPCON2bits.SEN) {
}// wait for end of start sequence
PORTD = 0b11000001;
}
void sendRepeatedStartSequence(void) {
IdleI2C();
PORTD = 0b10000010;
data = SSPBUF; //read any previous stored content in buffer to clear buffer full status
SSPCON2bits.RSEN = 1; // send a repeated start sequence
while (SSPCON2bits.RSEN) {
}// wait for end of repeated start sequence
while (SSPSTATbits.R_NOT_W) {
}// transmit is in progress
PORTD = 0b11000010;
}
unsigned char sendReadCommand(void) {
IdleI2C();
PORTD = 0b10000110;
SSPCON2bits.RCEN = 1; // send a read command sequence
while (SSPCON2bits.RCEN) {
}// wait for end of read command sequence
while (!SSPSTATbits.BF) {
}
data = SSPBUF;
PORTD = 0b11000110;
return data;
}
void writeAddressOfSlave(unsigned char add1, unsigned char modus) {
PORTD = 0b10000011;
do {
status = WriteI2C(add1 | modus); //write the address of slave
if (status == -1) //check if bus collision happened
{
PORTD = 0b10000001;
data = SSPBUF; //upon bus collision detection clear the buffer,
SSPCON1bits.WCOL = 0; // clear the bus collision status bit
}
} while (status != 0); //write untill successful communication
PORTD = 0b11000011;
}
void sendStopSequence(void) {
PORTD = 0b10000100;
SSPCON2bits.PEN; // initiate stop sequence
while (SSPCON2bits.PEN) {
}
PORTD = 0b11000100;
}
void sendReadAcknowledge(void) {
PORTD = 0b10000101;
SSPCON2bits.ACKDT = 0;
SSPCON2bits.ACKEN; // initiate read ACK
while (SSPCON2bits.ACKEN) {
}
PORTD = 0b11000101;
}
void sendReadNotAcknowledge(void) {
PORTD = 0b10000110;
SSPCON2bits.ACKDT = 1;
SSPCON2bits.ACKEN; // initiate read NAK
while (SSPCON2bits.ACKEN) {
}
PORTD = 0b11000110;
}
void delay_sec(unsigned char sec) {
unsigned char counter1 = 0;
unsigned char counter2 = 0;
unsigned char counter3 = 0;
unsigned char counter4 = 0;
for (counter1 = 0; counter1 < sec; counter1++) {
for (counter2 = 0; counter2 < 50; counter2++) {
for (counter3 = 0; counter3 < 100; counter3++) {
for (counter4 = 0; counter4 < 100; counter4++) {
Nop();
// (5 * 2) * 100 * 100 * 100
}
}
}
}
}
void delay_msec(unsigned char msec) {
unsigned char counter1 = 0;
unsigned char counter2 = 0;
unsigned char counter3 = 0;
for (counter1 = 0; counter1 < msec; counter1++) {
for (counter2 = 0; counter2 < 50; counter2++) {
for (counter3 = 0; counter3 < 10; counter3++) {
Nop();
// (5 * 2) * 100 * 100 * 100
}
}
}
}
void leds_test(void) {
PORTD = 0b11111111;
delay_msec(250);
PORTD = 0b00000000;
delay_msec(250);
PORTD = 0b11111111;
delay_msec(250);
PORTD = 0b00000001;
delay_msec(250);
PORTD = PORTD << 1;
delay_msec(250);
PORTD = PORTD << 1;
delay_msec(250);
PORTD = PORTD << 1;
delay_msec(250);
PORTD = PORTD << 1;
delay_msec(250);
PORTD = PORTD << 1;
delay_msec(250);
PORTD = PORTD << 1;
delay_msec(250);
PORTD = PORTD << 1;
delay_sec(1);
}
N.B. my example code has hard coded values for PORT A-E for testing purposes, but as the comment shows, you can just change it to have the real data in it. Every pin is currently defined as output So don't forget to define the right inputs as well!
Part III is about connecting the PIC18F4550 (slave) to a Raspberry Pi (master).