|
|
View previous topic :: View next topic |
Author |
Message |
Brian Grunewaldt Guest
|
Using I2c to interface with 16F877 and LM92 |
Posted: Tue Feb 11, 2003 10:38 pm |
|
|
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 |
Posted: Wed Feb 12, 2003 2:35 am |
|
|
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 |
Posted: Wed Feb 12, 2003 10:52 am |
|
|
:=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 |
Posted: Wed Feb 12, 2003 11:57 am |
|
|
<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
|
Re: Using I2c to interface with 16F877 and LM92 |
Posted: Wed Feb 12, 2003 1:17 pm |
|
|
<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 |
Posted: Thu Feb 13, 2003 2:48 am |
|
|
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 |
Posted: Sun Feb 16, 2003 9:47 pm |
|
|
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 |
|
|
|
|
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
|