كود:
// LCD module connections
sbit LCD_RS at RB0_bit; // LCD_RS assigned to PORT RB0;
sbit LCD_EN at RB1_bit; // LCD_EN assigned to PORT RB1;
sbit LCD_D4 at RB4_bit; // LCD_D4 assigned to PORT RB4;
sbit LCD_D5 at RB5_bit; // LCD_D5 assigned to PORT RB5;
sbit LCD_D6 at RB6_bit; // LCD_D6 assigned to PORT RB6;
sbit LCD_D7 at RB7_bit; // LCD_D7 assigned to PORT RB7;
sbit LCD_RS_Direction at TRISB0_bit; // LCD_RS assigned to TRIS B0;
sbit LCD_EN_Direction at TRISB1_bit; // LCD_EN assigned to TRIS B1;
sbit LCD_D4_Direction at TRISB4_bit; // LCD_D4 assigned to TRIS B4;
sbit LCD_D5_Direction at TRISB5_bit; // LCD_D5 assigned to TRIS B5;
sbit LCD_D6_Direction at TRISB6_bit; // LCD_D6 assigned to TRIS B6;
sbit LCD_D7_Direction at TRISB7_bit; // LCD_D7 assigned to TRIS B7;
// End LCD module connections
char second,minute,hour,weekday,day,month,year;
//--------------------- Reads time and date information from RTC (DS1307)
void Read_Time()
{
I2C1_Start(); // Issue start signal
I2C1_Wr(0xD0); // Address DS1307, see DS1307 datasheet
I2C1_Wr(0); // Start from address 0
I2C1_Repeated_Start(); // Issue repeated start signal
I2C1_Wr(0xD1); // Address DS1307 for reading R/W=1
second =I2C1_Rd(1); // Read seconds byte
minute =I2C1_Rd(1); // Read minutes byte
hour =I2C1_Rd(1); // Read hours byte
weekday =I2C1_Rd(1); // Read week day byte
day =I2C1_Rd(1); // Read day byte
month =I2C1_Rd(1); // Read month byte
year =I2C1_Rd(0); // Read Year byte
I2C1_Stop(); // Issue stop signal
}
//-----------------write time routine------------------
void Write_Time(char minute, char hour ,char weekday,char day,char month,char year)
{
char tmp1, tmp2;
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
I2C1_Start(); // issue start signal
I2C1_Wr(0xD0); // address DS1307
I2C1_Wr(0); // start from word at address (REG0)
I2C1_Wr(0x80); // write $80 to REG0. (pause counter + 0 second)
I2C1_Wr(minute); // write minutes word to (REG1)
I2C1_Wr(hour); // write hours word (24-hours mode)(REG2)
I2C1_Wr(weekday); // write 6 - Saturday (REG3)
I2C1_Wr(day); // write 14 to date word (REG4)
I2C1_Wr(month); // write 5 (May) to month word (REG5)
I2C1_Wr(year); // write 01 to year word (REG6)
I2C1_Wr(0x80); // write SQW/Out value (REG7)
I2C1_Stop(); // issue stop signal
I2C1_Start(); // issue start signal
I2C1_Wr(0xD0); // address DS1307
I2C1_Wr(0); // start from word at address 0
I2C1_Wr(0); // write 0 to REG0 (enable counting + 0 second)
I2C1_Stop(); // issue stop signal
}
//-------------------- Formats date and time---------------------
void Transform_Time()
{
second = ((second & 0x70) >> 4)*10 + (second & 0x0F);
minute = ((minute & 0xF0) >> 4)*10 + (minute & 0x0F);
hour = ((hour & 0x30) >> 4)*10 + (hour & 0x0F);
weekday =(weekday & 0x07);
day = ((day & 0xF0) >> 4)*10 + (day & 0x0F);
month = ((month & 0x10) >> 4)*10 + (month & 0x0F);
year = ((year & 0xF0)>>4)*10+(year & 0x0F);
}
//------------------------Display time---------------------------
char *txt,*mny;
void Display_Time()
{
switch(weekday)
{
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(1, 1,txt);
LCD_chr(1, 4,',');
switch(month)
{
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_Chr(1, 6, (day / 10) + 48); // Print tens digit of day variable
Lcd_Chr(1, 7, (day % 10) + 48); // Print oness digit of day variable
Lcd_Out(1, 9,mny);
Lcd_out(1,13,"20");
Lcd_Chr(1,15, (year / 10) + 48); // we can set year 00-99 [tens]
Lcd_Chr(1,16, (year % 10) + 48); // we can set year 00-99 [ones]
Lcd_Chr(2, 1, (hour / 10) + 48);
Lcd_Chr(2, 2, (hour % 10) + 48);
Lcd_Chr(2, 3,':');
Lcd_Chr(2, 4, (minute / 10) + 48);
Lcd_Chr(2, 5, (minute % 10) + 48);
Lcd_Chr(2, 6,':');
Lcd_Chr(2, 7, (second / 10) + 48);
Lcd_Chr(2, 8, (second % 10) + 48);
}
/*-------------------------------------------------------------*/
//-------------------Display Time in Set mode--------------------
char minute1,hour1,weekday1,day1,month1,year1;
char minute2,hour2,weekday2,day2,month2,year2;
void Display_Time_SetMode()
{
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(1, 1,txt);
LCD_chr(1, 4,',');
Lcd_Chr(1, 6, (day1 / 10) + 48); // Print tens digit of day variable
Lcd_Chr(1, 7, (day1 % 10) + 48); // Print oness digit of day variable
Lcd_chr(1,10, (month1 / 10) + 48); // Print tens digit of month variable
Lcd_chr(1,11, (month1 % 10) + 48); // Print oness digit of month variable
Lcd_out(1,13,"20");
Lcd_Chr(1,15, (year1 / 10) + 48); // Print tens digit of year variable
Lcd_Chr(1,16, (year1 % 10) + 48); // Print oness digit of year variable
Lcd_Chr(2, 1, (hour1 / 10) + 48); // Print tens digit of hour variable
Lcd_Chr(2, 2, (hour1 % 10) + 48); // Print oness digit of hour variable
Lcd_Chr(2, 3,':');
Lcd_Chr(2, 4, (minute1 / 10) + 48); // Print tens digit of minute variable
Lcd_Chr(2, 5, (minute1 % 10) + 48); // Print oness digit of minute variable
Lcd_Chr(2, 6,':');
Lcd_Chr(2, 7, (0 / 10) + 48);
Lcd_Chr(2, 8, (0 % 10) + 48);
}
char SPos;
//----------------------Move cursor routine----------------------
char index;
void movecursor()
{
char i,moveto;
if(SPos==0)
lcd_cmd(_lcd_first_row); // set weekday;
if(SPos==1)
lcd_cmd(_lcd_first_row); // set day;
if(SPos==2)
lcd_cmd(_lcd_first_row); // set month;
if(SPos==3)
lcd_cmd(_lcd_first_row); // set year;
if(SPos==4)
lcd_cmd(_lcd_second_row); // set hours;
if(SPos==5)
lcd_cmd(_lcd_second_row); // set minutes;
moveto = 2;
switch(index)
{
case 0: moveto = 2;break;
case 1: moveto = 6;break;
case 2: moveto =10;break;
case 3: moveto =15;break;
case 4: moveto = 1;break;
case 5: moveto = 4;break;
}
for(i=1; i<= moveto; i++)
lcd_cmd(_lcd_move_cursor_right);
}
/////////////////////////////////////////////////////////////////////////
//------------Start Buttons routine--------------;
char setuptime=0;
void Press_Switch()
{
if(setuptime)// After Button SET pressed first time
{
if(Button(&portc,2,1,0)) // If buttons at port c2 is pressed , cursor or select item
{
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(&portc,0,1,0)) // If buttons at port c0 is pressed , INC
{
Delay_ms(200);
weekday1++;
if(weekday1 > 7)
weekday1=1;
Display_Time_SetMode();
index=0;
movecursor();
}
if(button(&portc,1,1,0)) // If buttons at port c1 is pressed , DEC
{
Delay_ms(200);
weekday1--;
if(weekday1 < 1)
weekday1=7;
Display_Time_SetMode();
index=0;
movecursor();
}
break;
case 1: if(button(&portc,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(&portc,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(&portc,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(&portc,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(&portc,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(&portc,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(&portc,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(&portc,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(&portc,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(&portc,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(&portc,5,1,0)) // If buttons at port c5 is pressed ,Enter SETUP mode
{
Delay_ms(200);
setuptime = !setuptime;
if(SetupTime)
{
lcd_cmd(_lcd_clear);
lcd_cmd(_lcd_blink_cursor_on);
weekday1=weekday;
hour1=hour;
minute1=minute;
day1=day;
month1=month;
year1=year;
Display_Time_SetMode();
SPos=0;
index=0;
movecursor();
}
else
{
Lcd_Cmd(_Lcd_clear);
lcd_cmd(_lcd_cursor_off);
weekday2=weekday1;
hour2=hour1;
minute2=minute1;
day2=day1;
month2=month1;
year2=year1;
Write_time(minute2,hour2,weekday2,day2,month2,year2);
}
}
}
//----------------------End Buttons Routine-------------------
//------------------Temperature sensor routines---------------
const unsigned short TEMP_RESOLUTION = 12; // 9 for DS1820 and 12 for DS18B20
char *text = "000,0";
unsigned temp;
void Display_Temperature(unsigned int temp2write)
{
const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
char temp_whole;
unsigned int temp_fraction;
unsigned short isNegative = 0x00;
// Check if temperature is negative
if (temp2write & 0x8000)
{
text[0] = '-';
temp2write = ~temp2write + 1;
isNegative = 1;
}
// Extract temp_whole
temp_whole = temp2write >> RES_SHIFT ;
// Convert temp_whole to characters
if (!isNegative){
if (temp_whole/100)
text[0] = temp_whole/100 + 48; // Extract hundreds digit
else
text[0] = '+';
}
text[1] = (temp_whole/10)%10 + 48; // Extract tens digit
text[2] = temp_whole%10 + 48; // Extract ones digit
// Extract temp_fraction and convert it to unsigned int
temp_fraction = temp2write << (4-RES_SHIFT);
temp_fraction &= 0x000F;
temp_fraction *= 625;
// Convert temp_fraction to characters
text[4] = temp_fraction/1000 + 48; // Extract thousands digit
// Print temperature on LCD
Lcd_Out(2, 10,text);
lcd_chr(2, 15,223); // Ascii code for degrees symbol;
Lcd_chr(2, 16,'C'); // Show symbol "C" from Celsius
}
//----------------Read and display Temperature from DS18B20--------------
void Read18b20()
{
//--- Perform temperature reading
Ow_Reset(&PORTC, 7); // Onewire reset signal;
Ow_Write(&PORTC, 7, 0xCC); // 0xCC Issue command SKIP_ROM;
Ow_Write(&PORTC, 7, 0x44); // Issue command CONVERT_T;
Delay_us(700); // delay 0,7s (required for signal
// processing);
Ow_Reset(&PORTC, 7); // Onewire reset signal;
Ow_Write(&PORTC, 7, 0xCC); // Issue command SKIP_ROM;
Ow_Write(&PORTC, 7, 0xBE); // Issue command READ_SCRATCHPAD;
temp = Ow_Read(&PORTC, 7); // Next Read Temperature, read Byte
// 0 from Scratchpad;
temp = (Ow_Read(&PORTC, 7) << 8) + temp; // Then read Byte 1 from Scratchpad
// and shift 8 bit left and add the Byte 0;
//--- Format and display result on Lcd
Display_Temperature(temp); // Call Display_Temperature;
}
//------------------Temperature sensor routines---------------
void Init_Main()
{
CMCON |=7; //TURN OFF ANALOGUE COMPARATOR AND MAKE PORTA TO DIGITAL I/O;
I2C1_Init(100000); // initialize I2C
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear LCD display
Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off
//Display_Time();
!setuptime=1;//setuptime=0;
index=0;
SPos=0;
}
//-----------------Here we have the Main Routine----------------
void main()
{
Init_Main();
while (1) // While loop
{
Read_Time(); // read time from RTC(DS1307)
Transform_Time(); // Transform time
Press_Switch(); // Check buttons;
if(!setuptime)
{
Display_Time();
Read18b20();
}
}
}