全国电子大赛模拟路灯控制系统

更新时间:2024-06-20 02:16:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

题目名称:模拟路灯控制系统(I题)

摘要: 本模拟路灯控制系统以

AT89S52为主控芯片,通过传感器在晚

上是否有行人路过对路灯进行自动开启和关闭,并对路灯的运行状况进行及时反馈,然后通过数码管来显示状况。在提倡节能和高效的今天,大多数的路灯晚上是否有行人都是常开着的,这不仅浪费了电能而且影响了路灯的寿命。而我们设计的模拟路灯不仅在节能上得到了认可,而且在寿命上远远比普通的路灯寿命更长。

关键词: 传感器 ; 路灯 ;节能

Abstract: AT89S52 is used as the master chip in this simulating street light control system. Judging by sensors, the street lights are turned on or off automatically in the evening whether there are pedestrians passing by. The operating conditions of the street lights can be timely feedback and displayed on LEDs. Energy conservation and efficiency are promoted today, while most of the street lights are often turned on at night whether there are pedestrians passing by. This not only wastes energy but also affected the life of the lamps. In our design, not only the simulating street lights’energy-saving has been recognized, but also their lives are far longer than ordinary ones.

Key words: sensor ; street light ; energy-saving

1

1. 方案论证与比较

1.1 LED灯驱动的比较与选择

1W的LED灯不能使用普通的三极管作为驱动,因为普通的三极管功率为0.6W左右,若驱动1W的LED灯,三极管功率太低,发热量大,极容易烧坏。而1W的三极管种类也有很多,而我们选择3DA18A三极管作为LED的驱动,这是因为3DA18A管耗小,功率为1W符合驱动三极管的条件。

1.2 传感器的比较与选择

用光敏电阻组成光敏探测器。光敏电阻的阻值可以跟随周围环境光线的变化而变化。当光线照射到物体上时,光线反射,反射光一般好弱,考虑到试题的要求,因此光敏电阻在晚上对行人的检测将不再起大作用,因此我们考虑其他的方案。用RPR220型光电对管。RPR220是一种一体化反射型光电探测器,其发射器是一个砷化镓红外发光二极管,而接收器是一个高灵敏度,硅平面光电三极管。采用RPR220完全可以有效的降低干扰,而且方便可行,能够准确的实施检测。RPR220采用DIP4封装,其具有如下特点:塑料透镜可以提高灵敏度。内置可见光过滤器能减小离散光的影响。体积小,结构紧凑。且当发光二极管发出的光反射回来时,三极管导通输出低电平。

1.3 显示模块的比较与选择

本模拟路灯控制系统中,要求显示时钟和路灯出故障时显示相应的路灯,此时的显示可以用液晶模块1602来显示,或者采用其他的LCD模块来显示,也可以采用数码管来显示,对于这个系统,采用LED作为显示,数码管显示亮度高,由于显示模块只是用来显示一些简单数字,且根据要求所显示数字为清晰可见这就为使用数码管的变成了可能。用数码管作为显示模块也能体现性价比,所以我们选择了一个四位一体共阳的数码管作为显示模块。

1.4 测量方法比较和选择

传感器的传感距离在可行的范围之内越近越好,我们可以选择接触式测量和 非接触式测量,对于该系统,我们选择了非接触是的测量比较接近实际而又符合生活中实际路灯对晚上行人的感触。而测量路灯运行的正常状况,我们可以加高电压或者电流让LED灯烧坏,此时CPU发出报警和显示相应烧坏的路灯序号,而一般情况下我们不采取这种做法,在可行的情况的下,我们可以选择截断LED灯一根电源供应线,此时电路的相当于烧坏LED的作用,测量的效果亦可以起到烧坏LED灯的作用,所以我们选择了后者作为LED灯运行状况的测量。

2

2.硬件设计

2.1 总体设计

模拟路灯控制控制系统有五大板块组成,划分为:电源模块,单片机控制模块,传感模块,LED灯驱动模块,报警模块,各个模块并不是相互独立的,而是彼此工作,一旦有一板块停止工作,都会影响其他的模块。电源模块输入的220V的交流电,经变压器两降压和相关元件整流,滤波,稳压后输出5V的直流电源输送给各个模块,控制模块是整个电路的核心,它收集来自各个模块的信号,并对信号进行处理发出相应的控制指令,传感模块对环境和路灯下是否有行人进行信号的发射和收集,当传感器检测到环境是晚上,检测到是否有人路过,自动开启和关闭路灯,并对路灯的好坏情况反映给控制模块,让CPU作出相应的处理。

