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

ds1307 reading wrong
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
andrefrejat



Joined: 24 Feb 2013
Posts: 3

View user's profile Send private message

ds1307 reading wrong
PostPosted: Sun Feb 24, 2013 6:24 pm     Reply with quote

Hello,
I have to make a simulation of a digital clock using the ds1307 and PIC18F4520, but since i'm really new at programing i'm having a lot of problems.
Now, basically when I try to read the hour and date I get it right, no problem. But when I try to increment something the ds1307 give me error like:
1-the months goes from 0 up to 19 (instead of 1-12)
2-the days up to 40
3-the hours up to 30 something....

so basically i'm reading everything wrong. Probably it's simple the answer but I really can't figure it out.

Thanks in advance.


Code:
#include <18F4520.h>
#device adc=8

#FUSES NOWDT,WDT128,LP,NOPROTECT,BROWNOUT,BORV25,NOPUT,NOCPD,STVREN,NODEBUG,LVP,NOWRT,NOWRTD,IESO,FCMEN,PBADEN,NOWRTC,NOWRTB,NOEBTR,NOEBTRB,NOCPB,LPT1OSC,MCLR,XINST

#use delay(clock=2000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3)

#include <LCD.C>
#include <ds1307.c>

byte day = 01,month=01,year=13,dow=1,hrs=00,min=00,sec=00;

void main()
{

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   lcd_init();
   ds1307_init(DS1307_ALL_DISABLED );
   ds1307_set_date_time(day,month,year,dow,hrs,min,sec);
//Setup_Oscillator parameter not selected from Intr Oscillotar Config tab

   // TODO: USER CODE!!
while(1){
   ds1307_get_time(hrs, min, sec);
   ds1307_get_date(day,month,year,dow);
   printf(lcd_putc,"\f %2u:%2u:%2u \n %2u-%2u-%2u %2s",hrs,min,sec,day,month,year,days_of_week[dow]);
   delay_us(500);
   if(input(pin_B0)){
      day++;
      ds1307_set_date_time(day,month,year,dow,hrs,min,sec);
      delay_ms(50);
   }
   if(input(pin_B1)){
      month++;
      ds1307_set_date_time(day,month,year,dow,hrs,min,sec);
   }
   if(input(pin_B2)){
      year++;
      ds1307_set_date_time(day,month,year,dow,hrs,min,sec);
   }
   if(input(pin_B3)){
      dow++;
      ds1307_set_date_time(day,month,year,dow,hrs,min,sec);
   }
   if(input(pin_B4)){
      hrs++;
      ds1307_set_date_time(day,month,year,dow,hrs,min,sec);
   }
   if(input(pin_B5)){
      min++;
      ds1307_set_date_time(day,month,year,dow,hrs,min,sec);
   }
   if(input(pin_B6)){
      sec++;
      ds1307_set_date_time(day,month,year,dow,hrs,min,sec);
   }
}
}


