|
|
View previous topic :: View next topic |
Author |
Message |
akay
Joined: 29 Sep 2020 Posts: 17
|
ds1307 bcd to decimal why add 48? |
Posted: Fri Nov 06, 2020 6:46 am |
|
|
hello everyone
The code I have shown below is the part of the conversion from bcd to decimal to ds1307..
Why did we add 48 after converting bcd to binary code?
time[12] = second % 10 + 48;
pls explain me?
for example: second is bcd 48
48 binary: 0011 0000
0011 0000 >> 4
0000 0011 : 03
3x10= 30
0011 0000 & 0000 1111
0000 0000
30+0 =30
and our second : decimal = 30
so why we are add to 48?
Code: | char time[] = "TIME: : : ";
char calendar[] = "DATE: / /20 ";
unsigned int8 second, minute, hour, date, month, year, day;
void ds1307_display(){
// Convert BCD to decimal
second = (second >> 4) * 10 + (second & 0x0F);
minute = (minute >> 4) * 10 + (minute & 0x0F);
hour = (hour >> 4) * 10 + (hour & 0x0F);
date = (date >> 4) * 10 + (date & 0x0F);
month = (month >> 4) * 10 + (month & 0x0F);
year = (year >> 4) * 10 + (year & 0x0F);
// End conversion
time[12] = second % 10 + 48;
time[11] = second / 10 + 48;
time[9] = minute % 10 + 48;
time[8] = minute / 10 + 48;
time[6] = hour % 10 + 48;
time[5] = hour / 10 + 48;
calendar[14] = year % 10 + 48;
calendar[13] = year / 10 + 48;
calendar[9] = month % 10 + 48;
calendar[8] = month / 10 + 48;
calendar[6] = date % 10 + 48;
calendar[5] = date / 10 + 48;
lcd_gotoxy(1, 1); // Go to column 1 row 1
printf(lcd_putc, time); // Display time
lcd_gotoxy(1, 2); // Go to column 1 row 2
printf(lcd_putc, calendar); // Display calendar |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Fri Nov 06, 2020 8:09 am |
|
|
As I pointed out to another poster in a recent thread, it is critical to
understand that the ASCII digit '0', is not the 'number' 0.
Conversion between the two involves an offset (in decimal), of '48'.
The table PCM_Programmer points you to, shows the numeric values for
characters, and gives this offset.... |
|
|
akay
Joined: 29 Sep 2020 Posts: 17
|
|
Posted: Fri Nov 06, 2020 4:57 pm |
|
|
i know this is not related in this topic, but there is an issue i cannot solve..
when i push "asagi" (enter to switch menu) the numbers are mixed up and the program freezes...
it works normally when there is no menu(switch case menu) ..
i think there is an mistake in the transition from decimal to bcd..
Code: | #define LCD_ENABLE_PIN PIN_D0 ////
#define LCD_RS_PIN PIN_D2 ////
#define LCD_RW_PIN PIN_D1 ////
#define LCD_DATA4 PIN_D4 ////
#define LCD_DATA5 PIN_D5 ////
#define LCD_DATA6 PIN_D6 ////
#define LCD_DATA7 PIN_D7 ////
#include <16F877a.h>
#device adc=10 //adc yi 10 bit olarak kullandik YANI 0-5V ARASINI 2uzeri10 parcaya boler 2 uzeri 10 = 1023 olur 5V/1023=0,00488758553V
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NODEBUG
#define use_portd_lcd TRUE
#use delay(clock = 8000000)
#use i2c(master, sda=PIN_C4, scl=PIN_C3)
#include <lcd.c>
int8 menu=0, menu_say=0, set_m=0;
#define YUKARI PIN_C2
#define ASAGI PIN_C5
char zaman[] = "saat: : : ";
char takvim[] = "tarih: / / ";
unsigned int8 saniye, dakika, saat, gun, ay, yil, haftaningunu;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ana_ekran()
{
saniye = (saniye >> 4) * 10 + (saniye & 0x0F);
dakika = (dakika >> 4) * 10 + (dakika & 0x0F);
saat = (saat >> 4) * 10 + (saat & 0x0F);
gun = (gun >> 4) * 10 + (gun & 0x0F);
ay = (ay >> 4) * 10 + (ay & 0x0F);
yil = (yil >> 4) * 10 + (yil & 0x0F);
// End conversion
zaman[12] = saniye % 10 + 48;
zaman[11] = saniye / 10 + 48;
zaman[9] = dakika % 10 + 48;
zaman[8] = dakika / 10 + 48;
zaman[6] = saat % 10 + 48;
zaman[5] = saat / 10 + 48;
takvim[13] = yil % 10 + 48;
takvim[12] = yil / 10 + 48;
takvim[10] = ay % 10 + 48;
takvim[9] = ay / 10 + 48;
takvim[7] = gun % 10 + 48;
takvim[6] = gun / 10 + 48;
lcd_gotoxy(1,1); // Go to column 1 row 1
printf(lcd_putc,zaman); // Display time
lcd_gotoxy(1,2); // Go to column 1 row 2
printf(lcd_putc,takvim);
}
///////////////////////////////////////////////////////////////////////////////
void ds1307_veriyaz(unsigned int8 adres, datalar)
{
i2c_start(); // Start I2C protocol
i2c_write(0xD0); // DS1307 address
i2c_write(adres); // Send register address
i2c_write(datalar); // Write data to the selected register
i2c_stop(); // Stop I2C protocol
}
void ds1307_okuma()
{
i2c_start(); // Start I2C
i2c_write(0xD0); // DS1307 address
i2c_write(0x00); // Send register address
i2c_start(); // Restart I2C
i2c_write(0xD1); // Initialize data read
saniye =i2c_read(1); // Read seconds from register 0
dakika =i2c_read(1); // Read minuts from register 1
saat = i2c_read(1); // Read hour from register 2
haftaningunu = i2c_read(1); // Read day from register 3
gun = i2c_read(1); // Read date from register 4
ay = i2c_read(1); // Read month from register 5
yil = i2c_read(0); // Read year from register 6
i2c_stop(); // Stop I2C
}
////////////////////////////////////////////////////////////////////////////////
void main(){
lcd_init();
lcd_putc('\f');
while(TRUE)
{
ds1307_okuma(); // Read data from DS1307 RTCC
delay_ms(20);
IF ((menu==0))
{ ana_ekran (); }
if (input(ASAGI)&&(menu==0)) // ENTER A BASILIRSA VE MENU=0 ISE
{
delay_ms(300);
printf(lcd_putc,"\f");
menu=1; // MENU LOJIK 1 OLUR
menu_say=0; // MENU_SAY LOJIK 0 OLUR // M_SN LOJIK 0 OLUR
}
if (menu>0) // MENU 0'DAN BUYUK VE SET_M LOJIK 0 ISE
{
switch(menu_say)
{
case 0:
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"Software&Circuit");
lcd_gotoxy(1,2);
printf(lcd_putc,"Akay AYDIN");//EGER ENTER'A BASILIR VE M_SN 0 DAN BUYUKSE set menüye git
break;
case 1:
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"Dakika AYARI");
lcd_gotoxy(1,2);
printf(lcd_putc,"%02u", dakika);
if(input(YUKARI)) dakika++;
if(dakika > 59)
dakika = 0;
break;
case 2:
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"Saat AYARI");
lcd_gotoxy(1, 2);
printf(lcd_putc,"%02u", saat);
if(input(YUKARI)) saat++;
if(saat > 23)
saat = 0;
break;
case 3:
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"Gun AYARI");
lcd_gotoxy(1,2);
printf(lcd_putc,"%02u", gun);
if(input(YUKARI)) gun++;
if(gun > 31)
gun = 1;
break;
case 4:
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"Ay AYARI");
lcd_gotoxy(1,2);
printf(lcd_putc,"%02u", ay);
if(input(YUKARI)) ay++;
if(ay > 12)
ay = 1;
break;
case 5:
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"YIL AYARI");
lcd_gotoxy(1,2);
printf(lcd_putc,"%02u", yil);
if(input(YUKARI)) yil++;
if(yil > 99)
yil = 20;
BREAK;
case 6:
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"Gun AYARI");
lcd_gotoxy(1,2);
printf(lcd_putc,"akay");
if(input(YUKARI)) haftaningunu++;
if(haftaningunu > 6)
haftaningunu = 0;
BREAK;
CASE 7:
printf(lcd_putc,"\f");
DELAY_MS(20);
menu=0;
}
if(input(ASAGI)&&(menu_say<8)) //EGER ASAGI TUSUNA BASILIR VE MENU_SAY 4'DEN KUCUK USE
{
DELAY_MS(25);
menu_say=menu_say+1;
if(menu_say==8)
ana_ekran();
DELAY_MS(20);
}
IF(MENU==1){
// Convert decimal to BCD
dakika = ((dakika / 10) << 4) + (dakika % 10);
saat = ((saat / 10) << 4) + (saat % 10);
gun = ((gun / 10) << 4) + (gun % 10);
ay = ((ay / 10) << 4) + (ay % 10);
yil = ((yil / 10) << 4) + (yil % 10);
// End conversion
// Write minute value to DS1307
ds1307_veriyaz(1, dakika);
ds1307_veriyaz(2, saat);
ds1307_veriyaz(4, gun);
ds1307_veriyaz(5, ay);
ds1307_veriyaz(6, yil);
ds1307_veriyaz(0, 0); //Reset seconds and start oscillator
delay_ms(200);
}
}
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sat Nov 07, 2020 2:56 am |
|
|
Learn to actually indent your code so the indentation reflects what is actually happening. Then 'think'.
Code: |
#define LCD_ENABLE_PIN PIN_D0 ////
#define LCD_RS_PIN PIN_D2 ////
#define LCD_RW_PIN PIN_D1 ////
#define LCD_DATA4 PIN_D4 ////
#define LCD_DATA5 PIN_D5 ////
#define LCD_DATA6 PIN_D6 ////
#define LCD_DATA7 PIN_D7 ////
#include <16F877a.h>
#device adc=10 //adc yi 10 bit olarak kullandik YANI 0-5V ARASINI 2uzeri10 parcaya boler 2 uzeri 10 = 1023 olur 5V/1023=0,00488758553V
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NODEBUG
#define use_portd_lcd TRUE
#use delay(clock = 8000000)
#use i2c(master, sda=PIN_C4, scl=PIN_C3)
#include <lcd.c>
int8 menu=0, menu_say=0, set_m=0;
#define YUKARI PIN_C2
#define ASAGI PIN_C5
char zaman[] = "saat: : : ";
char takvim[] = "tarih: / / ";
unsigned INT8 saniye, dakika, saat, gun, ay, yil, haftaningunu;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ana_ekran()
{
saniye = (saniye >> 4) * 10 + (saniye&0x0F);
dakika = (dakika >> 4) * 10 + (dakika&0x0F);
saat = (saat >> 4) * 10 + (saat&0x0F);
gun = (gun >> 4) * 10 + (gun&0x0F);
ay = (ay >> 4) * 10 + (ay & 0x0F);
yil = (yil >> 4) * 10 + (yil&0x0F);
// End conversion
zaman[12] = saniye % 10 + 48;
zaman[11] = saniye / 10 + 48;
zaman[9] = dakika % 10 + 48;
zaman[8] = dakika / 10 + 48;
zaman[6] = saat % 10 + 48;
zaman[5] = saat / 10 + 48;
takvim[13] = yil % 10 + 48;
takvim[12] = yil / 10 + 48;
takvim[10] = ay % 10 + 48;
takvim[9] = ay / 10 + 48;
takvim[7] = gun % 10 + 48;
takvim[6] = gun / 10 + 48;
lcd_gotoxy(1,1); // Go to column 1 row 1
printf (lcd_putc, zaman); // Display time
lcd_gotoxy (1, 2); // Go to column 1 row 2
printf (lcd_putc, takvim);
}
///////////////////////////////////////////////////////////////////////////////
void ds1307_veriyaz(UNSIGNED int8 adres, datalar)
{
i2c_start (); // Start I2C protocol
i2c_write (0xD0); // DS1307 address
i2c_write (adres); // Send REGISTER address
i2c_write (datalar); // Write data to the selected REGISTER
i2c_stop (); // Stop I2C protocol
}
void ds1307_okuma()
{
i2c_start (); // Start I2C
i2c_write (0xD0); // DS1307 address
i2c_write (0x00); // Send REGISTER address
i2c_start (); // Restart I2C
i2c_write (0xD1); // Initialize data read
saniye = i2c_read (1); // Read seconds from REGISTER 0
dakika = i2c_read (1); // Read minuts from REGISTER 1
saat = i2c_read (1); // Read hour from REGISTER 2
haftaningunu = i2c_read (1); // Read day from REGISTER 3
gun = i2c_read (1); // Read date from REGISTER 4
ay = i2c_read (1); // Read month from REGISTER 5
yil = i2c_read (0); // Read year from REGISTER 6
i2c_stop (); // Stop I2C
}
////////////////////////////////////////////////////////////////////////////////
void main()
{
lcd_init ();
lcd_putc ('\f') ;
WHILE (TRUE)
{
ds1307_okuma (); // Read data from DS1307 RTCC
delay_ms (20) ;
IF ((menu == 0))
{ ana_ekran (); }
IF (input(ASAGI)&&(menu==0)) // ENTER A BASILIRSA VE MENU=0 ISE
{
delay_ms (300) ;
printf (lcd_putc, "\f") ;
menu = 1; // MENU LOJIK 1 OLUR
menu_say = 0; // MENU_SAY LOJIK 0 OLUR // M_SN LOJIK 0 OLUR
}
IF (menu > 0) // MENU 0'DAN BUYUK VE SET_M LOJIK 0 ISE
{
SWITCH (menu_say)
{
CASE 0:
printf (lcd_putc, "\f") ;
lcd_gotoxy (1, 1) ;
printf (lcd_putc, "Software&Circuit") ;
lcd_gotoxy (1, 2) ;
printf (lcd_putc, "Akay AYDIN"); //EGER ENTER'A BASILIR VE M_SN 0 DAN BUYUKSE set menüye git
BREAK;
CASE 1:
printf (lcd_putc, "\f") ;
lcd_gotoxy (1, 1) ;
printf (lcd_putc, "Dakika AYARI") ;
lcd_gotoxy (1, 2) ;
printf (lcd_putc, " % 02u", dakika);
IF (input (YUKARI)) dakika++;
IF (dakika > 59)
dakika = 0;
BREAK;
CASE 2:
printf (lcd_putc, "\f") ;
lcd_gotoxy (1, 1) ;
printf (lcd_putc, "Saat AYARI") ;
lcd_gotoxy (1, 2);
printf (lcd_putc, " % 02u", saat);
IF (input (YUKARI)) saat++;
IF (saat > 23)
saat = 0;
BREAK;
CASE 3:
printf (lcd_putc, "\f") ;
lcd_gotoxy (1, 1) ;
printf (lcd_putc, "Gun AYARI") ;
lcd_gotoxy (1, 2) ;
printf (lcd_putc, " % 02u", gun);
IF (input (YUKARI)) gun++;
IF (gun > 31)
gun = 1;
BREAK;
CASE 4:
printf (lcd_putc, "\f") ;
lcd_gotoxy (1, 1) ;
printf (lcd_putc, "Ay AYARI") ;
lcd_gotoxy (1, 2) ;
printf (lcd_putc, " % 02u", ay);
IF (input (YUKARI)) ay++;
IF (ay > 12)
ay = 1;
BREAK;
CASE 5:
printf (lcd_putc, "\f") ;
lcd_gotoxy (1, 1) ;
printf (lcd_putc, "YIL AYARI") ;
lcd_gotoxy (1, 2) ;
printf (lcd_putc, " % 02u", yil);
IF (input (YUKARI)) yil++;
IF (yil > 99)
yil = 20;
BREAK;
CASE 6:
printf (lcd_putc, "\f") ;
lcd_gotoxy (1, 1) ;
printf (lcd_putc, "Gun AYARI") ;
lcd_gotoxy (1, 2) ;
printf (lcd_putc, "akay") ;
IF (input (YUKARI)) haftaningunu++;
IF (haftaningunu > 6)
haftaningunu = 0;
BREAK;
CASE 7:
printf (lcd_putc, "\f") ;
DELAY_MS (20) ;
menu = 0;
}
IF (input (ASAGI)&& (menu_say < 8)) //EGER ASAGI TUSUNA BASILIR VE MENU_SAY 4'DEN KUCUK USE
{
DELAY_MS (25) ;
menu_say = menu_say + 1;
IF (menu_say == 8)
ana_ekran () ;
DELAY_MS (20) ;
}
IF (MENU == 1)
{
// Convert decimal to BCD
dakika = ( (dakika / 10) << 4) + (dakika % 10);
saat = ( (saat / 10) << 4) + (saat % 10);
gun = ( (gun / 10) << 4) + (gun % 10);
ay = ( (ay / 10) << 4) + (ay % 10);
yil = ( (yil / 10) << 4) + (yil % 10);
// End conversion
// Write minute value to DS1307
ds1307_veriyaz (1, dakika);
ds1307_veriyaz (2, saat);
ds1307_veriyaz (4, gun);
ds1307_veriyaz (5, ay);
ds1307_veriyaz (6, yil);
ds1307_veriyaz (0, 0); //Reset seconds and start oscillator
delay_ms (200) ;
}
}
}
}
|
The big problem is that you set 'menu' to 1 the first time ASAGI is
pushed. It goes through the dakika setting, and then sets the clock chip.
The values used for all the other variables will be random numbers
depending on what the variables just happen to have in them at boot.
You then go through all the other settings, and the clock doesn't get
updated again. So when you get to case 8, and display the value,
you probably have garbage.....
The actual logic of your code is flawed. |
|
|
akay
Joined: 29 Sep 2020 Posts: 17
|
|
Posted: Sat Nov 07, 2020 5:14 am |
|
|
thank u your valuable message..
so what can i do for fix this code?
could you pls help me to fix? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sat Nov 07, 2020 12:43 pm |
|
|
That's down to you writing your program correctly.
You need to input all the time/date fields, and write to the chip when all are
finished, not just after the first one. |
|
|
|
|
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
|