电源模块 光电传感器模块

单片机控制 光敏电阻感应模块 LED驱动模块 模拟路灯控制系统总体框架图

2.2 单元电路设计

2.2.1反射式光电传感器模块设计:

依题意,“可移动物体M(在物体前端标出定位点,由定位点确定物体位置)

由左至右到达S点时(见图2),灯1亮”,可见,要感应物体M的移动,可用红外传感器来感应物体的到来和离去,把物体的移动信息及时的传送至CPU,让CPU作出相应的处理,我们选择了RPR220传感器,因为它具有发射和接收

3

功能,而且管耗小,较灵敏,其工作电压为为5V,光电传感模块原理图如下所示:

2.2.2 光敏电阻感应模块设计:

本系统使用的光敏电阻是龙信达科技公司生产的型号为LXD95系列的Φ9

的光敏电阻,该电阻对光比较灵敏,而且价格便宜,额定电压为3.5V,光阻为0.7K,暗阻为110K。该电阻配合光电模块起作用,白天,光电模块送低电平到单片机,晚上,送高电平,让单片机作出相应的处理,光敏电阻感应模块原理图如下:

2.2.3 LED灯驱动电路模块设计:

本设计使用的LED灯为1W的大功率发光二极管,不能使用普通的三极管来做驱动,这是因为普通的三极管功率小,发热量大,极易烧坏,所以必须使用中大功率的三极管来做驱动,我们选择了3DA 18A三极管,它的额定功率为1W,最大电压为5V,最大电流为220MA,DIP金属封装,管耗小。LED灯驱动电路模块的原理图如下:

4

2.2.4 电源模块的设计

由于整个系统的正常工作电压是5V,所以我们打算用12V的变压器把220V的交流电降压到12V,然后再通过KBP307进行整流,经过7805稳压到5V,电源模块原理图如下:

5

3 .软件设计

我们选用了AT89S52单片机作为中央处理器,它内部具有4KB的程序存储空间,3个定时、计数器。我们采用了C语言编程来控制单片机。程序的大致流程图如下图所示: 开始 初始化 启动5MS定定时中断 按键判断 时 计算时间 显示LED 否 送段码到缓冲区 是否定时驱动 中断结束 晚上 是 定时驱动 检测环境 白天 检测环境 关灯 判断行人走过 从左到右 有 报警 灯亮顺序1 从右到左 灯亮顺序2 环境检测 有 报警

程序流程图

6

4.系统测试

4.1时钟功能的测试:

通过按键的设置,可以任意设置时间,由于是采用四位一体数码管,所以只能显示分钟和秒的时间,虽然不能显小时的时间,但也总算是实现了部分时钟的功能。

4.2 设定、显示开关时间并控制整条支路按设好的时间开灯和关灯功能的测试:

首先我们先通过按键设置好多少时间以后就马上开灯或者关灯,数码管上显示的时间久开始倒计时,一旦达到所设置的时间就马上开灯或者关灯。在实验中,我们分别设置了一分钟以后就开灯和关灯,结果从灯的亮灭情况来看确实是达到了要求,因此我们这一步的设计是成功的。

4.3 根据环境明暗变化,自动开灯和关灯的测试:

我们测试这个功能很简单,在白天的情况下,LED灯是处于熄灭的状态,当我们用物体把光敏电阻罩住,阻止光照射到光敏电阻,两个LED灯就马上亮起来,因此我们的这一步的设计是成功的。 4.4 自动调节亮灯状态的测试:

我们用一个当物体经过第一个光电传感器时,灯1亮;当物体经过第二个光电传感器时,灯1灭,灯2亮;当物体经过第三个光电传感器时,灯2灭。若物体以相反的次序经过光电传感器,那么灯亮次序与上相反。由此我们也实现了这一功能。

4.5 灯出现故障,能显示出故障灯的灯号,并能报警:

由于灯出现故障,大多数情况是断路,由此我们只要在灯亮的情况下使灯不接入电路就可以人为制造故障了检测显示和报警的功能。在具体操作时,我们把1号灯不接入,那么数码管显示数字1,蜂鸣器发出报警声;当我们把2号灯不接入,那么数码管娴熟数字2,蜂鸣器发出报警声。

7

总结

测试表明,模拟路灯控制系统灯能够实现本次设计的基本要求。通过各种方案的讨论及尝试,再经过多次的整体软硬件结合调试,不断地对系统进行优化,才终于把此次设计完成。

