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 support@ccsinfo.com

Using I2c to interface with 16F877 and LM92

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







Using I2c to interface with 16F877 and LM92
PostPosted: Tue Feb 11, 2003 10:38 pm     Reply with quote

I'm trying to figure out why my code is not working correctly. I am trying to read the temperature from a LM92 digital temp sensor using the I2C bus. Everything looks correct to me....please help. The I'm using PCW Compiler, PCM version 3.050. On the LCD I never see the ackn1, which tells me I'm not getting an acknowledge from the LM92 but I'm not sure why. All I ever see on the LCD is "temp1 = FF" and "temp2 = FF", but I know this is incorrect. Does this compiler version work correctly with I2C? I only added the force_hw to see what would happen because without it, I see nothing on the LCD.

#include "math.h"
#include <16F877.h>
#use delay(clock=20000000)
#fuses HS,WDT,PUT,WRT,NOLVP
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#use i2c(scl=PIN_C3,sda=PIN_C4,master,force_hw)
#use standard_io(c)

#define ON 1
#define OFF 0
int16 counter;
void Init_Ports(void); //intitializing Ports

void Init_Ports()//initializes ports and set initial values
{
SETUP_ADC(ADC_OFF);
SETUP_ADC_PORTS(NO_ANALOGS);
set_tris_a(0x00);
set_tris_b(0xF0);
set_tris_c(0x00);
set_tris_d(0x00);
set_tris_e(0x02);
}

void main()
{
int temp1, temp2,ackn1;
Init_Ports();
setup_counters( RTCC_INTERNAL, RTCC_DIV_256);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
setup_wdt(WDT_2304MS);
while(1)
{
delay_ms(1100);
i2c_start();
ackn1=i2c_write(0x91);
delay_ms(10);
if (ackn1 == 0)
{ putc(18); printf("ack1");}
delay_ms(10);
temp1=i2c_read(1);
temp2=i2c_read(0);
i2c_stop();
delay_ms(10);
putc(12);
putc(18);
printf("temp1 = \%X",temp1);
putc(10);
putc(13);
putc(18);
printf("temp2 = \%X",temp2);
}//end main function loop
}//end main