the ds1307 driver im using:
Code:
///////////////////////////////////////////////////////////////////////////////////////
///                               DS1307.C                                           ///
///                     Driver for Real Time Clock                                   ///
///                     modified by Redpic 08/2006                                   ///
///                  http://picmania.garcia-cuervo.com                               ///
///                                                                                  ///
/// void ds1307_init(val)                                                            ///
///                  - Enable oscillator without clearing the seconds register       ///
///                    used when PIC loses power and DS1307 run from 3V BAT          ///
///                  - Config Control Register with next parameters:                 ///
///                     DS1307_ALL_DISABLED          All disabled                    ///
///                     DS1307_OUT_ON_DISABLED_HIHG  Out to Hight on Disable Out     ///
///                     DS1307_OUT_ENABLED           Out Enabled                     ///
///                     DS1307_OUT_1_HZ              Freq. Out to 1 Hz               ///
///                     DS1307_OUT_4_KHZ             Freq. Out to 4.096 Khz          ///
///                     DS1307_OUT_8_KHZ             Freq. Out to 8.192 Khz          ///
///                     DS1307_OUT_32_KHZ            Freq. Out to 32.768 Khz         ///
///                                                                                  ///
///                     Example init:                                                ///
///                     ds1307_init(DS1307_ALL_DISABLED);                            ///
///                     ds1307_init(DS1307_OUT_ENABLED | DS1307_OUT_1_HZ);           ///
///                                                                                  ///
/// void ds1307_set_date_time(day,mth,year,dow,hour,min,sec) - Set the date/time     ///
///                                                                                  ///
/// void ds1307_get_date(day,mth,year,dow)                   - Get the date          ///
///                                                                                  ///
/// void ds1307_get_time(hr,min,sec)                         - Get the time          ///
///                                                                                  ///
/// char ds1307_read_nvram_byte(char addr)                   - Read byte in address  ///
///                                                                                  ///
/// void ds1307_write_nvram_byte(char addr, char value)      - Write byte in address ///
///                                                                                  ///
/// void ds1307_get_day_of_week(char* ptr)                   - Get string Day Of Week///
///                                                                                  ///
/// If defined USE_INTERRUPTS all functions disable Global Interrupts on starts and  ///
///                           enable Global on ends else usar can do it hiself       ///
///                                                                                  ///
///////////////////////////////////////////////////////////////////////////////////////

#ifndef RTC_SDA
#define RTC_SDA  PIN_C4
#define RTC_SCL  PIN_C3
#endif

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

#define DS1307_ALL_DISABLED         0b00000000 // All disabled
#define DS1307_OUT_ON_DISABLED_HIHG 0b10000000 // Out to Hight on Disable Out
#define DS1307_OUT_ENABLED          0b00010000 // Out Enabled
#define DS1307_OUT_1_HZ             0b00000000 // Freq. Out to 1 Hz
#define DS1307_OUT_4_KHZ            0b00000001 // Freq. Out to 4.096 Khz
#define DS1307_OUT_8_KHZ            0b00000010 // Freq. Out to 8.192 Khz
#define DS1307_OUT_32_KHZ           0b00000011 // Freq. Out to 32.768 Khz

#define Start_user_address_nvram    0x08
#define End_user_address_nvram      0x3f

char days_of_week[7][11]={"Lunes\0","Martes\0","Miércoles\0","Jueves\0","Viernes\0","Sábado\0","Domingo\0"};

byte ds1307_bin2bcd(byte binary_value);
byte ds1307_bcd2bin(byte bcd_value);

void ds1307_init(int val){

   byte seconds = 0;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x00);
   i2c_start();
   i2c_write(0xD1);
   seconds = ds1307_bcd2bin(i2c_read(0));
   i2c_stop();
   seconds &= 0x7F;

   delay_us(3);

   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x00);
   i2c_write(ds1307_bin2bcd(seconds));
   i2c_start();
   i2c_write(0xD0);
   i2c_write(0x07);
   i2c_write(val);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_set_date_time(byte day, byte mth, byte year, byte dow, byte hr, byte min, byte sec){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  sec &= 0x7F;
  hr &= 0x3F;

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);
  i2c_write(ds1307_bin2bcd(sec));
  i2c_write(ds1307_bin2bcd(min));
  i2c_write(ds1307_bin2bcd(hr));
  i2c_write(ds1307_bin2bcd(dow));
  i2c_write(ds1307_bin2bcd(day));
  i2c_write(ds1307_bin2bcd(mth));
  i2c_write(ds1307_bin2bcd(year));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_date(byte &day, byte &mth, byte &year, byte &dow){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);
  i2c_start();
  i2c_write(0xD1);
  dow  = ds1307_bcd2bin(i2c_read() & 0x7f);
  day  = ds1307_bcd2bin(i2c_read() & 0x3f);
  mth  = ds1307_bcd2bin(i2c_read() & 0x1f);
  year = ds1307_bcd2bin(i2c_read(0));
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_time(byte &hr, byte &min, byte &sec){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);
  i2c_start();
  i2c_write(0xD1);
  sec = ds1307_bcd2bin(i2c_read() & 0x7f);
  min = ds1307_bcd2bin(i2c_read() & 0x7f);
  hr  = ds1307_bcd2bin(i2c_read(0) & 0x3f);
  i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}