在这次电子竞赛设计中,我们也从中学到了一些有关电子方面的知识,比如大功率LED的驱动,非接触式传感器的工作原理等,同时我们在电路检测这一环节中,也学到了一些检测基本电路故障的方法,比如在光电传感器这一部分电路中,很多次都不能实现传感器的作用,电路不工作正常,单片机无法采样电平,于是我们就在面包板上一个一个元器件的替换,后来才知道每个元器件不同的数值会直接影响传感器的正常工作,通过不断的调试,终于找出了能让传感器正常工作的元器件数值。虽然我们这次设计基本上达到了要求,但还有很多的不足,比如在制作PCB板中,没有很好布局与布线,在各个电路模块中,也没有很好考虑到整个控制系统的方便性,由于要用传感器采样,所以就必须要制作多个模块,于是决定采用导线把模块接到单片机并控制各个模块的工作情况,这样就增加了电路的复杂性,同时电路受到的不明干扰性也增大。

在部分模块电路的硬件测试中,刚开始做面包板试验时,电路连接是对了,但没有实现相应的功能,我们就一直在改电路,甚至想换掉整个模块,经过反复的思考,我们就怀疑芯片是坏的,于是我们就单独检测了芯片的功能,终于发现原来芯片是坏的,由此我们就得到一点经验,那就是在做面包板试验时,要仔细认真检测每个元器件的好坏,哪怕是刚买回来的元器件也可能是坏的。还有一个要注意的问题,那就是在调试各个模块的时候要记得仔细检查各个焊点是否短路和虚焊,如果不确定的地方,最好是用万用表检测一下。另外,在软件调试时,我们采用先编好一个模块的程序,并实现功能,接着继续编其他模块的程序,一个一个模块功能实现的方式,最后才把各个程序串联起来,经过不断的调试与修改,最后终于能使整个程序正常运行起来,并可以实现各个模块的功能,总体上达到了设计的基本要求。由于时间的原因,我们没有把发挥部分做出来,这也是很大的遗憾,因为我们在前阶段元器件的选择和调试中浪费了很多的时间,以至于到最后都没有时间去做发挥的部分,不管怎样,我们还是感到比较欣慰,毕竟是已经很努力去做了。

8

参考文献

1.《模拟电子线路基础》,吴运昌著,广州:华南理工大学出版社,2004年; 2.《数字电子技术基础》,阎石著,北京:高等教育出版社,1997年; 3.《单片机原理及应用》,李建忠著,西安:西安电子科技大学,2002年;

附1:电路原理图 附2: 源程序

附录:

9

#include

//****************************************************************

typedef unsigned char uint8; /* 无符号8

位整型变量 */

typedef signed char int8; /* 有符号8

位整型变量 */

typedef unsigned short uint16; /* 无符号16

位整型变量 */

typedef signed short int16; /* 有符号16

位整型变量 */

sbit P1_0 = P1^0; sbit P1_1 = P1^1; sbit P1_2 = P1^2; sbit P1_3 = P1^3; sbit P1_4 = P1^4; sbit P1_5 = P1^5; sbit P1_6 = P1^6; sbit P1_7 = P1^7; sbit P2_0 = P2^0; sbit P2_1 = P2^1; sbit P2_2 = P2^2; sbit P2_3 = P2^3; sbit P2_4 = P2^4; sbit P2_5 = P2^5; sbit P2_6 = P2^6; sbit P2_7 = P2^7; sbit P3_0 = P3^0; sbit P3_1 = P3^1; sbit hj_jc = P3^2; sbit P3_3 = P3^3; sbit flag_8 = P3^4; sbit flag_9 = P3^5;

//----------------------------------------------------------------------------------------------------//

//“1234”- 固定显示的数,可根据具体情况更改(可改为 0 -

10)

const uint8 leds_gd[4] = {1,2,10,10};

//led显示时用的显示数据缓冲区(led段码管上的显示内容就是

数组里的内容)

uint8 leds[4] = {0,0,0,0};

10

uint8 led_zimo[11] =

{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF};

//--------------------------------------------------------------------------------------------------------//

/*

按键为 4 个,定义及键码分别为:(不可改,否则按键处理时

对不上号)

切换/确认键:EKB_OK = 1 ,用来切换设置状态和显示状态 加键:EKB_ADD = 2 ,焦点数字加 1 减健:EKB_SUB = 4 ,焦点数字减 1

显示模式切换键:EKB_MODE = 8 ,手动切换 时间显示 和

“1234”显示

//--*/ #define EKB_OK 1 #define EKB_ADD 2 #define EKB_SUB 4 #define EKB_MODE 8 //按键信息结构 typedef struct {

uint8 io_s; //按键状态【更新前为上

一次状态,更新后为当前状态】

