|
|
View previous topic :: View next topic |
Author |
Message |
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
I2C Help!! |
Posted: Tue Jan 19, 2010 1:28 pm |
|
|
Hello!!
I'm new to programming in C, made a program to work with the DS1307 and DS1631 and PIC 16F877A on the same I2C bus,PIn C3 and C4 of the PIC 16F877A, but does not work!
I've been reading all the CCS forum and found nothing that helps me to
You can check, which has errors and correcting the program please!
The program source, and libraries is attached !!
Thank you very much .
Source program
Code: |
#include <16f877A.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4000000)
//#use i2c(master,sda=PIN_C4,scl=PIN_C3,FORCE_HW)// DS1307
#include <RTC_DS1307.c>// RTC DS1307
#include <flex_lcd.c>
#include <DS1631.c>
#use standard_io (b)
#use standard_io (a)
#use standard_io(c)
#use standard_io(D)
void main()
{
BYTE sec;
BYTE min;
BYTE hrs;
BYTE day;
BYTE month;
BYTE yr;
BYTE dow;
float value;
lcd_init();
delay_ms(50);
init_temp();
delay_ms(50);
ds1307_init();
delay_ms(50);
lcd_putc("\f testing");
delay_ms(500);
ds1307_set_date_time(10,10,10,0,10,10,00);
while(1)
{
delay_ms(1000);
ds1307_get_date(day,month,yr,dow);
ds1307_get_time(hrs,min,sec);
printf(lcd_Putc,"\f \%02d/\%02d/\%02d\r\n",day,month,yr);
printf(lcd_Putc," %02d:\%02d:\%02d", hrs,min,sec);
delay_ms(500);
value = (float)read_full_temp();
value /= 100.0;
value=(value-32)/1.8;
lcd_gotoxy(15,1);
printf(lcd_putc,"temp.%03.1f", value);
}
}
|
Library for a Dallas DS 1631 and DS1307
Code: |
//// Library for a Dallas 1631 Temperature chip ////
//// ////
#define read_temp read_full_temp // for backwards compatability
#use i2c(master, sda=DAL_SDA, scl=DAL_SCL)
void temp_config(BYTE data) {
i2c_start();
i2c_write(0x92);
i2c_write(0xac);
i2c_write(data);
i2c_stop();
}
void init_temp() {
output_high(DAL_SDA);
output_high(DAL_SCL);
i2c_start();
i2c_write(0x92);
i2c_write(0x51);
i2c_stop();
temp_config(0xc);
}
signed long read_full_temp() { // Returns hundreths of degrees F (-67 to 257)
long datal; //long datal;
signed long datah, data;
i2c_start();
i2c_write(0x92);
i2c_write(0xaa);
i2c_start();
i2c_write(0x93);
datah=i2c_read();
datal=i2c_read(0);
i2c_stop();
data = datah * 100;
data += (datal << 8) / 655;
data=data*9;
data = (data / 5) + 3200;
return(data);
}
/// DS1307.C ///
/// Driver for Real Time Clock ///
#define DAL_SCL PIN_C3
#define DAL_SDA PIN_C4
#use i2c(master, sda=DAL_SDA, scl=DAL_SCL)
BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);
void ds1307_init(void)
{
BYTE seconds = 0;
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_start();
i2c_write(0xD1); // RD from RTC
seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
i2c_stop();
seconds &= 0x7F;
delay_us(3);
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x00); // REG 0
i2c_write(bin2bcd(seconds)); // Start oscillator with current "seconds value
i2c_start();
i2c_write(0xD0); // WR to RTC
i2c_write(0x07); // Control Register
i2c_write(0x01); // Disable squarewave output pin
i2c_stop();
}
void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
sec &= 0x7F;
hr &= 0x3F;
i2c_start();
i2c_write(0xD0); // I2C write address
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_write(bin2bcd(sec)); // REG 0
i2c_write(bin2bcd(min)); // REG 1
i2c_write(bin2bcd(hr)); // REG 2
i2c_write(bin2bcd(dow)); // REG 3
i2c_write(bin2bcd(day)); // REG 4
i2c_write(bin2bcd(mth)); // REG 5
i2c_write(bin2bcd(year)); // REG 6
i2c_write(0x01); // REG 7 - Disable squarewave output pin
i2c_stop();
}
void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x03); // Start at REG 3 - Day of week
i2c_start();
i2c_write(0xD1);
dow = bcd2bin(i2c_read() & 0x7f); // REG 3
day = bcd2bin(i2c_read() & 0x3f); // REG 4
mth = bcd2bin(i2c_read() & 0x1f); // REG 5
year = bcd2bin(i2c_read(0)); // REG 6
i2c_stop();
}
void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_start();
i2c_write(0xD1);
sec = bcd2bin(i2c_read() & 0x7f);
min = bcd2bin(i2c_read() & 0x7f);
hr = bcd2bin(i2c_read(0) & 0x3f);
i2c_stop();
}
BYTE bin2bcd(BYTE binary_value)
{
BYTE temp;
BYTE retval;
temp = binary_value;
retval = 0;
while(1)
{
// Get the tens digit by doing multiple subtraction
// of 10 from the binary value.
if(temp >= 10)
{
temp -= 10;
retval += 0x10;
}
else // Get the ones digit by adding the remainder.
{
retval += temp;
break;
}
}
return(retval);
}
// Input range - 00 to 99.
BYTE bcd2bin(BYTE bcd_value)
{
BYTE temp;
temp = bcd_value;
// Shifting upper digit right by 1 is same as multiplying by 8.
temp >>= 1;
// Isolate the bits for the upper digit.
temp &= 0x78;
// Now return: (Tens * 8) + (Tens * 2) + Ones
return(temp + (temp >> 2) + (bcd_value & 0x0f));
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 19, 2010 2:04 pm |
|
|
Tell us what you mean by "does not work". What output do you get ?
Do you have 4.7K pull-up resistors on the SDA and SCL lines ?
What is your compiler version ? |
|
|
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
|
Posted: Tue Jan 19, 2010 3:55 pm |
|
|
PCM programmer wrote: | Tell us what you mean by "does not work". What output do you get ?
Do you have 4.7K pull-up resistors on the SDA and SCL lines ?
What is your compiler version ? |
"It does not work", that is to not show anything on the LCD, the temperature, clock and calendar! with the two chips (DS1631 + DS1307) connected on the same bus!
I have 47K pull-up resistors on the SDA and SCL lines because I changed the 10K but is the same!
My compiler version is 4.068
I thank you help |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 19, 2010 4:06 pm |
|
|
Quote: | lcd_putc("\f testing"); |
Here you have a line that should display "testing". Do you see that ? |
|
|
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
|
Posted: Tue Jan 19, 2010 4:38 pm |
|
|
PCM programmer wrote: | Quote: | lcd_putc("\f testing"); |
Here you have a line that should display "testing". Do you see that ? |
yes, it shows in the LCD,yes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 19, 2010 5:12 pm |
|
|
Change your code and your hardware so it tests only the ds1307.
Get that working first. Disconnect the ds1631 chip from the i2c bus
completely.
Try to make your program as close as possible to the test program
shown in the ds1307 driver link:
http://www.ccsinfo.com/forum/viewtopic.php?t=23255
But don't use the "\r" in the printf statement. You'll note that I've edited
that out below. Also, your posted code had the #use i2c statement
commented out. I've put it back in. Also, I've removed the "FORCE_HW"
parameter. It's safer to start with a software i2c master. You have
NOBROWNOUT below. If you're using a "wall wart" transformer, it's
better to have BROWNOUT in there. You'll note that I removed your
settings for the date and time, and I put in the settings from the sample
code in the ds1307 link. Try to keep everything as close to his code
as possible, because it presumably works. Get it working that way first.
With respect to your hardware, make sure you have a 32.768 KHz
watch crystal connected to the ds1307's crystal pins. No capacitors
are used with this crystal. Also, make sure you have a 3 volt lithium
battery connected to the Vbat pin. Don't substitute some other voltage.
Code: |
#include <16f877A.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4000000)
#use i2c(master, sda=PIN_C4, scl=PIN_C3)
#include <RTC_DS1307.c>
#include <flex_lcd.c>
void main()
{
BYTE sec;
BYTE min;
BYTE hrs;
BYTE day;
BYTE month;
BYTE yr;
BYTE dow;
lcd_init();
ds1307_init();
lcd_putc("\f testing");
delay_ms(500);
// Set date for -> 15 June 2005 Tuesday
// Set time for -> 15:20:55
ds1307_set_date_time(15,6,5,2,15,20,55);
while(1)
{
delay_ms(1000);
ds1307_get_date(day,month,yr,dow);
ds1307_get_time(hrs,min,sec);
printf(lcd_Putc,"\f \%02d/\%02d/\%02d\n",day,month,yr);
printf(lcd_Putc," %02d:\%02d:\%02d", hrs,min,sec);
}
}
|
|
|
|
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
|
Posted: Tue Jan 19, 2010 5:42 pm |
|
|
PCM I made the changes and now the DS1307 works very, very good! But only with the DS1307!
Then I made only with the DS1631 and does not work, the problem is in the code of the DS1631, where is the error? can help me in this code?
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 19, 2010 5:54 pm |
|
|
Quote: | #use i2c(master, sda=DAL_SDA, scl=DAL_SCL) |
Post the lines that #define the i2c pins used for the ds1631.
Here are the lines from the CCS driver file, ds1631.c. It defaults to
using pins B0 and B1. Is it possible that you left this code in there,
you're accidently using pins B0 and B1 ?
Quote: | #ifndef DAL_SCL
#if defined(__PCD__)
#define DAL_SCL PIN_D0
#define DAL_SDA PIN_D1
#else
#define DAL_SCL PIN_B0
#define DAL_SDA PIN_B1
#endif
#endif |
Quote: | void temp_config(BYTE data) {
i2c_start();
i2c_write(0x92);
i2c_write(0xac);
i2c_write(data);
i2c_stop();
}
|
In the code above you are using 0x92 as the base address for the
ds1631. But, the CCS ds1631.c driver uses 0x90, as shown below:
Code: |
void temp_config(BYTE data
i2c_start();
i2c_write(0x90);
i2c_write(0xac);
i2c_write(data);
i2c_stop();
} |
What connections do you have to the A0, A1, and A2 pins of the ds1631
chip on your board ? These pins set the slave address. |
|
|
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
|
Posted: Tue Jan 19, 2010 6:16 pm |
|
|
I used the same lines of the DS1307, or # use i2c (master, sda = PIN_C4, scl = PIN_C3)
The address of the DS1631 use A2 = 0, A1 = 0, A0 = 1.
Also tested A2 = 0, A1 = 0, A0 = 0, and does not work |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 19, 2010 6:33 pm |
|
|
Quote: | The address of the DS1631 use A2 = 0, A1 = 0, A0 = 1.
|
That means you have pin A0 connected to +5v, and pins A1 and A2
connected to ground. Is that true ?
Post your current driver file and test program for the ds1631. |
|
|
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
|
Posted: Tue Jan 19, 2010 6:56 pm |
|
|
PCM programmer wrote: | Quote: | The address of the DS1631 use A2 = 0, A1 = 0, A0 = 1.
|
That means you have pin A0 connected to +5v, and pins A1 and A2
connected to ground. Is that true ?
|
Exactly!
The driver file and test program for the ds1631is.
Code: |
#include <16f877A.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4000000)
#use i2c(master,sda=PIN_C4,scl=PIN_C3)
#include <flex_lcd.c>
#include <DS1631.c>
#use standard_io (b)
#use standard_io (a)
#use standard_io(c)
#use standard_io(D)
void main()
{
float value;
lcd_init();
delay_ms(100);
init_temp();
delay_ms(100);
while(1)
{
delay_ms(1000);
value = read_full_temp();
value /= 100.0;
value=(value-32)/1.8;
lcd_gotoxy(15,1);
printf(lcd_putc,"\f temp.%04.1f", value);
delay_ms(100);
}
}
|
Code: |
//// Library for a Dallas 1631 Temperature chip ////
//// ////
//#use i2c(master,sda=PIN_C4,scl=PIN_C3)
#define read_temp read_full_temp // for backwards compatability
void temp_config(BYTE data) {
i2c_start();
i2c_write(0x92);
i2c_write(0xac);
i2c_write(data);
i2c_stop();
}
void init_temp() {
output_high(DAL_SDA);
output_high(DAL_SCL);
i2c_start();
i2c_write(0x92);
i2c_write(0x51);
i2c_stop();
temp_config(0xc);
}
signed long read_full_temp() { // Returns hundreths of degrees F (-67 to 257)
long datal; //long datal;
signed long datah, data;
i2c_start();
i2c_write(0x92);
i2c_write(0xaa);
i2c_start();
i2c_write(0x93);
datah=i2c_read();
datal=i2c_read(0);
i2c_stop();
data = datah * 100;
data += (datal << 8) / 655;
data=data*9;
data = (data / 5) + 3200;
return(data);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 19, 2010 7:24 pm |
|
|
What values are displayed on the LCD ?
Did you use the CCS driver to make your driver ? I was comparing your
routine for read_full_temp() to the CCS driver code, and your routine
looks like the CCS code, except it's been heavily edited. I would put
the ds1631.c driver back the way it was. Use it in the non-edited form.
See what you get. |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 20, 2010 3:18 am |
|
|
fiasgardone wrote: | PCM programmer wrote: | Tell us what you mean by "does not work". What output do you get ?
Do you have 4.7K pull-up resistors on the SDA and SCL lines ?
What is your compiler version ? |
"It does not work", that is to not show anything on the LCD, the temperature, clock and calendar! with the two chips (DS1631 + DS1307) connected on the same bus!
I have 47K pull-up resistors on the SDA and SCL lines because I changed the 10K but is the same!
My compiler version is 4.068
I thank you help |
Go lower.
Read the I2C specs. 10K, gives you a maximum allowed bus capacitance of 80pF, for 'standard' speed operation. Most of the diagrams don't even go as high as 10K. The minimum value allowed for 5v, is 1.75K, and typical 'likely to work' values will fall in the area between 2.2K, and 4.7K.
It is worth getting the resistor into the proper range, before looking for other causes to the problem.
With two devices on the bus, you _need_ to be able to cope with a reasonable amount of capacitance...
PCM programmer suggested 4.7K, and this is the sort of level you should be using.
Best Wishes |
|
|
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
|
Posted: Wed Jan 20, 2010 4:42 am |
|
|
Quote: | PCM programmer suggested 4.7K, and this is the sort of level you should be using. |
Yes, I am using the 4.7K Pull-up resistors !!
Thanks! |
|
|
fiasgardone
Joined: 19 Jan 2010 Posts: 71
|
|
Posted: Wed Jan 20, 2010 5:50 am |
|
|
I tested the code with the driver of the CCS,and also does not work!
I used the pins D0 and D1 of the PIN PIC, did not use pins B0 and B1 because the use for the LCD, but does not show the temperature on the LCD, where the errors are?
The address of the DS1631 is now A2 = 0, A1 = 0, A0 = 0 in hardware
See below;
Code: |
#include <16f877A.h>
#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4000000)
#use i2c(master,sda=PIN_D1,scl=PIN_D0)
#include <flex_lcd.c>
#include <DS1631.c>
#use standard_io (b)
#use standard_io (a)
#use standard_io(c)
#use standard_io(D)
void main()
{
float value;
lcd_init();
delay_ms(100);
init_temp();
delay_ms(100);
while(1)
{
delay_ms(1000);
value = read_full_temp();
value /= 100.0;
value=(value-32)/1.8;
lcd_gotoxy(15,1);
printf(lcd_putc,"\f temp.%04.1f", value);
delay_ms(100);
}
}
|
Last edited by fiasgardone on Thu Jan 21, 2010 10:24 am; edited 1 time in total |
|
|
|
|
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
|