2024年6月10日发(作者:练秀华)
一、 概述
二、 51单片机 ,TM1638芯片+DS1302驱动共阴数码管时钟,最后包括
按键检测程序(是分开的。)
TM1638是带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集
成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。主要应用于冰
箱、
空调 、家庭影院等产品的高段位显示屏驱动。
二、 特性说明
• 采用功率CMOS 工艺
• 显示模式 10 段×8 位
• 键扫描(8×3bit)
• 辉度调节电路(占空比8 级可调)
• 串行接口(CLK,STB,DIO)
• 振荡方式:RC 振荡(450KHz+5%)
• 内置上电复位电路
• 采用SOP28封装
三、、 管脚定
义:
电路图数码管:
程序代码:
/*************** TM1638.H头文件 *******************/
#ifndef _TM1638_H
#define _TM1638_H
//引脚定义
sbit DIO=P1^0;
sbit CLK=P1^1;
sbit STB=P1^2;
//写一个8Bit数据
void TM1638_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
if(DATA&0X01)
DIO=1;
else
DIO=0;
DATA>>=1;
CLK=1;
}
}
/*unsigned char TM1638_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp=0;
DIO=1; //设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
CLK=0;
if(DIO)
temp|=0x80;
CLK=1;
}
return temp;
} */
void Write_COM(unsigned char cmd) //发送命令字
{
STB=0;
TM1638_Write(cmd); //写命令
STB=1;
}
void Write_DATA(unsigned char add,unsigned char DATA) //指定地址写入数据
{
Write_COM(0x44);
STB=0;
TM1638_Write(0xc0|add); //地址高位为1:11** ****,写地址
TM1638_Write(DATA);
STB=1;
}
void init_TM1638(void)
{
unsigned char i;
Write_COM(0x8a);//亮度
Write_COM(0x40); //写 数据命令,写数据到显示寄存器
STB=0;
TM1638_Write(0xc0); //写地址命令
for(i=0;i<16;i++)
TM1638_Write(0x00);
STB=1;
}
#endif
/***************************DS1302.H头文件***************************/
#ifndef DS1302_H
#define DS1302_H
#define uchar unsigned char
#define uint unsigned int
#include"DELAY.h"
sbit acc0=ACC^0; //移位时的第0位
sbit acc7=ACC^7; //移位时用的第7位
uchar second,minute,hour,day,month,year,week,count=0;
uchar ReadValue,num,time;
sbit SCLK=P2^0;
sbit DATA=P2^1;
sbit RST=P2^2;
void Write1302(uchar dat)
{
uchar i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delay1(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写8个二进制位数据
{
DATA=dat&0x01; //取出dat的第0位数据写入1302
delay(2); //稍微等待,使硬件做好准备
SCLK=1; //上升沿写入数据
delay1(2); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}
}
void WriteSet1302(uchar Cmd,uchar dat)
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
delay1(2); //稍微等待,使硬件做好准备
Write1302(Cmd); //写入命令字
Write1302(dat); //写数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
}
uchar Read1302(void)
{
uchar i,dat;
delay(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续读8个二进制位数据
{
dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位
if(DATA==1) //如果读出的数据是1
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出
delay1(2); //稍微等待
SCLK=0; //拉低SCLK,形成脉冲下降沿
delay1(2); //稍微等待
}
return dat; //将读出的数据返回
}
uchar ReadSet1302(uchar Cmd)
{
uchar dat;
RST=0; //拉低RST
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
Write1302(Cmd); //写入命令字
dat=Read1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
return dat; //将读出的数据返回
}
void Init_DS1302(void)
{
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指
令
WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值
WriteSet1302(0x82,((41/10)<<4|(41%10))); //根据写分寄存器命令字,写入分的初始值
WriteSet1302(0x84,((15/10)<<4|(15%10))); //根据写小时寄存器命令字,写入小时的初始值
WriteSet1302(0x86,((29/10)<<4|(24%10))); //根据写日寄存器命令字,写入日的初始值
WriteSet1302(0x88,((2/10)<<4|(2%10))); //根据写月寄存器命令字,写入月的初始值
WriteSet1302(0x8c,((10/10)<<4|(11%10))); //nian
WriteSet1302(0x8a,((0/10)<<4|(0%10)));
WriteSet1302(0x8E,0x80); //根据写状态寄存器命令字,写入保护指令
}
#endif
/***************显示头文件*******************************/
#include"TM1638.h"
uchar data DisBuffer[8]={0,0,0,0,0,0,0,0}; /*显示缓存区*/ //各个数码管显示的值
uchar code
tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71
,0x40,0xef};
void display1638(uchar hour,uchar minute,uchar second)
{
uchar i;
DisBuffer[0]=hour/10;
DisBuffer[1]=hour%10;
DisBuffer[3]=minute/10;
DisBuffer[4]=minute%10;
DisBuffer[6]=second/10;
DisBuffer[7]=second%10;
DisBuffer[2]=16;
DisBuffer[5]=16;
for(i=0;i<8;i++)
{
Write_DATA(i*2,tab[DisBuffer[i]]);
}
}
void DisplayHour(newval)
{
DisBuffer[0]=newval/10;
DisBuffer[1]=newval%10;
for(i=0;i<2;i++)
{
Write_DATA(i*2,tab[DisBuffer[i]]);
}
}
#endif
/**********************************************************/
//下面是处理程序头文件,调试功能的实现,但是本人接调时的来源是
//是鼠标芯片,所以这里都写上,各位可以根据自己是按键还是其他的,做修改
/***********************************************/
#ifndef CHULI_H
#define CHULI_H
#define uchar unsigned char
#define uint unsigned int
#include"DISPLAY.h"
#include"DS1302.h"
void read_date(void)
{
ReadValue = ReadSet1302(0x81);
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x83);
minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x85);
hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x87);
day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x89);
month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x8d);
year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue=ReadSet1302(0x8b); //读星期
week=ReadValue&0x07;
display1638(hour,minute,second) ;
}
void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num)
{
newval=ReadSet1302(newaddr); //读取当前时
间
newval=((newval&0x70)>>4)*10+(newval&0x0f);
十进制
if(flag) //判断是加一还是减一
{
newval++;
switch(s1num)
{ case 1: if(newval>99) newval=0;
DisplayYear(newval);
break;
case 2: if(newval>12) newval=1;
DisplayMonth(newval);
break;
case 3: if(newval>31) newval=1;
DisplayDay(newval);
break;
case 4: if(newval>6) newval=0;
DisplayWeek(newval);
break;
case 5: if(newval>23) newval=0;
DisplayHour(newval);
break;
case 6: if(newval>59) newval=0;
DisplayMinute(newval);
break;
case 7: if(newval>59) newval=0;
DisplaySecond(newval);
break;
default:break;
}
}
else
{
newval--;
switch(s1num)
{ case 1: if(newval==0) newval=99;
//将bcd码转换成
DisplayYear(newval);
break;
case 2: if(newval==0) newval=12;
DisplayMonth(newval);
break;
case 3: if(newval==0) newval=31;
DisplayDay(newval);
break;
case 4: if(newval<0) newval=6;
DisplayWeek(newval);
break;
case 5: if(newval<0) newval=23;
DisplayHour(newval);
break;
case 6: if(newval<0) newval=59;
DisplayMinute(newval);
break;
case 7: if(newval<0) newval=59;
DisplaySecond(newval);
break;
default:break;
}
}
WriteSet1302((newaddr-1),((newval/10)<<4)|(newval%10));
入寄存器
}
void write_flsh(uchar com,uchar dat)
{ Write_DATA(com,tab[16]);
delay(100);
Write_DATA(com,tab[dat]);
}
void sp2_mouse(void)
{
uchar miao,z,flag=0;
rd=0;
miao=ReadSet1302(0x81);
second=miao;
WriteSet1302(0x80,miao|0x80);
while(1)
{ led=0;
///////////////////////////////////////
/* if((move_x<4)&&(flag==0))
//将新数据写
{
write_flash(0x02,1) ;
if((mouse_data[0]&0x01)&&(flag==1))
{
while(mouse_data[0]&0x01);
while(1)
{ write_flash(0x02,1) ;
z=move_x;
if(move_x>z)
{ delayms(10);
turn_val(year,1,0x8d,1);
}
if(z>move_x)
{delayms(10);
turn_val(year,0,0x8d,1);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=3;
z=move_x;
break;
}
}
}
}
///////////////////////////////////////////////////////
if((move_x>=4)&&(move_x<6)&&(flag==0))
{
write_com(0x87);
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{ z=move_x;
write_com(0x87);
if(move_x>z)
{ delayms(10);
turn_val(month,1,0x89,2);
}
if(z>move_x)
{delayms(10);
turn_val(month,0,0x89,2);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=5;
z=move_x;
break;
}
}
}
}
/////////////////////////////////////////////////////////
if((move_x>=6)&&(move_x<8)&&(flag==0))
{
write_com(0x8a);
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_com(0x8a);
if(move_x>z)
{ delayms(10);
turn_val(day,1,0x87,3);
}
if(z>move_x)
{ delayms(10);
turn_val(day,0,0x87,3);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=7;
z=move_x;
break;
}
}
}
}
///////////////////////////////////////////////////////////
if((move_x>=8)&&(move_x<10)&&(flag==0))
{
write_com(0x8e);
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_com(0x8e);
if(move_x>z)
{ delayms(10);
turn_val(week,1,0x8b,4);
}
if(z>move_x)
{delayms(10);
turn_val(week,0,0x8b,4);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=9;
z=move_x;
break;
}
}
}
} */
////////////////////////////////////////////////////////////
if((move_x>=10)&&(move_x<12)&&(flag==0))
{
write_flash(0x02,1) ;
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_flash(0x02,1) ;
if(move_x>z)
{ delayms(10);
turn_val(hour,1,0x85,5);
}
if(z>move_x)
{ delayms(10);
turn_val(hour,0,0x85,5);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=11;
z=move_x;
break;
}
}
}
}
//////////////////////////////////////////////////////////////
if((move_x>=12)&&(move_x<14)&&(flag==0))
{
write_com(0xc4) ;
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_com(0xc4) ;
if(move_x>z)
{ delayms(10);
turn_val(minute,1,0x83,6);
}
if(z>move_x)
{delayms(10);
turn_val(minute,0,0x83,6);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=13;
z=move_x;
break;
}
}
}
}
//写入分寄存器
//写入分寄存器
////////////////////////////////////////////////////////////////
if((move_x>=14)&&(flag==0))
{
write_com(0xc7);
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_com(0xc7);
if(move_x>z)
{ delayms(10);
turn_val(second,1,0x81,7);
}
if(z>move_x)
{delayms(10);
turn_val(second,0,0x81,7);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=15;
z=move_x;
break;
}
}
}
}
///////////////////////////////////////////////////////////////
if((mouse_data[0]&0x01)&&(z!=move_x))
{flag=0;
while(mouse_data[0]&0x01);
}
//////////////////////////////////////////////////////////////
if((mouse_data[0]&0x01)&&(flag==1)&&(z==move_x))
{flag=0;
delayms(300);
miao=ReadSet1302(0x81);
second=miao;
WriteSet1302(0x80,second&0x7f);
write_com(0x0c) ;
WriteSet1302(0x8E,0x80); //根据写状态寄存器命令字,
写入不保护指令
break;
}
}
}
#endif
/*********鼠标芯片*****/
#ifndef PS2_H
#define PS2_H
#include"DELAY.h"
sbit mouse_SDA=P3^4;//数据线P3_5 计数器0输入端口
sbit mouse_CLK=P3^3;//时钟线P3_3 外部中断1输入端口
sbit led=P3^6;
bit pp=0;
bit ACK=0;
uchar bdata mouse_byte; //接收字节 bdata-->可寻址的片内RAM
sbit mouse_byte_bit0=mouse_byte^0;//mouse_byte第0位
sbit mouse_byte_bit1=mouse_byte^1;//mouse_byte第1位
sbit mouse_byte_bit2=mouse_byte^2;//mouse_byte第2位
sbit mouse_byte_bit3=mouse_byte^3;//mouse_byte第3位
sbit mouse_byte_bit4=mouse_byte^4;//mouse_byte第4位
sbit mouse_byte_bit5=mouse_byte^5;//mouse_byte第5位
sbit mouse_byte_bit6=mouse_byte^6;//mouse_byte第6位
sbit mouse_byte_bit7=mouse_byte^7;//mouse_byte第7位
uchar mouse_buffer[11];//接收位数据缓冲区
uchar mouse_buffer_bit=0;//mouse_buffer[mouse_buffer_bit]
uchar mouse_data[4];//接收鼠标数据缓冲区,分别存放:功能信息字节,x位移量,y位移量
uchar mouse_data_bit=0;//mouse_data[mouse_data_bit]
uchar move_x;//存放横坐标
uint move_y;//存放纵坐标
uchar move_z;
extern uchar move_x;
/***********************************************************************
发送数据
************************************************************************/
void Init_ter(void)
{
EA=1; //开放中断
EX1=1;//允许外部中断1
PX1=1;//设置中断优先级 设外部中断1为最高优先级别
}
void host_to_mouse(uchar cmd)
{
uchar i;
EX1=0;
mouse_CLK=0;
delay100;
delay100;
ACC=cmd;
pp=~P; //获得奇偶校验位
mouse_SDA=0;
mouse_CLK=1;
for(i=0;i<8;i++)
{
while(mouse_CLK==1);
mouse_SDA=cmd&0x01;
cmd>>=1;
while(mouse_CLK==0);
}
while(mouse_CLK==1);
mouse_SDA=pp; //发送奇偶校验位
while(mouse_CLK==0);
while(mouse_CLK==1);
mouse_SDA=1;
while(mouse_CLK==0);
while(mouse_CLK==1);
ACK=mouse_SDA; //接收应答位
while(mouse_CLK==0);
EX1=1;
}
void Init_mouse(void)
{
host_to_mouse(0xf4);
delayms(50);
Init_ter();
delayms(50);
host_to_mouse(0xf3);
delayms(50);
host_to_mouse(0xc8);
delayms(50);
host_to_mouse(0xf3);
delayms(50);
host_to_mouse(0x64);
delayms(50);
host_to_mouse(0xf3);
delayms(50);
host_to_mouse(0x50);
delayms(50);
host_to_mouse(0xf2);
delayms(200);
mouse_data[0]=0;
mouse_data[1]=0;
mouse_data[2]=0;
mouse_data[3]=0;
move_x=10;
move_y=0;
move_z=0;
}
/*********************************************
奇校检
**********************************************/
uchar Checkout(void)
{
ACC=mouse_byte;
if(~P==mouse_buffer[9])
return 1;
else
return 0;
}
/*********************************************************
数据分析及处理
**********************************************************/
void data_analyse(void)
{
//将收到的11位信号中截取8位数据放进mouse_byte
mouse_byte_bit0=mouse_buffer[1];
mouse_byte_bit1=mouse_buffer[2];
mouse_byte_bit2=mouse_buffer[3];
mouse_byte_bit3=mouse_buffer[4];
mouse_byte_bit4=mouse_buffer[5];
mouse_byte_bit5=mouse_buffer[6];
mouse_byte_bit6=mouse_buffer[7];
mouse_byte_bit7=mouse_buffer[8];
if(Checkout())//如果校验正确
{
if(mouse_data_bit<4)
mouse_data[mouse_data_bit++]=mouse_byte;
if(mouse_data_bit==4)
{
mouse_data_bit=0;
if(mouse_data[0]&0x10)//如果"X sign bit"为1,表示鼠标向右左移
{
move_x-=(256-mouse_data[1]);//x坐标减
if(move_x<=1)move_x=17;
}
else
{
move_x+=mouse_data[1];//x坐标加
if(move_x>=17)move_x=2;
}
if(mouse_data[0]&0x20)
{
move_y-=(256-mouse_data[2]);//y坐标减
}
else
{
move_y+=mouse_data[2];//y坐标加
}
if(mouse_data[3]&0x08)
{
move_z-=(16-(mouse_data[3]&0x0f));
}
else
{
mouse_data[3]=mouse_data[3]&0x0f;
move_z+=mouse_data[3]; //Z坐标加
}
}
}
}
/**************************************************
外部中断1
***************************************************/
void ReceiveData(void) interrupt 2
{ led=0;
if(mouse_buffer_bit<=10)
{
while(mouse_CLK==0);//等待设备拉高时钟线
mouse_buffer[mouse_buffer_bit++]=mouse_SDA;//接收数据
}
if(mouse_buffer_bit==10)
{
data_analyse();//数据分析及处理
mouse_buffer_bit=0;
}
}
#endif
////////////////////////////////主函数部分////////////////////////////////////////////////////
#include
#include"TM1638.h"
#include"DS1302.h"
#include"DELAY.h"
#include"CHULI.h"
#include"DISPLAY.h"
void main()
{
delayms(500);
init_TM1638();
delayms(50);
Init_DS1302(); //将1302初始化
delay(500);
while(1)
{
read_date();
delayms(50);
}
}
/**********************************************/
再来一个按键测试的程序:这个是另外的,与上面的无关;
#ifndef _TM1638_H
#define _TM1638_H
#include
#define DATA_COMMAND 0X40
#define DISP_COMMAND 0x80
#define ADDR_COMMAND 0XC0
//引脚定义
sbit DIO=P1^0;
sbit CLK=P1^1;
sbit STB=P1^2;
unsigned char code
tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71
,0x40};
void TM1638_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
if(DATA&0X01)
DIO=1;
else
DIO=0;
DATA>>=1;
CLK=1;
}
}
unsigned char TM1638_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp=0;
DIO=1; //设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
CLK=0;
if(DIO)
temp|=0x80;
CLK=1;
}
return temp;
}
void Write_COM(unsigned char cmd)
{
STB=0;
TM1638_Write(cmd);
STB=1;
}
//发送命令字
unsigned char Read_key(void)
{
unsigned char c[4],i,key_value=0;
STB=0;
TM1638_Write(0x42); //读取键盘值
for(i=0;i<4;i++)
c[i]=TM1638_Read();
STB=1; //4个字节数据合成一个字节
for(i=0;i<4;i++)
key_value|=c[i];
for(i=0;i<4;i++)
if(c[i]==key_value)
break;
return (i*8+key_value);
}
void Write_DATA(unsigned char add,unsigned char DATA) //指定地址写入数据
{
Write_COM(0x44);
STB=0;
TM1638_Write(0xc0|add);
TM1638_Write(DATA);
STB=1;
}
/*void Write_oneLED(unsigned char num,unsigned char flag) //单独控制一个LED函数,num
为需要控制的led序号,flag为0时熄灭,不为0时点亮
{
if(flag)
Write_DATA(2*num+1,1);
else
Write_DATA(2*num+1,0);
}
void Write_allLED(unsigned char LED_flag) //控制全部LED函数,
LED_flag表示各个LED状态
{
unsigned char i;
for(i=0;i<8;i++)
{
if(LED_flag&(1<
Write_DATA(2*i+1,3);
else
Write_DATA(2*i+1,0);
}
} */
void init_TM1638(void)
{
unsigned char i;
Write_COM(0x8a);//亮度
Write_COM(0x40);
STB=0;
TM1638_Write(0xc0);
for(i=0;i<16;i++)
TM1638_Write(0x00);
STB=1;
}
#endif
#include
#include
#include "555.h"
unsigned char num[8]; //各个数码管显示的值
unsigned char x=0xff;
sbit key=P3^4;
int main(void)
{
init_TM1638();
system_init();
display(x);
delay_ms(200);
display1638();
while(1)
{
display1638();
// detectkey();
x=Read_key();
display(~x);
}
}
void display1638()
{ uchar i;
if(sec_flag|i)
{
num[0]=hour/10;
num[1]=hour%10;
num[3]=minute/10;
num[4]=minute%10;
num[6]=second/10;
num[7]=second%10;
num[2]=16;
num[5]=16;
for(i=0;i<8;i++)
{
Write_DATA(i*2,tab[num[i]]);
}
}
}
#ifndef _555_H
#define _555_H
#include
#define uchar unsigned char
void delay_ms(uchar);
void display();
void detectkey();
void display1638();
uchar code tap[10]={
0xC0,/*0*/
0xF9,/*1*/
0xA4,/*2*/
0xB0,/*3*/
0x99,/*4*/
0x92,/*5*/
0x82,/*6*/
0xF8,/*7*/
0x80,/*8*/
0x90,/*9*/
};
sbit key_hour=P3^5;
sbit key_min=P3^6;
uchar hour=12;
uchar minute=0;
uchar second=0;
uchar flag=0;
uchar sec_flag=0;
/*************************
初始化程序
**************************/
void system_init()
{ TMOD=0x01;
EA=1;
ET0=1;
EX0=1;
IT0=1;
TR0=1;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
}
/*************************
定时器中断0中断处理程序
**************************/
void int1_ISR() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
flag++;
if(flag==20)
{
sec_flag=1;
second++;
flag=0;
}
if(second==60)
{
second=0;
minute++;
}
if(minute==60)
{
minute=0;
hour++;
hour%=24;
}
}
/*************************
按键程序
**************************/
void detectkey()
{
delay_ms(10);
if(key_hour==0)
{
hour++;
hour=hour%24;
while(!key_hour)
display();
}
if(key_min==0)
{
minute++;
minute=minute%60;
while(!key_min)
display();
}
if(P3_7==0)
{
hour=12;
minute=0;
second=0;
while(!P3_5)
display();
}
}
/*************************
显示程序
**************************/
void display(uchar i)
{
P0=i;
}
/*************************
延时处理程序
**************************/
void delay_ms(uchar no)
{
uchar i,j;
for(i=0;i { for(j=0;j<164;j++); for(j=0;j<164;j++); } } #endif 说明:按键值送P0接的LED显示。其过程不影响数码管显示时间。 希望对各位有帮助!
2024年6月10日发(作者:练秀华)
一、 概述
二、 51单片机 ,TM1638芯片+DS1302驱动共阴数码管时钟,最后包括
按键检测程序(是分开的。)
TM1638是带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集
成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。主要应用于冰
箱、
空调 、家庭影院等产品的高段位显示屏驱动。
二、 特性说明
• 采用功率CMOS 工艺
• 显示模式 10 段×8 位
• 键扫描(8×3bit)
• 辉度调节电路(占空比8 级可调)
• 串行接口(CLK,STB,DIO)
• 振荡方式:RC 振荡(450KHz+5%)
• 内置上电复位电路
• 采用SOP28封装
三、、 管脚定
义:
电路图数码管:
程序代码:
/*************** TM1638.H头文件 *******************/
#ifndef _TM1638_H
#define _TM1638_H
//引脚定义
sbit DIO=P1^0;
sbit CLK=P1^1;
sbit STB=P1^2;
//写一个8Bit数据
void TM1638_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
if(DATA&0X01)
DIO=1;
else
DIO=0;
DATA>>=1;
CLK=1;
}
}
/*unsigned char TM1638_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp=0;
DIO=1; //设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
CLK=0;
if(DIO)
temp|=0x80;
CLK=1;
}
return temp;
} */
void Write_COM(unsigned char cmd) //发送命令字
{
STB=0;
TM1638_Write(cmd); //写命令
STB=1;
}
void Write_DATA(unsigned char add,unsigned char DATA) //指定地址写入数据
{
Write_COM(0x44);
STB=0;
TM1638_Write(0xc0|add); //地址高位为1:11** ****,写地址
TM1638_Write(DATA);
STB=1;
}
void init_TM1638(void)
{
unsigned char i;
Write_COM(0x8a);//亮度
Write_COM(0x40); //写 数据命令,写数据到显示寄存器
STB=0;
TM1638_Write(0xc0); //写地址命令
for(i=0;i<16;i++)
TM1638_Write(0x00);
STB=1;
}
#endif
/***************************DS1302.H头文件***************************/
#ifndef DS1302_H
#define DS1302_H
#define uchar unsigned char
#define uint unsigned int
#include"DELAY.h"
sbit acc0=ACC^0; //移位时的第0位
sbit acc7=ACC^7; //移位时用的第7位
uchar second,minute,hour,day,month,year,week,count=0;
uchar ReadValue,num,time;
sbit SCLK=P2^0;
sbit DATA=P2^1;
sbit RST=P2^2;
void Write1302(uchar dat)
{
uchar i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delay1(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写8个二进制位数据
{
DATA=dat&0x01; //取出dat的第0位数据写入1302
delay(2); //稍微等待,使硬件做好准备
SCLK=1; //上升沿写入数据
delay1(2); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}
}
void WriteSet1302(uchar Cmd,uchar dat)
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
delay1(2); //稍微等待,使硬件做好准备
Write1302(Cmd); //写入命令字
Write1302(dat); //写数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
}
uchar Read1302(void)
{
uchar i,dat;
delay(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续读8个二进制位数据
{
dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位
if(DATA==1) //如果读出的数据是1
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出
delay1(2); //稍微等待
SCLK=0; //拉低SCLK,形成脉冲下降沿
delay1(2); //稍微等待
}
return dat; //将读出的数据返回
}
uchar ReadSet1302(uchar Cmd)
{
uchar dat;
RST=0; //拉低RST
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
Write1302(Cmd); //写入命令字
dat=Read1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
return dat; //将读出的数据返回
}
void Init_DS1302(void)
{
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指
令
WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值
WriteSet1302(0x82,((41/10)<<4|(41%10))); //根据写分寄存器命令字,写入分的初始值
WriteSet1302(0x84,((15/10)<<4|(15%10))); //根据写小时寄存器命令字,写入小时的初始值
WriteSet1302(0x86,((29/10)<<4|(24%10))); //根据写日寄存器命令字,写入日的初始值
WriteSet1302(0x88,((2/10)<<4|(2%10))); //根据写月寄存器命令字,写入月的初始值
WriteSet1302(0x8c,((10/10)<<4|(11%10))); //nian
WriteSet1302(0x8a,((0/10)<<4|(0%10)));
WriteSet1302(0x8E,0x80); //根据写状态寄存器命令字,写入保护指令
}
#endif
/***************显示头文件*******************************/
#include"TM1638.h"
uchar data DisBuffer[8]={0,0,0,0,0,0,0,0}; /*显示缓存区*/ //各个数码管显示的值
uchar code
tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71
,0x40,0xef};
void display1638(uchar hour,uchar minute,uchar second)
{
uchar i;
DisBuffer[0]=hour/10;
DisBuffer[1]=hour%10;
DisBuffer[3]=minute/10;
DisBuffer[4]=minute%10;
DisBuffer[6]=second/10;
DisBuffer[7]=second%10;
DisBuffer[2]=16;
DisBuffer[5]=16;
for(i=0;i<8;i++)
{
Write_DATA(i*2,tab[DisBuffer[i]]);
}
}
void DisplayHour(newval)
{
DisBuffer[0]=newval/10;
DisBuffer[1]=newval%10;
for(i=0;i<2;i++)
{
Write_DATA(i*2,tab[DisBuffer[i]]);
}
}
#endif
/**********************************************************/
//下面是处理程序头文件,调试功能的实现,但是本人接调时的来源是
//是鼠标芯片,所以这里都写上,各位可以根据自己是按键还是其他的,做修改
/***********************************************/
#ifndef CHULI_H
#define CHULI_H
#define uchar unsigned char
#define uint unsigned int
#include"DISPLAY.h"
#include"DS1302.h"
void read_date(void)
{
ReadValue = ReadSet1302(0x81);
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x83);
minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x85);
hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x87);
day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x89);
month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x8d);
year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue=ReadSet1302(0x8b); //读星期
week=ReadValue&0x07;
display1638(hour,minute,second) ;
}
void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num)
{
newval=ReadSet1302(newaddr); //读取当前时
间
newval=((newval&0x70)>>4)*10+(newval&0x0f);
十进制
if(flag) //判断是加一还是减一
{
newval++;
switch(s1num)
{ case 1: if(newval>99) newval=0;
DisplayYear(newval);
break;
case 2: if(newval>12) newval=1;
DisplayMonth(newval);
break;
case 3: if(newval>31) newval=1;
DisplayDay(newval);
break;
case 4: if(newval>6) newval=0;
DisplayWeek(newval);
break;
case 5: if(newval>23) newval=0;
DisplayHour(newval);
break;
case 6: if(newval>59) newval=0;
DisplayMinute(newval);
break;
case 7: if(newval>59) newval=0;
DisplaySecond(newval);
break;
default:break;
}
}
else
{
newval--;
switch(s1num)
{ case 1: if(newval==0) newval=99;
//将bcd码转换成
DisplayYear(newval);
break;
case 2: if(newval==0) newval=12;
DisplayMonth(newval);
break;
case 3: if(newval==0) newval=31;
DisplayDay(newval);
break;
case 4: if(newval<0) newval=6;
DisplayWeek(newval);
break;
case 5: if(newval<0) newval=23;
DisplayHour(newval);
break;
case 6: if(newval<0) newval=59;
DisplayMinute(newval);
break;
case 7: if(newval<0) newval=59;
DisplaySecond(newval);
break;
default:break;
}
}
WriteSet1302((newaddr-1),((newval/10)<<4)|(newval%10));
入寄存器
}
void write_flsh(uchar com,uchar dat)
{ Write_DATA(com,tab[16]);
delay(100);
Write_DATA(com,tab[dat]);
}
void sp2_mouse(void)
{
uchar miao,z,flag=0;
rd=0;
miao=ReadSet1302(0x81);
second=miao;
WriteSet1302(0x80,miao|0x80);
while(1)
{ led=0;
///////////////////////////////////////
/* if((move_x<4)&&(flag==0))
//将新数据写
{
write_flash(0x02,1) ;
if((mouse_data[0]&0x01)&&(flag==1))
{
while(mouse_data[0]&0x01);
while(1)
{ write_flash(0x02,1) ;
z=move_x;
if(move_x>z)
{ delayms(10);
turn_val(year,1,0x8d,1);
}
if(z>move_x)
{delayms(10);
turn_val(year,0,0x8d,1);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=3;
z=move_x;
break;
}
}
}
}
///////////////////////////////////////////////////////
if((move_x>=4)&&(move_x<6)&&(flag==0))
{
write_com(0x87);
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{ z=move_x;
write_com(0x87);
if(move_x>z)
{ delayms(10);
turn_val(month,1,0x89,2);
}
if(z>move_x)
{delayms(10);
turn_val(month,0,0x89,2);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=5;
z=move_x;
break;
}
}
}
}
/////////////////////////////////////////////////////////
if((move_x>=6)&&(move_x<8)&&(flag==0))
{
write_com(0x8a);
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_com(0x8a);
if(move_x>z)
{ delayms(10);
turn_val(day,1,0x87,3);
}
if(z>move_x)
{ delayms(10);
turn_val(day,0,0x87,3);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=7;
z=move_x;
break;
}
}
}
}
///////////////////////////////////////////////////////////
if((move_x>=8)&&(move_x<10)&&(flag==0))
{
write_com(0x8e);
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_com(0x8e);
if(move_x>z)
{ delayms(10);
turn_val(week,1,0x8b,4);
}
if(z>move_x)
{delayms(10);
turn_val(week,0,0x8b,4);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=9;
z=move_x;
break;
}
}
}
} */
////////////////////////////////////////////////////////////
if((move_x>=10)&&(move_x<12)&&(flag==0))
{
write_flash(0x02,1) ;
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_flash(0x02,1) ;
if(move_x>z)
{ delayms(10);
turn_val(hour,1,0x85,5);
}
if(z>move_x)
{ delayms(10);
turn_val(hour,0,0x85,5);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=11;
z=move_x;
break;
}
}
}
}
//////////////////////////////////////////////////////////////
if((move_x>=12)&&(move_x<14)&&(flag==0))
{
write_com(0xc4) ;
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_com(0xc4) ;
if(move_x>z)
{ delayms(10);
turn_val(minute,1,0x83,6);
}
if(z>move_x)
{delayms(10);
turn_val(minute,0,0x83,6);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=13;
z=move_x;
break;
}
}
}
}
//写入分寄存器
//写入分寄存器
////////////////////////////////////////////////////////////////
if((move_x>=14)&&(flag==0))
{
write_com(0xc7);
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
while(1)
{
z=move_x;
write_com(0xc7);
if(move_x>z)
{ delayms(10);
turn_val(second,1,0x81,7);
}
if(z>move_x)
{delayms(10);
turn_val(second,0,0x81,7);
}
if(mouse_data[0]&0x01)
{
while(mouse_data[0]&0x01);
flag=1;
move_x=15;
z=move_x;
break;
}
}
}
}
///////////////////////////////////////////////////////////////
if((mouse_data[0]&0x01)&&(z!=move_x))
{flag=0;
while(mouse_data[0]&0x01);
}
//////////////////////////////////////////////////////////////
if((mouse_data[0]&0x01)&&(flag==1)&&(z==move_x))
{flag=0;
delayms(300);
miao=ReadSet1302(0x81);
second=miao;
WriteSet1302(0x80,second&0x7f);
write_com(0x0c) ;
WriteSet1302(0x8E,0x80); //根据写状态寄存器命令字,
写入不保护指令
break;
}
}
}
#endif
/*********鼠标芯片*****/
#ifndef PS2_H
#define PS2_H
#include"DELAY.h"
sbit mouse_SDA=P3^4;//数据线P3_5 计数器0输入端口
sbit mouse_CLK=P3^3;//时钟线P3_3 外部中断1输入端口
sbit led=P3^6;
bit pp=0;
bit ACK=0;
uchar bdata mouse_byte; //接收字节 bdata-->可寻址的片内RAM
sbit mouse_byte_bit0=mouse_byte^0;//mouse_byte第0位
sbit mouse_byte_bit1=mouse_byte^1;//mouse_byte第1位
sbit mouse_byte_bit2=mouse_byte^2;//mouse_byte第2位
sbit mouse_byte_bit3=mouse_byte^3;//mouse_byte第3位
sbit mouse_byte_bit4=mouse_byte^4;//mouse_byte第4位
sbit mouse_byte_bit5=mouse_byte^5;//mouse_byte第5位
sbit mouse_byte_bit6=mouse_byte^6;//mouse_byte第6位
sbit mouse_byte_bit7=mouse_byte^7;//mouse_byte第7位
uchar mouse_buffer[11];//接收位数据缓冲区
uchar mouse_buffer_bit=0;//mouse_buffer[mouse_buffer_bit]
uchar mouse_data[4];//接收鼠标数据缓冲区,分别存放:功能信息字节,x位移量,y位移量
uchar mouse_data_bit=0;//mouse_data[mouse_data_bit]
uchar move_x;//存放横坐标
uint move_y;//存放纵坐标
uchar move_z;
extern uchar move_x;
/***********************************************************************
发送数据
************************************************************************/
void Init_ter(void)
{
EA=1; //开放中断
EX1=1;//允许外部中断1
PX1=1;//设置中断优先级 设外部中断1为最高优先级别
}
void host_to_mouse(uchar cmd)
{
uchar i;
EX1=0;
mouse_CLK=0;
delay100;
delay100;
ACC=cmd;
pp=~P; //获得奇偶校验位
mouse_SDA=0;
mouse_CLK=1;
for(i=0;i<8;i++)
{
while(mouse_CLK==1);
mouse_SDA=cmd&0x01;
cmd>>=1;
while(mouse_CLK==0);
}
while(mouse_CLK==1);
mouse_SDA=pp; //发送奇偶校验位
while(mouse_CLK==0);
while(mouse_CLK==1);
mouse_SDA=1;
while(mouse_CLK==0);
while(mouse_CLK==1);
ACK=mouse_SDA; //接收应答位
while(mouse_CLK==0);
EX1=1;
}
void Init_mouse(void)
{
host_to_mouse(0xf4);
delayms(50);
Init_ter();
delayms(50);
host_to_mouse(0xf3);
delayms(50);
host_to_mouse(0xc8);
delayms(50);
host_to_mouse(0xf3);
delayms(50);
host_to_mouse(0x64);
delayms(50);
host_to_mouse(0xf3);
delayms(50);
host_to_mouse(0x50);
delayms(50);
host_to_mouse(0xf2);
delayms(200);
mouse_data[0]=0;
mouse_data[1]=0;
mouse_data[2]=0;
mouse_data[3]=0;
move_x=10;
move_y=0;
move_z=0;
}
/*********************************************
奇校检
**********************************************/
uchar Checkout(void)
{
ACC=mouse_byte;
if(~P==mouse_buffer[9])
return 1;
else
return 0;
}
/*********************************************************
数据分析及处理
**********************************************************/
void data_analyse(void)
{
//将收到的11位信号中截取8位数据放进mouse_byte
mouse_byte_bit0=mouse_buffer[1];
mouse_byte_bit1=mouse_buffer[2];
mouse_byte_bit2=mouse_buffer[3];
mouse_byte_bit3=mouse_buffer[4];
mouse_byte_bit4=mouse_buffer[5];
mouse_byte_bit5=mouse_buffer[6];
mouse_byte_bit6=mouse_buffer[7];
mouse_byte_bit7=mouse_buffer[8];
if(Checkout())//如果校验正确
{
if(mouse_data_bit<4)
mouse_data[mouse_data_bit++]=mouse_byte;
if(mouse_data_bit==4)
{
mouse_data_bit=0;
if(mouse_data[0]&0x10)//如果"X sign bit"为1,表示鼠标向右左移
{
move_x-=(256-mouse_data[1]);//x坐标减
if(move_x<=1)move_x=17;
}
else
{
move_x+=mouse_data[1];//x坐标加
if(move_x>=17)move_x=2;
}
if(mouse_data[0]&0x20)
{
move_y-=(256-mouse_data[2]);//y坐标减
}
else
{
move_y+=mouse_data[2];//y坐标加
}
if(mouse_data[3]&0x08)
{
move_z-=(16-(mouse_data[3]&0x0f));
}
else
{
mouse_data[3]=mouse_data[3]&0x0f;
move_z+=mouse_data[3]; //Z坐标加
}
}
}
}
/**************************************************
外部中断1
***************************************************/
void ReceiveData(void) interrupt 2
{ led=0;
if(mouse_buffer_bit<=10)
{
while(mouse_CLK==0);//等待设备拉高时钟线
mouse_buffer[mouse_buffer_bit++]=mouse_SDA;//接收数据
}
if(mouse_buffer_bit==10)
{
data_analyse();//数据分析及处理
mouse_buffer_bit=0;
}
}
#endif
////////////////////////////////主函数部分////////////////////////////////////////////////////
#include
#include"TM1638.h"
#include"DS1302.h"
#include"DELAY.h"
#include"CHULI.h"
#include"DISPLAY.h"
void main()
{
delayms(500);
init_TM1638();
delayms(50);
Init_DS1302(); //将1302初始化
delay(500);
while(1)
{
read_date();
delayms(50);
}
}
/**********************************************/
再来一个按键测试的程序:这个是另外的,与上面的无关;
#ifndef _TM1638_H
#define _TM1638_H
#include
#define DATA_COMMAND 0X40
#define DISP_COMMAND 0x80
#define ADDR_COMMAND 0XC0
//引脚定义
sbit DIO=P1^0;
sbit CLK=P1^1;
sbit STB=P1^2;
unsigned char code
tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71
,0x40};
void TM1638_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK=0;
if(DATA&0X01)
DIO=1;
else
DIO=0;
DATA>>=1;
CLK=1;
}
}
unsigned char TM1638_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp=0;
DIO=1; //设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
CLK=0;
if(DIO)
temp|=0x80;
CLK=1;
}
return temp;
}
void Write_COM(unsigned char cmd)
{
STB=0;
TM1638_Write(cmd);
STB=1;
}
//发送命令字
unsigned char Read_key(void)
{
unsigned char c[4],i,key_value=0;
STB=0;
TM1638_Write(0x42); //读取键盘值
for(i=0;i<4;i++)
c[i]=TM1638_Read();
STB=1; //4个字节数据合成一个字节
for(i=0;i<4;i++)
key_value|=c[i];
for(i=0;i<4;i++)
if(c[i]==key_value)
break;
return (i*8+key_value);
}
void Write_DATA(unsigned char add,unsigned char DATA) //指定地址写入数据
{
Write_COM(0x44);
STB=0;
TM1638_Write(0xc0|add);
TM1638_Write(DATA);
STB=1;
}
/*void Write_oneLED(unsigned char num,unsigned char flag) //单独控制一个LED函数,num
为需要控制的led序号,flag为0时熄灭,不为0时点亮
{
if(flag)
Write_DATA(2*num+1,1);
else
Write_DATA(2*num+1,0);
}
void Write_allLED(unsigned char LED_flag) //控制全部LED函数,
LED_flag表示各个LED状态
{
unsigned char i;
for(i=0;i<8;i++)
{
if(LED_flag&(1<
Write_DATA(2*i+1,3);
else
Write_DATA(2*i+1,0);
}
} */
void init_TM1638(void)
{
unsigned char i;
Write_COM(0x8a);//亮度
Write_COM(0x40);
STB=0;
TM1638_Write(0xc0);
for(i=0;i<16;i++)
TM1638_Write(0x00);
STB=1;
}
#endif
#include
#include
#include "555.h"
unsigned char num[8]; //各个数码管显示的值
unsigned char x=0xff;
sbit key=P3^4;
int main(void)
{
init_TM1638();
system_init();
display(x);
delay_ms(200);
display1638();
while(1)
{
display1638();
// detectkey();
x=Read_key();
display(~x);
}
}
void display1638()
{ uchar i;
if(sec_flag|i)
{
num[0]=hour/10;
num[1]=hour%10;
num[3]=minute/10;
num[4]=minute%10;
num[6]=second/10;
num[7]=second%10;
num[2]=16;
num[5]=16;
for(i=0;i<8;i++)
{
Write_DATA(i*2,tab[num[i]]);
}
}
}
#ifndef _555_H
#define _555_H
#include
#define uchar unsigned char
void delay_ms(uchar);
void display();
void detectkey();
void display1638();
uchar code tap[10]={
0xC0,/*0*/
0xF9,/*1*/
0xA4,/*2*/
0xB0,/*3*/
0x99,/*4*/
0x92,/*5*/
0x82,/*6*/
0xF8,/*7*/
0x80,/*8*/
0x90,/*9*/
};
sbit key_hour=P3^5;
sbit key_min=P3^6;
uchar hour=12;
uchar minute=0;
uchar second=0;
uchar flag=0;
uchar sec_flag=0;
/*************************
初始化程序
**************************/
void system_init()
{ TMOD=0x01;
EA=1;
ET0=1;
EX0=1;
IT0=1;
TR0=1;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
}
/*************************
定时器中断0中断处理程序
**************************/
void int1_ISR() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
flag++;
if(flag==20)
{
sec_flag=1;
second++;
flag=0;
}
if(second==60)
{
second=0;
minute++;
}
if(minute==60)
{
minute=0;
hour++;
hour%=24;
}
}
/*************************
按键程序
**************************/
void detectkey()
{
delay_ms(10);
if(key_hour==0)
{
hour++;
hour=hour%24;
while(!key_hour)
display();
}
if(key_min==0)
{
minute++;
minute=minute%60;
while(!key_min)
display();
}
if(P3_7==0)
{
hour=12;
minute=0;
second=0;
while(!P3_5)
display();
}
}
/*************************
显示程序
**************************/
void display(uchar i)
{
P0=i;
}
/*************************
延时处理程序
**************************/
void delay_ms(uchar no)
{
uchar i,j;
for(i=0;i { for(j=0;j<164;j++); for(j=0;j<164;j++); } } #endif 说明:按键值送P0接的LED显示。其过程不影响数码管显示时间。 希望对各位有帮助!