uint8 io_n; //按键状态连续持续

ticks个数记录

uint8 kb_s; //当前键盘状态【0 - 未

按下;1 - 按下】

uint8 kb_chg; //键盘状态变位标识【1 |

0,读清零,1 时不产生新的状态以等待程序处理】

} T_KB;

//按键状态宏定义 - 按键按下 #define _KBS_PRESS 1 //按键动作宏定义 #define _KBS_FREE 0 //按键未按

#define _KBS_DOWN 1 //按键按下 //按键去抖时间(_KB_DITHERT × 5ms = 去抖时间,可根

据实际情况修改。数字越大,按键越不灵敏)

#define _KB_DITHERT 10 //按键状态缓存 T_KB t_kb[4];

//--------------------------------------------------------------------------------------------------------//

11

//当前页面序号(0 - 正常页面,时间和“1234”切换;1 - 时

间设置页面)

uint8 scr_cur = 0;

//当前页面序号备份(上一次的值,用于判断页面切换) uint8 scr_curc = 1;

//自动换屏的定时常数定义(单位:毫秒)- 可根据实际情况

修改,如需要 5秒 自动换屏,则 改为 5000

#define _SCR_AUTOTIME 3000 //闪烁时焦点熄灭的时间定义(单位:毫秒; 显示时间则为 1000

- _SCR_FLASH_HIDETIME)

#define _SCR_FLASH_HIDETIME 300

//闪烁时led不显示任何值(即熄灭)的值的宏定义(在 码表

里 该值 表示 led灯全灭)【该值可改,但建议别改】

#define _LED_KC_BLANK 10

//--------------------------------------------------------------------------------------------------------//

//秒计时器(作为当前时间) uint16 value=0,tmr_sec = 0;

//毫秒计时器(累计计时,一直累加) uint16 tmr_ms = 0;

//毫秒计时器(进位计时,用于 分钟的累计) uint16 tmr_ms2 = 0;

//时间变化值宏定义(1 - 时间增加,正计时;-1 - 时间减

小,倒计时,单位:秒。如果要 正计时 的话,改成 1)

uint8

flag=0,flag_2=0,alm1,alm2,flag_10=0,flag_7=0,flag_6=0,num=0;

#define _TMR_CHG -1

//定时器超时定时值(固定为 5ms,所以需要一个 5ms 的定时

器。若你的定时器为 10ms的循环定时器,则将其改为 10)

#define _TMR_TICKTIME 5

void tmr_isr(void); void led_display(void);

//----------------------------------------------------------------------------------------------------//

