|
|
View previous topic :: View next topic |
Author |
Message |
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
DS1307 interface |
Posted: Sat Apr 04, 2015 3:13 pm |
|
|
Dear all,
I am trying to work with my RTC DS1307 module and it does not work. The main program is this:
Code: | #include <program.h>
#define LCD_RS_PIN PIN_A3
#define LCD_RW_PIN PIN_A2
#define LCD_ENABLE_PIN PIN_A1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
#include <ds1307.C>
int count1 = 0;
//timeclock variables
BYTE sec;
BYTE min;
BYTE hrs;
BYTE day;
BYTE month;
BYTE yr;
BYTE dow;
#INT_EXT
void EXT_isr(void)
{
if (PIN_A4)
{
output_toggle(PIN_E2);
}
}
void main()
{
lcd_init();
lcd_putc("\fReady...\n");
enable_interrupts(INT_EXT);
ds1307_init();
delay_ms(1000);
ds1307_set_date_time(15,6,5,2,15,20,55);
enable_interrupts(GLOBAL);
printf("done");
while(TRUE)
{
delay_ms(1000);
ds1307_get_date(day,month,yr,dow);
ds1307_get_time(hrs,min,sec);
printf( "\f\%02d/\%02d/\%02d\r\n",day,month,yr);
printf( "\%02d:\%02d:\%02d", hrs,min,sec);
}
} |
and the driver is:
Code: | ////////////////////////////////////////////////////////////////////////////////
/// DS1307.C ///
/// Driver for Real Time Clock ///
/// ///
/// ds1307_init() - Enable oscillator without clearing the seconds register -///
/// used when PIC loses power and DS1307 run from 3V BAT ///
/// - Disable squarewave output ///
/// ///
/// ds1307_set_date_time(day,mth,year,dow,hour,min,sec) Set the date/time ///
/// ///
/// ds1307_get_date(day,mth,year,dow) Get the date ///
/// ///
/// ds1307_get_time(hr,min,sec) Get the time ///
/// ///
////////////////////////////////////////////////////////////////////////////////
#define RTC_SDA PIN_D7
#define RTC_SCL PIN_D6
#use i2c(master, sda=RTC_SDA, scl=RTC_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(0x80); // 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(0x80); // 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));
} |
now since I already have the MAX517 on pins C4 and C3 (hardware I2C) I used a software I2C for the RTC as can be seen on the RTC driver. But the LCD remains "Ready..." and on the hyperterminal nothing is being displayed. The module I am using is shown here:
http://www.instructables.com/id/Arduino-Shower-Monitor-2/
the module has built in 3k3 on I2C bus that's why I used a seperate i2c ports. |
|
|
huynhhai
Joined: 04 Apr 2015 Posts: 39
|
|
Posted: Sat Apr 04, 2015 9:06 pm |
|
|
You should use direct code to display lcd & read RTC no using interrupt & do it step by step, display any your info on lcd ok, then read RTC to display LCD, don't forgot enable internal oscillate of RTC, can you check it
Regards, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Apr 04, 2015 10:17 pm |
|
|
Quote: | #define LCD_RS_PIN PIN_A3
#define LCD_RW_PIN PIN_A2
#define LCD_ENABLE_PIN PIN_A1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#define RTC_SDA PIN_D7
#define RTC_SCL PIN_D6 |
You are using the same pins for the LCD and the ds1307.
Don't do that. |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Sun Apr 05, 2015 2:19 am |
|
|
Dear all, thanks for your replies. Actually i removed all the enable_interrupts including the global one and it worked perfectly even on the same max517 i2c bus line C3 and C4 pins. What could be the problem? |
|
|
huynhhai
Joined: 04 Apr 2015 Posts: 39
|
|
Posted: Sun Apr 05, 2015 11:58 am |
|
|
Maybe, your code at the programs interrupt no ok, therefore programs can not return to main programs ==> can not read RTC to display LCD |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Sun Apr 05, 2015 12:06 pm |
|
|
Is there any pattern or sequence where i should list the enable interrupts e.g. at the beginning of the main routine or after the initialization of the drivers? Or it does not make any difference? |
|
|
huynhhai
Joined: 04 Apr 2015 Posts: 39
|
|
Posted: Sun Apr 05, 2015 1:17 pm |
|
|
try to put this code look like below
Code: |
#include <program.h>
#include <lcd.c>
#include <ds1307.C>
#INT_EXT
void EXT_isr(void)
{
if (PIN_A4)
{
output_toggle(PIN_E2);
}
} |
you put interrupt code wrong position maybe interrupt no active, check it again |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 05, 2015 1:29 pm |
|
|
This won't work:
To read a pin, you must use the input() function. Example:
Code: |
if(input(PIN_A4))
{
output_toggle(PIN_E2);
}
|
|
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Mon Apr 06, 2015 12:50 am |
|
|
Ooops...yes you are right! I will update the code and try again. |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Mon Apr 06, 2015 3:16 am |
|
|
Dear All,
continue to working on the "strange" situation that I have on my code regaring the #INT statements! This is the code.
Code: | #include <program.h>
#include <MAX517.C>
#include <ds1307.C>
#define LCD_RS_PIN PIN_A3
#define LCD_RW_PIN PIN_A2
#define LCD_ENABLE_PIN PIN_A1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
//timeclock variables
BYTE sec;
BYTE min;
BYTE hrs;
BYTE day;
BYTE month;
BYTE yr;
BYTE dow;
void main()
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //104 ms overflow
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_RDA);
enable_interrupts(INT_TBE);
enable_interrupts(GLOBAL);
ds1307_init();
delay_ms(400);
lcd_init();
delay_ms(400);
while(true)
{
ds1307_get_date(day,month,yr,dow);
ds1307_get_time(hrs,min,sec);
lcd_gotoxy(0,0);
printf(lcd_putc, "Date: \%02d/\%02d/\%02d\r\n",day,month,yr);
lcd_gotoxy(0,1);
printf(lcd_putc, "Time: \%02d:\%02d:\%02d", hrs,min,sec);
}
} |
This code is working 100% but when I insert the following code just after the timeclock variables the program hangs:
Code: | #INT_TIMER1
void TIMER1_isr(void)
{
}
#INT_EXT
void EXT_isr(void)
{
}
#INT_RDA
void RDA_isr(void)
{
}
#INT_TBE
void TBE_isr(void)
{
}
|
I tried to put one statement at a time, and also change the place where i put this code, but it was in vain. Sorry but I need to use all the interrupts that's why I put them all. |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Mon Apr 06, 2015 3:18 am |
|
|
sorry forgot to mention, I am using PIC18F4520 with crystal 20MHz |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Mon Apr 06, 2015 3:44 am |
|
|
Maybe there is a char in the RX reg and it keeps on firing the INT_RDA, try reading the RX reg and try.
When you tried adding them one at a time you did disable the interrupts that
didn't had any handler.
Just suggestions.
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Mon Apr 06, 2015 4:21 am |
|
|
Of course it would.....
Alan has given the first potential part. An INT_RDA handler _must_ always read a character, or the code will hang forever if this triggers. However even if this doesn't trigger there is a second problem.
The second part is INT_TBE. This _must_ only be enabled, when you have characters to send. Look at how ex_stisr works. The interrupt is disabled in the handler, once the last character is sent. INT_TBE says 'I want a character to transmit'. Unless you transmit one, the interrupt _will_ trigger again instantly.
You can never enable INT_TBE, until you have data waiting to send. The handler needs to either load a character, or disable the interrupt, or it can never exit. |
|
|
huynhhai
Joined: 04 Apr 2015 Posts: 39
|
|
Posted: Tue Apr 07, 2015 12:54 am |
|
|
Are you forgot setup for priority interrupt? test one interrupt actived |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Tue Apr 07, 2015 1:08 am |
|
|
thanks for everyone. Now everything is sorted regarding this issue. |
|
|
|
|
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
|