ADGAN
Full Member level 5

Hi! The following shows a code that is written to display time in big fonts. The problem is with displaying hours. From morning to afternoon (12.00 AM) it works fine. But when displaying time after 12.00 AM, i.e. 1.00 PM(13.00), 2.00 PM (14.00)........ it displays as 26.00,27.00. I want to keep the clock running in 12hr mode. I did necessary adjustments for that. But I can't find what's the issue with this. I'm using 4 buttons to adjust time. I have use PIC18F45K22 and DS1307.
Thanks in advance.

Thanks in advance.

Code:
// LCD module connections
sbit LCD_RS at LATB2_bit;
sbit LCD_EN at LATB3_bit;
sbit LCD_D4 at LATB4_bit;
sbit LCD_D5 at LATB5_bit;
sbit LCD_D6 at LATB6_bit;
sbit LCD_D7 at LATB7_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections
unsigned char txt1[] = "Hello";
unsigned char txt2[] = "20";
unsigned char txt3[] = "AM";
unsigned char txt4[] = "PM";
unsigned char txt5[] = "Set Time & Date";
const char segments[8][8] = {{31,31,31,0,0,0,0,0}, // segmento 0
{0,0,0,0,0,31,31,31}, // segmento 1
{31,31,31,0,0,0,31,31}, // segmento 2
{28,30,31,31,31,31,30,28}, // segmento 3
{7,15,31,31,31,31,15,7}, // segmento 4
{0,0,0,0,0,0,0,0}, // segmento 5
{31,31,31,31,31,31,31,31}, // segmento 6 - FULL
{0,0,0,14,14,14,12,8} // segmento 7 - DOT
};
const char charPattern[11][6] = {{6,0,6,6,1,6}, // caracter 0
{0,6,' ',1,6,1}, // caracter 1
{0,2,3,4,1,1},
{2,2,3,1,1,3},
{6,1,1,' ',6,' '},
{6,2,0,1,1,3},
{4,2,0,4,1,3},
{0,0,3,' ',6,' '},
{4,2,3,4,1,3},
{4,2,3,' ',' ',6},
{' ',' ',' ',7,' ',' '}, // caracter 10 - DOT
};
void writeCGRAM() {
char i,j=0;
for (i=0; i<=7; i++) {
LCD_Cmd(64+i*8);
for (j = 0; j<=7; j++) {
LCD_Chr_Cp(segments[i][j]);
}
LCD_Cmd(_LCD_RETURN_HOME);
}
}
void ASCIItoDec(char *string, short size) {
short i=0;
for(i=0; i<=size; i++) {
if ( (string[i]==46) || (string[i]==0)) {
string[i]=10; // posicao do DOT no charPattern
} else if (string[i]!=32){
string[i] = string[i]-48;
}
}
}
void writeBigChar(short column, char character) {
short i = 0;
for (i=0; i <=6; i++) {
LCD_Chr(3, column, charPattern[character][0]);
LCD_Chr(3, column+1, charPattern[character][1]);
LCD_Chr(3, column+2, charPattern[character][2]);
LCD_Chr(4, column, charPattern[character][3]);
LCD_Chr(4, column+1, charPattern[character][4]);
LCD_Chr(4, column+2, charPattern[character][5]);
};
}
void writeBigFloat(short column, float floatNumber) {
char stringOutput[5];
short i=0;
int size;
size = sprintf(stringOutput,"%4.1f",floatNumber);
ASCIItoDec(stringOutput,size);
for (i=0; i<=size-1; i++) {
if(stringOutput[i]!=32) { // espao vazio da sada do sprintf
writeBigChar(column,stringOutput[i]);
if(stringOutput[i]==10) { // dot
column+=1;
} else {
column+=3;
}
}
}
}
/*******************************************************************************
* DS1307 Functions
*******************************************************************************/
// RTC Definitions
#define RTC_ADDR 0xD0
// Global date/time variables
unsigned char sec,min1,hr,week_day,day,mn,year;
/*******************************************************************************
* Read time from RTC DS1307
* input : pointer to variables where RTC data will be stored
* output: variables with RTC data
*******************************************************************************/
void Read_Time(unsigned char *sec, unsigned char *min, unsigned char *hr, unsigned char *week_day,
unsigned char *day, unsigned char *mn, unsigned char *year){
I2C1_Start(); // Issue start signal
I2C1_Wr(RTC_ADDR); // Address DS1307, see DS1307 datasheet
I2C1_Wr(0); // Start from address 0
I2C1_Repeated_Start(); // Issue repeated start signal
I2C1_Wr(RTC_ADDR + 1); // Address DS1307 for reading R/W=1
*sec = I2C1_Rd(1); // Read seconds byte
*min = I2C1_Rd(1); // Read minutes byte
*hr = I2C1_Rd(1); // Read hours byte
*week_day =I2C1_Rd(1); // Read week day byte
*day =I2C1_Rd(1); // Read day byte
*mn =I2C1_Rd(1); // Read month byte
*year =I2C1_Rd(0); // Read year byte
I2C1_Stop(); // Issue stop signal
}
/*******************************************************************************
* Write time to RTC DS1307
* input : variables with RTC data
*******************************************************************************/
void Write_Time(unsigned char minute, unsigned char hour ,unsigned char weekday,
unsigned char day,unsigned char month,unsigned char year){
unsigned char tmp1, tmp2;
unsigned char pm;
tmp1 = minute / 10; //Write tens of minute
tmp2 = minute % 10; //Write unit of minute
minute = tmp1 * 16 + tmp2; //Includes all value
tmp1 = hour / 10; //Write tens of hour
tmp2 = hour % 10; //Write unit of hour
hour = tmp1 * 16 + tmp2; //Includes all value
tmp1 = weekday / 10; //Write tens of weekday
tmp2 = weekday % 10; //Write unit of weekday
weekday = tmp1 *16 +tmp2; //Includes all value
tmp1 = day / 10; //Write tens of day
tmp2 = day % 10; //Write unit of day
day = tmp1 *16 +tmp2; //Includes all value
tmp1 = month / 10; //Write tens of month
tmp2 = month % 10; //Write unit of month
month = tmp1 *16 +tmp2; //Includes all value
tmp1 = year / 10; //Write tens of year
tmp2 = year % 10; //Write unit of year
year = tmp1 *16 +tmp2; //Includes all value
if (hour > 12)
{
hour -= 12;
pm = 0x20;
}
else pm = 0;
I2C1_Start(); // issue start signal
I2C1_Wr(RTC_ADDR); // address DS1307
I2C1_Wr(0); // start from word at address (REG0)
I2C1_Wr(0x80); // write $80 to REG0. (pause counter + 0 sec)
I2C1_Wr(minute); // write 0 to minutes word to (REG1)
I2C1_Wr(hour | pm | 0x40);// write 17 to hours word (12-hours mode)(REG2)
I2C1_Wr(weekday); // write 2 - Monday (REG3)
I2C1_Wr(day); // write 4 to date word (REG4)
I2C1_Wr(month); // write 5 (May) to month word (REG5)
I2C1_Wr(year); // write 01 to year word (REG6)
I2C1_Stop(); // issue stop signal
I2C1_Start(); // issue start signal
I2C1_Wr(RTC_ADDR); // address DS1307
I2C1_Wr(0); // start from word at address 0
I2C1_Wr(0); // write 0 to REG0 (enable counting + 0 sec)
I2C1_Stop(); // issue stop signal
}
//-------------------- Formats date and time---------------------
void Transform_Time(unsigned char *sec, unsigned char *min, unsigned char *hr, unsigned char *week_day,
unsigned char *day, unsigned char *mn,unsigned char *year)
{ //Converts variables in BCD format to Decimal
*sec = ((*sec & 0x70) >> 4)*10 + (*sec & 0x0F);
*min = ((*min & 0xF0) >> 4)*10 + (*min & 0x0F);
*hr = ((*hr & 0x30) >> 4)*10 + (*hr & 0x0F);
*week_day =(*week_day & 0x07);
*day = ((*day & 0xF0) >> 4)*10 + (*day & 0x0F);
*mn = ((*mn & 0x10) >> 4)*10 + (*mn & 0x0F);
*year = ((*year & 0xF0)>>4)*10+(*year & 0x0F);
}
/*******************************************************************************
* Show on the LCD display
* input : variables with RTC data
*******************************************************************************/
char *txt,*mny;
void Display_Time(unsigned char sec, unsigned char min, unsigned char hr, unsigned char week_day,
unsigned char day, unsigned char mn, unsigned char year)
{
switch(week_day)
{
case 1: txt="Sun"; break;
case 2: txt="Mon"; break;
case 3: txt="Tue"; break;
case 4: txt="Wed"; break;
case 5: txt="Thu"; break;
case 6: txt="Fri"; break;
case 7: txt="Sat"; break;
}
switch(mn)
{
case 1: mny="Jan"; break;
case 2: mny="Feb"; break;
case 3: mny="Mar"; break;
case 4: mny="Apr"; break;
case 5: mny="May"; break;
case 6: mny="Jun"; break;
case 7: mny="Jul"; break;
case 8: mny="Aug"; break;
case 9: mny="Sep"; break;
case 10: mny="Oct"; break;
case 11: mny="Nov"; break;
case 12: mny="Dec"; break;
}
Lcd_Out(1,6,txt1); //Display Asia Timber
Lcd_Out(2,4,txt); //Display the current day
Lcd_Chr(2, 8, (day / 10) + 48); //Print tens digit of day variable
Lcd_Chr(2, 9, (day % 10) + 48); //Print ones digit of day variable
// Lcd_Chr_CP('/'); //Print '/' character on cursor position
Lcd_Out(2, 11,mny);
Lcd_Out(2,15,txt2);
// Lcd_Chr(2, 14, (mn / 10) + 48); //Print tens digit of month variable
// Lcd_Chr(2,15, (mn % 10) + 48); //Print oness digit of month variable
// Lcd_Chr_CP('/'); //Print '/' character on cursor position
Lcd_Chr(2,17, (year / 10) + 48); //Print tenss digit of year variable
Lcd_Chr(2,18, (year % 10) + 48); //Print oness digit of year variable
Lcd_Chr(4,17, (sec / 10) + 48); //Print tenss digit of seconds variable
Lcd_Chr(4,18, (sec % 10) + 48); //Print oness digit of seconds variable
writeCGRAM();
writeBigChar(3, hr/10);
writeBigChar(6, hr%10);
writeBigChar(11, min/10);
writeBigChar(14, min%10);
if(hr & 0x20 == 0x20)Lcd_out(3,17,txt3);
else Lcd_out(3,17,txt4);
}
//-------------------Display Time in Set mode--------------------
char minute1,hour1,weekday1,month1;
char minute,hour,weekday,day1,month,year1;
void Display_Time_SetMode()
{
Lcd_Out(1,4,txt5);
switch(weekday1)
{
case 1: txt="Mon"; break; // Monday;
case 2: txt="Tue"; break; // Tuesday;
case 3: txt="Wed"; break; // Wednesday;
case 4: txt="Thu"; break; // Thursday;
case 5: txt="Fri"; break; // Friday;
case 6: txt="Sat"; break; // Saturday;
case 7: txt="Sun"; break; // Sunday;
}
LCD_Out(3, 4,txt);
Lcd_Chr(3, 8, (day1 / 10) + 48); // Print tens digit of day variable
Lcd_Chr(3, 9, (day1 % 10) + 48); // Print oness digit of day variable
Lcd_Chr_CP('/');
Lcd_chr(3,11, (month1 / 10) + 48); // Print tens digit of month variable
Lcd_chr(3,12, (month1 % 10) + 48); // Print oness digit of month variable
Lcd_Chr_CP('/');
Lcd_out(3,14,txt2);
Lcd_Chr(3,16, (year1 / 10) + 48); // Print tens digit of year variable
Lcd_Chr(3,17, (year1 % 10) + 48); // Print oness digit of year variable
Lcd_Chr(4, 7, (hour1 / 10) + 48); // Print tens digit of hour variable
Lcd_Chr(4, 8, (hour1 % 10) + 48); // Print oness digit of hour variable
Lcd_Chr(4, 9,':');
Lcd_Chr(4, 10, (minute1 / 10) + 48); // Print tens digit of minute variable
Lcd_Chr(4, 11, (minute1 % 10) + 48); // Print oness digit of minute variable
Lcd_Chr(4, 12,':');
Lcd_Chr(4, 13, (0 / 10) + 48);
Lcd_Chr(4, 14, (0 % 10) + 48);
}
char SPos;
//----------------------Move cursor routine----------------------
char index;
void movecursor()
{
char i,moveto;
if(SPos==0)
lcd_cmd(_lcd_third_row); // set weekday;
if(SPos==1)
lcd_cmd(_lcd_third_row); // set day;
if(SPos==2)
lcd_cmd(_lcd_third_row); // set month;
if(SPos==3)
lcd_cmd(_lcd_third_row); // set year;
if(SPos==4)
lcd_cmd(_lcd_fourth_row); // set hours;
if(SPos==5)
lcd_cmd(_lcd_fourth_row); // set minutes;
moveto = 2;
switch(index)
{
case 0: moveto = 5;break;
case 1: moveto = 8;break;
case 2: moveto =11;break;
case 3: moveto =16;break;
case 4: moveto = 7;break;
case 5: moveto = 10;break;
}
for(i=1; i<= moveto; i++)
lcd_cmd(_lcd_move_cursor_right);
}
//------------Start Buttons routine--------------;
char setuptime=0;
void Press_Switch()
{
if(setuptime)
{
if(Button(&porta,2,1,0)) // If buttons at port a2 is pressed
{
delay_ms(200);
SPos++;
if(SPos>5)
SPos=0;
index++;
if(index > 5)
index=0;
movecursor();
}
//-----------------------------case mode to set all values---------------------
switch(SPos)
{
case 0: if(button(&porta,0,1,0)) // If buttons at port c0 is pressed
{
Delay_ms(200);
weekday1++;
if(weekday1 > 7)
weekday1=1;
Display_Time_SetMode();
index=0;
movecursor();
}
if(button(&porta,1,1,0)) // If buttons at port c1 is pressed
{
Delay_ms(200);
weekday1--;
if(weekday1 < 1)
weekday1=7;
Display_Time_SetMode();
index=0;
movecursor();
}
break;
case 1: if(button(&porta,0,1,0)) // If buttons at port c0 is pressed
{
Delay_ms(200);
day1++;
if(day1 > 31)
day1 = 1;
Display_Time_SetMode();
index=1;
movecursor();
}
if(button(&porta,1,1,0)) // If buttons at port c1 is pressed
{
Delay_ms(200);
day1--;
if(day1 < 1)
day1 = 31;
Display_Time_SetMode();
index=1;
movecursor();
}
break;
case 2: if(button(&porta,0,1,0)) // If buttons at port c0 is pressed
{
Delay_ms(200);
month1++;
if(month1 > 12)
month1 = 1;
Display_Time_SetMode();
index=2;
movecursor();
}
if(button(&porta,1,1,0)) // If buttons at port c1 is pressed
{
Delay_ms(200);
month1--;
if(month1 < 1)
month1 = 12;
Display_Time_SetMode();
index=2;
movecursor();
}
break;
case 3: if(button(&porta,0,1,0)) // If buttons at port c0 is pressed
{
Delay_ms(200);
year1++;
if(year1 > 99)
year1 = 1;
Display_Time_SetMode();
index=3;
movecursor();
}
if(button(&porta,1,1,0)) // If buttons at port c1 is pressed
{
Delay_ms(200);
year1--;
if(year1 < 1)
year1 = 99;
Display_Time_SetMode();
index=3;
movecursor();
}
break;
case 4: if(button(&porta,0,1,0)) // If buttons at port c0 is pressed
{
Delay_ms(200);
hour1++;
if(hour1 > 23)
hour1 = 0;
Display_Time_SetMode();
index=4;
movecursor();
}
if(button(&porta,1,1,0)) // If buttons at port c1 is pressed
{
Delay_ms(200);
hour1--;
if(hour1 > 23)
hour1 = 0;
Display_Time_SetMode();
index=4;
movecursor();
}
break;
case 5: if(button(&porta,0,1,0)) // If buttons at port c0 is pressed
{
Delay_ms(200);
minute1++;
if(minute1 > 59)
minute1 = 0;
Display_Time_SetMode();
index=5;
movecursor();
}
if(button(&porta,1,1,0)) // If buttons at port c1 is pressed
{
Delay_ms(200);
minute1--;
if(minute1 > 59)
minute1 = 0;
Display_Time_SetMode();
index=5;
movecursor();
}
break;
} // end "if is in switch mode"
} // end "if is in setup"
if(button(&porta,3,1,0)) // If buttons at port a3 is pressed
{
Delay_ms(200);
setuptime = !setuptime;
if(SetupTime)
{
lcd_cmd(_lcd_clear);
lcd_cmd(_lcd_blink_cursor_on);
weekday1=week_day;
hour1=hr;
minute1=min1;
day1=day;
month1=mn;
year1=year;
Display_Time_SetMode();
SPos=0;
index=0;
movecursor();
}
else
{
Lcd_Cmd(_Lcd_clear);
lcd_cmd(_lcd_cursor_off);
weekday=weekday1;
hour=hour1;
minute=minute1;
day=day1;
month=month1;
year=year1;
Write_time(minute,hour,weekday,day,month,year);
}
}
}
//----------------------End Buttons Routine-------------------
bit PIR_input;
unsigned int on_time,off_time;
#define RELAY1 F2
#define RELAY2 F3
#define RELAY3 F4
#define RELAY4 F5
#define POWER_LED F0
#define LCD F1
/*******************************************************************************
* Main function
*******************************************************************************/
void main()
{
ANSELA = 0; // Configure PORTA pins as digital
ANSELB = 0; // Configure PORTB pins as digital
ANSELC = 0; // Configure PORTC pins as digital
ANSELE = 0; // Configure PORTE pins as digital
SLRCON = 0; // Configure all PORTS at the standard Slew
ADCON1 |= 0x0F; // Configure AN pins as digital
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0; //
TRISA = 0xFF; //PortA configured as input for push buttons
PORTA = 0;
LATA = 0;
TRISB = 0; //PortB confgured as output
PORTB = 0; //Reset PORTB
LATB = 0;
TRISC = 0x18; //T1CKI, SCL, SDA and RX set as input
PORTC = 0; //Reset PORTC
LATC = 0;
TRISD = 0; //PORTD pins are outputs for Relays
PORTD = 0;
LATD = 0;
TRISE = 0x01; //PORTE pins
Lcd_Init(); //Initialize the LCD
Delay_ms(100); // Delay 100ms
Lcd_Cmd(_LCD_CURSOR_OFF);//Cursor off
Lcd_Cmd(_LCD_CLEAR); //Clear the LCD
I2C1_Init(100000); //Initialize at 100KHz
Delay_ms (100); //Delay 100ms
on_time = 0x12;
off_time = 0x06;
PIR_input = 0;
!setuptime=1;
index=0;
SPos=0;
while(1){
Read_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // read time from RTC(DS1307)
Transform_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // Transform time
Press_Switch(); // Check buttons
if(!setuptime)
{
Display_Time(sec, min1, hr, week_day, day, mn, year);
}
Delay_ms(100);
if(hr>=on_time || hr<off_time){
LATD.RELAY1 = 1;
LATD.RELAY2 = 1;
LATD.RELAY3 = 1;
LATD.RELAY4 = 1;
}
else{
LATD.RELAY1 = 0;
LATD.RELAY2 = 0;
LATD.RELAY3 = 0;
LATD.RELAY4 = 0;
}
}
}