void delayms(uint8 value) {

uint8 i=0,j=0;

for(j=0;j

void t0_int()

12

{

TMOD=0x11;

TH0=(65536-5000)>>8; TL0=(65536-5000);

TH1=(65536-50000)>>8; TL1=(65536-50000); ET1=1; ET0=1; EA=1; TR0=1; }

void time0() interrupt 1 {

TH0=(65536-5000)>>8; TL0=(65536-5000); TF0=0; tmr_isr(); led_display(); }

void time1() interrupt 3 {

TH1=(65536-50000)>>8; TL1=(65536-50000); TF1=0; num++; }

/*****************************************************

****************************************************

** 函数名称 : expend16u ** 输 入 : 起始值,结束值 ** 输 出 : 差值

** 功能描述 : 计算两个数据的线性差值(uint16): 用计算

值的备份值计算,不会因为值的随即变化而影响计算结果

******************************************************

****************************************************/

uint16 expend16u(uint16 istart,uint16 iend) {

if (iend >= istart)

13

return (iend - istart); else return (iend + ((uint16)0xFFFF - istart) + 1); }

//--------------------------------------------------------------------------------------------------------//

/*****************************************************

****************************************************

** 函数名称 : led_output

** 输 入 : 预显示数据数组首地址 ** 输 出 : 无

** 功能描述 : led数据准备(数据固定为 4 个字符) ******************************************************

****************************************************/

void led_output(uint8 *pdat) {

uint8 i;

for (i = 0; i < 4; i ++) { if ((pdat[i] <= 9) || (pdat[i] == _LED_KC_BLANK)) leds[i] = pdat[i]; //将需要显示的

数据拷贝到显示缓冲区

else leds[i] = _LED_KC_BLANK; }

/* if(num==0) {

for (i = 0; i < 4; i ++) { if ((pdat[i] <= 9) || (pdat[i] == _LED_KC_BLANK)) leds[i] = pdat[i]; //将需要显示的

数据拷贝到显示缓冲区

else leds[i] = _LED_KC_BLANK; } } else {

14

switch(flag_1) {

case 1: leds[0] = pdat[0];leds[1] = 10;leds[2] =

10;leds[3] = 10;break;

case 2: leds[0] = 10;leds[1] = pdat[1];leds[2] = 10;leds[3]

= 10; break;

case 3: leds[0] = pdat[0];leds[1] = pdat[1];leds[2] =

10;leds[3] = 10; break;

} } */ }

/*****************************************************

****************************************************

** 函数名称 : led_display ** 输 入 : 无 ** 输 出 : 无

** 功能描述 : led数据打印(数据固定为 4 个字符)【即

led输出驱动。。。】

******************************************************

****************************************************/

void led_display(void) {

//在这里把 leds[] 里的数据分别显示到 4 个led上。。。 //leds[0] 为 分钟的十位;leds[1] 为 分钟的个位 //leds[2] 为 秒的十位;leds[3] 为 秒的个位

//leds[?] 里的数为 0-9 时,显示为对应的数字,为

_LED_KC_BLANK(默认为 10) 时,对应的那一位led段码管不亮

uint8 i=0;

static uint8 iled = 0; iled = (iled + 1) % 4; P0 = 0xFF;

switch(iled) {

case 3: P1_3=0; P1_2=1; P1_1=1; P1_0=1; break; case 0: P1_3=1;

15

P1_2=1; P1_1=1; P1_0=0; break; case 1: P1_3=1; P1_2=1; P1_1=0; P1_0=1; break; case 2: P1_3=1; P1_2=0; P1_1=1; P1_0=1; break; }

// for (i = 0; i < 250; i ++);

if (iled == 1) P0 = led_zimo[leds[iled]] & (0x7F); else P0 = led_zimo[leds[iled]]; }

//--------------------------------------------------------------------------------------------------------//

/*****************************************************

****************************************************

** 函数名称 : kb_init ** 输 入 : 无 ** 输 出 : 无

** 功能描述 : 按键初始化

******************************************************

****************************************************/

void kb_init(void) {

uint8 i;

for (i = 0; i < 4; i ++) { t_kb[i].io_s = 0; t_kb[i].io_n = 0; t_kb[i].kb_s = 0; t_kb[i].kb_chg = 0; } }

/*****************************************************

16

****************************************************

** 函数名称 : kb_updata

** 输 入 : 切换确认键的当前状态,加键当前状态,减

键当前状态,模式键当前状态

** 输 出 : 无

** 功能描述 : 键盘扫描状态更新:按键未按下时为 0;按

键按下时为 1。【注意 参数顺序别错了,否则相当于按键被交换了】

******************************************************

****************************************************/

void kb_updata(uint8 iok, uint8 iadd, uint8 isub, uint8 imode) {

uint8 i,k,n;

n = (iok == _KBS_PRESS) | ((iadd == _KBS_PRESS) << 1) | ((isub == _KBS_PRESS) << 2) | ((imode == _KBS_PRESS) << 3) ; for (i = 0; i < 4; i ++) { k = ((n & (1 << i)) != 0);

//获得 键盘扫描状态

if (t_kb[i].io_s != k) {

//两次间状态不同,重置累计数据

t_kb[i].io_n = 1; } else t_kb[i].io_n ++; t_kb[i].io_s = k;

//更新当前状态到状态缓存,用于下一次判定时使用

if (t_kb[i].io_n >= _KB_DITHERT) {

//去抖动ok后,进行实质性判断,否则,保持现状

if (t_kb[i].io_s == _KBS_PRESS) {

//键按下状态

if (t_kb[i].io_n == _KB_DITHERT) {

//按键去抖后产生的“按下”动作

t_kb[i].kb_s = _KBS_DOWN; t_kb[i].kb_chg = 1; } } else

17

{

//键弹起状态,复位状态

t_kb[i].kb_s = _KBS_FREE; } t_kb[i].io_n = _KB_DITHERT; } } }

/*****************************************************

****************************************************

** 函数名称 : kb_getstatus ** 输 入 : 无

** 输 出 : 当前按键状态

** 功能描述 : 获得按键状态,按键状态按键码放置

******************************************************

****************************************************/

uint8 kb_getstatus(void) {

uint8 i,r; r = 0;

for (i = 0; i < 4; i ++) { r |= ((t_kb[i].kb_chg == 1) << i); //将 按下的按

键状态 输出

t_kb[i].kb_chg = 0; }

return r; }

//--------------------------------------------------------------------------------------------------------//

/*****************************************************

****************************************************

** 函数名称 : tmr_updata ** 输 入 : 无 ** 输 出 : 无

** 功能描述 : led数据准备(数据固定为 4 个字符) ******************************************************

****************************************************/

void tmr_updata(void) {

tmr_ms += _TMR_TICKTIME;

18

tmr_ms2 += _TMR_TICKTIME; if (tmr_ms2 >= 1000) { //累计计时超过

1秒,进行秒计时器的操作

tmr_sec += _TMR_CHG; //秒计数器更新 if (tmr_sec >= 6000) tmr_sec = 0; //计时超过 100 分

钟的限制后,强制为 0。倒计时时表现为 计时到0后停止变化。

tmr_ms2 -= 1000; //毫秒计时器数

字更新

} }

/*****************************************************

****************************************************

** 函数名称 : tmr_isr ** 输 入 : 无 ** 输 出 : 无

** 功能描述 : 定时器中断服务程序执行内容:定时器为

5ms 循环 定时

** : 把本程序放到 5ms 的定时器中断服务程序中,

按要求给定键盘输入参数。

******************************************************

****************************************************/

void tmr_isr(void) {

//计时更新 tmr_updata();

//按键状态更新:按要求给定键盘输入参数。。。 kb_updata(P2_1==0, P2_2==0, P2_3==0,P2_4==0); }

//--------------------------------------------------------------------------------------------------------//

/*****************************************************

****************************************************

** 函数名称 : scr_normal

** 输 入 : 按键状态,是否初始化页面[1 - 初始化] ** 输 出 : 无

** 功能描述 : 正常显示模式的页面程序

******************************************************

****************************************************/

void scr_normal(uint8 ikb, uint8 bfresh) {

19

static uint16 scr_auto_tmr = 0; //自动循环显示的计时

器,用于页面的定时切换

static uint8 iscr = 0; //时间 和 “1234”显示选

择(0 - 显示时间(不换屏);1 - 显示时间(换屏);2 - 显示“1234”(换屏))

uint8 i,k; uint8 tmp[4];

if (bfresh) { //屏幕切换进来时初始

化内容

scr_auto_tmr = tmr_ms; //自动页面切换计时器

更新

iscr = 0; //进入页面时默认显示 时

}

// if(flag_1!=0)if(iscr==0)iscr=1; if ((((alm1 || alm2)&&(flag_10))||((alm1 ||

alm2)&&(flag_7==1))) && (iscr == 0)) iscr = 1;

