|
|
View previous topic :: View next topic |
Author |
Message |
cleberalbert
Joined: 25 Feb 2014 Posts: 34 Location: Brazil
|
16 bits I2C communication between 2 PICs 18F |
Posted: Thu Jul 31, 2014 2:51 pm |
|
|
This program is to provide 16 bits I2C communication between 2 PICs 18F. The code was done on CCS 5.018, it's commented and working. Tested with PIC18F4520.
Master.c
Code: |
#include <18f4520.h>
#fuses HS
#fuses PUT
#fuses NOWDT //No Watch Dog Timer
#fuses NOBROWNOUT //No brownout reset
#fuses NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#fuses NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(crystal=20MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS) //+++ up baud rate?
#use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW)
/* Bit defines */
#define EEPROM_SCL PIN_C3
#define EEPROM_SDA PIN_C4
#define SLAVE_ADDRESS 0x20 // addr=2 reserved, note address masking.
#define I2C_DELAY_US 16 // worked 20 //Worked 32 //75 //100
#define I2C_INTERBYTE_DELAY_US 60 // worked 80
#byte PIC_SSPCON2 = 0xfc5
void initI2C (void);
void writeI2C (int16 word, unsigned int slave_addr);
int16 readI2C (unsigned int slave_addr);
int16 mainI2C ();
void initI2C (void)
{
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);
}
void writeI2C (int16 word, unsigned int slave_addr)
{
i2c_start();
delay_us(I2C_DELAY_US);
i2c_write(slave_addr); /* Device Address */
delay_us(I2C_DELAY_US);
i2c_write(word & 0x00ff); //LSB first
delay_us(I2C_DELAY_US);
i2c_write((word & 0xff00) >> 8); //MSB second
delay_us(I2C_DELAY_US);
i2c_stop();
delay_us(I2C_DELAY_US);
}
int16 readI2C (unsigned int slave_addr)
{
int8 b1=0, b2=0;
i2c_start(); // restart condition
delay_us(I2C_DELAY_US);
i2c_write(slave_addr + 1);
delay_us(I2C_INTERBYTE_DELAY_US);
b1 = i2c_read(1);
delay_us(I2C_INTERBYTE_DELAY_US);
b2 = i2c_read(0);
delay_us(I2C_DELAY_US);
i2c_stop();
return make16(b2, b1);
}
void main(){
int16 data_to_send=18099;
int16 data_received;
initI2C();
delay_ms(10);
// Write
writeI2C(data_to_send, SLAVE_ADDRESS);
printf("Message sent successfully from the Master to the Slave: %ld\n",data_to_send);
// Read
data_received = readI2C(SLAVE_ADDRESS);
printf("Answer received successfully from the Slave to the Master: %ld\n",data_received);
printf("\n");
}
|
Slave.c
Code: |
#include <18f4520.h>
#fuses HS
#fuses PUT
#fuses NOWDT //No Watch Dog Timer
#fuses NOBROWNOUT //No brownout reset
#fuses NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#fuses NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(crystal=20MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Slave, Slow, sda=PIN_C4, scl=PIN_C3, force_hw, address=0x20)
/* PIC Registers */
#byte SSPBUF = 0xfc9
#byte SSPADD = 0xfc8
#byte SSPSTAT = 0xfc7
#byte SSPCON1 = 0xfc6
#byte SSPCON2 = 0xfc5
#byte PIE1 = 0xf9d
#byte TRISC = 0xf94
int16 data_to_send=18100; //In the next step of the code development this data is going to change every loop (sensor data)
int16 data_sent;
int16 data_received;
#int_SSP
void i2c_interrupt() {
//Get state
int state;
int writeBuffer[2];
int readBuffer[2];
state = i2c_isr_state();
if(state==0) //Address match received with R/W bit clear, perform i2c_read( ) to read the I2C address.
i2c_read();
else if (state==0x80) //Address match received with R/W bit set; perform i2c_read( ) to read the I2C address, and use i2c_write( ) to pre-load the transmit buffer for the next transaction (next I2C read performed by master will read this byte).
i2c_read(2);
if (state>=0x80) //Master is waiting for data
{
writeBuffer[0] = (data_to_send & 0xFF); //LSB first
writeBuffer[1] = ((data_to_send & 0xFF00)>>8); //MSB secound
i2c_write(writeBuffer[state - 0x80]); //Write appropriate byte, based on how many have already been written
if ((state-0x80)==2){
data_sent=make16(writeBuffer[1],writeBuffer[0]);
printf("\nFull data sent: %ld\n",data_sent);
}
}
else if(state>0) //Master has sent data; read.
{
readBuffer[state - 1] = i2c_read(); //LSB first and MSB secound
if (state==2){
data_received=make16(readBuffer[1],readBuffer[0]);
printf("\nFull data received: %ld\n",data_received);
}
}
}
void main() {
enable_interrupts(INT_SSP); //Enable interrupts
enable_interrupts(GLOBAL);
i2c_slaveAddr(0x20);
while (TRUE)
delay_us(10);
}
|
|
|
|
emazzu630
Joined: 14 Aug 2018 Posts: 20 Location: Ouro Verde - SC
|
Comunicação I2C de 16 bits entre 2 PICs 18F |
Posted: Mon Oct 28, 2019 2:15 pm |
|
|
I was looking at Google for support to implement I2C and found this post.
The code is exactly what I need, but I had a hard time assembling the
circuit diagram ... Please if anyone has access to the Proteus file or
simply the schematic, I really need it. You can send me by the following
emails: [email protected], [email protected] |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 28, 2019 6:15 pm |
|
|
The hardware schematic looks like this:
https://i.stack.imgur.com/SdGJy.jpg
Connections are from SCL to SCL, and SDA to SDA, with a 4.7K pull-up
resistor on each one. The pull-up voltage is the same as the PIC's Vdd.
In the schematic shown, it is +5 volts. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|