|
|
View previous topic :: View next topic |
Author |
Message |
elcrcp
Joined: 11 Mar 2016 Posts: 62 Location: izmir / Turkey
|
PIC to PIC I2C problem with 16f1827 |
Posted: Fri Mar 11, 2016 9:36 am |
|
|
Hello,
I'm new here and this is my first post here (so hello all again) I'm new at CCS, used to use another compiler before and I stuck with a simple problem, couldn't solve it alone so I need some help. I would be grateful if anyone can see the problem.
I'm using 2 16f1827's to set a I2C master - slave communication, sending 5 bytes of data from master and storing them in an array in slave and when 5 bytes of data received, I'm checking these data if they are what I sent.
I established connection, sending and receiving data over I2C but an "if" condition in my code is never working and can't see thats why. I set data_ready variable to 1 when 5 bytes of data received, then checking in a "while" if data_ready is 1, program enters to part of code where data_ready set to 5 but it does not confirm in "while" loop that data_ready is one.
I'm using indicator LED's to see where program is running and where it is not running. I'll explain more with comments in my code.
This is my master code and it looks like working fine
Code: | //-------------Master--------------------------
#include <16F1827.H>
#fuses NOWDT,NOPUT,BROWNOUT,NOLVP, MCLR, NOCPD, NOBROWNOUT, NOCLKOUT
#FUSES INTRC_IO, NOIESO, NOFCMEN, NOWRT, PLL_SW, NOSTVREN
#byte OSCCON = 0x70
#byte OSCTUNE = 0
#byte DACCON0 = 0
#byte SRCON0 = 0
#use delay(clock = 8000000)
#use i2c(MASTER, SDA=PIN_B1, SCL=PIN_B4)
#byte TRISA = 0x20
#byte TRISB = 0x13
#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8)
#byte APFCON0 = 0x11D //ALTERNATE PIN FUNCTION CONTROL REGISTER 0
#byte APFCON1 = 0x11E //ALTERNATE PIN FUNCTION CONTROL REGISTER 1
#define SLAVE1_WRT_ADDR 0x08
#define SLAVE1_READ_ADDR 0x09
//====================================
#INT_EXT
void ext_isr(void)
{
putc('\n');
putc('\r');
printf("test");
output_toggle(pin_b6);
}
void main()
{
setup_adc_ports(NO_ANALOGS);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
i2c_start();
i2c_write(SLAVE1_wrt_ADDR);
i2c_write(0x0F);
delay_ms(10);
i2c_write(0x10);
delay_ms(10);
i2c_write(0x18);
delay_ms(10);
i2c_write(0xFF);
delay_ms(10);
i2c_write(0xF0);
delay_ms(10);
i2c_stop();
delay_ms(100);
output_toggle(pin_b7);
}
}//main
|
This is my slave code
Code: | ///------------------Slave-------------------------
#include <16F1827.H>
#fuses NOWDT,NOPUT,NOLVP,MCLR,NOCPD,NOBROWNOUT,NOCLKOUT
#FUSES INTRC_IO,NOIESO,NOFCMEN,NOWRT,PLL_SW,NOSTVREN
#byte OSCCON = 0x70
#byte OSCTUNE = 0
#byte DACCON0 = 0
#byte SRCON0 = 0
#use delay(clock = 8000000)
#use i2c(SLAVE, SDA=PIN_B1, SCL=PIN_B4, ADDRESS=0x08)
//#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8)
#byte TRISA = 0x20
#byte TRISB = 0x13
#byte APFCON0 = 0x11D //ALTERNATE PIN FUNCTION CONTROL REGISTER 0
#byte APFCON1 = 0x11E //ALTERNATE PIN FUNCTION CONTROL REGISTER 1
int8 test_result, mdirect;
int8 datain[6];
int8 incoming, state, readcnt;
unsigned long stepamount;
volatile int8 data_ready;
#INT_SSP
void ssp_isr(void)
{
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
incoming = i2c_read();
datain[readcnt]=incoming;
readcnt=readcnt+1;
if(readcnt==5){
data_ready=1;
readcnt=0;
output_toggle(pin_b7); //I'm tracing this signal with oscillascope and I see changes on this pin, so program enters in this "if" statement and setting data_ready to 1
}
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(0xFF);
}
}
#INT_EXT
void ext_isr(void)
{
output_toggle(pin_b6);
}
//======================================
void main ()
{
readcnt=0;
data_ready=0;
i2c_SlaveAddr(0x08);
setup_adc_ports(NO_ANALOGS);
enable_interrupts(INT_SSP);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
/*&&(datain[0]=0x0F)&&(datain[4]=0xF0)*/
while(1)
{
//if I put an indicator code here (toggling a led) I can see that it is toggling and program looping in this "while"
if (data_ready==1){
output_toggle(pin_b6); // my problem is here, although program indicates that it enters I2C ISR and since it is entering there, it sets data_ready to 1 but it never enters this part.
mdirect=datain[1];
stepamount=make16(datain[3],datain[2]);
for (int i=0;i=5;i++){
datain[i]=0;
}
data_ready=0;
if (mdirect==0x10){
output_toggle(pin_b5);
}
if (stepamount==0xFF18){
output_toggle(pin_b6);
}
}
}
} |
I set up the circuit in both protheus and on a board, I'm sending protheus schematics to show what I'm working on
_________________ There is nothing you can't do if you try |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 11, 2016 11:04 am |
|
|
Quote: | #byte OSCCON = 0x70
#byte OSCTUNE = 0
#byte DACCON0 = 0
#byte SRCON0 = 0 |
These statements are incorrect. The #byte statement lets you specify
the address of a PIC register, so you can r/w directly to the register in
your program. But haven't specified the addresses of the listed registers.
0x70 is not the address of the OSCCON register. Check the PIC data
sheet. 0 is not the address of the other registers.
Quote: | #define SLAVE1_WRT_ADDR 0x08
#define SLAVE1_READ_ADDR 0x09
#use i2c(SLAVE, SDA=PIN_B1, SCL=PIN_B4, ADDRESS=0x08)
i2c_SlaveAddr(0x08);
|
0x8 is a reserved address for an i2c slave. The lowest slave address
that you can legally use is 0x10. This is in the NXP i2c specification.
Quote: | #byte TRISA = 0x20
#byte TRISB = 0x13 |
Again, #byte is not used to set the value of a register. #byte is used to
set the address of a register. The real addresses are 0x8C and 0x8D.
But if you want to set the TRIS, CCS has a function to do it. See the
manual.
Quote: | for (int i=0;i=5;i++){
datain[i]=0;
} |
This loop is supposed to clear the datain[6] array, but it won't work
because the middle test is wrong. It should be
Your bottom schematic is missing a pullup resistor on Pin B4, the SCL line. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Mar 11, 2016 12:40 pm |
|
|
Also as one little comment, OSCTUNE, is loaded automatically with the
calibration value stored in the chip's memory, at boot. If you were writing to it, you should not be writing to it. OSCCON, is also setup by the clock
settings (change the clock statement to say (INTERNAL=8MHz)). This
will ensure OSCCON is correctly setup.
For 99.9% of code you should never have to touch a register directly in CCS. |
|
|
elcrcp
Joined: 11 Mar 2016 Posts: 62 Location: izmir / Turkey
|
Solved |
Posted: Fri Mar 11, 2016 2:02 pm |
|
|
I greatly thank you 'PCM programmer' and 'Ttelmah' for your comments and warnings, as I said before, I used to use another lang and compiler for PIC and I'm new at CCS so there are lot of things and functions I don't know in CCS.
I used to write directly to registers to setup a PIC and since I don't know how they done in CCS yet, it will take some time for me to get used to not to write directly to registers
I thought #byte is writing directly to predefined registers so that is why I used it like that. I edited my codes due to your warnings and tried again, now they working without any problem, here are my edited working codes for if anyone encounters the same fate
Code: | //-------------Master--------------------------
#include <16F1827.H>
#fuses NOWDT,NOPUT,BROWNOUT,NOLVP, MCLR, NOCPD, NOBROWNOUT, NOCLKOUT
#FUSES INTRC_IO, NOIESO, NOFCMEN, NOWRT, PLL_SW, NOSTVREN
#use delay(clock = 8000000)
#use i2c(MASTER, SDA=PIN_B1, SCL=PIN_B4)
#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8)
#byte TRISA = 0x08C
#byte TRISB = 0x08D
#byte OSCCON = 0x099
#byte OSCTUNE = 0x098
#byte DACCON0 = 0x118
#byte SRCON0 = 0x11A
#byte APFCON0 = 0x11D //ALTERNATE PIN FUNCTION CONTROL REGISTER 0
#byte APFCON1 = 0x11E //ALTERNATE PIN FUNCTION CONTROL REGISTER 1
#define SLAVE1_WRT_ADDR 0xA8
#define SLAVE1_READ_ADDR 0xA9
//====================================
#INT_EXT
void ext_isr(void)
{
putc('\n');
putc('\r');
printf("test");
output_toggle(pin_b6);
}
void main()
{
TRISA = 0x20;
TRISB = 0x13;
OSCCON = 0x70;
OSCTUNE = 0;
DACCON0 = 0;
SRCON0 = 0;
setup_adc_ports(NO_ANALOGS);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
i2c_start();
i2c_write(SLAVE1_wrt_ADDR);
i2c_write(0x0F);
delay_ms(10);
i2c_write(0x10);
delay_ms(10);
i2c_write(0x18);
delay_ms(10);
i2c_write(0xFF);
delay_ms(10);
i2c_write(0xF0);
delay_ms(10);
i2c_stop();
delay_ms(100);
output_toggle(pin_b7);
}
}
|
Code: | ///------------------Slave-------------------------
#include <16F1827.H>
#fuses NOWDT,NOPUT,NOLVP,MCLR,NOCPD,NOBROWNOUT,NOCLKOUT
#FUSES INTRC_IO,NOIESO,NOFCMEN,NOWRT,PLL_SW,NOSTVREN
#use delay(clock = 8000000)
#use i2c(SLAVE, SDA=PIN_B1, SCL=PIN_B4, ADDRESS=0xA8)
#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8)
#byte TRISA = 0x08C
#byte TRISB = 0x08D
#byte OSCCON = 0x099
#byte OSCTUNE = 0x098
#byte DACCON0 = 0x118
#byte SRCON0 = 0x11A
#byte APFCON0 = 0x11D //ALTERNATE PIN FUNCTION CONTROL REGISTER 0
#byte APFCON1 = 0x11E //ALTERNATE PIN FUNCTION CONTROL REGISTER 1
volatile int8 datain[8];
volatile int8 state, readcnt, mdirect, data_ready;
volatile unsigned long stepamount;
#INT_SSP
void ssp_isr(void)
{
state = i2c_isr_state();
if(state < 0x80) // Master is sending data
{
datain[readcnt] = i2c_read();
readcnt=readcnt+1;
if(readcnt==6){
data_ready=1;
readcnt=0;
output_toggle(pin_b7);
}
}
if(state >= 0x80) // Master is requesting data from slave
{
i2c_write(0xFF);
}
}
#INT_EXT
void ext_isr(void)
{
output_toggle(pin_b6);
}
//======================================
void main ()
{
readcnt=0;
data_ready=0;
i2c_SlaveAddr(0xA8);
TRISA = 0x20;
TRISB = 0x13;
OSCCON = 0x70;
OSCTUNE = 0;
DACCON0 = 0;
SRCON0 = 0;
setup_adc_ports(NO_ANALOGS);//
enable_interrupts(INT_SSP);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
if ((data_ready==1)&&(datain[1]=0x0F)&&(datain[5]=0xF0)){
mdirect=datain[2];
stepamount=make16(datain[4],datain[3]);
printf("Direction: %X",mdirect);
printf(" Step Amount: %4X\n\r",stepamount);
for (int i=0;i<=6;i++){
datain[i]=0;
}
data_ready=0;
if (mdirect==0x10){
output_toggle(pin_b5);
}
if (stepamount==0xFF18){
output_toggle(pin_b6);
}
}
}
} |
_________________ There is nothing you can't do if you try |
|
|
|
|
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
|