if (!(((alm1 || alm2)&&(flag_10))||((alm1 ||

alm2)&&(flag_7==1))))iscr = 0;

if (iscr == 2) {

// num=1; //显示“1234” P2_0=1;

tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0x0A; switch(flag_10) { case 1:tmp[0] = 1;break; case 2:tmp[0] = 2;break; } if(flag_7==1) { if (alm1) tmp[0] = 1; if (alm2) { if (alm1) tmp[1] = 2; else tmp[0] = 2; } }

20

led_output(tmp);

// led_output((uint8 *)leds_gd); // num=1 } else {

// num=0; P2_0=0; //显示时间,如

“12:1”显示为:1201

i = tmr_sec / 60; //分 k = tmr_sec % 60; //秒 tmp[0] = (i / 10) % 10; //分 - 十位 tmp[1] = i % 10; //分 - 个位 tmp[2] = k / 10; //秒 - 十位 tmp[3] = k % 10; //秒 - 个位 led_output(tmp); //显示当前时间:分 + 秒 }

if (iscr != 0) { //自动换屏 if (expend16u(scr_auto_tmr, tmr_ms) >=

_SCR_AUTOTIME)

{ //自动换屏时间到,

切换页面

if (iscr == 1) iscr = 2; else iscr = 1; scr_auto_tmr = tmr_ms; //自动页面切换计

时器更新

} }

// if(ikb==0&flag!=0) ikb=8;

//下面为当前页面下,对按键状态的处理 switch (ikb) { case EKB_OK: //切换键 - 切换页面

到“时间设置”

case EKB_ADD: //加键 - 切换页面到

“时间设置”

case EKB_SUB: //减键 - 切换页面到

21

“时间设置”

scr_cur = 1; break; case EKB_MODE: //显示模式切换键

- “时间”和“1234”切换

//显示模式切换 if (iscr != 0) iscr = 0; else iscr = 1; //模式切换后,自动页面切换计时器更新 scr_auto_tmr = tmr_ms; break; } }

/*****************************************************

****************************************************

** 函数名称 : scr_setting

** 输 入 : 按键状态,是否初始化页面[1 - 初始化] ** 输 出 : 无

** 功能描述 : 时间设置模式显示模式的页面程序

******************************************************

****************************************************/

