CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C 18f8722 to 18f4431 problems
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
billy
Guest







I2C 18f8722 to 18f4431 problems
PostPosted: Sat Mar 15, 2008 1:20 pm     Reply with quote

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?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 15, 2008 1:50 pm     Reply with quote

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
billy
Guest







PostPosted: Sat Mar 15, 2008 2:09 pm     Reply with quote

Ok, changed everything as you suggested, all I get back is "read ΓΏ"
The ACK returned by spi_read(); is still 1
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 15, 2008 3:45 pm     Reply with quote

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.
billy
Guest







PostPosted: Sat Mar 15, 2008 4:03 pm     Reply with quote

>>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)

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 15, 2008 4:12 pm     Reply with quote

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 ?
Guest








PostPosted: Sat Mar 15, 2008 4:24 pm     Reply with quote

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!)
billy
Guest







PostPosted: Sat Mar 15, 2008 4:26 pm     Reply with quote

And in case you ask, both share common ground and 5v power supply ;)
billy
Guest







PostPosted: Sat Mar 15, 2008 4:41 pm     Reply with quote

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.
billy
Guest







PostPosted: Sat Mar 15, 2008 4:58 pm     Reply with quote

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.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 15, 2008 5:45 pm     Reply with quote

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.
Ttelmah
Guest







PostPosted: Sun Mar 16, 2008 3:37 am     Reply with quote

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
billy
Guest







PostPosted: Sun Mar 16, 2008 4:09 am     Reply with quote

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.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 2:09 pm     Reply with quote

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.
billy
Guest







PostPosted: Mon Mar 17, 2008 3:55 am     Reply with quote

Thanks PCM Programmer. The irony is that my maintenance agreement has just run out...
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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