一、课程规划内容与要求
1)时钟显现功用,选用数码管的动态扫描作业方法,可经过键盘别离挑选显现年或许月/日或许时/分或许分/秒,
2)在键盘电路中,第一次中止判别有无键按下,若有按下则实施守时一次,下一次中止开端扫描。
3)具有校准年、月、日、时、分的功用。
4)闹钟功用,可按设定的时刻闹时,随时敞开或封闭闹钟。
二、元器材的介绍
我在这次的课程规划中运用的主芯片是LPC2103,下面临其进行扼要的介绍。
LPC2103是一个依据支撑实时仿真的16/32位ARM7 TDMI-S CPU的微操控器,并带有32kB的嵌入高速Flash存储器,128位宽度的存储器接口和共同的加快结构使32位代码能够在最大时钟速率下运转。
较小的封装和极低的功耗使LPC2103适用于拜访操控器和POS机等小型运用体系中;因为内置了宽规模的串行通讯接口(2个UART、SPI、SSP和2个I2C)和8KB的片内SRAM,LPC2103也合适用在通讯网关和协议转化器中。32/16位守时器、增强型10位ADC、守时器输出匹配PWM特性、多达13个边缘、电平触发的外部中止、32条高速GPIO,使得LPC2103微操控器特别适用于工业操控和医疗体系中。
器材信息:
管脚信息:(LQFP48管脚装备 )
三、规划方案
硬件电路规划介绍:
1、键盘模块
整个硬件上一共运用了10个独立键盘,4个是开发板上原有的按键,6个是我运用剩余的IO引脚焊接的按键。按键在没有被按下时,10个按键(P0.16 P0.14 P0.15 P0.18 P0.2 P0.3 P0.4 P0.5 P0.27 P0.6 P0.7)经过10K的电阻衔接到3.3V的高电平,当按键被按下时,和GND相衔接,被置为低电平。
2、数码管显现模块
运用串行输入/并行输出的8位移位寄存器74HC164,该移位寄存器是上升沿有用,将8位笔段码送给共阳数码管。(注:DATA为数据输入端,接P0.26;CLK为时钟输入端,接P0.13),与三极管相连的是数码管的位选端,挑选哪位数码管被点亮,用于数码管的动态显现。
3、蜂鸣器模块
该蜂鸣器是一个无源蜂鸣器,要运用PWM驱动。其衔接的是芯片的P0.5端。
4、LED模块
LED的衔接如图所示,当管脚置为低电平常,能够将LED点亮,6个LED别离与LPC2103的P0.25 P0.12 P0.11 P0.10 P0.24 P0.23相连。
5、UART接口电路模块
因为开发板是3.3V供电体系,需求运用电平转化芯片SP3232E来进行RS-232电平转化。SP3232E的作业电压为3.3V,电平转化电路如图所示。当运用ISP功用下载程序时,需求将PC机的串口与开发板的串口相连,按下与P0.14相连的按键,短接P0.14,在体系复位时,进入ISP状况,用于下载HEX文件。这个开发板有两个串口,一个用于下载程序进主芯片,别的一个用于串口在上位机上输出显现各个变量的值,可用于调试程序。
按键功用介绍:(用户运用阐明书)
Key1(P0.16):对显现的数码管进行年月日时分秒的显现切换
Key2(P0.14):在时刻设置或许闹钟设置按键有用的状况下,进行自加1的向上调理,对时刻或许闹钟进行设置,其他状况下该按键是无效状况
Key3(P0.15):在时刻设置或许闹钟设置按键有用的状况下,进行自减1的向下调理,对时刻或许闹钟进行设置,其他状况下该按键是无效状况
Key4(P0.18):时刻设置按键,按下表明开端进行时刻设置或跳出时刻设置
Key5(P0.2 ):闹钟设置按键,按下表明开端进行闹钟设置
Key6(P0.3 ):闹钟设置移位按键,按下表明进行闹钟时和分的切换设置
Key7(P0.4 ):闹钟设置完毕按键,按下表明跳出闹钟设置形式;别的能够封闭蜂鸣器
Key8(P0.27):闹钟敞开按键,在Key5按下的状况下按下此键表明敞开该组闹钟
Key9(P0.6 ):闹钟封闭按键,在Key5按下的状况下按下此键表明封闭该组闹钟
Key10(P0.7):用于串口输出信息,能够输出当时的时刻和显现敞开的闹钟设置时刻
当Key10按下时,会在串口中输出信息如图所示:(RTC为输出当时时刻,接下来是闹钟)
时刻和闹钟设置程序流程图:
IO口的初始化模块:
LPC2103操控器的引脚都具有多种功用,可是每个引脚在某一时刻只能挑选一种功用。当运用一个功用外设时,假如需求相应的引脚参加(如GPIO等),则有必要在完结这一功用之前先设置好引脚的功用,不然无法完结该外设功用。LPC2103具有两个PINSEL寄存器,PINSEL0和PINSEL1,PINSEL0和PINSEL1寄存器中的每两个位操控着一个引脚的功用,所以一个引脚最多能够有4种不同的功用挑选。当引脚挑选GPIO功用时,运用寄存器IODIR能够操控引脚的方向,别的IOCLR、IOSET两个寄存器别离能够将引脚初始化设置为低电平或许高电平。所以,在主程序开端是时的GPIO初始化中包含如下几个子函数:
void GPIO_init(UINT8 GPIO_num); 将管脚初始为GPIO功用
void GPIO_inout(UINT8 GPIO_num,UINT8 in_out); 设置GPIO为输入或许输出
UINT8 GPIO_READ(UINT8 GPIO_num); 读出GPIO当时的状况
void GPIO_SET(UINT8 GPIO_num,UINT8 High_Low); GPIO初始化后置1或许置0
守时器的初始化模块:
该程序中运用了3个守时器,守时器0、1、2。守时器0设置为PWM输出形式,发生2kHZ的方波,用于驱动无源蜂鸣器,当设置的闹钟时刻和当时时刻匹配时,将守时器0发动,发生方波驱动蜂鸣器宣布响声提示。
守时器1用于时刻计数,即当时时钟的计时器,它设置为1秒钟发生一次中止,其间止程序分配为最高的优先级,当一秒的守时时刻届时,在服务程序中首要铲除中止标志位,然后秒变量进行自加1(miao++),别的还进行秒闪耀标志位(g_Dot)的取反标志,使秒标志位能够闪耀。
守时器2的初始化有多个功用。守时器2的优先级是次于守时器1的,守时器设置为5毫秒发生一次中止,首要是用于四位八段LRD的动态扫描显现,使四位数码管的改写频率为50Hz,别的是10mS的标志位(time10)自加1,当10mS标志位计时时刻届时,就履行一次键盘扫描程序,即10个独立键盘每10mS被扫描一次。终究是铲除中止标志位,告诉中止服务程序完毕。
时刻更新子函数模块:
该函数首要是对当时时刻的处理,守时器1对秒变量进行了计数,而此程序便是对时分秒年月日变量的值进行判别和约束,使其超越最大值后对其进行归零,比方分秒的值不能大于59,时的最大值为23。大小月以及二月份天数的处理是经过调用UINT8 yue_deal()这个函数完结的。该函数首要是运用一个switch case 句子,对大月份回来一个值31,小月份回来30,别的经过调用UINT8 nian_deal()来判别是平年仍是闰年【闰年条件:if((nian%4==0&&nian%100!=0)||nian%400==0)】,闰年回来29,平年回来28。详细的程序见附录。
数码管动态显现模块程序:
四位数码管的改写频率为50Hz,即一位显现时刻为(1∕50×4)即5mS,用守时器2每5ms发生一次中止进行改写,每次中止发生时只将一位数码管的位选端点亮,用void Refresh_LED(UINT16 dat)函数完结这一功用,因为数码管的笔段码输入端接的是8位移位寄存器74HC164,故需求运用移位将笔段码送到数码管笔段输入端【void data_shift(UINT8 dat)函数】。
注:显现程序担任当时时刻的显现和闹钟设置时的显现内容,需求改动的是即将显现的数值用变量display进行保存成为十进制的四位数。
键盘扫描程序:
假如10毫秒守时时刻到的标志位有用,就进入键盘扫描的子程序UINT8 GetKey()中。经过查找材料,该部分的程序规划选用的是状况机的思维,用如下图所示,其间体系的输入信号是与按键衔接的I/O口电平,“1”表明按键处于敞开状况,“0”表明按键处于闭合状况。而体系的输出信号则表明检测和承认到一次按键的闭合操作,用“1”表明。
上图给出了一个简略按键状况机的状况转化图。在图中,将一次按键完好的操作进程分解为3个状况,选用时刻序列周期为10ms。下面临该图做进一步的剖析和阐明,并依据状况图给出软件的完结办法。首要,要充沛领会时刻序列的效果。在这个体系中,选用的时刻序列周期为10ms,它意味着,每隔10ms检测一次按键的输入信号,并输出一次按键确实认信号,一起按键的状况也发生一次转化。图中“状况0”为按键的初始状况,当按键输入为“1”时,表明按键处于敞开,输出“0”(1/0),下一状况依旧为“状况0”。当按键输入为“0”,表明按键闭合,但输出仍是“0”(0/0)(没有经过消抖,不能承认按键真实按下),下一状况进入“状况1”。“状况1”为按键闭合承认状况,它表明了在10ms前按键为闭合的,因而当再次检测到按键输入为“0”时,能够承认按键被按下了(经过10ms的消抖),输出“1”表明承认按键闭合(0/1),下一状况进入“状况2”。而当再次检测到按键的输入为“1”时,表明按键或许处在颤动搅扰,输出为“0”(1/0),下一状况回来到“状况0”。这样,运用状况1,完结了按键的消抖处理。“状况2”为等候按键开释状况,因为只要等按键开释后,一次完好的按键操作进程才算完结。从对上图的剖析中能够知道,在一次按键操作的整个进程,按键的状况是从“状况0”->“状况1”->“状况2”,终究回来到“状况0”的。并且在整个进程中,按键的输出信号仅在“状况1”时给出了仅有的一次承认按键闭合的信号“1”(其它状况均输出“0”)。所以上面状况机所表明的按键体系,不只克服了按键颤动的问题,一起也保证在一次按键整个的进程中,体系只输出一次按键闭合信号(“1”)。换句话讲,不论按键被按下的时刻坚持多长,在这个按键的整个进程中都只给出了一次承认的输出,因而在这个规划中,按键没有“连发”功用,它是一个最简略和根本的按键。一旦有了正确的状况转化图,就能够依据状况转化图编写软件了。在软件中完结状况机的办法和程序结构一般运用多分支结构(IF-ELSEIF-ELSE、CASE等)完结。下面是依据上图、依据状况机方法编写的简略按键接口函数GetKey()。
该简略按键接口函数GetKey()在整个体系程序中应每隔10ms调用履行一次,每次履行时进入用switch结构构成的状况机。switch结构中的case句子别离完结了3个不同状况的处理判别进程,在每个状况中将依据状况的不同,以及key4的值(状况机的输入)承认输出值(keyreturn),和承认下一次按键的状况值(keystate)。函数GetKey()的回来参数供给上层程序运用。回来值为0时,表明按键无动作;而回来1表明有一次按键闭合动作,需求进入按键处理程序做相应的键处理。在函数GetKey()中界说了2个部分变量,其间keyreturn为一般一般的部分变量,每次函数履行时,keyreturn为函数的回来值,总是先初始化为0,只要在状况1中从头置1,作为表明按键承认的标志回来。变量keystate非常重要,它保存着按键的状况值,该变量的值在函数调用完毕后不能消失,有必要保存原值,因而在程序中界说为“部分静态变量”。经过对按键的扫描程序后,就知道了哪一个独立键盘的按键被按下了,经过void keysure()函数来界说每一个按键的功用。
中止优先级的界说:
LPC2103的向量中止操控器VIC(Vectored Interrupt Controller)具有32个中止恳求输入。可将这些中止编程分为3类:FIQ、向量IRQ、非向量IRQ。其间快速中止恳求FIQ(Fast Interrupt reQuest)具有最高的优先级。向量IRQ(Vectored IRQ)具有中等优先级。该等级可分配32个中止恳求中的16个。32个恳求中的恣意一个都可分配到16个向量IRQ slot中的恣意一个,其间slot0具有最高优先级,而slot15则为最低优先级。非向量IRQ(Non-vectored IRQ)的优先级最低。
在这个多功用时钟的程序规划中,运用了两个中止都是分配为向量IPQ。守时器1作为时钟的基准计数时钟,有最高的优先级;守时器2分配为下一个优先级。相关的句子设置如下:
VICVectCntl0 = 0x20 | 5; /* 守时器1分配为向量IRQ通道0 */
VICVectAddr0 = (UINT32) Timer1ISR; /* 分配中止服务程序地址0 */
VICVectCntl1 = 0x20 | 26; /* 守时器2分配为向量IRQ通道1 */
VICVectAddr1 = (UINT32) Timer2ISR; /* 分配中止服务程序地址1 */
VICIntEnable = 1 << 26; /* 守时器2中止使能 */
VICIntEnable = 1 << 5; /* 守时器1中止使能 */
四、调试进程
因为这次的规划运用的是LPC2103的开发板,所以在硬件上不需求太多的去调试。在运用开发板硬件资源的根底上,因为这次的多功用闹钟规划运用的模块较多,根本上各个模块的调试是分隔进行的。首要包含初始化的程序调试、按键子程序调试、LED显现调试这几部分子程序的调试。将这三部分调试成功,那么整个规划的软件部分也就根本完结了。在该课程规划中,选用的集成开发环境是uVision,在软件规划进程中,有时分不小心插入了一个中文的符号(如分号),就会使软件编译不经过,开端在这个过错上糟蹋不少时刻,但后来留意到了这个状况,避免了相似的过错的发生。
我首要进行的是键盘扫描模块的程序规划及调试。该模块首要由按键的状况承认函数(UINT8 GetKey())和按键承认函数(void keysure())共同完结。按键的状况函数首要是由一个回来值来承认按键的状况,开端的时分,因为短少一个句子:keyreturn=0;即每次进入函数的时分要将按键的状况清零,导致按键在一次按下之后就呈现了不正常的状况,终究找到问题的地点,就纠正了过来。因为这个模块是我最早进行的,所以开端的时分我并没有给每个按键界说相应的功用,每个按键的功用我都是界说为每次按下对相应的LED进行取反操作,在之后的规划中,再在相应的按键承认句子下增参加相应的功用,这也是模块化程序规划的一个表现。
四位的数码管选用的是动态显现形式,改写频率为50Hz,别的,因为开发板的硬件选用的是移位寄存器送笔段码,所以在软件规划方面要用到将8位笔段码不断循环右移,添加了规划的难度。起先我以为悉数程序都编写得差不多的时分,烧进芯片的程序使数码管显现一片含糊,根本上显现的都是8,后来从程序的开端查起,总算找到原因,本来动态显现程序中,每次只能是一位的数码管点亮,但在程序规划中,在点亮下一位数码管时,忘记了将上一次点亮的位给关掉,导致四位数码管时一起被点亮的,终究,在点亮数码管前首要将四位数码管悉数封闭,再以50Hz的频率进行点亮改写,显现方回到正常状况。
终究便是在这两个模块的根底上来对全体的程序进行相关的调试和完善。例如在原先设置有当进入时刻设置或许闹钟挂起时有LED点亮进行提示,设置时刻时相关的设置超越相应的极限值,这些在终究的调试进程中得到完善,使其作业在正常的状况,调试进程也就这样根本得到完结。
五、定论
这次的课程规划根本上完结了任务书中所提出的要求。终究的制品具有如下功用:
经过数码管动态扫描的作业方法完结时分秒年月日星期的显现,运用键盘完结运用四位数码管能够进行如上时刻的自在切换,时钟具有时刻设置和随时的校准功用。有三组可随意设置翻开或许封闭的闹钟,闹钟匹配时有蜂鸣器响和LED闪耀两种方法进行提示。运用串口能够输出当时时刻和被挂起的闹钟。
综上所述,本次的课程规划到达预期的规划要求。
六、小结与评论
经过为期一个星期以来的单片机课程规划,感觉自己在这么的一个进程下来,仍是很有收成的。这个规划的标题教师是在亚运放假之前就给咱们的,我知道教师是期望咱们用亚运放假的时刻去考虑、去预备的进程。
从暑假以来,我就运用暑假闲暇的时刻,来自学ARM7TDMI-S内核的一款芯片LPC2103,其与单片机相识的一些功用我都有触及性的学习过了,在9月份,我买了它的开发板,进行相关的实践性学习。依据上述的原因,所以这次的课程规划我就想用这款LPC2103的芯片开进行这次的课程规划,也是对我之前的学习的一种查验。曾经用开发板学习的时分,都是针对其的独自一个功用进行相关程序的规划,而这次的课程规划会触及比较多的功用模块的归纳运用,所以,开端的时分有点摸不着头脑的感觉。终究经过几番的考虑,我就决议,针对每一个模块,一个个进行攻破,终究完结了多功用电子时钟的悉数的功用。
首要,我运用LPC2103的实时时钟功用(RTC),先对其进行初始化,使其的时钟跑起来,在这个根底上,我最早是开端键盘模块的规划,这就触及到:键盘扫描,键盘去颤动,键盘判别相关的问题,终究经过两天的编程,规划,调试,考虑才把键盘模块的问题顺畅地处理了。从开端的模型规划,到详细功用的完结,直到终究的软件规划和调试进程,每一个环节都让我加深了对实践问题的考虑,有利于自己着手才能的进步。
这次的课程规划让我学会了体系地去处理一个实践的问题,了解到了单片机规划的根本进程、开发规划进程中需求留意的问题、学会处理调试进程中呈现的问题.,学会了奇妙运用模块化规划的思维,在整个的程序化规划进程中,学会将功用细化,分红一个小功用来完结,在规划好一个功用之后,再在这个根底上去添加其他的功用,终究完结整个多功用电子时钟的规划。总归,经过这次的课程规划,查验了我所学习的常识,使我将平常书本上的理论常识与实践很好地结合起来,利于加深对理论常识的了解和进步自己的实践着手操作才能。
七、参考文献
1、《ARM微操控器根底与实战》 出版社:北京航空航天大学出版社 2005年
2、《ARM7易学通》 出版社:人民邮电出版社 2006年
3、《EasyARM2103教材》 出版社:北京航空航天大学出版社 2008年
4、《新编单片机原理与运用》 出版社:西安电子科技大学出版社 2007年
5、《新编单片机原理与运用试验》 出版社:西安电子科技大学出版社 2005年
附录:
开发板实物图
#include
#include
UINT8 keystate=0; //按键的状况标志有0、1、2三种状况
UINT16 key4=1023;//按键的扫描输入端
UINT8 keyreturn=0; //按键的回来值
UINT8 time10=0;//10ms标志位
UINT8 settime=0; //进入时刻设置标志位
UINT8 alarm=0;//闹钟设置有用标志位
UINT8 al_shi1=0; // 以下是闹钟的序号和用数组贮存的闹钟时、分位
UINT8 al_num=0;
UINT8 al_shi[4];
UINT8 al_fen[4];
UINT8 al_yunxu=0; //闹钟才开端比较,保证设置期间不比较
UINT8 LS=0; //闹钟时刻到,铃声有用位,0为无效状况
UINT8 al_on3off[4]={0,0,0,0}; //用数组记载闹钟是否敞开
UINT8 al_flag=0;//闹钟组数1.2.3,0表明没有闹钟被挂起
UINT8 al_fen1=0;
static UINT8 g_Dot = 0;
static UINT16 display = 0;//数码管显现缓存
UINT8 yue=8;
UINT8ri=8;
UINT8week=5;
UINT8shi=20;
UINT8 fen=0;
UINT8miao;
//——————————————————————————–
{
UINT16 Fdiv;
U1LCR = 0x83; // DLAB = 1,可设置波特率
Fdiv = (Fpclk / 16)/ UART_BPS; // 设置波特率
U1DLM = Fdiv / 256;
U1DLL = Fdiv % 256;
U1LCR = 0x03;
}
{
if(GPIO_num < 16)
PINSEL0&= ~(0x03 << (GPIO_num * 2));
else
PINSEL1&= ~(0x03 << ((GPIO_num-16) * 2));
}
{
if(in_out)
IODIR |= (0x01 << GPIO_num);//output 1
else
IODIR &= ~(0x01 << GPIO_num);//input 0
}
{
if(IOPIN & (1 << GPIO_num))
return 1;
else
return 0;
}
{
if(High_Low)
IOSET |= (0x01 << GPIO_num);
else
IOCLR |= (0x01 << GPIO_num);
}
void LEDchange(UINT8 GPIO_num)//对二极管进行取反
{
if ((IO0PIN & (0x01 << GPIO_num)) == 0) {
IO0SET |= (0x01 << GPIO_num); // 点亮发光二极管
}
else IO0CLR |= (0x01 << GPIO_num);
}
{ if((nian%4==0&&nian%100!=0)||nian%400==0)
return 1;
else return 0;
{
switch(yue)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:return 31;
case 2:
{
if(nian_deal())
return 29;
else return 28;
}
case 4:
case 6:
case 9:
case 11: return 31;
default: return 1;
}
}
{
if(GPIO_READ(14)==0)//对每一位进行切换
{
if(settime!=0)
{
switch(dis_bit)
{case 0:
if(settime==1)
{shi++;
if(shi>23)
shi=0;
}
else {fen++;
if(fen>59)
fen=0;
}
break;
case 1:
week++;
if(week>7)
week=1;
break;
case 2:
nian++;
break;
case 3:
if(settime==1)
{yue++;
if(yue>12)
yue=1;
}
else
{ri++;
if(ri>yue_deal())
ri=1;
}
break;
}
}
if(alarm!=0)
{if(alarm==1)
{
al_shi1++;
if(al_shi1>23)
al_shi1=0;
al_shi[al_num]=al_shi1;
}
else
{al_fen1++;
if(al_fen1>59)
al_fen1=0;
al_fen[al_num]=al_fen1;
}
}
}
if(GPIO_READ(15)==0)
{
if(settime!=0)
{
switch(dis_bit)
{case 0:
if(settime==1)
{shi–;
if(shi>23)
shi=23;
}
else {fen–;
if(fen>59)
fen=59;
}
break;
case 1:
week–;
if(week==0)
week=7;
break;
case 2:
nian–;
break;
case 3:
if(settime==1)
{yue–;
if(yue==0)
yue=12;
}
else
{ri–;
if(ri==0)
ri=yue_deal();
}
break;
}
if(alarm!=0)
{if(alarm==1)
{
al_shi1–;
if(al_shi1>23)
al_shi1=23;
al_shi[al_num]=al_shi1;
}
else
{al_fen1–;
if(al_fen1>59)
al_fen1=59;
al_fen[al_num]=al_fen1;
}
}
}
if(GPIO_READ(16)==0)
{
if(dis_bit==3)
dis_bit=0;
elsedis_bit++;
}
if(GPIO_READ(18)==0)
{if(settime>1)
{
settime=0;
T1TCR = 0x01;
GPIO_SET(23,1);
}
else {settime++;
T1TCR = 0x00;
GPIO_SET(23,0);}
}
if(GPIO_READ(2)==0)
{al_yunxu=0;
alarm=1;
al_num++;
if(al_num>3)
al_num=1;
//al_num++;
}
if(GPIO_READ(3)==0)
{
alarm++; //对闹钟的时分为进行设置切换
if(alarm>2)
alarm=1;
}
if(GPIO_READ(4)==0)
{
if(alarm!=0)
{alarm=0;
al_shi1=0;
al_yunxu=1;
al_flag=0;
for(al_num=0;al_num<4;al_num++)
{ if(al_on3off[al_num]==1)
al_flag++;
}
if(al_flag!=0)
GPIO_SET(24,0);
if(al_flag==0)
GPIO_SET(24,1);
}
else
{
LS=0;
GPIO_SET(25,1);
GPIO_SET(11,1);
GPIO_SET(12,1);
}
}
{
if(alarm!=0)
{al_on3off[al_num]=1;
}
if(settime!=0)
nian=nian+10;
//表明有闹钟挂起,要加上一些标明位
}
if(GPIO_READ(6)==0)
{ if(alarm!=0)
{
al_on3off[al_num]=0;
}
if(settime!=0)
nian=nian-10;
}
{
//发动 输出敞开的闹钟信息
printf(“RTC —-%02d -%02d -%02d _ %02d : %02d : %02d WEEK=%d– \n”,nian,yue,ri,shi,fen,miao,week);
for(al_num=0;al_num<4;al_num++)
{
if(al_on3off[al_num]==1)
{
printf(“The number%d alarm is on.—Alarm time–%d : %d –\n”,al_num,al_shi[al_num],al_fen[al_num]);
}
}
UINT8 GetKey()
{keyreturn=0;
switch (keystate)
{
case 0:
if(key4!=1023) //检测到有按键,转到状况1,适当所以消抖进程
{
keystate=1;
}
break;
case 1:
if(key4!=1023) //再次检测到有按键,承认按键按下,回来一个值,并转到状况2
{
keyreturn=1;
keystate=2;
}
else
{
keystate=0; //没有检测到按键,阐明状况0检测到是一个颤动,从头转到状况0
}
break;
case 2:
if(key4==1023) //检测到按键松开,状况转到状况0,一次完好的按键进程完毕
{
keystate=0;
}
break;
}
return keyreturn;
}
{
UINT8 i;
for(i=0; i<8; i++)
{
GPIO_SET(CLK,LOW);
GPIO_SET(DATA,0);
}
else{
GPIO_SET(DATA,1);
}
GPIO_SET(CLK,HIGH);
dat >>= 1;
}
}
void Refresh_LED(UINT16 dat)
{
static UINT8 i = 0;
UINT8 a,b,c,d;
b = dat % 1000 / 100;
c = dat % 1000 % 100 /10;
d = dat % 1000 % 100 % 10;
switch(i)
{
case 0:
i++;
GPIO_SET(DIG_EN0,LOW);
data_shift(DIGData[d]);
break;
case 1:
i++;
GPIO_SET(DIG_EN1,LOW);
data_shift(DIGData[c]);
break;
case 2:
i++;
GPIO_SET(DIG_EN2,LOW);
if(g_Dot)
data_shift(DIGData[b] & ~(0x01 << 0));
else
data_shift(DIGData[b] | (0x01 << 0));
break;
case 3:
i = 0;
GPIO_SET(DIG_EN3,LOW);
data_shift(DIGData[a]);
break;
}
** Function name: Timer1_ISR
** Descriptions: 守时器1中止主程序
** input parameters: 无
** ouput parameters: 无
** Returned value: 无
*********************************************************************************************************/
void __irq Timer1ISR (void)
{
T1IR = 0x01; /* 铲除中止标志 */
miao++;
if(g_Dot)
g_Dot = 0;
else
g_Dot = 1;
VICVectAddr = 0x00; /* 中止向量完毕 */
}
{
GPIO_SET(DIG_EN0,HIGH);
GPIO_SET(DIG_EN1,HIGH);
GPIO_SET(DIG_EN2,HIGH);
GPIO_SET(DIG_EN3,HIGH);
Refresh_LED(display);
time10++;
T2IR = 0x01; /* 铲除中止标志 */
VICVectAddr = 0x00; /* 中止向量完毕 */
}
{
T1TCR = 0x02; /* 守时器1复位 */
T1PR = 0; /* 不设时钟分频 */
T1MCR = 0x03; /* 匹配后复位TC,并发生中止 */
T1MR0 = Fpclk ; /* 设置1秒匹配值 */
T1IR = 0x01; /* 铲除中止标志 */
T1TCR = 0x01; /* 发动守时器1 */
}
{
{
fen++;
if(al_flag&&al_yunxu) //表明闹钟敞开,bian a!!
{
for(al_num=0;al_num<4;al_num++)
{if(fen==al_fen[al_num]&&shi==al_shi[al_num]&&al_on3off[al_num]==1)
{ al_flag–;
al_on3off[al_num]=0;
if(al_flag==0)
GPIO_SET(24,1);
LS=1;
}
}
}
miao=0;
if(fen>59)
{
shi++;
fen=0;
if(shi>23)
{
ri++;
week++;
if(week>7){week=1;}
shi=0;
if(ri>yue_deal())
{
yue++;
ri=1;
if(yue>12)
{
nian++;
yue=1;
if(nian>9999)
nian=1000;
}
}
}
}
}
}
/*********************************************************************************************************
** Function name: Timer0\2Init
** Descriptions: 守时器0&2初始化
** input parameters: 无
** ouput parameters: 无
** Returned value: 无
*********************************************************************************************************/
void Timer2Init(void) //这儿也初始化了T0,用于pwm输出,驱动蜂鸣器
{
PINSEL0 &= ~(3 << 10);
PINSEL0 |= (2 << 10); //P0.5 作MAT0.1输出
T0TCR=0x02; //复位
T0PR =0x00; //不预分频
T0PWMCON=0x02; //MAT0.1为PWM输出,在P0.5脚
T0MR0=Fcclk/1000;
T0MCR=0x02; //每FCLK/1000复位一次T0
T0MR1=((Fcclk/2000)/10)*10;
T2PR = 0; /* 不设时钟分频 */
T2MCR = 0x03; /* 匹配后复位TC,并发生中止 */
T2MR0 = Fpclk /200; /* 设置5毫秒匹配值 */
T2IR = 0x01; /* 铲除中止标志 */
T2TCR = 0x01; /* 发动守时器2 */
}
{
PLLCON = 1;
#if (Fcco / Fcclk) == 2
PLLCFG = ((Fcclk / Fosc) – 1) | (0 << 5);
#endif
#if (Fcco / Fcclk) == 4
PLLCFG = ((Fcclk / Fosc) – 1) | (1 << 5);
#endif
#if (Fcco / Fcclk) == 8
PLLCFG = ((Fcclk / Fosc) – 1) | (2 << 5);
#endif
#if (Fcco / Fcclk) == 16
PLLCFG = ((Fcclk / Fosc) – 1) | (3 << 5);
#endif
PLLFEED = 0xaa;
PLLFEED = 0x55;
while((PLLSTAT & (1 << 10)) == 0);
PLLCON = 3;
PLLFEED = 0xaa;
PLLFEED = 0x55;
}
{
UART1_Init();
GPIO_init(14); // 挑选GPIO功用
GPIO_init(15);
GPIO_init(16);
GPIO_init(18);
GPIO_init(2);
GPIO_init(3);
GPIO_init(4);
GPIO_init(27);
GPIO_init(6);
GPIO_init(7);
GPIO_inout(14,0); // 设置输入
GPIO_inout(15,0);
GPIO_inout(16,0);
GPIO_inout(18,0);
GPIO_inout(2,0);
GPIO_inout(3,0);
GPIO_inout(4,0);
GPIO_inout(27,0);
GPIO_inout(6,0);
GPIO_inout(7,0);
GPIO_init(23); //LED操控端的初始化
GPIO_init(24);
GPIO_init(10);
GPIO_init(11);
GPIO_init(12);
GPIO_init(25);
GPIO_inout(23,1);
GPIO_inout(24,1);
GPIO_inout(10,1);
GPIO_inout(11,1);
GPIO_inout(12,1);
GPIO_inout(25,1);
GPIO_SET(23,1);
GPIO_SET(24,1);
GPIO_SET(10,1);
GPIO_SET(11,1);
GPIO_SET(12,1);
GPIO_SET(25,1);
GPIO_init(DATA);
GPIO_init(CLK);
GPIO_init(DIG_EN0);
GPIO_init(DIG_EN1);
GPIO_init(DIG_EN2);
GPIO_init(DIG_EN3);
GPIO_inout(CLK,OUTPUT);
GPIO_inout(DIG_EN0,OUTPUT);
GPIO_inout(DIG_EN1,OUTPUT);
GPIO_inout(DIG_EN2,OUTPUT);
GPIO_inout(DIG_EN3,OUTPUT);
GPIO_SET(DATA,HIGH);
//GPIO_init(5);
//GPIO_inout(5,1);
//GPIO_SET(5,1);
Timer1Init();
Timer2Init(); // 守时器初始化
VICIntSelect = 0<<26; // 守时器2分配为IRQ中止
VICVectCntl1 = 0x20 | 26; /* 守时器2分配为向量IRQ通道0 */
VICVectAddr1 = (UINT32) Timer2ISR; /* 分配中止服务程序地址 */
VICIntEnable = 1 << 26; /* 守时器2中止使能 */
VICIntSelect = 0<<5;
VICVectCntl0 = 0x20 | 5; /* 守时器1分配为向量IRQ通道0 */
VICVectAddr0 = (UINT32) Timer1ISR; /* 分配中止服务程序地址 */
V%&&&&&%IntEnable = 1 << 5; /* 守时器1中止使能 */
{
timeupdate();
if(alarm!=0)
{
if(al_on3off[al_num]==0)
display=al_num*1111;
else
display=al_shi[al_num]*100+al_fen[al_num];
}
else
{ switch(dis_bit)
{ case 0:
display=shi*100+fen;
break;
case 1:
display=miao*100+week;
break;
case 2:
display=nian;
break;
case 3:
display=yue*100+ri;
break;
}
}
{time10=0;
if(GetKey()==1)
{
keysure();
}
}
{ if(miao%2==0)
{ GPIO_SET(25,1);
GPIO_SET(11,1);
GPIO_SET(12,1);
T0TCR=0x01;
}
else
{ GPIO_SET(25,0);
GPIO_SET(11,0);
GPIO_SET(12,0);
T0TCR=0x00;
}
}
}
}
typedef unsigned int UINT16 ;
typedef unsigned int UINT32 ;
//——————————————————————————–
#define Fosc(11059200)//晶振频率,10MHz~25MHz,应当与实践一至
#define Fcclk(Fosc * 4) //66.3552 体系频率,有必要为Fosc的整数倍(1~32),且<=60MHZ
#define Fcco(Fcclk * 4) //CCO频率,有必要为Fcclk的2、4、8、16倍,规模为156MHz~320MHz
#define Fpclk(Fcclk / 4) * 1 //016.5888,VPB时钟频率,只能为(Fcclk / 4)的1 ~ 4倍
typedef enum
{
LOW,
HIGH
}en_Level;
{
INPUT,
OUTPUT
}en_InOut;
{
FALSE,
TRUE
};
#defineSG(0x01 << 1)
#defineSF(0x01 << 2)
#defineSE(0x01 << 3)
#defineSD(0x01 << 4)
#defineSC(0x01 << 5)
#defineSB(0x01 << 6)
#defineSA(0x01 << 7)
{
SA |SB |SC | SD |SE |SF,//0
SB | SC,//01
SA |SB |SG | SE | SD,//02
SA |SB |SC | SD | SG,//03
SB |SF | SG | SC,//04
SA |SF |SG |SC | SD,//05
SA |SC | SD | SE | SG | SF,//06
SA | SB| SC,//07
SA |SB |SC | SD | SE | SF | SG,//08
SA |SB |SC|SD | SF | SG,//09
0,//mask – 10
SG//minus – 11
};
#defineLED212
#defineLED311
#defineLED410
#defineLED524
#defineCLK13
#defineDIG_EN120
#defineDIG_EN219
#defineDIG_EN317
#defineINT114
#defineINT215
#defineBUZZER23
//——————————————————————————–
void Timer0_Init(void);
void UART1_Init (void);
UINT8 GPIO_READ(UINT8 GPIO_num) ;
void GPIO_init(UINT8 GPIO_num);
void GPIO_inout(UINT8 GPIO_num,UINT8 in_out);
//inline voidGPIO_SET(UINT8 GPIO_num,UINT8 High_Low);
void __irq IRQ_Timer0 (void);
void GPIO_SET(UINT8 GPIO_num,UINT8 High_Low);
//——————————————————————————–