最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

TM1638芯片+DS1302驱动共阴数码管时钟

IT圈 admin 24浏览 0评论

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显示。其过程不影响数码管显示时间。

希望对各位有帮助!

发布评论

评论列表 (0)

  1. 暂无评论