void scr_setting(uint8 ikb, uint8 bfresh) {

static uint16 scr_flash_tmr = 0; //闪烁显示计时器(用于焦

点闪烁计时)

static uint8 scr_flash_status = 0; //闪烁状态【0 - 显示焦点;

1 - 不显示焦点】

static uint8 scr_focus = 0; //操作的焦点[0 - 3 -- 表示

第一个到第四个led段码管]

static uint16 tmr_backup; //修改的时间参数临时缓存

uint8 tmp[4],tmp2[4]; // int8 n;

if (bfresh) { //屏幕切换进来时初始

化内容

//初始化闪烁计时器及闪烁状态 scr_flash_tmr = tmr_ms - (1000 -

_SCR_FLASH_HIDETIME - 100);

scr_flash_status = 0;

22

为:隐藏

//操作的焦点初始化 scr_focus = 0; //修改值初值取当前时间值 tmr_backup = tmr_sec; }

tmp2[0] = tmr_backup / 60; tmp2[1] = tmr_backup % 60;

tmp[0] = (tmp2[0] / 10) % 10; tmp[1] = tmp2[0] % 10; tmp[2] = tmp2[1] / 10; tmp[3] = tmp2[1] % 10; tmp2[0] = tmp[0];

//分 //秒

//分 - 十位 //分 - 个位 //秒 - 十位 //秒 - 个位

//tmp2 在数字修改时

tmp2[1] = tmp[1];

tmp2[2] = tmp[2]; tmp2[3] = tmp[3];

//确保焦点在有效范围内:0 - 3 if (scr_focus >= 4) scr_focus = 0;

//将闪烁时处于“隐藏”状态的数去掉 if (scr_flash_status == 1) { //“隐藏”对应的数位 tmp[scr_focus] = _LED_KC_BLANK; }

led_output(tmp); //更新闪烁状态值

if (scr_flash_status == 1) { //当前闪烁状态

tmr_ms)

>=

if (expend16u(scr_flash_tmr,

_SCR_FLASH_HIDETIME)

{

到,切换成“显示”

scr_flash_status = 0; scr_flash_tmr = tmr_ms;

} } else {

//“隐藏”时间

//更新闪烁计时

//当前闪烁状态

23

为:显示

if (expend16u(scr_flash_tmr, tmr_ms) >= (1000 -

_SCR_FLASH_HIDETIME))

{ //“隐藏”时间

到,切换成“显示”

scr_flash_status = 1; scr_flash_tmr = tmr_ms; //更新闪烁计时

} }

//下面为当前页面下,对按键状态的处理 switch (ikb) { case EKB_OK: //切换/确认键 - 从数

字高位逐个移动修改的焦点,然后保存修改值后退出页面,返回“时间”页面

//移动焦点:从 分钟的十位 到 秒的个位 scr_focus ++; if (scr_focus >= 4) { //所有数位都修改后,退

出该页面,切换到“时间”页面

tmr_sec = tmr_backup; //保存修改后的时间值 scr_cur = 0; //切换到“时间”页面 } break; case EKB_ADD: //加键 - 将焦点数位

加 1

case EKB_SUB: //减键 - 将焦点数位

减 1

if (ikb == EKB_ADD) { if (scr_focus == 2) { //scr_focus == 2,修

改 秒的十位,进制为 6

tmp2[scr_focus] = (tmp2[scr_focus] + 1) % 6; } else { //分的十位、个位

及 秒的个位,进制为 10

tmp2[scr_focus] = (tmp2[scr_focus] + 1) %

10;

}

24

} else { if (scr_focus == 2) { //scr_focus == 2,修

改 秒的十位,进制为 6

if (tmp2[scr_focus] == 0) tmp2[scr_focus] = 5; else tmp2[scr_focus]--; } else { //分的十位、个位

及 秒的个位,进制为 10

if (tmp2[scr_focus] == 0) tmp2[scr_focus] = 9; else tmp2[scr_focus] --; } } //将修改后的各个数位组合成新的修改值 tmr_backup = (((uint16)((tmp2[0] * 10) + tmp2[1])) *

60) + (uint16)((tmp2[2] * 10) + tmp2[3]);

break; case EKB_MODE: //显示模式切换键

- 直接切换到“时间”页面

scr_cur = 0; break; } }

//--------------------------------------------------------------------------------------------------------//

/*****************************************************

****************************************************

** 函数名称 : main ** 输 入 : 无 ** 输 出 : 无

** 功能描述 : 主程序入口

******************************************************

****************************************************/

