凌阳61单片机使用7段数码管显示数字时钟的程序
- 格式:doc
- 大小:76.00 KB
- 文档页数:5
七段数码管显示设计报告目录一、设计任务二、题目分析与整体构思三、硬件电路设计四、程序设计五、心得体会一.设计任务数码的显示方式一般有三种:第一种是字型重叠式;第二种是分段式;第三种是点阵式。
目前以分段式应用最为普遍,主要器件是七段发光二极管(LED)显示器。
它可分为两种,一是共阳极显示器(发光二极管的阳极都接在一个公共点上),另一是共阴极显示器(发光二极管的阳极都接在一个公共点上,使用时公共点接地)。
数码管动态扫描显示,是将所用数码管的相同段(a~g 和p)并联在一起,通过选位通信号分时控制各个数码管的公共端,循环依次点亮各个数码管。
当切换速度足够快时,由于人眼的“视觉暂留”现象,视觉效果将是数码管同时显示。
根据七段数码管的显示原理,设计一个带复位的七段数码管循环扫描程序,本程序需要着重实现两部分:1. 显示数据的设置:程序设定4 位数码管从左至右分别显示1、2、3、4;2. 动态扫描:实现动态扫描时序。
利用EXCD-1 开发板实现七段数码管的显示设计,使用EXCD-1 开发板的数码管为四位共阴极数码管,每一位的共阴极7 段数码管由7 个发光LED 组成,7 个发光LED 的阴极连接在一起,阳极分别连接至FPGA相应引脚。
四位数码管与FPGA 之间通过8 位拨码开关(JP1)进行连接。
二.题目分析与整体构思使用EXCD-1 开发板的数码管为四位共阴极数码管,每一位的共阴极7 段数码管由7个发光LED 组成,呈“”字状,7 个发光LED 的阴极连接在一起,阳极分别连接至FPGA 相应引脚。
SEG_SEL1、SEG_SEL2、SEG_SEL3 和SEG_SEL4 为四位7 段数码管的位选择端。
当其值为“1”时,相应的7 段数码管被选通。
当输入到7 段数码管SEG_A~ SEG_G 和SEG_DP 管脚的数据为高电平时,该管脚对应的段变亮,当输入到7 段数码管SEG_A~SEG_G 和SEG_DP 管脚的数据为低电平时,该管脚对应的段变灭。
附录A 八位七段数码管显示程序library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;--------------------------------------------------------------------entity led isport( clk : in std_logic; --Clock Signaldata_in : in std_logic_vector(7 downto 0); --data busledag : out std_logic_vector(6 downto 0); --定义七位输出信号sel : out std_logic_vector(2 downto 0) --ledag Select);end led;--------------------------------------------------------------------architecture behave of led issignal dcount : std_logic_vector(2 downto 0);signal adh,adl : std_logic_vector(6 downto 0);signal adcount : std_logic_vector(7 downto 0);signal din_h,din_l : std_logic_vector(3 downto 0);signal coclk : std_logic;beginprocess(clk) --out enable signalbeginif(clk'event and clk='1') thenif adcount="10000000" thencoclk<='1';adcount<="00000000";elseadcount<=adcount+1;coclk<='0';end if;end if;end process;process(clk) --rd the adc databeginif(clk'event and clk='1') thendin_h<=data_in(7 downto 4);din_l<=data_in(3 downto 0);end if;end process;process(clk)begincase din_h iswhen "0000"=>adh<="0111111"; --display 0when "0001"=>adh<="0000110"; --display 1when "0010"=>adh<="1011011"; --display 2when "0011"=>adh<="1001111"; --display 3when "0100"=>adh<="1100110"; --display 4when "0101"=>adh<="1101101"; --display 5when "0110"=>adh<="1111101"; --display 6when "0111"=>adh<="0000111"; --display 7when "1000"=>adh<="1111111"; --display 8when "1001"=>adh<="1101111"; --display 9when "1010"=>adh<="1110111"; --display awhen "1011"=>adh<="1111100"; --display bwhen "1100"=>adh<="0111001"; --display cwhen "1101"=>adh<="1011110"; --display dwhen "1110"=>adh<="1111001"; --display ewhen "1111"=>adh<="1110001"; --display fwhen others=>adh<=adh; --no changeend case;case din_l iswhen "0000"=>adl<="0111111"; --display 0when "0001"=>adl<="0000110"; --display 1when "0010"=>adl<="1011011"; --display 2when "0011"=>adl<="1001111"; --display 3when "0100"=>adl<="1100110"; --display 4when "0101"=>adl<="1101101"; --display 5when "0110"=>adl<="1111101"; --display 6when "0111"=>adl<="0000111"; --display 7when "1000"=>adl<="1111111"; --display 8when "1001"=>adl<="1101111"; --display 9when "1010"=>adl<="1110111"; --display awhen "1011"=>adl<="1111100"; --display bwhen "1100"=>adl<="0111001"; --display cwhen "1101"=>adl<="1011110"; --display dwhen "1110"=>adl<="1111001"; --display ewhen "1111"=>adl<="1110001"; --display fwhen others=>adl<=adl; --no changeend case;end process;process(coclk) --display processbeginif(coclk'event and coclk='1') thendcount<=dcount+1;sel<=dcount;case dcount iswhen "000"=>ledag<="1000000";when "001"=>ledag<="1000000";when "010"=>ledag<="1000000";when "011"=>ledag<=adh;when "100"=>ledag<=adl;when "101"=>ledag<="1000000";when "110"=>ledag<="1000000";when "111"=>ledag<="1000000";when others=>ledag<="0000000";end case;end if;end process;end behave;。
//=========================================================================== //// The information contained herein is the exclusive property of// Sunplus Technology Co. And shall not be distributed, reproduced,// or disclosed in whole in part without prior written permission.//// (C) COPYRIGHT 2001 SUNPLUS TECHNOLOGY CO.// ALL RIGHTS RESERVED//// The entire notice above must be reproduced on all authorized copies.////=========================================================================== =// 工程名称:Time.scs; Time.spj "语音播报电子钟"// 功能描述: 结合"61板"的三个按键完成带有语音播报功能的电子钟:// 1、KEY1--按一下播放年、月、日,再按一下播放时、分;(I/O口A0)// 连续按3s,则进入调整状态;调整状态下调整内容的切换// 2、KEY2--年、月、日、时、分的增加(I/O口A0)// 3、KEY3--年、月、日、时、分的减少(I/O口A0)// 文件来源:61板说明书// IDE环境:SUNPLUS u'nSPTM IDE 1.8.0(or later)//// 涉及的库:(a) C-Lib: (CMacro.lib);// (b) SACM-Lib: SacmV25.lib;Sacmv32e.lib// 硬件连接:针对配合SPCE061A精简开发板使用// 组成文件:// main.c// FIQ.asm/key.asm/system.asm// hardware.asm/Resource.asm// Time.h/Resource.inc// 日期: 2003-5-22(建立)// 2003-6-16(添加版本说明及版权声明)// 2003-7-16(代码标准化)//=========================================================================== ===#include "a2000.h"#include "consist.h"unsigned int SpeechAdjustTemp=0; //读时间中间变量unsigned int Key=0;unsigned int KeyPressFlag=0; //有键按下标志unsigned int TimeCount = 0; //两分钟计时单元unsigned int SleepFlag=0; //睡眠标志unsigned int TimeChangeCount=0; //校时状态下按键计时unsigned int KeyStatus=0; //校时状态还是报时状态,1-----校时unsigned int KeyAdjust=0; //0-YY 1-MM 2-DD 3-hh 4-mm 5-ss 6-exit unsigned int YearOrTime=0; //报时1----year 0----timeunsigned int TimeChangeKey = 0; //校时状态下加减标志unsigned int KeyCount=0; //按键计数单元unsigned int SecondAddOne=0;unsigned int HourMinTemp=0; //读时、分unsigned int i=0;unsigned int j=0;//作息时间表unsigned int gTimeVSShem[16]={0x0800,0x0832,0x0900,0x0932,0x0934,0x0a05,0x0a0a,0x0b00,0x0b0a,0x0c00,0x0d1e,0x0e14,0x0e1e,0x0f14,0x0f15,0x0f32};//************************播放提示语音*********************////input: 播放序号//*********************************************************//void PlayRespond(unsigned int Result){ SACM_A2000_Initial(1);SACM_A2000_Play(Result,3,3);while((SACM_A2000_Status()&0x0001) != 0){ Clear_WatchDog();SACM_A2000_ServiceLoop();}SACM_A2000_Stop();}//***************延时子程序********************************////*********************************************************//void Delay3ms(){int delaytemp=0;for(delaytemp=0;delaytemp<0xFFFF;delaytemp++);}//***************语音报时**********************************////函数:PlayAdjustTime(AdjustTemp)//描述:调用子函数:// ReadRealYear(): 年---16进制低14位// ReadRealMonthDay(): 月----高8位日---低8位16进制// ReadRealHourMin(): 时----高8位分---低8位16进制// ReadRealSecond(): 秒16进制//参数:0---年;1---月;2--日;3--时;4---分;5---秒//返回:无//*********************************************************// PlayAdjustTime(AdjustTemp) //*************调整时间播放{switch(AdjustTemp){case 0: //年SpeechAdjustTemp=ReadRealYear();PlaySpeakYear(SpeechAdjustTemp);break;case 1: //月SpeechAdjustTemp=ReadRealMonthDay();PlaySpeakMonth(SpeechAdjustTemp>>8);break;case 2: //日SpeechAdjustTemp=ReadRealMonthDay();PlaySpeakDay(SpeechAdjustTemp & 0x00ff);break;case 3: //时SpeechAdjustTemp=ReadRealHourMin();PlaySpeakHour(SpeechAdjustTemp>>8);break;case 4: //分SpeechAdjustTemp=ReadRealHourMin();PlaySpeakMinute(SpeechAdjustTemp & 0x00ff);break;// case 5: //秒// SpeechAdjustTemp=ReadRealSecond();// PlaySpeakSecond(SpeechAdjustTemp);// break;case 5: break;default: break;}}//***************语音报时子函数****************************// //函数:PlayAdjustTime(AdjustTemp)//描述:调用子函数:// PlaySpeakYear(): 报年// PlaySpeakMonth(): 报月// PlaySpeakDay(): 报日// PlaySpeakHour(): 报时// PlaySpeakMinute(): 报分//参数:年;月;日;时;分;数据均为16进制//返回:无//*********************************************************////input: 年-----16进制//*********************************************************//PlaySpeakYear(int YearTemp) //*************年{PlayRespond((YearTemp/1000)+C_T00);PlayRespond((YearTemp%1000)/100+C_T00);PlayRespond((YearTemp%100)/10+C_T00);PlayRespond((YearTemp%10)+C_T00);PlayRespond(C_YEAR);}//input:月------16进制//*********************************************************//PlaySpeakMonth(int MonthTemp) //*************月{if(MonthTemp<10) PlayRespond(MonthTemp+C_T00);else if(MonthTemp==10) PlayRespond(C_T10);else if(MonthTemp==11) PlayRespond(C_T11);else if(MonthTemp==12) PlayRespond(C_T12);PlayRespond(C_MONTH);}//input:日------16进制//*********************************************************//PlaySpeakDay(int DayTemp) //*************日{ if((DayTemp/10)> 1) PlayRespond(DayTemp/10+C_T00); //十位>1报if((DayTemp/10)>0) PlayRespond(C_T10); //报十,十位为1不报1 if((DayTemp%10)!= 0) PlayRespond(DayTemp%10+C_T00);PlayRespond(C_DAY);}//input: 时------16进制//*********************************************************//PlaySpeakHour(int DayTemp) //*************时{if(DayTemp>=1 && DayTemp<=7){ PlayRespond(C_LINGCHEN); //1—7 凌晨if(DayTemp==2) PlayRespond(C_S02); //两else PlayRespond(DayTemp+C_T00);}else if(DayTemp>=8 && DayTemp<=12){ PlayRespond(C_NOON); //8--12 上午switch(DayTemp){ case 10:PlayRespond(C_T10); break; //十点case 11:PlayRespond(C_T11); break; //十一点case 12:PlayRespond(C_T12); break; //十二点default: PlayRespond(DayTemp+C_T00);break;}}else if(DayTemp>=13 && DayTemp<=19){ PlayRespond(C_AFTERNOON); //13--19 下午1--7if(DayTemp==14) PlayRespond(C_S02); //两else PlayRespond(DayTemp-12+C_T00);}else if(DayTemp>=20 && DayTemp<=24){ PlayRespond(C_NIGHT); //20--24 晚上8--12switch(DayTemp){ case 22:PlayRespond(C_T10); break; //十点case 23:PlayRespond(C_T11); break; //十一点case 24:PlayRespond(C_T12); break; //十二点default: PlayRespond(DayTemp-12+C_T00);break;}}PlayRespond(C_DIAN); //点}//input: 分------16进制//*********************************************************//PlaySpeakMinute(int MinTemp) //*************分{if(MinTemp==0) PlayRespond(C_ZHENG); //正点else{ if((MinTemp/10)>1) PlayRespond(MinTemp/10+C_T00); //分的十位if((MinTemp/10) >0) PlayRespond(C_T10); //分的十位大于1报,为1不报1if((MinTemp%10)!=0) PlayRespond(MinTemp%10+C_T00); //分的个位不为0则报PlayRespond(C_MIN); //分}}//input:秒------16进制//*********************************************************//PlaySpeakSecond(int SecondTemp) //*************秒{ if(SecondTemp == 0) PlayRespond(SecondTemp + C_T00); //0秒if((SecondTemp/10)>1) PlayRespond(SecondTemp/10+C_T00); //秒的十位大于1报,为1只报十if((SecondTemp/10)> 0) PlayRespond(C_T10);if((SecondTemp%10)!= 0) PlayRespond(SecondTemp%10+C_T00);PlayRespond(C_SECOND);}//********************报时*********************************////input:1 ----- 报年、月、日// 0 ----- 报时、分、秒//*********************************************************//void SpeakTime(TimeType){if(TimeType == 0x01){PlayAdjustTime(CON_YEAR); //年PlayAdjustTime(CON_MONTH); //月PlayAdjustTime(CON_DAY); //日}else{PlayRespond(C_BELL); //报时声PlayRespond(C_NOW); //现在时刻PlayAdjustTime(CON_HOUR); //时PlayAdjustTime(CON_MINUTE); //分}}//*********************************************************////函数:main()//描述:主函数//*********************************************************//int main(){System_Initial();while(1){Key_Scan_ServiceLoop(); //键盘扫描//**********************TRIG/TIME**************************************************//if(Key==1 && KeyStatus==0 ) //keystate 校时状态还是报时状态,1-----校时{KeyCount=1; //按键计数单元Key=0;}if(Key==0x8001 && KeyStatus==0 ){KeyCount++;Key=0;}if (KeyPressFlag==0 && KeyCount>0 ){if(KeyCount<20) //报时{YearOrTime=YearOrTime ^ 0x01; //报年月日或时分:报时1----year 0----timeSpeakTime(YearOrTime);KeyCount=0;}else if(KeyCount>=20) //进入调整时间状态{KeyCount=0;KeyStatus=1;KeyAdjust=0;TimeCount = 0;Start256HzRTC();PlayAdjustTime(KeyAdjust);}}//*********************************************************************************//if(KeyStatus==1) //keystate 校时状态还是报时状态,1-----校时{switch(Key){case 1:KeyAdjust++;if(KeyAdjust == 5) //KeyAdjust:0-YY 1-MM 2-DD 3-hh 4-mm 5-ss 6-exit{KeyStatus=0; KeyAdjust=0;PlayAdjustTime(CON_YEAR); //年PlayAdjustTime(CON_MONTH); //月PlayAdjustTime(CON_DAY); //日PlayAdjustTime(CON_HOUR); //时PlayAdjustTime(CON_MINUTE); //分Stop256HzRTC();}elsePlayAdjustTime(KeyAdjust);Key=0;TimeCount = 0;TimeChangeKey=0;break;case 2:Adjust_Time_Up(KeyAdjust);TimeChangeCount = 0; //调校时间状态下,有键按下,计时器清0TimeChangeKey=1; //调校时间状态下,有加减键按下标志TimeCount = 0; //两分钟计时单元Key=0;break;case 4:Adjust_Time_Down(KeyAdjust);//KeyAdjust:0-YY 1-MM 2-DD 3-hh 4-mm 5-ss 6-exitTimeChangeCount = 0;TimeChangeKey=1;TimeCount = 0; //两分钟计时单元Key=0;break;default:break;}if(TimeChangeKey==1 && TimeChangeCount > 40){TimeChangeKey=0;PlayAdjustTime(KeyAdjust);}if(TimeCount > 120){KeyStatus=0;KeyAdjust=0;}}//*********************************************************************************//Calendar_Counter(); //调整万年历if(SecondAddOne==0xFFFF) //分加1时,与作息时间比较{SecondAddOne=0;HourMinTemp=ReadRealHourMin();for(i=0;i<16;i++) //作息时间if(HourMinTemp==gTimeVSShem[i]){for(j=0;j<15;j++){LightOn(); //LED闪烁15次Delay3ms();LightOff();Delay3ms();}break;}}if(SleepFlag == 0x01 && KeyStatus == 0 )SP_GoSleep(); // 进入睡眠模式}}//*****************************主程序结束******************************************// //*********************************************************************************//。
实验二七段数码管动态显示控制一、实验目的利用AT89S52和使用两位数码管显示器,循环显示两位数00-99。
其中P2.0和P2.1端口分别控制数码管的个位和十位的供电,当相应的端口变成低电平时,驱动相应的三极管会导通,+5V通过驱动三极管给数码管相应的位供电,这时只要P3口送出数字的显示代码,数码管就能正常显示数字。
二、实验要求1、使用两位数码管显示器,循环显示两位数00-99;2、具有电源开关和指示灯,有复位键;3、数码管动态显示,即扫描方式,每一位每间隔一段时间扫描一次。
字符的亮度及清晰度与每位点亮的停留时间和每位显示的时间内轮换导通次数有关。
三、实验电路四、实验器材AT89S52;动态扫描显示;共阳极数码管;电阻五、实验原理说明图1 AT89S52引脚图图2 共阳极七段数码管引脚图1AT89S52引脚图,说明如下:按照功能,AT89S52的引脚可分为主电源、外接晶体振荡或振荡器、多功能I/O 口、控制和复位等。
1.多功能I/O口AT89S52共有四个8位的并行I/O口:P0、P1、P2、P3端口,对应的引脚分别是P0.0 ~ P0.7,P1.0 ~ P1.7,P2.0 ~ P2.7,P3.0 ~ P3.7,共32根I/O线。
每根线可以单独用作输入或输出。
①P0端口,该口是一个8位漏极开路的双向I/O口。
在作为输出口时,每根引脚可以带动8个TTL输入负载。
当把“1”写入P0时,则它的引脚可用作高阻抗输入。
当对外部程序或数据存储器进行存取时,P0可用作多路复用的低字节地址/数据总线,在该模式,P0口拥有内部上拉电阻。
在对Flash存储器进行编程时,P0用于接收代码字节;在校验时,则输出代码字节;此时需要外加上拉电阻。
②P1端口,该口是带有内部上拉电阻的8位双向I/O端口,P1口的输出缓冲器可驱动(吸收或输出电流方式)4个TTL输入。
对端口写“1”时,通过内部的上拉电阻把端口拉到高电位,此时可用作输入口。
两位七段数码管的工作流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor. I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!1. 初始化设置数码管的引脚连接,确定每个引脚的功能(如段选、位选等)。
凌阳61单片机使用7段数码管显示数字时钟的程序#include<SPCE061v004.h>#include<unspmacro.h>//中断函数定义void IRQ1(void) __attribute__((ISR));void IRQ5(void) __attribute__((ISR));void IRQ6(void) __attribute__((ISR));enum{ RUN, CHGSECOND, CHGMINUTE, CHGHOUR } clock_status; //时钟的状态unsigned int hour,minute,second;unsigned int show_hour, show_minute, show_second;enum{ NOKEY, PRESSING, PRESSED } key_status; //键盘按下与否的状态unsigned key_code;// 7段LED数码管的字形码,采用高八位输出,决定显示的字形,如: '0'、'1'等const unsigned int zhixingma[] = { 0x3f00, 0x0600, 0x5b00, 0x4f00,0x6600, 0x6d00, 0x7c00, 0x0700,0x7f00,0x6f00 };//数码管选择的"位段码",决定哪一位数码管显示const unsigned int weiduanma[] = {0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040}; //数码管的两个DD引脚,为时,中间的冒号亮const unsigned int wei_DD = 0x0081;void display(unsigned int wei, unsigned int number){*P_IOA_Data = zhixingma[number];//设置位段码时,不能改变冒号的状态*P_IOB_Data = weiduanma[wei] | (*P_IOB_Buffer & wei_DD);}//取反数码管中间的冒号void opposite_dots(){*P_IOB_Data = wei_DD ^ (*P_IOB_Buffer);}void delay(unsigned int howlong){while(howlong--){unsigned int temp = 0x00ff;*P_Watchdog_Clear = 1;while(temp--);}}void init(){INT_OFF();*P_IOA_Dir = 0xff00;*P_IOA_Attrib = 0xff00;*P_IOB_Dir = 0x00ff;*P_IOB_Attrib = 0x00ff;*P_TimerA_Data = 0xffff - 256;*P_TimerA_Ctrl = C_SourceA_1 | C_SourceB_256Hz;*P_INT_Ctrl = C_IRQ1_TMA | C_IRQ6_TMB2 | C_IRQ5_2Hz; INT_IRQ();}void change_clock(){unsigned int key_code = get_key();static unsigned int max;switch(key_code){ // key_code == 0 will do nothing case 1:switch( clock_status ){case CHGSECOND:if(++second == 60) second = 0;break;case CHGMINUTE:if(++minute == 60) minute = 0;break;case CHGHOUR:if(++hour == 24) hour =0;break;default:break;}break;case 2:switch( clock_status ){case CHGSECOND:if(--second == 0) second = 59;break;case CHGMINUTE:if(--minute == 0) minute = 59;break;case CHGHOUR:if(--hour == 0) hour = 23;break;default:break;}break;case 3:switch( clock_status ){case RUN:clock_status = CHGSECOND;break;case CHGSECOND:clock_status = CHGMINUTE;break;case CHGMINUTE:clock_status = CHGHOUR;break;case CHGHOUR:clock_status = RUN;break;}break;default:break;}}int main(){init();while(1){change_clock();if(show_second){display(5, second % 10);delay(1);display(4, second / 10);delay(1);}if(show_minute){display(3, minute % 10);delay(1);display(2, minute / 10);delay(1);}if(show_hour){display(1, hour % 10);delay(1);display(0, hour / 10);delay(1);}}void IRQ1(){//时钟计数中断if( (C_IRQ1_TMA & *P_INT_Ctrl) != 0 ){ if( clock_status == RUN ){ second++;if(second >= 60 ) second=0, minute++;if(minute >= 60 ) minute=0, hour++;if(hour >= 24 ) hour=0;}*P_INT_Clear = C_IRQ1_TMA;}}void IRQ5(){//数码管闪烁if( (C_IRQ5_2Hz & *P_INT_Ctrl) != 0){switch(clock_status){case RUN:opposite_dots();show_hour = show_minute = show_second = 0xffff;break;case CHGSECOND:show_second ^= 0xffff;show_minute = show_hour = 0xffff;break;case CHGMINUTE:show_minute ^= 0xffff;show_second = show_hour = 0xffff;break;case CHGHOUR:show_hour ^= 0xffff;show_second = show_minute = 0xffff;break;}*P_INT_Clear = C_IRQ5_2Hz;}}void IRQ6(){ //每10ms扫描一次键盘static unsigned int old_key = 0;static unsigned int key_count = 0;unsigned int current_key;if( (C_IRQ6_TMB2 & *P_INT_Ctrl) != 0){ current_key = *P_IOA_Data & 0x0007;if( current_key != 0){ //有按键if( key_status == NOKEY ){ old_key = current_key;key_count++;key_status = PRESSING;}else{if( current_key == old_key) //不相等,抖动{if( ++key_count >= 5)//有>5次扫描的值相等,说明不是抖动,判断按键值{ if(current_key == 0x0001) key_code = 1;if(current_key == 0x0002) key_code = 2;if(current_key == 0x0004) key_code = 3;}}else{//抖动old_key = 0;key_count = 0;key_status = NOKEY;}}}else{ //无按键old_key = 0;key_count = 0;if( key_status == PRESSING ) key_status = PRESSED; //按键释放了 }*P_INT_Clear = C_IRQ6_TMB2;}}。
七段数码管动态显示程序七段数码管动态显示程序2009-04-20 19:20:06| 分类:计算机阅读1288 评论1 字号:大中小订阅; 七段数码管动态显示程序; 四位数码管固定显示"1234";************************************************* ACC EQU [05H] ;定义专用寄存器ACCTBLP EQU [07H] ;定义专用寄存器TBLPPCL EQU [06H] ;定义专用寄存器PCLPA EQU [12H] ;定义专用寄存器PAPAC EQU [13H] ;定义专用寄存器PACPB EQU [14H] ;定义专用寄存器PBPBC EQU [15H] ;定义专用寄存器PBCPC EQU [16H] ;定义专用寄存器PCPCC EQU [17H] ;定义专用寄存器PCCDISP_RAM EQU [78H] ;查表得到显示代码DISP_RAM1 EQU [79H] ;数码管1显示内容寄存器DISP_RAM2 EQU [7AH] ;数码管2显示内容寄存器DISP_RAM3 EQU [7BH] ;数码管3显示内容寄存器DISP_RAM4 EQU [7CH] ;数码管4显示内容寄存器DISP_NUM1 EQU [7DH] ;每个数码管显示时延时寄存器DISP_NUM2 EQU [7EH] ;一次调用显示时延时寄存器NUM1 EQU 20H ;每个LED显示时延时参数NUM2 EQU 30H ;一次调用显示时延时参数;---------------------------------------- ORG 000HJMP START ;芯片上电,程序开始执行地址ORG 004HRETI ;外中断子程序开始地址ORG 008HRETI ;定时器0中断子程序开始地址ORG 00CHRETI ;定时器1中断子程序开始地址ORG 020HSTART:MOV A,00HMOV PAC,A ;设置PA口为输出口MOV PCC,A ;设置PC口为输出口SET PA ;PA口为高,关LED数码管CLR PC ;PC口为低,关四个三极管MAIN:MOV A,01HMOV DISP_RAM1,A ;数码管1显示"1"MOV A,02HMOV DISP_RAM2,A ;数码管2显示"2"MOV A,03HMOV DISP_RAM3,A ;数码管3显示"3"MOV A,04HMOV DISP_RAM4,A ;数码管4显示"4"MAIN1:CALL DISPLAY ;调显示子程序JMP MAIN1 ;反复循环.;*****************************************; DISPLAY [DISP_RAM1]==> LED1 [DISP_RAM2]==> LED2 ; [DISP_RAM3]==> LED3 [DISP_RAM4]==> LED4;*****************************************DISPLAY PROC ;显示子程序MOV A,NUM2MOV DISP_NUM2,A ;四个数码管循环显示的次数.LOOP:MOV DISP_NUM1,A ;数码管1 显示的延时时间设置.MOV A,04HMOV PC,A ;PC.2=1,数码管1的VDD接通MOV A,DISP_RAM1MOV TBLP,A ;取显示值,放入查表的偏移量寄存器TABRDL DISP_RAM ;查表,取显示代码MOV A,DISP_RAMMOV PA,A ;将显示代码输出到PA口LOOP1:DEC DISP_NUM1SZ DISP_NUM1JMP LOOP1 ;延时功能SET PA ;关显示CLR PC.2 ;PC.2=0,数码管1的VDD断开MOV A,NUM1MOV DISP_NUM1,A ;数码管2 显示的延时时间设置MOV A,08HMOV PC,A ;PC.3=1,数码管2的VDD接通MOV A,DISP_RAM2MOV TBLP,A ;取显示值,放入查表的偏移量寄存器TABRDL DISP_RAM ;查表,取显示代码MOV A,DISP_RAMMOV PA,A ;将显示代码输出到PA口LOOP2:DEC DISP_NUM1SZ DISP_NUM1JMP LOOP2 ;延时功能SET PA ;关显示CLR PC.3 ;PC.3=0,数码管2的VDD断开MOV DISP_NUM1,A ;数码管3 显示的延时时间设置.MOV A,10HMOV PC,A ;PC.4=1,数码管3的VDD接通MOV A,DISP_RAM3MOV TBLP,A ;取显示值,放入查表的偏移量寄存器TABRDL DISP_RAM ;查表,取显示代码MOV A,DISP_RAMMOV PA,A ;将显示代码输出到PA口LOOP3:DEC DISP_NUM1SZ DISP_NUM1JMP LOOP3 ;延时功能SET PA ;关显示CLR PC.4 ;PC.4=0,数码管3的VDD断开MOV A,NUM1MOV DISP_NUM1,A ;数码管4 显示的延时时间设置.MOV A,20HMOV PC,A ;PC.5=1,数码管4的VDD接通MOV A,DISP_RAM4MOV TBLP,A ;取显示值,放入查表的偏移量寄存器TABRDL DISP_RAM ;查表,取显示代码MOV A,DISP_RAMMOV PA,A ;将显示代码输出到PA口LOOP4:DEC DISP_NUM1SZ DISP_NUM1JMP LOOP4 ;延时功能SET PA ;关显示CLR PC.5 ;PC.5=0,数码管4的VDD断开DEC DISP_NUM2 ;循环显示次数-1SZ DISP_NUM2 ;判断循环结束否?JMP LOOP ;没结束,跳去LOOP,继续循环RET ;循环结束,子程序返回.DISPLAY ENDP;****************************************; WORK1;****************************************WORK1 PROC ;WORK1功能模块,留给学习者自己加RETWORK1 ENDP;****************************************; WORK2;****************************************WORK2 PROC ;WORK2功能模块,留给学习者自己加RETWORK2 ENDP;************************************************************** **; 表格区,0~9对应的显示代码.;************************************************************** **ORG 0F00H; 0 1 2 3 4 5 6 7 8 9 TABLE: DW 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H ;************ ****************************************************END。
凌阳61单片机使用7段数码管显示数字时钟的程序#include<SPCE061v004.h>#include<unspmacro.h>//中断函数定义void IRQ1(void) __attribute__((ISR));void IRQ5(void) __attribute__((ISR));void IRQ6(void) __attribute__((ISR));enum{ RUN, CHGSECOND, CHGMINUTE, CHGHOUR } clock_status; //时钟的状态unsigned int hour,minute,second;unsigned int show_hour, show_minute, show_second;enum{ NOKEY, PRESSING, PRESSED } key_status; //键盘按下与否的状态unsigned key_code;// 7段LED数码管的字形码,采用高八位输出,决定显示的字形,如: '0'、'1'等const unsigned int zhixingma[] = { 0x3f00, 0x0600, 0x5b00, 0x4f00,0x6600, 0x6d00, 0x7c00, 0x0700,0x7f00,0x6f00 };//数码管选择的"位段码",决定哪一位数码管显示const unsigned int weiduanma[] = {0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040}; //数码管的两个DD引脚,为时,中间的冒号亮const unsigned int wei_DD = 0x0081;void display(unsigned int wei, unsigned int number){*P_IOA_Data = zhixingma[number];//设置位段码时,不能改变冒号的状态*P_IOB_Data = weiduanma[wei] | (*P_IOB_Buffer & wei_DD);}//取反数码管中间的冒号void opposite_dots(){*P_IOB_Data = wei_DD ^ (*P_IOB_Buffer);}void delay(unsigned int howlong){while(howlong--){unsigned int temp = 0x00ff;*P_Watchdog_Clear = 1;while(temp--);}}void init(){INT_OFF();*P_IOA_Dir = 0xff00;*P_IOA_Attrib = 0xff00;*P_IOB_Dir = 0x00ff;*P_IOB_Attrib = 0x00ff;*P_TimerA_Data = 0xffff - 256;*P_TimerA_Ctrl = C_SourceA_1 | C_SourceB_256Hz;*P_INT_Ctrl = C_IRQ1_TMA | C_IRQ6_TMB2 | C_IRQ5_2Hz; INT_IRQ();}void change_clock(){unsigned int key_code = get_key();static unsigned int max;switch(key_code){ // key_code == 0 will do nothing case 1:switch( clock_status ){case CHGSECOND:if(++second == 60) second = 0;break;case CHGMINUTE:if(++minute == 60) minute = 0;break;case CHGHOUR:if(++hour == 24) hour =0;break;default:break;}break;case 2:switch( clock_status ){case CHGSECOND:if(--second == 0) second = 59;break;case CHGMINUTE:if(--minute == 0) minute = 59;break;case CHGHOUR:if(--hour == 0) hour = 23;break;default:break;}break;case 3:switch( clock_status ){case RUN:clock_status = CHGSECOND;break;case CHGSECOND:clock_status = CHGMINUTE;break;case CHGMINUTE:clock_status = CHGHOUR;break;case CHGHOUR:clock_status = RUN;break;}break;default:break;}}int main(){init();while(1){change_clock();if(show_second){display(5, second % 10);delay(1);display(4, second / 10);delay(1);}if(show_minute){display(3, minute % 10);delay(1);display(2, minute / 10);delay(1);}if(show_hour){display(1, hour % 10);delay(1);display(0, hour / 10);delay(1);}}void IRQ1(){//时钟计数中断if( (C_IRQ1_TMA & *P_INT_Ctrl) != 0 ){ if( clock_status == RUN ){ second++;if(second >= 60 ) second=0, minute++;if(minute >= 60 ) minute=0, hour++;if(hour >= 24 ) hour=0;}*P_INT_Clear = C_IRQ1_TMA;}}void IRQ5(){//数码管闪烁if( (C_IRQ5_2Hz & *P_INT_Ctrl) != 0){switch(clock_status){case RUN:opposite_dots();show_hour = show_minute = show_second = 0xffff;break;case CHGSECOND:show_second ^= 0xffff;show_minute = show_hour = 0xffff;break;case CHGMINUTE:show_minute ^= 0xffff;show_second = show_hour = 0xffff;break;case CHGHOUR:show_hour ^= 0xffff;show_second = show_minute = 0xffff;break;}*P_INT_Clear = C_IRQ5_2Hz;}}void IRQ6(){ //每10ms扫描一次键盘static unsigned int old_key = 0;static unsigned int key_count = 0;unsigned int current_key;if( (C_IRQ6_TMB2 & *P_INT_Ctrl) != 0){ current_key = *P_IOA_Data & 0x0007;if( current_key != 0){ //有按键if( key_status == NOKEY ){ old_key = current_key;key_count++;key_status = PRESSING;}else{if( current_key == old_key) //不相等,抖动{if( ++key_count >= 5)//有>5次扫描的值相等,说明不是抖动,判断按键值{ if(current_key == 0x0001) key_code = 1;if(current_key == 0x0002) key_code = 2;if(current_key == 0x0004) key_code = 3;}}else{//抖动old_key = 0;key_count = 0;key_status = NOKEY;}}}else{ //无按键old_key = 0;key_count = 0;if( key_status == PRESSING ) key_status = PRESSED; //按键释放了 }*P_INT_Clear = C_IRQ6_TMB2;}}。