- 59.00 KB
- 2022-04-21 发布
- 1、本文档由用户上传,淘文库整理发布,可阅读全部内容。
- 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,请立即联系网站客服。
- 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细阅读内容确认后进行付费下载。
- 网站客服QQ:403074932
单片机电子钟设计代码(2)给你一个,我做的电子钟的程序,参考一下,时间是可以调整的,有按键扫描在里面;*************************************;Filename:timer_controlable;chiptype:atmelmega8;programetype:application;clockfrequency:8MHZ;memorymodel:small;ExternalSRAMsize:0;Datastacksize:256;*************************************.include"m8def.inc".deftime_counter=r16;时间计数单元.defkey_stime_counter=r17.defkey_input=r18;按键输入单元.defposit=r19;LED显示字符移位指针.deftemp=r20;临时寄存器.deftemp1=r21.defkey_press=r22.defkey_return=r23.defclock_state=r24;状态机中的状态.defkey_state=r25.defkey_temp=r7.defcount=r8.deftemp2=r1.defset_on=r2;校时闪烁标志n.defreturn_time=r3.defpoint_on=r4;秒闪烁标志.deftime_1s_ok=r5;1s到标志.defkey_stime_ok=r6;10ms到标志.equkey_no=0;无按键标志.equkey_k1=1;按键K1标志.equkey_k2=2;按键K2标志.equkey_mask=0b11000000;按键识别标志.equkey_state_0=0;状态0.equkey_state_1=1;状态1.equkey_state_2=2;状态2.org0x0000rjmpmain.org0x0003;T2比较匹配中断向量地址rjmptimer2_com_isr.org0x0020;-------------------------------------------------------------------------------------------------------------------------------------------;;主程序;-------------------------------------------------------------------------------------------------------------------------------------------;main:;*--初始化堆栈--*;nlditemp,0x5foutspl,templditemp,0x02outsph,temp;*--PB,PD初始化--*;lditemp,0x00outportb,temp;PB口输出做段码控制lditemp,0xffoutddrb,tempoutportd,templditemp,0x3f;PD0~5输出作位控制outddrd,temp;PD6~7作时间调整输入口;*--T2初始化--*;lditemp,0x0douttccr2,temp;内部时钟,128分频(8M/128=62.5KHZ),CTC模式lditemp,0x7coutOCR2,temp;OCR2=0X7C(124),(124+1)/62.5khz=2mslditemp,0x80outtimsk,temp;定时器2比较匹配中断使能;*--时钟初始化为:23:58:55--*;ldixl,low(time_buff)ldixh,high(time_buff)lditemp,55stx+,temp;秒:55lditemp,58stx+,temp;分:58lditemp,23stx,temp;时:23;*--初始化各值--*;nlditemp,0x00;清零各标志位,初始化各寄存器movtime_1s_ok,temp;清1s到标志movpoint_on,temp;清小数点标志movkey_stime_ok,temp;清10ms到标志movreturn_time,temp;清movposit,temp;清零显示位置寄存器movkey_stime_counter,temp;清movtime_counter,tempmovkey_state,tempmovset_on,tempsei;开全局中断while:sbrstime_1s_ok,0;1s到则跳过下一条指令,不跳转rjmpkey_hand;1s未到跳键处理程序clrtime_1s_ok;清零1s到标志lditemp,0x01eorpoint_on,temp;秒标志闪烁;*--时间调整--*;time_add:ldixl,low(time_buff)ldixh,high(time_buff)rcalldhm3;秒单元加1调整cpitemp,60brnetime_add_ret;未到60秒,跳出时间调整rcalldhm;分单元加1调整cpitemp,60brnetime_add_ret;未到60分,跳出时间调整nrcalldhm;时单元加1调整cpitemp,24brnetime_add_ret;24时未到,跳出时间调整clrtempstx,temp;到24时,时单元清零time_add_ret:rjmptime_to_disbuff_maindhm:clrtemp;清零当前单元dhm1:stx+,temp;当前时段清零,X指针加一dhm3:ldtemp,x;取出新时段数据inctempdhm2:stx,temp;将调整时间送回ret;*--时间送显示缓冲区--*;time_to_disbuff_main:increturn_timecpiclock_state,6;判断是否处于时间显示状态,若是则送时间至显示缓冲区breqtime_to_disbuff_promovtemp,return_timecpitemp,20;若不是则判断等待时间是否大于20sbrlokey_hand;等待时间小于20S,则继续扫描按键set_clock_state6:ldiclock_state,6;若等待时间大于20S,将状态设为时间显示状态time_to_disbuff_pro:nldixl,low(dis_buff)ldixh,high(dis_buff)ldiyl,low(time_buff)ldiyh,high(time_buff)lditemp,3movcount,temp;循环次数=3loop_time:clrtemp1ldtemp,x+;读一个时间单元loop1_time:cpitemp,10brloloop2_time;<10转inctemp1subitemp,10rjmploop1_timeloop2_time:sty+,temp;写入2个显示单元sty+,temp1;低位BCD码在前,高位在后deccountbrneloop_timerjmpkey_hand;跳至键处理程序;*--键处理--*;key_hand:sbrskey_stime_ok,0;10ms到,则跳过下一行rjmpwhile;10ms未到继续循环扫描clrkey_stime_ok;清零10ms到标志rcallread_key;10ms到调用按键接口程序movkey_temp,key_return;将按键值送按键临时寄存器movtemp1,key_tempcpitemp1,0x00nbreqwhile;没有键按下则继续跳至循环开始处循环clrreturn_time;有键按下则清零等待时间计数寄存器;--按键K1处理--;key1_hand:movtemp1,key_tempcpitemp1,key_k1brnekey2_hand;若按键值不为K1则跳至按键K2判断处incclock_state;状态转换cpiclock_state,7;比较下一状态是否为状态7,即此时状态是否为状态6brlojudg_clock_state6;若此状态不为6状态,则判断下一状态是否为6状态clear_state:;若为状态6则将状态转为状态0ldiclock_state,0;将0送显示缓冲区,所有位都显示为"0"time_to_disbuff_0_pro:ldixl,low(dis_buff)ldixh,high(dis_buff)lditemp,0x00stx+,tempstx+,tempstx+,tempstx+,tempstx+,tempstx,temprjmpkey2_hand;跳至K2处理程序处njudg_clock_state6:;若转为状态6,则将时间设置缓冲区数据送显示缓冲区cpiclock_state,6brnekey2_handtime_to_disbuff_pro2:;将设置时间送显示缓冲区ldixl,low(dis_buff)ldixh,high(dis_buff)ldiyl,low(time_set)ldiyh,high(time_set)lditemp,3movcount,temp;循环次数=3loop:clrtemp1ldtemp,x+;读一个时间单元loop1:cpitemp,10brloloop2;<10转inctemp1subitemp,10rjmploop1loop2:sty+,temp;写入2个显示单元sty+,temp1;低位BCD码在前,高位在后deccountbrneloop;3个时间单元->6个显示单元rjmpkey2_hand;跳至K2处理程序处;--按键K2处理--;nkey2_hand:movtemp1,key_tempcpitemp1,key_k2breqcom_clock_state_6rjmpwhile;按键不为K2跳至主循环处com_clock_state_6:cpiclock_state,6brnemov_clock_state;若为状态6跳至主循环处rjmpwhilemov_clock_state:movtemp,clock_stateanditemp,0x01cpitemp,0x01brneset_low;若为偶数则转至低位调整程序movtemp,clock_statelsrtemp;若为奇数,则为调整高位数,右移temp,即除2ldiyl,low(time_set)ldiyh,high(time_set);addyl,templditemp,0x00;time_set[clock_state/2]+=10adcyh,templdtemp,y;lditemp1,10addtemp,temp1;将时间设置寄存器加10sty,tempset_low:movtemp,clock_statelsrtemp;右移temp,即除2nldiyl,low(time_set)ldiyh,high(time_set);addyl,templditemp,0x00;adcyh,templdtemp,y;time_set[clock_state/2]-->tempmovtemp2,temp;将值保存至temp2loop21:cpitemp,10;第一次比较时间设置区数值是否大于10brlocom_to_9;若小于10则转至判断其是否为9处loop22:subitemp,10;若大于10,将其减10,循环,至其小于10,取其低位数cpitemp,10brshloop22;大于10,则继续循环减10com_to_9:cpitemp,9;比较低位数是否为9brneinc_time_set;若个位数不为9,则将时间设置缓冲区对应的数值加1clear_time_set_low:;时间设置缓冲区低位清零movtemp,temp2subitemp,9;若低位数为9,则清零低位sty,temprjmptime_set_0inc_time_set:inctemp2sty,temp2nrjmptime_set_0;--设置时间缓冲区时间调整--;time_set_0:ldiyl,low(time_set)ldiyh,high(time_set)ldtemp,ycpitemp,60brlotime_set_1subitemp,60sty,temptime_set_1:incylclrtempadcyh,templdtemp,ycpitemp,60brlotime_set_2subitemp,60sty,temptime_set_2:incylclrtempadcyh,templdtemp,ycpitemp,24brlotime_set_to_time_disbuffsubitemp,24sty,temptime_set_to_time_disbuff:ldixl,low(dis_buff)ldixh,high(dis_buff)nldiyl,low(time_set)ldiyh,high(time_set)lditemp,3movcount,temp;循环次数=3loop_key2:clrtemp1ldtemp,x+;读一个时间单元loop1_key2:cpitemp,10brloloop2_key2;<10转inctemp1subitemp,10rjmploop1_key2loop2_key2:sty+,temp;写入2个显示单元sty+,temp1;低位BCD码在前,高位在后deccountbrneloop_key2;3个时间单元->6个显示单元end_key_hand:rjmpwhile;---------------------------------------------------------------------------------------------------------------------------------------------------;;6位数码管动态扫描程序;---------------------------------------------------------------------------------------------------------------------------------------------------;display:nclrr0sertempoutportd,templdixl,low(dis_buff)ldixh,high(dis_buff)addxl,posit;posit为要显示的数字所在的位adcxh,r0ldtemp,x;temp中为要显示的数字clrr0ldizl,low(table_led_7*2)ldizh,high(table_led_7*2)addzl,tempadczh,r0lpm;将要显示的位的数据送r0outportb,r0;将显示数据送PB口movtemp,set_oncpitemp,1brnejud_point_oncpposit,clock_statebrnejud_point_onclrtempoutportb,tempjud_point_on:movtemp,point_oncpitemp,1brnetran_portdcpiposit,2breqportb_7_setncpiposit,4breqportb_7_setrjmptran_portdportb_7_set:intemp,portbanditemp,0x80outportb,temptran_portd:clrtempldizl,low(table_position_6*2)ldizh,high(table_position_6*2)addzl,positadczh,templdtemp,zoutportd,tempinc_posit:incposit;posit加1,移位显示cpiposit,6brnedis_retldiposit,0;若posit为6则将posit置0dis_ret:ret;返回;----------------------------------------------------------------------------------------------------------------------------------------------;;time2比较匹配中断服务,2ms定时;----------------------------------------------------------------------------------------------------------------------------------------------;timer2_com_isr:nintemp,sregpushtemprcalldisplay;调用显示inckey_stime_counter;cpikey_stime_counter,5brlotimer2_com_retclrkey_stime_counterlditemp,0x01movkey_stime_ok,tempinctime_countercpitime_counter,25;判断是否为250ms的倍数breqcom_set_oncpitime_counter,50breqcom_set_oncpitime_counter,75;breqcom_set_oncpitime_counter,100;brlotimer2_com_retclrtime_counterlditemp,0x01;1s到标志置位movtime_1s_ok,tempcom_set_on:lditemp,0x01;若是250ms的倍数,则将set_on取反eorset_on,temptimer2_com_ret:poptempoutsreg,tempretin;--------------------------------------------------------------------------------------------------------------------------------------------;;读键值;--------------------------------------------------------------------------------------------------------------------------------------------;read_key:ldikey_return,key_no;key_return初始值inkey_input,portd;读PD口状态,送入key_inputmovtemp,key_inputanditemp,key_maskmovkey_press,temp;key_press=key_input&key_maskcpikey_state,key_state_0;若为0状态brnekey_state_judg_1cpikey_press,key_mask;则将确认按键被按下breqkey_read_retldikey_state,key_state_1;若按键被按下,则转到下一状态rjmpkey_read_ret;若无按键则跳出读键子程序key_state_judg_1:;*状态1*;cpikey_state,key_state_1brnekey_state_judg_2movtemp,key_inputanditemp,key_maskmovtemp1,temp;取新按键值入temp1cpkey_press,temp1;key_press=key_input&key_masknbrnekey_init;若按键值和原值不相等转按键初始态程序cpikey_press,0b01000000brnekey_return_key2ldikey_return,key_k1;返回键值为K1key_return_key2:cpikey_press,0b10000000brnekey_state_2_returnldikey_return,key_k2;确认为按键2按下,返回K2值key_state_2_return:ldikey_state,key_state_2;状态转为状态2key_init:ldikey_state,key_state_0;状态转为初始态0rjmpkey_read_retkey_state_judg_2:;*状态2*;cpikey_state,key_state_2;为状态2则顺执brnekey_read_retcpikey_press,key_maskbrnekey_read_ret;按键没释放,继续保留状态为状态2ldikey_state,key_state_0;按键已释放则将状态转为初始态0key_read_ret:ret;返回.csegtable_led_7:;字符数据表.db0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6fntable_position_6:;显示位置数据表.db0xfe,0xfd,0xfb,0xf7,0xef,0xdf.dseg.org0x0100dis_buff:;显示缓冲单元.byte0x00;秒低位.byte0x00;秒高位.byte0x00;分低位.byte0x00;分高位.byte0x00;时低位.byte0x00;时高位.org0x0106time_buff:;时间缓冲单元.byte0x00;秒单元.byte0x00;分单元.byte0x00;时单元.org0x0109time_set:;时间设置缓冲单元.byte0x00;秒单元.byte0x00;分单元.byte0x00;时单元