赞
踩
程序编写结构还是中断函数结构的写法,只是由于定时器涉及的寄存器较多,中断初始条件函数中条件也就随之增多。
void 函数名()
{
主要写一些初始化变量。(基本的就是3.1~3.5所涉及的寄存器的初值条件设定)
}
void 函数名() interrupt 中断号
{
就是写时间到后执行什么。(但是为了中断的实时性,有时只写只写中断状态的标志,紧急事件用另一个函数来写,后续实践篇代码有讲)
}
别忘了还要查看对应的中断号
涉及的寄存器要查看手册,通常会涉及到:
高低位寄存器
TMOD寄存器
中断寄存器
TCON寄存器
涉及的模块:
这里涉及到了LED操作,故HC138接到4通道,才能是控制LED灯的,只有L1和L8两个灯,可以用sbit标出来,可读性比较强。
用到了定时,故定时的结构需要写出来。
在定时结构中,题目要求是Time0,查询资料手册,涉及的寄存器有如下,并写入代码:
L1灯单位是0.5秒,L8单位是5秒,两者成一个倍数关系,故只需要一个初值即可,以0.5秒为初值,但一个定时器运行完依次最多为65535us,即65.532ms,
需要0.5s即500ms即500000us,
故可以每次计时50000us,定时器运行10次,就到达了0.5s, 定时器运行100次,就到达了5秒。
按照之前所提的公式: TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
- void Init_Time0()
- {
- TMOD = 0x01;
- TH0 = (65535 - 50000) / 256;
- TL0 = (65535 - 50000) % 256;
- TR0 = 1;
- EA = 1;
- ET0 = 1;
-
- }
然后在中断服务函数上判断是否到达0.5s,到达了进行L1操作
在进一步判断是否到达5s,到达了进行L8操作。
这里解释以下:
(1)判断定时器运行10次和100次可以用一个变量累加来判断。然后取余操作判断是否达到了每一个10次,当达到100次时,变量清零重计数
(2)在中断中L1和L8的闪烁操作用的是取反:
为什么可以这样呢?中断程序是这样的,刚刚提到定时器运行10次才到达0.5s,默认L1初始为1,即不点亮,当定时器运行了10次才能到达0.5s,注意在这十次中,每一次,都进入了中断服务函数,但是执行到了count++后就不再执行下去,因为没满足if条件,故这段时间L1一直是熄灭的,熄灭时间为(0~9次),刚好10次,0.5秒。当执行第十次时,满足第一个if条件,到达0.5s,那么L1取反为0,点亮。在第11到第19次中,同样,每一次,都进入了中断服务函数,但是执行到了count++后就不再执行下去,因为没满足if条件,故在这段时间内L1一直=0,即L1一直是点亮状态,这段点亮持续了多久呢?(第10次到第19次),刚好10次,故点亮了0.5s。直到第20次,又满足了第一个if条件,L1取反为1,熄灭。
这就是在中断中可以用取反来表示LED闪烁的原因。
- #include "stc15f2k60s2.h"
-
- sbit L1 = P0^0;
- sbit L8 = P0^7;
-
- void selectHC138(unsigned int n)
- {
- switch(n)
- {
- case 0:
- P2 = (P2 & 0x1f) | 0x00; break;
- case 1:
- P2 = (P2 & 0x1f) | 0x20; break;
- case 2:
- P2 = (P2 & 0x1f) | 0x40; break;
- case 3:
- P2 = (P2 & 0x1f) | 0x60; break;
- case 4:
- P2 = (P2 & 0x1f) | 0x80; break;
- case 5:
- P2 = (P2 & 0x1f) | 0xa0; break;
- case 6:
- P2 = (P2 & 0x1f) | 0xc0; break;
- case 7:
- P2 = (P2 & 0x1f) | 0xe0; break;
- }
- }
-
- void Init_Time0()
- {
- TMOD = 0x01;
- TH0 = (65535 - 50000) / 256;
- TL0 = (65535 - 50000) % 256;
- TR0 = 1;
- EA = 1;
- ET0 = 1;
- }
-
- unsigned char count = 0;
- void Time0() interrupt 1
- {
-
- TH0 = (65535 - 50000) / 256;
- TL0 = (65535 - 50000) % 256;
- count ++;
- if (count % 10 == 0)
- {
- L1 = ~L1;
-
- }
- if (count %100 == 0)
- {
- L8 = ~L8;
- count = 0;
- }
-
- }
-
-
-
- void close() //关闭外设
- {
- selectHC138(5);
- P0 = 0x00;
- selectHC138(4);
- P0 = 0xff;
- }
-
- void main()
- {
- close();
- Init_Time0();
- selectHC138(4);
- while(1)
- {
-
- }
- }
-
这里涉及到多种模块:
定时器 :故定时器结构得写下来
数码管计时: 故要数码管得动态变化:数码管内容表(0~F,-) 数码管函数(包括内容和位置),数码管显示函数(显示什么内容),延时函数,HC138选择通道。
独立按键的使用:跳帽接到对应位置。由于只用了两个独立按键,可用sbit表示出来,要写个独立按键函数,判断是否按下。
这里主要的核心是定时器怎么设置:
题目要求设计秒表,分—秒—毫秒。
最小单位为50ms,即数码管最后两位每加1代表每加50ms,即01=50ms,02=100ms。
又1s= 1000ms ,最小单位为50ms,故数码管最后两位加到20就为1s,秒的两个位置(s位)+1,且数码管最后两位(ms位)清零。
同理,1min=60s,当秒位加到60,清零,min位+1。
数码管显示动态显示对应的位置,由于分—秒—毫秒都是各占两位,如用除和区域可得到各自的十位和个位。
注意:
TR0 = ~TR0; //表停止计时
- #include "stc15f2k60s2.h"
- sbit S4 = P3^3;
- sbit S5 = P3^2;
-
- void selectHC138(unsigned int n)
- {
- switch(n)
- {
- case 0:
- P2 = (P2 & 0x1f) | 0x00; break;
- case 1:
- P2 = (P2 & 0x1f) | 0x20; break;
- case 2:
- P2 = (P2 & 0x1f) | 0x40; break;
- case 3:
- P2 = (P2 & 0x1f) | 0x60; break;
- case 4:
- P2 = (P2 & 0x1f) | 0x80; break;
- case 5:
- P2 = (P2 & 0x1f) | 0xa0; break;
- case 6:
- P2 = (P2 & 0x1f) | 0xc0; break;
- case 7:
- P2 = (P2 & 0x1f) | 0xe0; break;
- }
- }
-
- void Delay(unsigned char t)
- {
- while(t--);
- }
-
- code unsigned char SMG_Table[] =
- {
- 0xc0, //0
- 0xf9, //1
- 0xa4, //2
- 0xb0, //3
- 0x99, //4
- 0x92, //5
- 0x82, //6
- 0xf8, //7
- 0x80, //8
- 0x90, //9
- 0x88, //A
- 0x83, //b
- 0xc6, //C
- 0xa1, //d
- 0x86, //E
- 0x8e, //F
- 0xbf //-
- };
-
- unsigned char t_min = 0;
- unsigned char t_s = 0;
- unsigned char t_ms = 0;
- //==============================Timer============
- void InitTime0()
- {
- TMOD = 0x01;
- TH0 = (65535-50000) / 256;
- TL0 = (65535-50000) % 256;
- TR0 = 1;
- ET0 = 1;
- EA = 1;
- }
-
- void Time0() interrupt 1
- {
- TH0 = (65535-50000) / 256;
- TL0 = (65535-50000) % 256;
- t_ms++;
- if (t_ms == 20)
- {
- t_s++;
- t_ms = 0;
- if (t_s == 60)
- {
- t_min++;
- t_s = 0;
- }
- }
- if (t_min == 99)
- {
- t_ms = 0;
- t_s = 0;
- t_min = 0;
- }
- }
- //==============================================
-
- void showSMG(unsigned char position, unsigned char number)
- {
- selectHC138(6);
- P0 = 0x01 << position;
- selectHC138(7);
- P0 = SMG_Table[number];
- }
-
- void SMGDisplay()
- {
- showSMG(0,t_min/10);
- Delay(500);
- showSMG(1,t_min%10);
- Delay(500);
- showSMG(2,16);
- Delay(500);
- showSMG(3,t_s/10);
- Delay(500);
- showSMG(4,t_s%10);
- Delay(500);
- showSMG(5,16);
- Delay(500);
- showSMG(6,t_ms/10);
- Delay(500);
- showSMG(7,t_ms%10);
- Delay(500);
- }
-
- //void SMGDelay(unsigned char t)
- //{
- // while(t--)
- // {
- //
- // }
- //}
-
- void Key()
- {
- if(S4 == 0) //stop
- {
- Delay(50);
- if(S4 == 0)
- {
- TR0 = ~TR0; //停止计时
- while(S4 == 0)
- {
- SMGDisplay();
- }
- }
- }
- if(S5 == 0) // clear to 0
- {
- Delay(50);
- if(S5 == 0)
- {
- t_ms = 0;
- t_s = 0;
- t_min = 0;
- while(S5 == 0)
- {
- SMGDisplay();
- }
- }
- }
- }
-
- void close()
- {
- selectHC138(5);
- P0 = 0x00;
- selectHC138(4);
- P0 = 0xff;
- }
-
- void main()
- {
- close();
- InitTime0();
- while(1)
- {
- SMGDisplay();
- Key();
- }
- }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。