|
|
View previous topic :: View next topic |
Author |
Message |
john2003 Guest
|
bug I2C PCD |
Posted: Sun May 17, 2009 9:30 pm |
|
|
I use dspic30f4012 pcd 4.088
Code: | void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x00);
i2c_start();
i2c_write(0xD1);
sec = bcd2bin(i2c_read() & 0x7f); //read data is 0x00 always. no change.
min = bcd2bin(i2c_read() & 0x7f); //read data ok. change every minute.
hr = bcd2bin(i2c_read(0) & 0x3f); //read data ok. change every hour.
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); //read data ok
day = bcd2bin(i2c_read() & 0x3f); //read data ok
mth = bcd2bin(i2c_read() & 0x1f); //read data ok
year = bcd2bin(i2c_read(0)); //read data ok
i2c_stop();
}
|
|
|
|
john2003 Guest
|
|
Posted: Sun May 17, 2009 9:41 pm |
|
|
but this code i use 16f876 no problem. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon May 18, 2009 1:22 am |
|
|
It helps if you say what your problem is...
Also, the code is incomplete. Post a very small program demonstrating your problem. The program must be complete including fuses, etc., so it can be copy/pasted without changes. |
|
|
Ttelmah Guest
|
|
Posted: Mon May 18, 2009 3:38 am |
|
|
One 'obvious' thing would be the clock rate, and speed settings for the I2C bus. I'd guess that you are likely to be clocking the DSPic a lot faster than the 876, and unless you are explicity selecting 100K I2C, the bus may well be too fast for the chip....
A 'mini' program, that just shows the fault, so other people can compile it, and see what is wrong, is the only way to really go.
Best Wishes |
|
|
john2003 Guest
|
|
Posted: Mon May 18, 2009 3:58 am |
|
|
Code: | // I can not read second. data second is 0x00 alway not change.
// but I can read minute and hour.
#include <30f4012.h>
#use delay(clock=32M,restart_wdt)
#fuses XT_PLL8,PROTECT,NOWDT,NOWRT,NOCKSFSM,CKSNOFSM,NODEBUG,NOCOE
#use rs232(baud=9600,UART1A,ENABLE=PIN_D1)
#define RTC_SDA PIN_F2
#define RTC_SCL PIN_F3
#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)
BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);
unsigned int8 hr,min,sec,min_buf,sec_buf;
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(0x80); // Disable squarewave output pin
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); // REG 0
min = bcd2bin(i2c_read() & 0x7f); // REG 1
hr = bcd2bin(i2c_read(0) & 0x3f); // REG 2
i2c_stop();
}
BYTE bin2bcd(BYTE binary_value)
{
BYTE temp;
BYTE retval;
temp = binary_value;
retval = 0;
while(true)
{
// 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));
}
void main() {
ds1307_init();
while(true){
ds1307_get_time(hr,min,sec);
if(sec_buf!=sec){
sec_buf=sec;
printf("%X:%X:%X"hr,min,sec);
}
if(min_buf!=min){
sec_buf=min;
printf("%X:%X:%X"hr,min,sec);
}
}
} |
|
|
|
john2003 Guest
|
|
Posted: Mon May 18, 2009 4:04 am |
|
|
Code: | #include <30f4012.h>
#use delay(clock=32M,restart_wdt)
#fuses XT_PLL8,PROTECT,NOWDT,NOWRT,NOCKSFSM,CKSNOFSM,NODEBUG,NOCOE
#use rs232(baud=9600,UART1A,ENABLE=PIN_D1)
#define RTC_SDA PIN_F2
#define RTC_SCL PIN_F3
#use i2c(master, sda=RTC_SDA, scl=RTC_SCL)
BYTE bin2bcd(BYTE binary_value);
BYTE bcd2bin(BYTE bcd_value);
unsigned int8 hr,min,sec,min_buf,sec_buf;
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(0x80); // Disable squarewave output pin
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); // REG 0
min = bcd2bin(i2c_read() & 0x7f); // REG 1
hr = bcd2bin(i2c_read(0) & 0x3f); // REG 2
i2c_stop();
}
BYTE bin2bcd(BYTE binary_value)
{
BYTE temp;
BYTE retval;
temp = binary_value;
retval = 0;
while(true)
{
// 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));
}
void main() {
ds1307_init();
while(true){
ds1307_get_time(hr,min,sec);
if(sec_buf!=sec){
sec_buf=sec;
printf("%X:%X:%X"hr,min,sec);
}
if(min_buf!=min){
min_buf=min;
printf("%X:%X:%X"hr,min,sec);
}
}
} |
|
|
|
Ttelmah Guest
|
|
Posted: Mon May 18, 2009 4:17 am |
|
|
So try specifying a clock rate for the I2C:
#use i2c(master, sda=RTC_SDA, scl=RTC_SCL, SLOW)
Best Wishes |
|
|
john2003 Guest
|
|
Posted: Mon May 18, 2009 4:33 am |
|
|
// not work
#use i2c(master, sda=RTC_SDA, scl=RTC_SCL, SLOW) |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon May 18, 2009 3:20 pm |
|
|
I tried your last code version on a PIC24FJ128GA106 with a DS1337 RTC connected and it did display seconds as expected.
But I found a PCD bug with I2CBRG setup. For a clock frequency of 32 MHz, it should be set to 0x0122. Unfortunately, only an 8-Bit value is set. The programmer seems to have forgotten, that he's dealing with a 16-Bit processor.
Code: | 02C6 B3C220 mov.b #0x22,0x0000
02C8 B7E204 mov.b 0x0000,0x0204 |
The erroneous setting results in about 850 kHz I2C clock.
Set I2CBRG manually in your code as a workaround.
Code: | #word I2CBRG = 0x204
I2CBRG = 0x122; |
Best regards,
Frank |
|
|
john2003 Guest
|
|
Posted: Mon May 18, 2009 11:26 pm |
|
|
Why i can read hour and minute. but i can not read second. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue May 19, 2009 12:02 am |
|
|
Don't know. It may be related to the wrong frequency. Don't ask, please try.
I used most recent PCD V4.092. I didn't check for possible additional bugs with V4.088 or special
issues with dsPIC30 code. However, PIC24 I2C code has been operational for me since V4.079.
Because my application has a 16 MHz clock, I wasn't aware of the said bug. |
|
|
|
|
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
|