|
|
View previous topic :: View next topic |
Author |
Message |
andrefrejat
Joined: 24 Feb 2013 Posts: 3
|
ds1307 reading wrong |
Posted: Sun Feb 24, 2013 6:24 pm |
|
|
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: 1615 Location: Central Illinois, USA
|
|
Posted: Mon Feb 25, 2013 12:12 am |
|
|
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: 19537
|
|
Posted: Mon Feb 25, 2013 1:53 am |
|
|
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
|
|
Posted: Mon Feb 25, 2013 8:13 am |
|
|
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: 1635 Location: Perth, Australia
|
|
Posted: Mon Feb 25, 2013 9:36 am |
|
|
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: 9241 Location: Greensville,Ontario
|
|
Posted: Mon Feb 25, 2013 12:31 pm |
|
|
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
|
|
Posted: Mon Feb 25, 2013 2:33 pm |
|
|
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
|
|
Posted: Mon Feb 25, 2013 5:06 pm |
|
|
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
|
|
Posted: Mon Feb 25, 2013 5:15 pm |
|
|
Whilst you persist with Proteus, I'm out.
Nuff said.
Mike |
|
|
andrefrejat
Joined: 24 Feb 2013 Posts: 3
|
|
Posted: Mon Feb 25, 2013 6:14 pm |
|
|
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: 9241 Location: Greensville,Ontario
|
|
Posted: Mon Feb 25, 2013 7:15 pm |
|
|
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
|
|
Posted: Tue Feb 26, 2013 4:59 am |
|
|
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: 19537
|
|
Posted: Tue Feb 26, 2013 5:11 am |
|
|
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
|
|
Posted: Thu Feb 28, 2013 12:40 am |
|
|
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
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
|
|
Posted: Thu Feb 28, 2013 2:17 am |
|
|
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 |
|
|
|
|
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
|