uint8 kb_getstatus2(void) {

25

态 输出

uint8 i,r; r = 0;

for (i = 0; i < 4; i ++) { r |= ((t_kb[i].kb_s == 1) << i);

//将 按下的按键状

}

return r; }

int main (void) {

//添加按键的硬件端口部分初始化程序(如果需要的话)。。。

//添加led段码管相关硬件的初始化程序(如果需要的话)。。。 //注意:需要完成 led_display() 函数,将 leds[] 数组的数输

出到led灯上

//添加定时器初始化程序(必须要一个 5ms 的 循环 定时

器,在 定时器的中断服务程序中调用 tmr_isr())。。。

//注意:tmr_isr() 函数里的 “kb_updata(0, 0, 0, 0);” 处传递

的参数用实际的按键状态填充,否则,按键无效。

//按键初始化

uint8 ikb,flag_5=0,flag_0=0; t0_int();

kb_init(); P2_0=0; for(;;) {

alm1 = flag_8; alm2 = flag_9; if(num>=100) {

flag_6=0; num=0; TR1=0; }

ikb = kb_getstatus();

26

//

记录

记录

记录

记录

//

if(flag_1!=0)scr_cur=0; if (scr_cur == 1) { //时间设置页面

if (scr_cur != scr_curc) { scr_curc = scr_cur; //更新页面序号

scr_setting(ikb, 1); //页面切换后进入 } else {

scr_curc = scr_cur; //更新页面序号

scr_setting(ikb, 0); //页面未切换 } } else { //正常显示页面 if (scr_cur != scr_curc) { scr_curc = scr_cur; //更新页面序号 scr_normal(ikb, 1); //页面切换后进入 } else {

scr_curc = scr_cur; //更新页面序号

scr_normal(ikb, 0); //页面未切换 } }

led_display(); //led数据输出

if(value!=tmr_sec) {

if(tmr_sec==0) {

flag_2++; if(flag_2==4)flag_2=0; if(flag_2%2==0) {

27

flag_7=0; P3_0=0; P3_1=0; flag_10=0; flag_0=0; }

if(flag_2%2==1) { flag_7=1; P3_0=1; P3_1=1; flag_0=1; }

}

}

value=tmr_sec;

if(flag_0==1)continue; else {

if(hj_jc==0) {

delayms(10); if(hj_jc==0) {

P3_0=0; P3_1=0; } // P2_0=0; }

if(hj_jc==1) {

delayms(10); { if(hj_jc==1) { /*

28

if((P2_5==1)&&(P2_6==1)&&(P2_7==1)&&((flag_6==0)||(flag_5!=0)))

{ P3_0=0; P3_1=0; } */ if(flag_6==0) { if(P2_5==0) { flag_5=1; P3_0=1; P3_1=0; if(flag_9)flag_10=1; else flag_10=0; } if(P2_7==0) { flag_5=2; P3_0=0; P3_1=1; if(flag_8)flag_10=2; else flag_10=0; } } switch(flag_5) { case 1: if(P2_6==0) { flag_6=1; flag_5=0; P3_0=0; P3_1=1; if(flag_8)flag_10=2; else flag_10=0; } break; case 2: if(P2_6==0) { flag_6=2; flag_5=0; P3_0=1; P3_1=0; if(flag_9)flag_10=1; else flag_10=0;

29

} break; } switch(flag_6) { case 1: if(P2_7==0) { // flag_6=0; } } } } // if (((flag_8 flag_9)&&(flag_7==1)))P2_0=1;

// else P2_0=0; } return 0; }

P3_0=0; P3_1=0; flag_10=0; TR1=1; } break; case 2: if(P2_5==0) { // flag_6=0; P3_0=0; P3_1=0; flag_10=0; TR1=1; } break; || flag_9)&&(flag_10==1))||((flag_8

||

30

} 目录

一、 摘要……………………………………………………………(1) 二、 方案论证与比较………………………………………..(2) 三、 硬件设计……………………………………………………..(4) 四、 软件设计……………………………………………………..(5) 五、 系统测试………………………………………………………(7) 六、 总结…………………...............................................................(8) 七、 参考文献……………………………………………….

31

目录

一、 摘要……………………………………………………………(1) 二、 方案论证与比较………………………………………..(2) 三、 硬件设计……………………………………………………..(4) 四、 软件设计……………………………………………………..(5) 五、 系统测试………………………………………………………(7) 六、 总结…………………...............................................................(8) 七、 参考文献……………………………………………….

31

本文来源:https://www.bwwdw.com/article/t013.html

Top