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

Help for 2 PICs and I2C

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
sv_shady



Joined: 07 Mar 2008
Posts: 28

View user's profile Send private message

Help for 2 PICs and I2C
PostPosted: Fri Mar 07, 2008 3:56 pm     Reply with quote

Hi Smile This is the first time I am writing in this forum and hope I'll receive the needed info. Here is the problem I am constructing a robot and right now I am working on the radio control, I am using XBeePro modules. One PIC (16F877A) reads a modified computer joystick throug the ADC, then sends the values over RS232 to the XBeePro module. The other module should receive the values, send them via RS232 to another PIC16F877a. The second pic should read the incoming data over RS232 and send it via i2c to a third PIC 16F877a which should print the data to a 2x20 display. Everything is working exept the I2C and the problem is very strange... If I send a number between 1 and 99 it appears on the display every time it is sent, but if I send a number between 100 and 255 it is printed just once and then every time it should appear on the LCD, the slave address is printed....
Here is the source for the master:

Code:
#include <16F877A.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock=10000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,FAST,sda=PIN_C4,scl=PIN_C3,force_hw)

void INIT(void)   
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
}

int x = 0;
#int_RDA
void  RDA_isr(void)
{
   int c;
   disable_interrupts(GLOBAL);
   output_bit(PIN_B5, 1);
   c = getc();
   i2c_start();
   i2c_write(0x10);             
   i2c_write(x);
   i2c_stop();
   output_bit(PIN_B5, 0);
   x++;
   enable_interrupts(GLOBAL);
}

void main()
{
   INIT(); 
   for(;;);
}

For every byte received via RS232 on the display the slave address (16) and the data (x) are printed. While x < 100 everything works fine, but when x >= 100 on the display appears the slave address 16 and instead of the value of x, 16 appears again...
And this is the source for the slave

Code:

#include <16F877A.h>
#device adc=8
#include <string.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES PUT                      //Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected

#use delay(clock = 10000000)
#use i2c(Slave, sda = PIN_C4, scl = PIN_C3, force_hw, address = 0x10)

#define I2C_SCL PIN_C3
#define I2C_SDA PIN_C4

#define BL PIN_B3
#define RS PIN_B2
#define RW PIN_B1
#define E  PIN_B0
/*---------------------======PIN DEFINITION======-------------------------------
PIN_B3 - BackLight(BL)
PIN_B2 - Register Select (RS)
PIN_B1 - Read/Write (RW)
PIN_B0 - Enable (E)
PIN_D0 - Data Bit 0 (DB0)
PIN_D1 - Data Bit 1 (DB1)
PIN_D2 - Data Bit 2 (DB2)
PIN_D3 - Data Bit 3 (DB3)
PIN_D4 - Data Bit 4 (DB4)
PIN_D5 - Data Bit 5 (DB5)
PIN_D6 - Data Bit 6 (DB6)
PIN_D7 - Data Bit 7 (DB7)
==============================================================================*/

void Clear_Display(void);
//Clears display and AC (address counter) = 0
void Home(void);
//Sets cursor at home
void Mode_Set(int1 ID, int1 SH);
//I/D  0 - decrease  SH 0 - display shift off at Read/Write
//     1 - increase     1 - display shift on at Read/Write
void Disp_Curs_On_Off(int1 D, int1 C, int1 B);
//D 0 - display off  C 0 - cursor off  B 0 - cursor blinking off
//D 1 - display on     1 - cursor on     1 - cursor blinking on
void Disp_Curs_Shift(int1 S_CD, int1 RL);
//S_CD 0 - cursor shift  RL 0 - left
//     1 - display shift    1 - right
void Function_Set(int1 DL, int1 N, int1 F);
//DL 0 - 4bits interface  N 0 - 1 row  F 0 - 5x8 font
//   1 - 8bits interface  N 1 - 2 rows   1 - 5x10 font
void CGRAM_Adrs(int Adrs);
//Send CGRAM Adrs, Adrs - 6bits
void DDRAM_Adrs(int Adrs);
//Send DDRAM Adrs, Adrs - 7bits
void Write_Data(int data);
//Send data(char), data - 8bits
int Read_Data(int data);
//Read data
int1 Read_BF_AC(int* AC);
//Read Busy Flag (BF) and Address Counter (AC)
void Init_LCD(void);
//initialize LCD
void Set_Zeros(void);
//Set zeros after instruction
void Write_str(char* data, int n);
//write string on the LCD
void Write_number(signed int32 d);
//write number on the LCD

void INIT(void)
{
   set_tris_b(0x00);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   Init_LCD();
}

void main()
{
   INIT();
   for(;;)
   {
      if(i2c_poll())
         write_number(i2c_read());
   }
}

I have deleted the functions for the LCD because they are a little bit long and work just excellent so the problem is not with them. The version of the compiler is 4.057
I am out of ideas... I have 10k pull-ups, it should be working in theory, but it doesn't. Do you have ideas where the problem might be ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 07, 2008 4:13 pm     Reply with quote

I didn't look at all your code in detail, but you need to fix one part:
Get rid of the two lines that enable/disable Global interrupts in the
#int_rda routine. The PIC handles it.
sv_shady



Joined: 07 Mar 2008
Posts: 28

View user's profile Send private message

PostPosted: Fri Mar 07, 2008 11:31 pm     Reply with quote

First I've tried without these two lines, then I wrote them because I wanted to be sure that this is not the problem. So with or without them the problem still exists... I thing the problem is with the slave
Ttelmah
Guest







PostPosted: Sat Mar 08, 2008 4:56 am     Reply with quote

As a comment though, 'enable_interrupts(GLOBAL)', inside an interrupt handler, is a _sure formula for really major problems_. Never _ever_ do this.
The problem is that enabling the interrupt inside the handler, can allow the interrupt handler to be interrupted. This is why he chip has a 'special' interrupt 'return' function (RETFIE), which causes the return t happen, and _then_ the interrupts to be enabled 'afterwards'. Ading this, didn't prove anything, except one way to crash the code....

Now, second comment, add 'ERRORS' to the RS232 declaration. This should be considered the 'default' setting, since without it, if anything goes wrong on the RS232 (overrun etc.), the hardware will become hung. :(

Now, when you perform an 'I2C_READ', on the slave device, two different things happen, according to the status of the I2C bus. If a byte has already been received, the function returns immediately, giving the value of the byte in the holding register. If no byte is waiting, the function will delay, and wait for a byte tbe received. By using I2C_POLL, you avoid this second behaviour. The fact that the system goes wrong >100, says that in fact the problem _is_ with the LCD code (there is no significance to '100', internally to the PIC, or the I2C bus, while there is to a printout routine). The problem is almost certainly, that the LCD code, _takes longer_ to print the value, and almost certainly the intermediate 'data' value, is being missed...
Look at making the slave code interrupt driven (look at ex_slave.c), so that bytes _will_ be handled, whatever is happening in the LCD code.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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