#int_rtcc // This function is called every time
clock_isr() // the RTCC (timer0) overflows (255->0).
{ // For this program this is apx 4797 times
if(--counter==0) // per second. clk speed/(4*256)
{
blink = 1;
counter = 15000;
}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 11572
nilsener
Guest







Re: Using I2c to interface with 16F877 and LM92
PostPosted: Wed Feb 12, 2003 2:35 am     Reply with quote

Dear,

perhaps the set_tris_c(0x00); in your Init_Ports() function is the problem. You set the complete portc to outputs and your I2C is on portc, too. An output can not read data.

regards nilsener

:=I'm trying to figure out why my code is not working correctly. I am trying to read the temperature from a LM92 digital temp sensor using the I2C bus. Everything looks correct to me....please help. The I'm using PCW Compiler, PCM version 3.050. On the LCD I never see the ackn1, which tells me I'm not getting an acknowledge from the LM92 but I'm not sure why. All I ever see on the LCD is "temp1 = FF" and "temp2 = FF", but I know this is incorrect. Does this compiler version work correctly with I2C? I only added the force_hw to see what would happen because without it, I see nothing on the LCD.
:=
:=#include "math.h"
:=#include <16F877.h>
:=#use delay(clock=20000000)
:=#fuses HS,WDT,PUT,WRT,NOLVP
:=#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
:=#use i2c(scl=PIN_C3,sda=PIN_C4,master,force_hw)
:=#use standard_io(c)
:=
:=#define ON 1
:=#define OFF 0
:=int16 counter;
:=void Init_Ports(void); //intitializing Ports
:=
:=void Init_Ports()//initializes ports and set initial values
:={
:= SETUP_ADC(ADC_OFF);
:= SETUP_ADC_PORTS(NO_ANALOGS);
:= set_tris_a(0x00);
:= set_tris_b(0xF0);
:= set_tris_c(0x00);
:= set_tris_d(0x00);
:= set_tris_e(0x02);
:=}
:=
:=void main()
:={
:= int temp1, temp2,ackn1;
:= Init_Ports();
:= setup_counters( RTCC_INTERNAL, RTCC_DIV_256);
:= enable_interrupts(INT_RTCC);
:= enable_interrupts(GLOBAL);
:= setup_wdt(WDT_2304MS);
:= while(1)
:= {
:= delay_ms(1100);
:= i2c_start();
:= ackn1=i2c_write(0x91);
:= delay_ms(10);
:= if (ackn1 == 0)
:= { putc(18); printf("ack1");}
:= delay_ms(10);
:= temp1=i2c_read(1);
:= temp2=i2c_read(0);
:= i2c_stop();
:= delay_ms(10);
:= putc(12);
:= putc(18);
:= printf("temp1 = \%X",temp1);
:= putc(10);
:= putc(13);
:= putc(18);
:= printf("temp2 = \%X",temp2);
:= }//end main function loop
:=}//end main
:=
:=#int_rtcc // This function is called every time
:=clock_isr() // the RTCC (timer0) overflows (255->0).
:={ // For this program this is apx 4797 times
:= if(--counter==0) // per second. clk speed/(4*256)
:= {
:= blink = 1;
:= counter = 15000;
:= }
:=}
___________________________
This message was ported from CCS's old forum
Original Post ID: 11581
Brian Grunewaldt
Guest







Re: Using I2c to interface with 16F877 and LM92
PostPosted: Wed Feb 12, 2003 10:52 am     Reply with quote

:=Dear,
:=
:=perhaps the set_tris_c(0x00); in your Init_Ports() function is the problem. You set the complete portc to outputs and your I2C is on portc, too. An output can not read data.
:=
:=regards nilsener
:=

In master mode, does the SCL need to be an ouput and the SDA input/ouput? How do you configure SDA to be an input/ouput? Can I just set it to input? I did have set_tris_c(0x00); commented out before since I was using #use standard_io(c) and it still didn't work. Please elaborate.......and thank you for your suggestion.

BG
___________________________
This message was ported from CCS's old forum
Original Post ID: 11605
nilsener
Guest







Re: Using I2c to interface with 16F877 and LM92
PostPosted: Wed Feb 12, 2003 11:57 am     Reply with quote

<font face="Courier New" size=-1>I only have experiences with a serial EEPROM and I2C, however,

you must not set the SDA line to input or output because in master mode it is a bidirectional data port, input if datas will be received and output if datas will be transmitted. Don't worry, it switches between input and output automatically.

first check the address of the LM92, the datasheet says the slave address is MSB 10010 A1 A0 LSB whereas A1 and A0 represents the state at the pins A1 and A0 (ground or +Vdd). If you have wired the lines A1 and A0 to ground, the slave address should be 1001000 binary and this is 0x48 in hex. Change your i2c_write(0x91); to i2c_write(0x48); and perhaps you will get the expected ack ?


Further I suggest to restart your watchdog timer, have a look to restart_wdt(); to prevent the cpu from getting a reset. Perhaps it helps to move the #use standard_io statement in front of the #use I2C(...).

I use this code:

#use standard_io(C)
#use delay (clock = 19660800, RESTART_WDT)
#use I2C(MASTER, SDA=PIN_C4, SCL=PIN_C3, RESTART_WDT, SLOW, FORCE_HW)

Hope it helps,

regards nilsener



:=:=Dear,
:=:=
:=:=perhaps the set_tris_c(0x00); in your Init_Ports() function is the problem. You set the complete portc to outputs and your I2C is on portc, too. An output can not read data.
:=:=
:=:=regards nilsener
:=:=
:=
:=In master mode, does the SCL need to be an ouput and the SDA input/ouput? How do you configure SDA to be an input/ouput? Can I just set it to input? I did have set_tris_c(0x00); commented out before since I was using #use standard_io(c) and it still didn't work. Please elaborate.......and thank you for your suggestion.
:=
:=BG</font>
___________________________
This message was ported from CCS's old forum
Original Post ID: 11609
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: Using I2c to interface with 16F877 and LM92
PostPosted: Wed Feb 12, 2003 1:17 pm     Reply with quote

<font face="Courier New" size=-1>:=you must not set the SDA line to input or output because in master mode it is a bidirectional data port, input if datas will be received and output if datas will be transmitted. Don't worry, it switches between input and output automatically.
---------------------------------------------------------

In the 16F877 data sheet, in section 9.2 (MSSP Operation),
on the right side of the page, it says "Before selecting
any i2c mode, the SCL and SDA pins must be programmed to
inputs by setting the appropriate TRIS bits".

I tested this just now, with my 24LC256 test program and
it's true. If I change the initialize function so it
does this:

output_low(PIN_C3);
output_low(PIN_C4);

then the program fails. It gets read errors. It also
fails if I use output_high(). To make it work, it must be:

output_float(PIN_C3);
output_float(PIN_C4);

This could also be done with the set_tris_c() function.


Note: This test was done by using hardware i2c. (FORCE_HW).




</font>
___________________________
This message was ported from CCS's old forum
Original Post ID: 11611
Brian Grunewaldt
Guest







Re: Using I2c to interface with 16F877 and LM92
PostPosted: Thu Feb 13, 2003 2:48 am     Reply with quote

In response to that, I think I'm getting closer to getting it working. I don't use standard_io(C) now because I want to be able to set it myself for other pins on the C port. I use i2c_write(0x91); because 10010001 is the actual address since the LSB is the read/write bit. It is a 1 when it's reading and 0 when it's writing, and yes I have A0 and A1 grounded. I hooked it up to an oscilloscope and am using force_hw to see everything on the SDA pin except an acknowledge from the LM92. I thought that maybe the chip had a problem so I tried a different one and I still don't get an acknowledge from it. The timing looks perfect and the bits line up to the SCL but it keeps reading FF as the data. I have tried looking at different pointer addresses like the Manufacturers ID and I always get FF. I think it is because the LM92 is not sending anything back, but I don't understand why. I might try calling National Semi to get help. If you have any other suggestions, I'm all ears.

Thanks,
BG


:=<font face="Courier New" size=-1>I only have experiences with a serial EEPROM and I2C, however,
:=
:=you must not set the SDA line to input or output because in master mode it is a bidirectional data port, input if datas will be received and output if datas will be transmitted. Don't worry, it switches between input and output automatically.
:=
:=first check the address of the LM92, the datasheet says the slave address is MSB 10010 A1 A0 LSB whereas A1 and A0 represents the state at the pins A1 and A0 (ground or +Vdd). If you have wired the lines A1 and A0 to ground, the slave address should be 1001000 binary and this is 0x48 in hex. Change your i2c_write(0x91); to i2c_write(0x48); and perhaps you will get the expected ack ?
:=
:=
:=Further I suggest to restart your watchdog timer, have a look to restart_wdt(); to prevent the cpu from getting a reset. Perhaps it helps to move the #use standard_io statement in front of the #use I2C(...).
:=
:=I use this code:
:=
:=#use standard_io(C)
:=#use delay (clock = 19660800, RESTART_WDT)
:=#use I2C(MASTER, SDA=PIN_C4, SCL=PIN_C3, RESTART_WDT, SLOW, FORCE_HW)
:=
:=Hope it helps,
:=
:=regards nilsener
:=
:=
___________________________
This message was ported from CCS's old forum
Original Post ID: 11630
Brian Grunewaldt
Guest







Re: Using I2c to interface with 16F877 and LM92
PostPosted: Sun Feb 16, 2003 9:47 pm     Reply with quote

Turns out I'm just dumb and didn't have pullup resistors connected to SCL and SDA. After putting some 10k resistors in, everything worked fine.

BG
___________________________
This message was ported from CCS's old forum
Original Post ID: 11776
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