gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
I2C Master and Slave, both PIC18F26K22 |
Posted: Wed Feb 05, 2020 10:13 pm |
|
|
The programs posted is for I2C Master PIC18F26K22 and Slave PIC18F26K22.
Both PIC works at 64MHz. The I2C setting is for Fast=400000, at Slow=100000 works also.
The Master initiating write/read sequence every 2000 ms, 8 bytes write and 8 bytes read.
Each write all the bytes are incremented by the master so the results can be analysed on a PC terminal, every 2000 ms. The data is sent to the PC as 9 bytes, first byte 0x00h denotes that the message is after I2C write/read
The Master initiating read sequence every 200 ms, 8 bytes read.
The results can be analysed on a PC terminal, every 2000 ms. The data is sent to the PC as 9 bytes, first byte 0xAAh denotes that the message is after I2C read.
The I2C Master and Slave were written with step by step BIG HELP from Ttelmah.
Thanks also for PCM Programmer for helping this project.
In the link bellow can see the development:
https://www.ccsinfo.com/forum/viewtopic.php?t=58095
The programs were tested for hours, no any errors occurred. Both PIC on the same board with 2K7 resistors on SDA and SCL, 5V supply.
Master:
Code: |
/////////////////////////////////////////////////////////////////////
//I2C26K22MT project based on Ttelmah CCS forum posts
//The program is for I2C Master PIC18F26K22 and Slave PIC18F26K22
//Program last update,February 6, 2020
/////////////////////////////////////////////////////////////////////
#include <18F26K22.h>
#device ADC=10
#FUSES WDT,WDT4,NOPBADEN,PUT,BROWNOUT,BORV29,HSH,PLLEN,NOIESO,NOFCMEN,NOHFOFST
#FUSES MCLR,STVREN,NOLVP,NOXINST,NODEBUG,NOPROTECT,NOCPD,NOWRT,NOWRTC,NOWRTD
#use delay(clock=64MHz,crystal=16MHz)
#use rs232(baud=9600, UART1, stream=PORT1, errors)
#use I2C(MASTER, FAST=400000, I2C1, STREAM=I2CPORT)
#byte SLRCON = GETENV("SFR:SLRCON")
/////////////////////////////////////////////////////////////////////
#define LED PIN_B5//flashes ones a second
int tx1words,tx1w0,tx1w1,tx1w2,tx1w3,tx1w4,tx1w5,tx1w6,tx1w7,tx1w8;
short I2CwriteF,I2CreadF,I2CwritedoneF,I2CreaddoneF,timer0F;
int flash=0,I2CstartR=20,I2CstartW=0,TXstart=0;
int data0=0x00,data1=0x20,data2=0x40,data3=0x60,data4=0x80,data5=0xA0,data6=0xC0,data7=0xE0;
int rpt0,rpt1,rpt2,rpt3,rpt4,rpt5,rpt6,rpt7;
/////////////////////////////////////////////////////////////////////
#int_TIMER0//Timer0 increments every 20ms
void TIMER0_isr(void)
{
timer0F=1;
set_timer0(45536);
}
#int_TBE//TX1 to PC; transmits 9 bytes
void TBE_isr(void)
{
switch(tx1words)
{
case 0:
{
fputc(tx1w0,PORT1);
tx1words++;
}
break;
case 1:
{
fputc(tx1w1,PORT1);
tx1words++;
}
break;
case 2:
{
fputc(tx1w2,PORT1);
tx1words++;
}
case 3:
{
fputc(tx1w3,PORT1);
tx1words++;
}
break;
case 4:
{
fputc(tx1w4,PORT1);
tx1words++;
}
break;
case 5:
{
fputc(tx1w5,PORT1);
tx1words++;
}
break;
case 6:
{
fputc(tx1w6,PORT1);
tx1words++;
}
case 7:
{
fputc(tx1w7,PORT1);
tx1words++;
}
break;
case 8:
{
fputc(tx1w8,PORT1);
tx1words=0;
disable_interrupts(INT_TBE);
}
break;
}
}
#int_RDA//RX1 not used
void RDA_isr(void)
{
delay_cycles(1);
}
//FUNCTIONS
void FUNCTIONS(void)
{
if(timer0F==1)
{
timer0F=0;
flash++;
I2CstartW++;
I2CstartR++;
if(flash>=25)
{
flash=0;
output_toggle(LED);
}
}
if(I2CstartW==100)//I2C write/read every 2000ms
{
I2CstartW=0;
data0++;//increment for write/read testing
data1++;//increment for write/read testing
data2++;//increment for write/read testing
data3++;//increment for write/read testing
data4++;//increment for write/read testing
data5++;//increment for write/read testing
data6++;//increment for write/read testing
data7++;//increment for write/read testing
I2CwriteF=1;
}
if(I2CwritedoneF==1)//after I2C write/read send message to PC
{
I2CwritedoneF=0;
tx1w0=0x00;
tx1w1=rpt0;
tx1w2=rpt1;
tx1w3=rpt2;
tx1w4=rpt3;
tx1w5=rpt4;
tx1w6=rpt5;
tx1w7=rpt6;
tx1w8=rpt7;
enable_interrupts(INT_TBE);
}
if(I2CstartR==10)//I2C read every 200ms
{
I2CstartR=0;
TXstart++;
I2CreadF=1;
}
if(I2CreaddoneF==1)//I2C2 read done
{
I2CreaddoneF=0;
if(TXstart==10)//sends read message to PC every 2000ms
{
TXstart=0;
tx1w0=0xAA;
tx1w1=rpt0;
tx1w2=rpt1;
tx1w3=rpt2;
tx1w4=rpt3;
tx1w5=rpt4;
tx1w6=rpt5;
tx1w7=rpt6;
tx1w8=rpt7;
enable_interrupts(INT_TBE);
}
}
}
///////////////////////////////////////////////////////////////////
void I2C (void)//I2C26K22M master write/read starts every 2000ms
{
if(I2CwriteF==1)
{
I2CwriteF=0;
//write data to Slave PIC
i2c_start();
delay_us(5);
i2c_write(0xB0);//Slave address with write
delay_us(5);
i2c_write(data0);
delay_us(5);
i2c_write(data1);
delay_us(5);
i2c_write(data2);
delay_us(5);
i2c_write(data3);
delay_us(5);
i2c_write(data4);
delay_us(5);
i2c_write(data5);
delay_us(5);
i2c_write(data6);
delay_us(5);
i2c_write(data7);
delay_us(5);
i2c_stop();
//read back data from the Slave PIC
delay_us(1000); //ensure the Slave has had time to complete the write
i2c_start();
delay_us(5);
i2c_write(0xB1);//Slave address with read
delay_us(5);
rpt0 = i2c_read();
delay_us(5);
rpt1 = i2c_read();
delay_us(5);
rpt2 = i2c_read();
delay_us(5);
rpt3 = i2c_read();
delay_us(5);
rpt4 = i2c_read();
delay_us(5);
rpt5 = i2c_read();
delay_us(5);
rpt6 = i2c_read();
delay_us(5);
rpt7 = i2c_read(0);
delay_us(5);
i2c_stop();
I2CwritedoneF=1;
}
//read data from the Slave PIC
else if(I2CreadF==1)
{
I2CreadF=0;
i2c_start();
delay_us(5);
i2c_write(0xB1);//Slave address with read
delay_us(5);
rpt0 = i2c_read();
delay_us(5);
rpt1 = i2c_read();
delay_us(5);
rpt2 = i2c_read();
delay_us(5);
rpt3 = i2c_read();
delay_us(5);
rpt4 = i2c_read();
delay_us(5);
rpt5 = i2c_read();
delay_us(5);
rpt6 = i2c_read();
delay_us(5);
rpt7 = i2c_read(0);
delay_us(5);
i2c_stop();
I2CreaddoneF=1;
}
}
///////////////////////////////////////////////////////////////////
#ZERO_RAM
void main()
{
SLRCON=0; //Turn off slew rate limit.
setup_adc_ports(NO_ANALOGS);
setup_wdt(WDT_16MS);//~16 ms reset
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);//65.536 ms overflow
enable_interrupts(INT_TIMER0);
disable_interrupts(INT_RDA);
disable_interrupts(INT_TBE);
enable_interrupts(GLOBAL);
while(TRUE)
{
restart_wdt();
FUNCTIONS();
I2C();
}
}
///////////////////////////////////////////////////////////////////// |
Slave:
Code: |
/////////////////////////////////////////////////////////////////////
//I2C26K22ST project based on Ttelmah posts
//The program is for Slave I2C PIC18F26K22 communicating with Master PIC18F26K22
//Program last update,February 6, 2020
/////////////////////////////////////////////////////////////////////
#include <18F26K22.h>
#device ADC=10
#FUSES WDT,WDT4,NOPBADEN,PUT,BROWNOUT,BORV29,HSH,PLLEN,NOIESO,NOFCMEN,NOHFOFST
#FUSES MCLR,STVREN,NOLVP,NOXINST,NODEBUG,NOPROTECT,NOCPD,NOWRT,NOWRTC,NOWRTD
#use delay(clock=64MHz,crystal=16MHz)
#use i2c(Slave,Address=0xB0,I2C1)//I2C1 module, automatically hardware
#byte SLRCON = GETENV("SFR:SLRCON")
/////////////////////////////////////////////////////////////////////
#define LED PIN_C5//flashes ones a second
int flash=0;
int state,value;
int data0,data1,data2,data3,data4,data5,data6,data7;
#int_TIMER0
void TIMER0_isr(void)
{
flash++;
if(flash>=25)//500ms
{
flash=0;
output_toggle(LED);
}
set_timer0(45536);
}
/////////////////////////////////////////////////////////////////////
//The core I2C slave code.
//Now states < 0x80, are read states. The master is sending us data
//However state 0x0, is where the master sends up the address itself
//so we need to use state-1 as the array index to write data
//State 0x80 is where the master sends the address for the write. On this
//we must read, and then write the byte for the reply.
/////////////////////////////////////////////////////////////////////
#INT_SSP
void I2C_isr (void)
{
state=i2c_isr_state();
if (state<=0x80)
{
switch(state)
{
case 0x80:
value=i2c_read(0x02);//here we need to read, and not release the clock
break;
case 0:
value=i2c_read();//throw away address read
break;
case 1:
data0=i2c_read();
break;
case 2:
data1=i2c_read();
break;
case 3:
data2=i2c_read();
break;
case 4:
data3=i2c_read();
break;
case 5:
data4=i2c_read();
break;
case 6:
data5=i2c_read();
break;
case 7:
data6=i2c_read();
break;
case 8:
data7=i2c_read();
break;
}
}
switch(state)
{
case 0x80:
i2c_write(data0);
break;
case 0x81:
i2c_write(data1);
break;
case 0x82:
i2c_write(data2);
break;
case 0x83:
i2c_write(data3);
break;
case 0x84:
i2c_write(data4);
break;
case 0x85:
i2c_write(data5);
break;
case 0x86:
i2c_write(data6);
break;
case 0x87:
i2c_write(data7);
break;
}
}
/////////////////////////////////////////////////////////////////////
#ZERO_RAM
void main()
{
SLRCON=0; //Turn off slew rate limit.
setup_adc_ports(NO_ANALOGS);
setup_wdt(WDT_16MS);//~16 ms reset
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);//65.536 ms overflow
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE)
{
restart_wdt();
}
}
///////////////////////////////////////////////////////////////////// |
Apologizing for my clumsy rs232. Can change it as anyone wish |
|