char ds1307_read_nvram_byte(char addr){

   char retval;

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);

   i2c_start();
   i2c_write(0xD1);
   retval = i2c_read(0);
   i2c_stop();

   return(retval);

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_write_nvram_byte(char addr, char value){

#ifndef USE_INTERRUPTS
   disable_interrupts(global);
#endif

   i2c_start();
   i2c_write(0xD0);
   i2c_write(addr);
   i2c_write(value);
   i2c_stop();

#ifndef USE_INTERRUPTS
   enable_interrupts(global);
#endif

}

void ds1307_get_day_of_week(char* ptr){

   byte lday;
   byte lmonth;
   byte lyr;
   byte ldow;
   ds1307_get_date(lday,lmonth,lyr,ldow);
   sprintf(ptr,"%s",days_of_week[ldow]);
}

///////////////////////////////////////////////////////////////////////////////

byte ds1307_bin2bcd(byte binary_value){

  byte temp;
  byte retval;

  temp = binary_value;
  retval = 0;
  while(1){
    if(temp >= 10){
      temp -= 10;
      retval += 0x10;
    }else{
      retval += temp;
      break;
    }
  }
  return(retval);
}

byte ds1307_bcd2bin(byte bcd_value){

  byte temp;

  temp = bcd_value;
  temp >>= 1;
  temp &= 0x78;
  return(temp + (temp >> 2) + (bcd_value & 0x0f));
}

///////////////////////////////////////////////////////////////////////////////


and the schematic
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 12:12 am     Reply with quote

Are you simulating this with Proteus?

You did see the PIC101 Sticky at the top of this sub-forum message list, yes?

http://www.ccsinfo.com/forum/viewtopic.php?t=47549

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Ttelmah



Joined: 11 Mar 2010
Posts: 19346

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 1:53 am     Reply with quote

The key thing here is number formats.

The clock chip used 'BCD'. Here the 4bit nibbles of a number each represent one digit.

So the clock represents months with 0x01 for the first month, counting up to 0x09 for the ninth, and then goes 0x10 for the tenth month. Now the 'reason', is that this is a very convenient format if you want (for instance), to feed the numbers to a LED display, where you can take each nibble, separate it out, and just display this as a number from 0 to 9. Problem is that 0x10, is the number 16, if treated as a normal number, so the months would count 1....9, 16,17,18 etc...

Same applies to the values the chip expects to receive when you set it.

This is where the two functions at the end of the driver you are using come in. bin2BCD, and bcd2bin. The latter, will take the number 0x10, and correctly turn it into the binary value 0b00001100, which would then display at '10' if output using printf. The former does the conversion the other way.

Use hex notation in your pre-programmed 'setting' values, so 'year=0x13', which will give the correct value to send to the chip.

When you retrieve the values, use bcd2bin, and then display the output this gives. So:
Code:

   ds1307_get_time(&hrs, &min, &sec); //remember these functions
   //want _pointers_.....
   ds1307_get_date(&day,&month,&year,&dow);
   hrs=bcd2bin(hrs);
   min=bcd2bin(min);
   sec=bcd2bin(sec);
   day=bcd2bin(day);
   month=bcd2bin(month);
   year=bcd2bin(year);
   //dow, never gets large enough to need conversion
   printf(lcd_putc,"\f %2u:%2u:%2u \n %2u-%2u-%2u %2s",hrs,min,sec,day,month,year,days_of_week[dow]);


Now, there is a problem when incrementing/decrementing numbers, that you need to increment/decrement the binary number, then convert this to BCD. You need to work out whether it is easier to just use binary numbers in your code, and convert these all to bcd as you send them to the chip, and back to binary as you read them, or keep the numbers in bcd, generate your own 'bcd_increment' and bcd_decrement functions, and just change them to binary to print. There are ways of doing this rather more elegantly, using a structure to hold the time values, and converting them all with a single routine. A bit of 'thought' needed.

