一、设计目的:
通过单片机应用产品的设计与调试过程,巩固课程所学理论知识,初步了解单片机应用系统设计与调试的方法。
二、设计要求:
设计一个以at89s51单片机为核心的数字电子钟控制器,实现电子钟的时间、日期交替显示、闹钟功能,并可通过按钮开关或键盘切换显示内容、调整参数、设置闹钟,在单片机实验板上模拟调试实现控制器的功能。具体设计要求如下:
1.开机自检,检查相关接口及数码管显示器、指示灯、蜂鸣器等外设是否正常。
2.8位数码管显示器平常以一定的时间间隔、合适的格式显示时间和日期信息,时间显示时、分、秒;日期显示年(2000~2099)、月、日;设置闹钟功能时显示时、分、开/关状态。
3.可通过按键设定时间、日期、闹钟等参数、手动切换显示。按键可用独立式按键或行列式键盘实现。设定参数过程有合适的方式指示当前可修改的内容。
4.对开关量输入进行软件消抖动处理,参数的设定有容错处理,如:小时不能超过23,日期中每月最大天数、闰年等。
5.用protel设计可实现上述功能的控制器的原理图(最小应用系统)。
扩展功能(选做):
1.可设置多次闹钟。
2.显示星期功能。
3.参数设定过程中,较长时间无操作,则自动恢复为正常显示方式。。
4.其它自选的扩展功能。
三、总体方案设计及说明
总体功能框图:
硬件:
8个led采用动态扫描以节约驱动成本;
走时采用内部t0计时中断;
4x4矩阵键盘扫描采用线反转法,以中断扫描计数防止抖动;
……
软件:
采用c语言实现。
四、系统资源分配说明(接口、存储器分配)
1.接口:
89s51的p1口接8个led小灯;
89s51的p3_2接蜂鸣器(低电平鸣响);
外扩一片8255:
89s51单片机的p0口是低8位地址与数据复用的,现在我们用74hc373分离出地址,89s51高位地址的p2_0(a8)接8255的片选端(/cs), 低位地址q1q0(a1a0)与8255的a1a0连接,数据位p0_7~p0_0分别接8255的d_7~d_0。 以此得到的8255端口的地址分别为:
pa:xxxxxxx0 xxxxxx00取0x0fefc; pb:xxxxxxx0 xxxxxx01取0x0fefd;
pc:xxxxxxx0 xxxxxx10取0x0fefd; ctl:xxxxxxx0 xxxxxx11取0x0feff;
8255的pa口控制led数码管的8个显示段;pb口分别接8个led数码管的共阳极;
pc口分别接4x4矩阵键盘的行线和列线。
2.存储分配:
struct{ //闹钟时、分、秒 ,共设6个闹钟(初始状态默认:00-00-f1)
uchar hour;
uchar minute;
uchar ison;
}alarm[6]={{0,0,0}};
uchar hour=12,minute=0,second=0;//时、分、秒
uchar temp_second; //用于立即切换显示时间/日期
uint year=2011;// 年
uchar month=12;// 月
uchar day=1; // 日
uchar week=6;// 星期
uchar mdays[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//各月天数
uchar alarm_ison=1; //闹钟总开关
uchar alarm_station=0; //闹钟状态
uchar ano; //闹钟号(当前时间到的闹钟号)
uchar start_minute;//开始响铃的时间(也就是所定闹钟的时间)
uint count_ms25=0; //软件计数器(计数40个25毫秒达1s)
uchar show_model=0; // 显示模式:[0]切换显示时间/日期 [1]切换显示日期/时间
const uchar fixtime=0x00;//时间修正量
uchar key=0xff;//获得的当前键值
uchar last_key=0xff; //最后一次扫描到的按键(非0xff)
uchar key_count=0;//扫描到同一按键的次数
uchar edown=0; //闹钟开关键是否按下
uchar led_buf[8]={24,24,24,24,24,24,24,24}; //时间日期显示缓冲区
uchar code led_table1[]={0x0c0,0x0f9,0x0a4,0x0b0, 0x99,0x92,0x82,0x0f8,0x80,0x90,
0x88,0x83,0x0c6,0x0a1,0x86,0x8e,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
0x08,0x03,0x46,0x21,0x06,0x0e,0x7f,0x0bf,0xff};//数码管段码
uchar code kbtable[] = {‘1’,‘2’,‘3’,‘f’,‘4’,‘5’,‘6’,‘e’,‘7’,‘8’,‘9’,‘c’,‘0’,‘a’,‘b’,‘d’};//键值(可有可无)
五、软件流程图及说明
1.流程图:
2.主要程序段说明:
(1)显示:
动态显示:即各位数码管轮流点亮,对于显示器各位数码管,每隔一段延时时间循环点亮一次。利用人的视觉暂留功能可以看到整个显示,但须保证扫描速度足够快,人的视觉暂留功能才可察觉不到字符闪烁。显示器的亮度与导通电流、点亮时间及间隔时间的比例有关。调整参数可以实现较高稳定度的显示。动态显示节省了驱动和i/o口,降低了能耗。
void led_show(uchar buf[])
{
uchar i,num,pled=0x80;
for(i=0;i《8;i++)
{
num=buf[i];
pa=led_table1[num]; /*送字段码*/
pb=pled; /*送字位码*/
pled》》=1; /*右移一位*/
delay(1); /*延时*/
}
}
(2)键盘(本次设计对下面两种扫描方式都进行了实现):
a.行扫描法:依次从第一至最末行线上发出低电平信号, 如果该行线所连接的键没有按下的话, 则列线所接的端口得到的是全“1”信号, 如果有键按下的话, 则得到非全“1”信号。
/*键盘扫描(行扫描法,延时消抖)********************************************************
uchar code kbtable[] = {
0xee,‘1’,0xde,‘4’,0xbe,‘7’,0x7e,‘0’,
0xed,‘2’,0xdd,‘5’,0xbd,‘8’,0x7d,‘a’,
0xeb,‘3’,0xdb,‘6’,0xbb,‘9’,0x7b,‘b’,
0xe7,‘f’,0xd7,‘e’,0xb7,‘c’,0x77,‘d’,
0x00,0xff};
uchar get_key(void); // 获取最终键值
{ uchar i;
uchar line, row, k_value;
static uchar lastkey=0xff;
ctl=0x88; //ch输入,cl输出 10001000
pc=pc & 0xf0; // pc0~pc3输出0 , 输入pc4~ pc7(默认1无键按下)
if ((pc & 0xf0) == 0xf0)
{
lastkey=0xff;
return 0xff; //无键按下
}
row = pc;
delay(4); //延时,消除抖动
if (row != pc)
{
lastkey=0xff;
return 0xff; //判为抖动
}
line=0xfe;
for (i=0;i《4;i++)
{ pc = line; //输出扫描信号
row=pc; //读键盘口
if ((row & 0xf0) != 0xf0)
break;
line=(line《《1)+1;
}
if (i==4)
{ lastkey=0xff; return 0xff; }
k_value = (row & 0xf0) “ (line & 0x0f) ;
for (i=0; i《32; i+=2)
if (k_value == kbtable[i])
break;
if(lastkey==kbtable[i+1])
return 0xff;
lastkey=kbtable[i+1];
return kbtable[i+1];
}
b.线反转法:线反转法也是识别闭合键的一种常用方法, 该法比行扫描速度快, 但在硬件上要求行线与列线外接上拉电阻。先将行线作为输出线, 列线作为输入线, 行线输出全“0”信号, 读入列线的值, 那么在闭合键所在的列线上的值必为0;然后从列线输出全“0”信号,再读取行线的输入值,闭合键所在的行线值必为 0。这样,当一个键被按下时, 必定可读到一对唯一的行列值。再由这一对行列值可以求出闭合键所在的位置。
//一次键盘扫描(线反转法,中断扫描计数去抖)*********************************************************
uchar code kbtable[] = {‘1’,‘2’,‘3’,‘f’,‘4’,‘5’,‘6’,‘e’,‘7’,‘8’,‘9’,‘c’,‘0’,‘a’,‘b’,‘d’};
//key_index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
uchar key_scan(void) //返回 ‘0’,‘1’,‘2’。..‘e’,‘f’,0xff
{ uchar key_index,temp=0;
ctl=0x88; //ch输入,cl输出 10001000
pc=pc & 0xf0; //将低四位置0
if(pc!=0xf0) //判断按键是否按下 如果按钮按下 会拉低ch其中的一个端口
{
temp=pc; //读pc口
temp=temp&0xf0; //屏蔽低四位
temp=~
三相逆变电路工作原理
苹果电脑最佳选择:aigo国民好物固态U盘U393+WTG系统
C++中函数重载的使用
电流隔离的LVDS接口
2021年5G手机的出货量达4.5亿,苹果也将推出5G新品
AT89S51单片机对数字电子钟的设计
DEKRA德凯受邀参加LNEC8-第8届中国锂电(钠电)新能源千人大会
PCBA加工中DIP插件的工艺流程介绍
现代半导体产业的诞生和信息时代正式开启
新加坡的智能举措是如何形成的
旗舰将至 诺基亚Edge,令人惊艳的双曲面5.7英寸4K屏幕
云计算基础知识汇总(概念、工作原理、优势、类型)
唐麦科技“四核双动圈”耳机
预测:2020年全球指纹识别芯片市场规模将近50亿美元
优化EEG放大器的性能并降低功耗
5G毫米波未来将如何发展?
三星直接跳过4nm先进工艺,将要批量生产3nm工艺
USB音量控制器的制作
git rebase与相关git merge命令比较
全球最小单片机问世——Microchip推出业界首款6引脚单