MikroPascal.
The goal is set the date and time trough rs232 Serial interface on
PCF8583 then display it on LCD.
The trouble is that when I try to set up a date on 2009, the result
after reading is 2001, on 2008 the reading is 2000 but on 2007 the
reading is 2003.
Someone could give me an idea about that, and how does it happen?
Thanks in advance
Gianluca
Code: Select all
type
TTime = record
year, month, day, hours, minutes, seconds : byte;
end;
var sec, min1, hr, day, mn, year : byte;
tnum, txt : array[6] of byte;
var TimeToWrite : TTime;
byteReceived, receivedOK : byte;
implementation
procedure SetTimeByRs232();
begin
TimeToWrite.year := 0;
TimeToWrite.month := 0;
TimeToWrite.day := 0;
TimeToWrite.hours := 0;
TimeToWrite.minutes := 0;
TimeToWrite.seconds := 0;
Uart1_Init(9600);
receivedOK := 0;
while (receivedOK = 0) do
begin
Uart1_Write_Text('Please send date in DD/MM/YY format');
Uart1_Write_Char(13);
Uart1_Write_Char(10);
receivedOK := 1;
Delay_ms(100);
while(Uart1_Data_Ready() = 1) do // clear received junk
Uart1_Read_Char();
while Uart1_Data_Ready() = 0 do nop; // day
byteReceived := Uart1_Read_Char-48; // char to num
TimeToWrite.day := byteReceived*10;
while Uart1_Data_Ready() = 0 do nop;
byteReceived := Uart1_Read_Char-48;
TimeToWrite.day := TimeToWrite.day + byteReceived;
while Uart1_Data_Ready() = 0 do nop;
if ( Uart1_Read_Char() <> '/') then receivedOK := 0; // receive "/"
while Uart1_Data_Ready() = 0 do nop; // month
byteReceived := Uart1_Read_Char-48;
TimeToWrite.month := byteReceived*10;
while Uart1_Data_Ready() = 0 do nop;
byteReceived := Uart1_Read_Char-48;
TimeToWrite.month := TimeToWrite.month + byteReceived;
while Uart1_Data_Ready() = 0 do nop;
if ( Uart1_Read_Char() <> '/') then receivedOK := 0; // receive "/"
while Uart1_Data_Ready() = 0 do nop; // year
byteReceived := Uart1_Read_Char-48;
TimeToWrite.year := byteReceived*10;
while Uart1_Data_Ready() = 0 do nop;
byteReceived := Uart1_Read_Char-48;
TimeToWrite.year := TimeToWrite.year + byteReceived;
Uart1_Write_Text('Please send time in HH:MM:SS 24h format');
Uart1_Write_Char(13);
Uart1_Write_Char(10);
while Uart1_Data_Ready() = 0 do nop; // hours
byteReceived := Uart1_Read_Char-48; // char to num
TimeToWrite.hours := byteReceived*10;
while Uart1_Data_Ready() = 0 do nop;
byteReceived := Uart1_Read_Char-48;
TimeToWrite.hours := TimeToWrite.hours + byteReceived;
while Uart1_Data_Ready() = 0 do nop;
if ( Uart1_Read_Char() <> ':') then receivedOK := 0; // receive "/"
while Uart1_Data_Ready() = 0 do nop; // minutes
byteReceived := Uart1_Read_Char-48;
TimeToWrite.minutes := byteReceived*10;
while Uart1_Data_Ready() = 0 do nop;
byteReceived := Uart1_Read_Char-48;
TimeToWrite.minutes := TimeToWrite.minutes + byteReceived;
while Uart1_Data_Ready() = 0 do nop;
if ( Uart1_Read_Char() <> ':') then receivedOK := 0; // receive "/"
while Uart1_Data_Ready() = 0 do nop; // seconds
byteReceived := Uart1_Read_Char-48;
TimeToWrite.seconds := byteReceived*10;
while Uart1_Data_Ready() = 0 do nop;
byteReceived := Uart1_Read_Char-48;
TimeToWrite.seconds := TimeToWrite.seconds + byteReceived;
if (receivedOK = 0) then
begin
Uart1_Write_Text('Receive error.');
Uart1_Write_Char(13);
Uart1_Write_Char(10);
end;
end;
Uart1_Write_Text('Received Ok');
Uart1_Write_Char(13);
Uart1_Write_Char(10);
Uart1_Write_Char((TimeToWrite.year mod 4) shl 6 + (TimeToWrite.day div 10) shl 4 +(TimeToWrite.day mod 10));
Uart1_Write_Char(13);
Uart1_Write_Char(10);
I2C_Init(100000); // initialize I2C
I2C_Start; // issue start signal
I2c_Write($A0); // address PCF8583
I2c_Write(0); // start from word at address 0 (configuration word)
I2c_Write($80); // write $80 to config. (pause counter...)
I2c_Write(0); // write 0 to cents word
I2c_Write((TimeToWrite.seconds div 10) shl 4 + (TimeToWrite.seconds mod 10)); // write seconds word
I2c_Write((TimeToWrite.minutes div 10) shl 4 + (TimeToWrite.minutes mod 10)); // write minutes word
I2c_Write((TimeToWrite.hours div 10) shl 4 + (TimeToWrite.hours mod 10)); // write hours word
I2c_Write((TimeToWrite.year mod 4) shl 6 + (TimeToWrite.day div 10) shl 4 +(TimeToWrite.day mod 10));
I2c_Write((TimeToWrite.month div 10) shl 4 + (TimeToWrite.month mod 10)); // write weekday/month
I2C_Stop; // issue stop signal
I2C_Start; // issue start signal
I2c_Write($A0); // address PCF8530
I2c_Write(0); // start from word at address 0
I2c_Write(0); // write 0 to config word (enable counting)
I2C_Stop; // issue stop signal
end;
procedure Zero_Fill(var value : array[10] of byte); // fill text repesentation
begin
if (value[1] = 0) then
begin // with leading zero
value[1] := value[0];
value[0] := 48;
value[2] := 0;
end;
end;
//-------------- Trims the leading spaces from array given with *pt
procedure rtrim(var src, dest : array[10] of byte);
var i, j : word;
begin
i := 0;
j := 0;
while (src[i] = ' ') do
inc(i);
while (src[i] <> 0) do
begin
dest[j] := src[i];
inc(i);
inc(j);
end;
dest[j] := 0;
end;
//--------------------- Reads time and date information from RTC (PCF8583)
procedure Read_Time(var sec, min, hr, day, mn : byte);
begin
I2C_Start();
I2C_Write(0xA0);
I2C_Write(2);
I2c_Restart();
I2C_Write(0xA1);
sec := I2c_Read(0);
min := I2c_Read(0);
hr := I2c_Read(0);
day := I2c_Read(0);
mn := I2c_Read(1);
I2C_Stop();
end;
//-------------------- Formats date and time
procedure Transform_Time(var sec, min, hr, day, mn, year : byte);
begin
sec := ((sec and 0xF0) shr 4)*10 + (sec and 0x0F);
min := ((min and 0xF0) shr 4)*10 + (min and 0x0F);
hr := ((hr and 0xF0) shr 4)*10 + (hr and 0x0F);
year := (day and 0xC0) shr 6;
day := ((day and 0x30) shr 4)*10 + (day and 0x0F);
mn := ((mn and 0x10) shr 4)*10 + (mn and 0x0F);
end;
//-------------------- Output values to LCD
procedure Display_Time( sec, min1, hr, day, mn, year : byte);
begin
WordToStr(word(day), tnum);
rtrim(tnum, txt);
Zero_Fill(txt);
Lcd_Out(1, 6, txt);
WordToStr(word(mn), tnum);
rtrim(tnum, txt);
Zero_Fill(txt);
Lcd_Out(1,9,txt);
WordToStr(word(year), tnum);
rtrim(tnum, txt);
Zero_Fill(txt);
Lcd_Out(1,14,txt);
// Lcd_Chr(1,15,48+year);
WordToStr(word(hr), tnum);
rtrim(tnum, txt);
Zero_Fill(txt);
Lcd_Out(2,6,txt);
WordToStr(word(min1), tnum);
rtrim(tnum, txt);
Zero_Fill(txt);
Lcd_Out(2,9,txt);
WordToStr(word(sec), tnum);
rtrim(tnum, txt);
Zero_Fill(txt);
Lcd_Out(2,12,txt);
end;
//------------------ Performs project-wide init
procedure Init_Main();
begin
ADPCFG := 0xFFFF;
TRISD := 0; // designate portd as output
Lcd_Init_DsPICPro3();
I2C_Init(100000); // initialize I2C
txt := 'Date:'; // prepare and output static text on LCD
Lcd_Out(1,1,txt);
Lcd_Chr(1,8,':');
Lcd_Chr(1,11,':');
txt := 'Time:';
Lcd_Out(2,1,txt);
Lcd_Chr(2,8,':');
Lcd_Chr(2,11,':');
txt := '----';
Lcd_Out(1,12,txt);
Lcd_Cmd(LCD_CURSOR_OFF); // cursor off
end;
//----------------- Main procedure
begin
Init_Main(); // perform initialization
SetTimeByRs232();
while true do
begin
Read_Time(sec, min1, hr, day, mn); // read time from RTC(PCF8583)
Transform_Time(sec, min1, hr, day, mn, year); // format date and time
Display_Time(sec, min1, hr, day, mn, year); // prepare and display on LCD
Delay_ms(1000); // wait 1s
end;