Best Wishes
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 8:13 am     Reply with quote

Hi,

In addition to the BCD vs. Binary issue, there are a couple of other things you should consider. If you are using real, physical switches for data entry, you need to be mindful of 'switch bounce', or the likelihood that your switch will 'chatter' when pressed and produce multiple entries. The code that increments the day has a 50ms delay, which might have been an attempt to deal with switch bounce by the original author. You need to look this if you intend to actually build this clock. If not, Proteus probably won't care, which is a major flaw of simulation. I use the 'button' function to handle switch debouncing - it works well, and can be found here on the forum.

The second thing you should consider is making your code 'aware' of valid day, month, and year numbers, etc. and deal with that correctly before sending any data to the RTC chip. For example, 'minutes' are never more than 59, so you want to add this limit to your code. Here is a little code snippet that shows the button function, and value limiting for the minute variable.

Code:

if(button(Inc_BTN, 0, 50, 10, SW2, 1)){
                  TempMinute++;
                  if (TempMinute > 59)
                     TempMinute = 0;
}


I deal with all time/date variables in binary in my main application, and then convert them all to BCD in my RTC driver.

John
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Mon Feb 25, 2013 9:36 am     Reply with quote

You have SOUT connected to +5V

That is a good way to kill the chip. SOUT if not used should be unconnected. If you want to use it then it should connect to +5v via a pull up resistor.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
temtronic



Joined: 01 Jul 2010
Posts: 9164
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 12:31 pm     Reply with quote

Good catch on the SOUT miswiring !
I've never liked anyone's 'ISIS' schematics...no power connections,bypass caps,XTAL,Vee on LCD,etc....
Also, uChip recommends series resistors on any 'switch' input to port pins to reduce blowing up the chip with static 'zaps'.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 2:33 pm     Reply with quote

You need to wake up to the fact that Proteus simulation is a complete waste of both your time and everyone elses.

You set a #FUSES for LP.
The microchip data sheet shows LP is intended for 32kHz watch type crystals.
Then you set a 2MHz clock.
The oscillator probably won't start.

Do yourself a favour, use REAL hardware.

Then come back if (when) there's a problem.

I don't want to sound harsh, but you have to face up to reality.

Mike
andrefrejat



Joined: 24 Feb 2013
Posts: 3

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 5:06 pm     Reply with quote

Quote:
Are you simulating this with Proteus?

You did see the PIC101 Sticky at the top of this sub-forum message list, yes?

http://www.ccsinfo.com/forum/viewtopic.php?t=47549

-Ben

Ben, actually I did not see it, sorry about that.... The only thing i missed was the compiler version, pcw 4.038

Ttelmah, thanks! when i get to my computer i'm going to try giving more thought on the problem, i really disconsidered the BCD thing and didn't think it trough.

Quote:
The second thing you should consider is making your code 'aware' of valid day, month, and year numbers, etc. and deal with that correctly before sending any data to the RTC chip. For example, 'minutes' are never more than 59, so you want to add this limit to your code. Here is a little code snippet that shows the button function, and value limiting for the minute variable.

John, I'm not going to make a real model of this, the 50ms delay was simply something I forgot to erase on one of the modifications I did. I'm gonna try later to implant the limitation, thanks.

asmallri, I didn't know I shouldn't do that, i didn't really get what to do with this pin so I just put on +5V and didn't seem to get me problems on proteus so i left it there.....

Mike, I used Proteus because my professor asked me to, it's not a question if it's a waste or not, just had to use it. I don't really have the real hardware here, i'm just simulating it for a project. But thanks on the advices
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 5:15 pm     Reply with quote

Whilst you persist with Proteus, I'm out.

Nuff said.

Mike
andrefrejat



Joined: 24 Feb 2013
Posts: 3

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 6:14 pm     Reply with quote

Mike, just a quick question. Do you suggest any other simulator or simply test on the real thing?

Andre
temtronic



Joined: 01 Jul 2010
Posts: 9164
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Feb 25, 2013 7:15 pm     Reply with quote

