#define uchar unsigned char //定義unsigned int為uint
#define uint unsigned int //定義unsigned uchar為uchar
sbit LCD_RS = P2^0 ;
sbit LCD_RW = P2^1 ;
sbit LCD_EN = P2^2 ;
sbit D_SDA = P2^6; //定義74HC164數據線為P2.6端口
sbit D_SCL = P2^7; //定義74HC164數據線為P2.7端口
sbit CLK = P1^3; /*實時時鐘時鐘線引腳 */
sbit IO = P1^4; /*實時時鐘數據線引腳 */
sbit RST = P1^5; /*實時時鐘復位線引腳 */
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
uchar time[8] = {0x50,0x30,0x19,0x30,0x12,0x06,0x06};
//========= 延時函數 ============
//延時時間以1ms為單位
//s決定延時時間長短
void delay_ms(uint s)
{
uint x;
for(s;s>0;s--)
{
x = 200;
while(x--);
}
}
//========= 送出壹個字節給74HC164(實現串並轉換) ==========
void send_out(unsigned char out)//傳送壹個字節8位
{
uchar i;
D_SCL = 0;
for (i=8;i>=1;i--)
{
D_SDA = out&0x80; //送數據到數據口
D_SCL = 1; //時鐘線置1
D_SCL = 0; //送壹時鐘
out<<=1; //左移
}
}
//========= 寫命令函數 ==========
void lcd_wcmd(uchar cmd)
{
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
send_out(cmd);
LCD_EN = 1;
LCD_EN = 0 ;
}
//========= 寫數據函數 ==========
void lcd_wdat(uchar dat)
{
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
send_out(dat);
LCD_EN = 1;
LCD_EN = 0;
}
//========= LCD初始化函數 ==========
void lcd_init()
{
lcd_wcmd(0x38);
delay_ms(1);
lcd_wcmd(0x0c); //顯示開,關光標
delay_ms(1);
lcd_wcmd(0x06); //向右移動光標
delay_ms(1);
lcd_wcmd(0x01); //清除LCD顯示屏
delay_ms(1);
}
//========== 往DS1302寫入1Byte數據 (內部函數) =============
void w_byte(uchar dat)
{
uchar i;
for(i=8; i>0; i--)
{
IO = dat & 0x01;
CLK = 1;
CLK = 0;
dat = dat >> 1;
}
}
//======== 從DS1302讀取1Byte數據 (內部函數) ===================
uchar r_byte(void)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >> 1;
ACC7 = IO;
CLK = 1;
CLK = 0;
}
return(ACC);
}
//========== 指定地址往DS1302寫入1Byte數據 (內部函數) =============
void write_byte(uchar addr, uchar dat)
{
RST = 0;
CLK = 0;
RST = 1;
w_byte(addr);
w_byte(dat);
CLK = 1;
RST = 0;
}
//========== 指定地址往DS1302讀1Byte數據 (內部函數) =============
uchar read_byte(uchar addr)
{
uchar ucData;
RST = 0;
CLK = 0;
RST = 1;
w_byte(addr);
ucData = r_byte();
CLK = 1;
RST = 0;
return(ucData);
}
//============ 設置ds1302日期和時間 =============
void write_ds1302(uchar *p)
{
uchar i;
uchar addr = 0x80;
write_byte(0x8e,0x00); // 控制命令,WP=0,寫操作
for(i =7; i>0; i--)
{
write_byte(addr,*p); // 秒 分 時 日 月 星期 年
p++;
addr +=2;
}
write_byte(0x8e,0x80); // 控制命令,WP=1,寫保護
}
//============ 讀ds1302當前日期和時間 =============
void read_ds1302(uchar *p)
{
uchar i;
uchar addr = 0x81;
for (i=0; i<7; i++)
{
*p = read_byte(addr); //格式為: 秒 分 時 日 月 星期 年
addr += 2;
p++;
}
}
//============ 顯示函數 ===================
void lcd_disp()
{
uchar addr = 4;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[2]>>4)&0x0f)+0x30); //顯示小時
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[2]&0x0f)+0x30);
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(':'); //顯示":"
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[1]>>4)&0x0f)+0x30); //顯示分
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[1]&0x0f)+0x30);
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(':'); //顯示":"
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat(((time[0]>>4)&0x0f)+0x30); //顯示秒
addr++;
lcd_wcmd(0x80 + addr);
lcd_wdat((time[0]&0x0f)+0x30);
addr = 2;
lcd_wcmd(0xc0 + addr); //在第二行顯示年月日和星期
lcd_wdat('2'); //顯示2
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat('0'); //顯示0
addr++;
lcd_wdat(((time[6]>>4)&0x0f)+0x30); //年
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[6]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(((time[4]>>4)&0x0f)+0x30); //顯示月
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[4]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(((time[3]>>4)&0x0f)+0x30); //顯示日
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[3]&0x0f)+0x30);
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat(' ');
addr++;
lcd_wcmd(0xc0 + addr);
lcd_wdat((time[5]&0x0f)+0x30); //顯示星期
}
//=========== 主函數 ===============
void main()
{
lcd_init(); // 初始化LCD
write_ds1302(time);
while(1)
{
read_ds1302(time); //讀DS1302數據
lcd_disp(); //LCD顯示
delay_ms(500); //延時0.5秒
}
}
這是壹個電子時鐘,在LCD1602上顯示,時鐘芯片是DS1302