![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
billy Guest
|
I2C 18f8722 to 18f4431 problems |
Posted: Sat Mar 15, 2008 1:20 pm |
|
|
I'm having trouble getting I2C working between two PIC's (It is my first go with I2C)
I have a PIC18f8722 as a master and an 18f4431 as the slave. Compiler Version is 4.068 and the scl and sda lines have 5k pullups, communication is via a 10cm ribbon cable between two PCB's.
Basically what I am trying to do is use the 8722 as a central controller and the 4431 as a dedicated motion controller so I can control several motors over the I2C bus.
The code below is for the master and slave and just sends a pair of bytes over the I2C, I have spent quite a while looking through the forum for help but have finally reached a full stop - I can't get the slave to respond in any way to the master...
Master Code:
Code: |
#include <18F8722.h>
#device adc=8
#device HIGH_INTS=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES H4 //High speed osc with HW enabled 4X PLL
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOEBTR //Memory not protected from table reads
#FUSES CCP2C1 //CCP2 input/output multiplexed with RE7
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled
#FUSES MCU //Microcontroller Mode
#use delay(clock=32000000)
#use rs232(baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//#use rs232(baud=9600,parity=N,xmit=PIN_D0,rcv=PIN_D1,bits=8)
#use i2c(master, sda = PIN_C4, scl = PIN_C3, FAST = 450000, FORCE_HW)
#zero_ram
BYTE I2CLeftMotorSpeed[2]; //two bytes for motor speed (14 bit PWM plus direction)
BYTE I2CRightMotorSpeed[2];
BYTE I2CLeftMotorAddress_Send = 0xa0; //address for sending data to left motor
BYTE I2CRightMotorAddress_Send = 0xa2;
BYTE I2CLeftMotorAddress_Recieve = 0xa1; //address for getting data from left motor
BYTE I2CRightMotorAddress_Recieve = 0xa3;
void SetI2CLeftMotor();
void SetI2CRightMotor();
void main()
{
setup_adc_ports(ALL_ANALOG|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_2);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);
setup_timer_1(T1_DISABLED|T1_DIV_BY_8);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_8);
setup_timer_4(T4_DISABLED,0,1);
setup_ccp4(false);
setup_ccp5(false);
setup_comparator(NC_NC_NC_NC);
setup_vref(false);
setup_low_volt_detect(FALSE);
delay_ms(50);
printf("Starting . . .");
delay_ms(1000);
while(1)
{
//I2C Test just send the two bytes to the left motor
//incriment the lower byte with each step
SetI2CLeftMotor();
delay_ms(100);
I2CLeftMotorSpeed[1]++;
}
}
//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
void SetI2CLeftMotor()
{
int8 ACK1, ACK2, ACK3, ACK4;
//Printf is for debugging to track progress via RS232
printf("Start LM\n");
i2c_start();
ACK1 = i2c_write(I2CLeftMotorAddress_Send); // Device address
ACK2 = i2c_write(0x00); // Address of data
ACK3 = i2c_write(I2CLeftMotorSpeed[0]); // Data to device
ACK4 = i2c_write(I2CLeftMotorSpeed[1]); // Data to device
i2c_stop();
printf("End LM\n");
printf("%u, %u, %u, %u\n",ACK1, ACK2, ACK3, ACK4);
}
//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
void SetI2CRightMotor()
{
printf("Start RM\n");
i2c_start();
i2c_write(I2CRightMotorAddress_Send); // Device address
i2c_write(0x00); // Address of data
i2c_write(I2CRightMotorSpeed[0]); // Data to device
i2c_write(I2CRightMotorSpeed[1]); // Data to device
i2c_stop();
printf("End RM\n");
}
|
When sending all the ACK values return as 1
And here is the slave code:
Code: |
#include <18F4431.h>
#device adc=10
#device HIGH_INTS=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES H4 //High speed osc with HW enabled 4X PLL
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV27 //Brownout reset at 2.7V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOWINEN //WDT Timer Window Disabled
#FUSES T1LOWPOWER //Timer1 low power operation when in sleep
#FUSES HPOL_HIGH //High-Side Transistors Polarity is Active-High (PWM 1,3,5 and 7)
#FUSES NOWRTC //configuration registers not write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES LPOL_LOW //Low-Side Transistors Polarity is Active-Low (PWM 0,2,4 and 6)
#FUSES PWMPIN //PWM outputs disabled upon Reset
#FUSES MCLR //Master Clear pin enabled
#FUSES FLTAD4 //FLTA input is multiplexed with RD4
#FUSES SSP_RD //SCK/SCL=RD3, SDA/SDI=RD2, SDO=RD1
#FUSES PWM4D5 //Power PWM Pin 4 output on RD5
#use delay(clock=32000000)
#use rs232(baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use I2C(slave, sda = PIN_D2, scl = PIN_D3, address=0xa0, FAST = 450000, FORCE_HW)
#int_SSP // interrupt on i2c activity
void i2c_isr();
int8 I2C_In_Buffer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int8 I2C_Out_Buffer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int8 I2C_Data_address = 0;
int1 I2CNewData = 0;
void main()
{
//setup_oscillator(False);
setup_adc_ports(sAN0|sAN1|sAN8|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_10|ADC_CONT_A);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_4,255,3);
setup_timer_5 (T5_INTERNAL | T5_DIV_BY_4);
enable_interrupts(INT_SSP);
enable_interrupts(global);
printf("\nMCStarting...\n");
while(1)
{
printf("Running\n");
printf("%u, %u\n", I2C_In_Buffer[0], I2C_In_Buffer[1]);
if( I2CNewData ) //New Data in the I2C buffer
{
printf("NewData ! ! !\n");
printf("%u, %u\n", I2C_In_Buffer[0], I2C_In_Buffer[1]);
I2CNewData = 0; //Reset this to indicate no new data
}
delay_ms(100);
}
}
//===========================================================
#int_SSP // interrupt on i2c activity
void i2c_isr()
{
int8 incoming, state;
//putc used for debug to track progress via RS232
putc('I');
state = i2c_isr_state();
putc(state+48);
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1)
{
//First received byte is address
I2C_Data_address = incoming;
putc('A');
}
if(state == 2)
{
//Second received byte is data1
I2C_In_Buffer[I2C_Data_address] = incoming;
putc('B');
}
if(state == 3)
{
//Third received byte is data2
I2C_In_Buffer[I2C_Data_address+1] = incoming;
putc('C');
I2CNewData = 1;
//Set I2CNewData flag to indicate that both bytes have been recieved
//and can now be used
}
}
if(state == 0x80) //Master is requesting data
{
// i2c_write(I2C_Out_Buffer[I2C_Data_address]);
}
}
|
The slave never gets to the SSP interrupt.
Any idea what I am doing wrong? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 15, 2008 1:50 pm |
|
|
1. Don't try to run the master in i2c "FAST" mode. Run it in SLOW mode.
Microchip doesn't guarantee that the slave will work in fast mode.
2. Remove the "FAST" parameter in the slave. The slave doesn't use
a baud rate generator. The master provides the clock.
3. Make very simple test programs for the master and the slave.
Prove that you can make i2c work between them. Then slowly change
it to be more like your final application. Prove that it works at each
stage as you change it.
Use the CCS example file code, Ex_Slave.c, for the Slave PIC.
It's in this directory:
Quote: | c:\Program Files\picc\Examples\Ex_Slave.c |
Use the code in this post for the Master PIC:
http://www.ccsinfo.com/forum/viewtopic.php?t=32368&start=3
If you need more help, then use the search page to search for this:
Quote: | Keywords: ex_slave master
Author: pcm programmer
Search for all terms: Yes |
|
|
![](templates/subSilver/images/spacer.gif) |
billy Guest
|
|
Posted: Sat Mar 15, 2008 2:09 pm |
|
|
Ok, changed everything as you suggested, all I get back is "read ΓΏ"
The ACK returned by spi_read(); is still 1 |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 15, 2008 3:45 pm |
|
|
1. Post your compiler version.
2. Post your new master program.
3. Post the first few lines of Ex_Slave.c, to show the changes that
you made to the #include, #fuses, #use delay() and #use i2c statements
so that it would work with your PIC. Don't post the rest of Ex_Slave.c. |
|
![](templates/subSilver/images/spacer.gif) |
billy Guest
|
|
Posted: Sat Mar 15, 2008 4:03 pm |
|
|
>>Compiler Version is 4.068
Master Code:
Code: |
#include <18F8722.h>
#device adc=8
#device HIGH_INTS=TRUE
//#device icd=true
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES H4 //High speed osc with HW enabled 4X PLL
//#fuses INTRC_IO
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOEBTR //Memory not protected from table reads
#FUSES CCP2C1 //CCP2 input/output multiplexed with RE7
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled
#FUSES MCU //Microcontroller Mode
#use delay(clock=32000000)
#use rs232(baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
//====================================
void main()
{
int8 data;
// Write the letter 'B' to the slave board.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write('B');
i2c_stop();
// Read from the slave board and display the data.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
data = i2c_read(0);
i2c_stop();
printf("read %c \n\r", data);
while(1);
}
|
Slave...
Code: |
#include <18F4431.h>
#device adc=10
#device HIGH_INTS=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES H4 //High speed osc with HW enabled 4X PLL
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV27 //Brownout reset at 2.7V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOWINEN //WDT Timer Window Disabled
#FUSES T1LOWPOWER //Timer1 low power operation when in sleep
#FUSES HPOL_HIGH //High-Side Transistors Polarity is Active-High (PWM 1,3,5 and 7)
#FUSES NOWRTC //configuration registers not write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES LPOL_LOW //Low-Side Transistors Polarity is Active-Low (PWM 0,2,4 and 6)
#FUSES PWMPIN //PWM outputs disabled upon Reset
#FUSES MCLR //Master Clear pin enabled
#FUSES FLTAD4 //FLTA input is multiplexed with RD4
#FUSES SSP_RD //SCK/SCL=RD3, SDA/SDI=RD2, SDO=RD1
#FUSES PWM4D5 //Power PWM Pin 4 output on RD5
#use delay(clock=32000000)
#use rs232(baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use I2C(slave, sda = PIN_D2, scl = PIN_D3, address=0xa0, FORCE_HW)
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 15, 2008 4:12 pm |
|
|
Change the printf() statement in the master so that it uses "%x" instead
of "%c". Then we can see the hex value that it reads. Run the test
and post the result.
Also, can you confirm that you are running these tests on real hardware
and you're not using a simulator ? |
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Sat Mar 15, 2008 4:24 pm |
|
|
It produces ff
I am using real hardware - two PCB's with SMD Pics (One has been used a lot and appears entirely reliable, the other (the 4431) was put together last week.
Probably worth mentioning that the 4431 board sometimes produces garbage on its first printf statement (when I had a printf before main) The garbage appears on power up but then works ok once it is running. Not sure what this could be but it might be related.
I have checked the connections, both sets of pins on each pic are connected (and continuity checked) to their counterparts on the other board.
Unfortunately I don't have access to a scope to check the signals. (This is an Easter holiday project and my scope is locked away at work!) |
|
![](templates/subSilver/images/spacer.gif) |
billy Guest
|
|
Posted: Sat Mar 15, 2008 4:26 pm |
|
|
And in case you ask, both share common ground and 5v power supply ;) |
|
![](templates/subSilver/images/spacer.gif) |
billy Guest
|
|
Posted: Sat Mar 15, 2008 4:41 pm |
|
|
One other thing. I have two identical 4431 (Slave) boards and I tested the code on both of them with the same results.
I might try using one of them as a master and the other as a slave just to see if that works. |
|
![](templates/subSilver/images/spacer.gif) |
billy Guest
|
|
Posted: Sat Mar 15, 2008 4:58 pm |
|
|
I tried the same code but using identical pics (18f4431) as master and slave but still get ff returned as the data
I think the printf problem I has was down to getting the tx and rx lines crossed on the USART (Bad board design on my part :o ) - I swapped them over and don't get garbage any more. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 15, 2008 5:45 pm |
|
|
I think I might have an 18F4431 chip in my parts box. If so, I can test
it on Sunday with vs. 4.068 and see if I can make it work. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Mar 16, 2008 3:37 am |
|
|
Given the comment about lines swapped on the USART, you have checked the really obvious things about the connections?. On I2C, the lines _do not swap_, so SDA on the first chip, goes to SDA on the second, and SCL on the first to SCL on the second. The lack of any response, does sound like something 'basic' like this...
'ff' is exactly what you would see, if there was no device connected.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
billy Guest
|
|
Posted: Sun Mar 16, 2008 4:09 am |
|
|
The crossed USART lines was down to me plugging a two pin connector in the wrong way round.
I have triple checked all the I2C connections, and now just checked them again. When the boards are all connected up the resistance between the SCL and SDA pins and Vdd appears OK (about 5.5k).
I just wish I had a scope meter . . . Actually, I might hook up the I2C pins to a pair of Interrupt on Change Pins to see what it can detect. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Mar 16, 2008 2:09 pm |
|
|
The problem is that the library code is incorrect when you use pins D2
and D3 and the SSP_RD fuse. It works OK if you pins C4 and C5.
Here's the .LST file for pins C4 and C5. It is correct.
Code: | ..... #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C5, address=0xa0)
009E: MOVF FC9,W // SSPBUF
00A0: MOVFF 2D,FC9
00A4: BSF FC6.4 // CKP bit = 1
00A6: BCF F9E.3 // SSPIF bit = 0
00A8: BTFSC FC7.0 // Test BF bit
00AA: BRA 00A8
00AC: CLRF 01
00AE: BTFSC FC6.4
00B0: INCF 01,F
00B2: GOTO 0112 (RETURN) |
Here's the .LST file for pins D2 and D3 with the SSP_RD fuse.
The registers and bits are not correct. It can't work.
Code: | .. #use i2c(SLAVE, SDA=PIN_D2, SCL=PIN_D3, address=0xa0, FORCE_HW)
009E: MOVF F66,W // CAP2BUFL register *** Bug
00A0: MOVFF 2D,F66 // *** Bug
00A4: BSF F63.4 // CAP1CON.4 bit *** Bug
00A6: BCF 00.0 // 00.0 bit *** Bug
00A8: BTFSC F64.0 // CAP3BUFL.0 bit *** Bug
00AA: BRA 00A8
00AC: CLRF 01
00AE: BTFSC F63.4 // *** Bug
00B0: INCF 01,F
00B2: GOTO 0112 (RETURN) |
I suggest that you report this bug to CCS and then use the other pins
until they release a fixed version.
Note: These tests were done with your version, vs. 4.068. I also
compiled it with vs. 4.069 and it still has the same problem. |
|
![](templates/subSilver/images/spacer.gif) |
billy Guest
|
|
Posted: Mon Mar 17, 2008 3:55 am |
|
|
Thanks PCM Programmer. The irony is that my maintenance agreement has just run out... |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|