/*
3位LCD字段屏显示时钟,
原程序不全,我把它弄好了,还加了声音、减、背光控制,大家看看还有什么需要的
*/
#include <REG52.H>
sbit LCD_DATA = P0^0;//=14-2051,14脚
sbit LCD_CLK = P0^1;//=15
sbit LCD_CS1 = P0^2;//=16
sbit clock_clk=P1^4;//=8
sbit clock_dat=P1^5;//=6
sbit clock_rst=P2^2;//=7
sbit ks5=P1^0;//=2 设置位
sbit ks4=P1^1;//=3 加
sbit ks3=P1^2;//=3 减
sbit ks2=P1^3;//=3 背光
sbit beep=P2^7;//=声音
bit bg=0;
//bit keyshi=1;//zhishi=9 没有意义
//bit keyfen=1;//=11
sbit a0 = ACC ^ 0;//为了编程方便定义的位变量
sbit a1 = ACC ^ 1;
sbit a2 = ACC ^ 2;
sbit a3 = ACC ^ 3;
sbit a4 = ACC ^ 4;
sbit a5 = ACC ^ 5;
sbit a6 = ACC ^ 6;
sbit a7 = ACC ^ 7;
unsigned char code digi[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x58,0x5e,0x79,0x71,0x76,0x37,0x6b,0x6e,0x48,0x40};
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, b, c, d, E, F, H, 17, 18, y, 20 -
unsigned char lcd_data[3],dat,set,d,e,t;
void dealy(unsigned int dealy_time) //延时子程序
{
for(;dealy_time>0;dealy_time--)
{}
}
void Beep()//BELL-扬声器--开机
{
unsigned char a;//定义变量用于发声的长度设置
// Led_EA = 1;//关列显示驱动,防止屏幕出现乱码
for(a=60;a>0;a--)//第一个声音的长度
{
beep = ~beep;//取反扬声器驱动口,以产生音频
dealy(100);//音调设置延时
}
for(a=100;a>0;a--)//同上
{
beep = ~beep;
dealy(80);//
}
for(a=100;a>0;a--)//同上
{
beep = ~beep;
dealy(30);//
}
}
//---------------------------------------------------
void Beep_set() //BELL -扬声器--按键
{
unsigned char a;//定义变量用于发声的长度设置
// Led_EA = 1;//关列显示驱动,防止屏幕出现乱码
for(a=250;a>0;a--)//第一个声音的长度
{
beep = ~beep;//取反扬声器驱动口,以产生音频
dealy(20);//音调设置延时
}
for(a=100;a>0;a--)//同上
{
beep = ~beep;
dealy(80);//
}
}
void delay_ms(unsigned int a)
{
unsigned char i;
while( --a != 0)
{
for(i = 0; i < 100; i++);
}
}
void LCD_init(void)
{
LCD_CS1=0;
LCD_DATA=0;
LCD_CLK=0;
LCD_CS1=1;
delay_ms(100);
LCD_CLK=1;
}
void LCD_write_char(unsigned char dat)
{
unsigned char i;
for(i=8;i>0;i--)
{
LCD_DATA=0;
if (dat&0x01) LCD_DATA=1;
LCD_CLK=0;
delay_ms(3);
LCD_CLK=1;
delay_ms(3);
dat=dat >> 1;
}
}
/*
void LCD_on()
{
LCD_CS1=0;
LCD_write_char(0x05); // 背光on 0x05 开
LCD_CS1=1;
delay_ms(3);
}
void LCD_off()
{
LCD_CS1=0;
LCD_write_char(0x01); // 背光off 0x04 关
LCD_CS1=1;
delay_ms(3);
}
*/
/**************读出一个字节,时序***************/
unsigned char clock_read() //读出一个字节,时序
{
clock_clk=1; clock_clk=0; a0=clock_dat;
clock_clk=1; clock_clk=0; a1=clock_dat;
clock_clk=1; clock_clk=0; a2=clock_dat;
clock_clk=1; clock_clk=0; a3=clock_dat;
clock_clk=1; clock_clk=0; a4=clock_dat;
clock_clk=1; clock_clk=0; a5=clock_dat;
clock_clk=1; clock_clk=0; a6=clock_dat;
clock_clk=1; clock_clk=0; a7=clock_dat;
return(ACC);
}
/****************************************************
ds1302程序
写入一个字节,
****************************************************/
void clock_write(unsigned char dd) //写入一个字节,DS1302时序
{
ACC=dd;
clock_clk=0 ;clock_dat=a0; clock_clk=1;
clock_clk=0 ;clock_dat=a1; clock_clk=1;
clock_clk=0 ;clock_dat=a2; clock_clk=1;
clock_clk=0 ;clock_dat=a3; clock_clk=1;
clock_clk=0 ;clock_dat=a4; clock_clk=1;
clock_clk=0 ;clock_dat=a5; clock_clk=1;
clock_clk=0 ;clock_dat=a6; clock_clk=1;
clock_clk=0 ;clock_dat=a7; clock_clk=1;
}
/******************** 向reg2写入date数据 向指定地址写数据 */
void write_clock(unsigned char reg2, unsigned char date)//向reg2写入date数据
{
clock_clk=0;
clock_rst=0;
clock_rst=1;
clock_write(reg2);
clock_write(date);
clock_rst=0;
}
/****从reg1寄存器读数据* 从指定地址读数据 **/
unsigned char read_clock(unsigned char reg1)//从reg1寄存器读数据 ///read_clock 从指定地址读数据 write_clock 向指定地址写数据
{
unsigned char dd=0;
clock_clk=0;
clock_rst=0;
clock_rst=1;
clock_write(reg1);
dd=clock_read();
clock_rst=0;
return(dd);
}
/*显示1*/
void display_lcd1(unsigned char num) //显示 小时 数据拆分
{
unsigned char i;
lcd_data[0] = digi[num%10];
lcd_data[1] = digi[(num%100)/10];
lcd_data[2] = 0x40;
LCD_CS1=0;
LCD_write_char(0x08); //写数据
for(i=0;i<3;i++) LCD_write_char(lcd_data[i]);
LCD_CS1=1;
delay_ms(3);
}
/*显示2*/
void display_lcd2(unsigned char num) //显示 分钟 数据拆分
{
unsigned char i;
lcd_data[0] = 0x40;
lcd_data[1] = digi[num%10];
lcd_data[2] = digi[(num%100)/10];
LCD_CS1=0;
LCD_write_char(0x08); //写数据
for(i=0;i<3;i++) LCD_write_char(lcd_data[i]);
LCD_CS1=1;
delay_ms(3);
}
//键盘 1 设置 2 加 3 减 4背光 成功
void key()
{
if(ks5==0)
{
delay_ms(30);
if(ks5==0)
{
while(ks5==0);
Beep_set();
set++;
if(set==3) set=0;
}
}
switch(set)
{
case 1:
t=((read_clock(0x83))/16)*10 + (read_clock(0x83))%16;
display_lcd1(t);
if(ks4==0)
{
delay_ms(30);
if(ks4==0)
{
while(ks4==0);
Beep_set();
write_clock(0x8e,0x00);//取消写保护
write_clock(0x80,0x80);//停止时钟
d=((read_clock(0x83))/16)*10 + (read_clock(0x83))%16; //16转10
d++;
if(d==60)d=0;
d=d/10*16+d%10;//十进制转换成DS1302要求的DCB码 10转16
write_clock(0x82,d);// 写分钟
write_clock(0x80,0x00);//启动时钟
write_clock(0x8e,0x80);//写保护
delay_ms(20);
}
}
if(ks3==0)
{
delay_ms(30);
if(ks3==0)
{
while(ks3==0);
Beep_set();
write_clock(0x8e,0x00);//取消写保护
write_clock(0x80,0x80);//停止时钟
d=((read_clock(0x83))/16)*10 + (read_clock(0x83))%16; //16转10
d--;
if(d==0)d=59;
d=d/10*16+d%10;//十进制转换成DS1302要求的DCB码 10转16
write_clock(0x82,d);// 写分钟
write_clock(0x80,0x00);//启动时钟
write_clock(0x8e,0x80);//写保护
delay_ms(20);
}
}
break;
case 2:
t=((read_clock(0x85))/16)*10 + (read_clock(0x85))%16;
display_lcd2(t);
if(ks4==0)
{
delay_ms(30);
if(ks4==0)
{
while(ks4==0);
Beep_set();
write_clock(0x8e,0x00);//取消写保护
write_clock(0x80,0x80);//停止时钟
d=((read_clock(0x85))/16)*10 + (read_clock(0x85))%16; //16转10
d++;
if(d==24)d=0;
d=d/10*16+d%10;//十进制转换成DS1302要求的DCB码 10转16
write_clock(0x84,d);// 写分钟
write_clock(0x80,0x00);//启动时钟
write_clock(0x8e,0x80);//写保护
delay_ms(20);
}
}
if(ks3==0)
{
delay_ms(30);
if(ks3==0)
{
while(ks3==0);
Beep_set();
write_clock(0x8e,0x00);//取消写保护
write_clock(0x80,0x80);//停止时钟
d=((read_clock(0x85))/16)*10 + (read_clock(0x85))%16; //16转10
d--;
if(d==0)d=23;
d=d/10*16+d%10;//十进制转换成DS1302要求的DCB码 10转16
write_clock(0x84,d);// 写分钟
write_clock(0x80,0x00);//启动时钟
write_clock(0x8e,0x80);//写保护
delay_ms(20);
}
}
break;
}
//*背光控制
if(ks2==0)
{
delay_ms(30);
if(ks2==0)
{
while(ks2==0);
Beep_set();
bg=~bg;
if(bg==0)
{
LCD_CS1=0;
LCD_write_char(0x04); // 背光off 原=0x01
LCD_CS1=1;
delay_ms(3);
}
else
{
LCD_CS1=0;
LCD_write_char(0x05); // 背光on
LCD_CS1=1;
delay_ms(3);
}
}
}
}
void show()//显示和闪烁函数
{
e=((read_clock(0x83))/16)*10 + (read_clock(0x83))%16;
display_lcd1(e); //显示分钟
delay_ms(1000);
e=((read_clock(0x85))/16)*10 + (read_clock(0x85))%16;
display_lcd2(e); //显示小时*/
delay_ms(1000);
// d=read_clock(0x87);//读日
//d=read_clock(0x89);//读月
// delay_ms(50);
//d=read_clock(0x8d);//读年
//d=read_clock(0x8b);//读年
}
/*--------------------时钟的初始化---------------------------*/
void Init_1302()//这部分是把杜样的初始化拿来的
{
///read_clock 从指定地址读数据 write_clock 向指定地址写数据
unsigned char Second,f,x=0;
Second=read_clock(0xc1); //read_clock
if(Second != 0x80) //第一次开机
{
write_clock(0x8e,0x00); // 允许写入
write_clock(0x8c,0x10); // 10 年
write_clock(0x88,0x11); // 11 月
write_clock(0x86,0x12); // 10 日
write_clock(0x8a,0x05); // 3 星期
write_clock(0x84,0x20); // 时
write_clock(0x82,0x52); // 分
write_clock(0x80,0x55); // 秒
write_clock(0xc0,0x80); // 二次开机标志
write_clock(0x90,0xa5); // 允许充电 一个二极管 2K电阻
for(f=0;f<60;f=f+2)//清除闹钟RAM位为0
{
write_clock(0xc2+f,0x00); //存储报时用
} //第一次开机要清除其余30个寄存器
write_clock(0x8e,0x80); // 禁止写入
}
}
void main()
{
// LCD_on(); // 背光OFF
set=0;
ks5=1;
ks4=1;
Beep(); //开机声
LCD_init();
// LCD_off(); // 背光ON
Init_1302();//DS1302寄存器初始化
// keyshi=1;
// keyfen=1;
delay_ms(10);
while(1)
{
key();
if(set==0)
{
show();
}
}
} |