I've got about 25+ years of using PICs, and started using microcomputers back in 1977.
Over the decades I've found out the ONLY proper,rock solid, REAL 'simulation' is to cut code, burn a chip and test in the REAL world.

NO 'simulator' is capable of emulating stuff like miswired PCB,bad etches, EMI,marginal power supplies,faulty grounds,no HF bypass caps onboard,'buzz' from those new 'energy efficient' CFLs and a host of other real world nightmares.

Chips these days are real cheap,protoboards are easy to come by and frankly you'll learn more in one day getting fingers burnt and smelling solder than a month of reading books.

Some here say the MPLAB simulator is good.I can't say as I only use real chips on real noards in the real world.Maybe I'm 'odd' but I still have wirewrapped PIC 'prototypes' in use after 24 years.

hth
jay
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Feb 26, 2013 4:59 am     Reply with quote

Temtronic has answered your question for me.

I do use MPLAB SIM.

1) Produces mostly believable results.
2) Allows you to step through code more quickly than when attached to the real thing.
3) Timings are sometimes an issue, quite often several machine cycles different to the real thing.
4) Is out of the same stable as the PICs, so fewer of the 3rd party issues.
5) It's no substitute for the real thing at the end of the day.

On the real thing you:-

a) Add diagnostic LEDs to give a visual indication of what's going on.
b) Hook the LED pins to a scope for other tests.
c) Connect the UART to a PC for commentary.

Mike


As an aside. You sometimes have to rock the boat.

I design switch mode power supplies for a living.
One of the myths in the trade is that toroidal chokes are near perfect from an EMI point of view.
(If wound as a neat single complete layer covering the whole surface.)
In practice they have winding capacitance which does resonate with the intended inductance.
At resonance you get a standing wave on the winding.
The phases of the currents are such that the whole thing behaves as a good dipole aerial!!
I was not very popular in the labs when I brought this to everyone's attention.


Last edited by Mike Walne on Tue Feb 26, 2013 11:20 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19346

View user's profile Send private message

PostPosted: Tue Feb 26, 2013 5:11 am     Reply with quote

You also have the other 'commonly forgotten' thing, that every wire on a board, connected to a semiconductor junction, can act as a receiver, and can also re-radiate normally odd harmonics only (because of the rectification). Delightful.....
On a different tack, everyone 'knows' semiconductor junctions are light sensitive, but then forgets that things like barometric pressure sensors, unless in an opaque casing with pipes attached, have an almost exposed semiconductor junction.

There are dozens of 'classic lovelies' waiting in the wings to catch you.

The key problem with 'simulators', is the same as in every field. Simulation, while good in many cases, is not 'reality'. Particularly with the PIC's, where the biggest problem commonly is the shear number of places where newer chips in particular 'differ' from their specified behaviour. I had 'great hopes' for Proteus some years ago, but it has been tempered with the increasing discovery of how badly it does get things wrong. Generally it takes longer to get the code working once in Proteus, then fix the problems this missed, than to do it with real hardware from the start.....

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 28, 2013 12:40 am     Reply with quote

As everyone has said, it's not our job on the CCS forum to fix Proteus
problems. But if you would just use Google to search for
Quote:
Proteus ds1307

or
Quote:
Proteus ds1307 debugger pullups

you would get some answers.

Don't ask us to find Proteus problems. Use Google.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Thu Feb 28, 2013 2:17 am     Reply with quote

Please ask your professor to comment here, giving us their justification for insisting on the use of Proteus by their students. I suspect the primary motivation is cost, on the somewhat misguided notion that software $£€ are somehow cheaper than hardware $£€.

I am serious: I want to know why students are being forced to use an inappropriate and inadequate "tool".

Proteus, apparently - I haven't used it personally - is useful for other projects. Its with PICs and the ICs they interface with, that it really falls down as the differences between its simulation and reality are often too far apart and cause a lot of additional work - just the sort of additional work simulation is supposed to eliminate! - as the simulation will work when real hardware doesn't and just as bad, the simulation will fail when real hardware would work fine.

RF Developer
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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