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

bug I2C PCD

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







bug I2C PCD
PostPosted: Sun May 17, 2009 9:30 pm     Reply with quote

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







PostPosted: Sun May 17, 2009 9:41 pm     Reply with quote

but this code i use 16f876 no problem.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon May 18, 2009 1:22 am     Reply with quote

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







PostPosted: Mon May 18, 2009 3:38 am     Reply with quote

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







PostPosted: Mon May 18, 2009 3:58 am     Reply with quote

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







PostPosted: Mon May 18, 2009 4:04 am     Reply with quote

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







PostPosted: Mon May 18, 2009 4:17 am     Reply with quote

So try specifying a clock rate for the I2C:

#use i2c(master, sda=RTC_SDA, scl=RTC_SCL, SLOW)

Best Wishes
john2003
Guest







PostPosted: Mon May 18, 2009 4:33 am     Reply with quote

// not work

#use i2c(master, sda=RTC_SDA, scl=RTC_SCL, SLOW)
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon May 18, 2009 3:20 pm     Reply with quote

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







PostPosted: Mon May 18, 2009 11:26 pm     Reply with quote

Why i can read hour and minute. but i can not read second.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue May 19, 2009 12:02 am     Reply with quote

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.
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