这是我做的单片机减一秒表计数设计,包含硬件电路相关介绍以及各部分原理说明。
最后附上软件部分的程序设计流程图以及相关的程序编写内容。
大家有需要的可以下载参考。
减1秒表设计(两位的LED数码减1数码显示,采用定时/计数器实现定时控制,能实现开始计数、停止计数和清零控制等功能)。
数值从99减到0,能启动开始计数、暂停、复位到99重新计数,对于实验室单片机硬件设备可用8255扩展的8位七段LED显示器选其两位进行显示,3种功能可用矩阵键盘来控制实现,1秒倒计时可用定时器T0选择模式2实现。
硬件设计(包括设计方案及说明、完整的硬件连接图等)
设计方案:2位七段LED显示器显示,定时器选用T0,选择模式2,采用内部中断,矩阵键盘控制不同情况。(停止计数可用使定时器停止工作和使LED显示当前数2种方法实现,这里选用使LED显示当前数暂停)
说明:选其1,2位七段LED显示器分别作为十位和个位,读其矩阵键盘键值进行判断再改变工作状态:
硬件连接:8255扩展七段LED显示器及矩阵键盘即可。
LED显示原理:
①实验箱上8155扩展的有8位七段LED显示器,采用动态方式驱动。即一位LED显示器显示一小段时间,然后是下一位LED显示器显示一段小时间。只要刷新频率不小于50Hz,利用人眼的视觉误差,就可以获得清晰稳定的显示效果。
②LED显示器的各段由8155的B口驱动,各段的驱动位如表;段引脚为低电平则对应段发光,高电平则对应段熄灭,显示字的字形代码如表;8个LED的选择位由8255的A口驱动,高电平则选中对应位,低电平则对应位熄灭。
程序流程图
单片机源程序编写:代码:
- #include <intrins.h>
- #include < absacc.h >
- #include<reg52.h>
- #define COM8155 XBYTE[0x1000] //8155写命令地址口
- #define PA8155 XBYTE[0x1001] //PA口读写地址口
- #define PB8155 XBYTE[0x1002] //PB口读写地址口
- #define PC8155 XBYTE[0x1003] //PC口读写地址口
- code unsigned char led_font[] = {0xc0,0xf9,0xa4,0xb0,
- 0x99,0x92,0x82,0xf8,
- 0x80,0x90,0x88,0x83,
- 0xc6,0xa1,0x86,0x8e,
- 0xff
- }; //共阴数码管0-9、a-f及全熄的字形码
- code unsigned char key_code[]={0x11,0x12,0x14,0x18,
- 0x21,0x22,0x24,0x28,
- 0x41,0x42,0x44,0x48,
- 0x81,0x82,0x84,0x88}; //此数组为键盘编码
- unsigned char key_read(void); //读键盘函数
- unsigned char led_data[8]={16,16,16,16,16,16,16,16};//当前的显示数字
- void delay_ms(unsigned charn); //延时程序
- void led_display(unsignedchar *p ); //LED动态显示子程序
- unsigned int m;
- void led_display(unsigned char *p)
- { unsigned char i;
- unsigned char j;
- unsigned char led_bit[8]={0x10,0x20,0x40,0x80,0x01,0x02,0x04,0x08};
- //LED的位选码表
- for (i=0;i<2;i++)
- {
- PB8155 =led_font[p[ i]];
- PA8155 = led_bit[ i];
- for (j=0;j<125;j++);
- }
- }
- void delay_ms(unsigned char n) //延时Nms
- {
- unsigned char i;
- while(n--) // 对于11.0592M时钟,约延时1ms
- {
- for (i=0;i<125;i++);
- }
- }
- unsigned char n=1; //用于暂停时等待再次启动的while循环
- unsigned char second; //定义计数second
- void main (void) //主函数
- {
- TMOD=0X02; //选定时器0,工作方式2
- TH0=0X06; //设定定时器初值
- TL0=0X06;
- ET0=1; //开定时器中断
- EA=1; //允许CPU中断
- second=99; //设定second初值99
- COM8155 = 0x03; //C口输入,A、B口输出
- while(1) //等待启动键0按下
- { n=1;
- if(key_read()==0) //按下启动键0
- {
- TR0=1; //开始计数
- }
- }
- }
- void t0(void) interrupt 1 using 0 //TL0计数溢出时进入中断函数
- {m++; //每次进入中断函数m++
- {
- led_display(led_data); //调用LED显示程序
- if(m==85) //m==85时一秒
- {
- m=0; //使m=0,用于下次m再计时
- second--; //到达一秒时当前值减1
- led_data[0]=second/10; //送出当前值显示(十位)
- led_data[1]=second%10; //(个位)
- }
- else //未到一秒时显示当前值
- {
- led_data[0]=second/10;
- led_data[1]=second%10;
- }
- if(second==-1) //second<0时再赋值99循环
- {
- second=99;
- }
- if(key_read()==1) //按下暂停键1时
- {
- while(n) //循环显示当前值
- {
- led_data[0]=second/10;
- led_data[1]=second%10;
- led_display(led_data); //调用LED显示程序
- if(key_read()==0) //再次按下启动键0时,n==0,跳出while循环
- {
- TR0=0;
- n=0;
- }
- }
- }
- if(key_read()==2) //按下复位键时,second=99
- {second=99;
- led_data[0]=second/10;
- led_data[1]=second%10;
- }
- }
- }
- unsigned char key_read(void) //读键盘值,PA低四位为输出端即键盘列输出端,PC低四位为输入端即键盘行输入端
- {
- unsigned char i,scandata;
- //col_out输出PA口低四位,row_in获取PC口低四位,组合成键码
- unsigned char key_current,col_out,row_in;
- scandata=0x01; //设定扫描初值
- PA8155=0x0f;
- delay_ms(5);
- if((PC8155&0x0f)==0x00) //无按键按下,防止读取不到键值,比如说是干扰
- {
- return 0xff;
- }
- for(i=0;i<4;i++)
- {
- PA8155=scandata; //PA口低四位循环输出0,扫描键盘
- col_out=0x0f&scandata; //存储PA口扫描的低四位
- if((PC8155&0x0f)!=0x00) //再次检测PC口低四位是否有低电平
- {
- row_in=(PC8155&0x0f)<<4; //存储PC口的低四位
- key_current=row_in+col_out; //key存储键盘编码,键码为行(高4位)加列(低4位)
- }
- scandata=_crol_(scandata,1); //此函数功能为左循环移位
- }
- for(i=0;i<16;i++) //查表获得相应的16进制值存放key_result中
- {
- if(key_current==key_code)
- {
- return i;
- }
- }
- return 0xff;
- }