|
上電后點亮數碼管的所有段碼,且蜂鳴器響,持續1秒。
設定定時時間,按S2加1(長按連加),按S1輸入下一位(長按退回千位)。
時間設定完成后開始倒計時,按下S2暫停(長按3秒復位),再按恢復,按S1無動作。
倒計時結束后顯示 End 蜂鳴器響6下,短按任意鍵返回,如有問題請跟帖回復。
單片機型號:STC任意 (STC89/90除外) 晶振頻率:12Mhz
數碼管掃描/按鍵消抖/長按連加/毫秒延時全部使用定時器中斷實現。
更改不同STC系列的型號,只需更改頭文件,不需要改動程序任何部分。
硬件連接:
按鍵S1 -> P3.0 (低電平按下)
按鍵S2 -> P3.1
有源蜂鳴器 -> P3.2 (低電平鳴叫)
繼電器或MOS管 -> P3.3 (低電平吸合或導通)
0.28~0.56英寸4位共陰數碼管:
段碼 -> P2.0~P2.7
位碼 -> P1.0~P1.3 單片機源程序如下:
- #include "STC15.h"
- #include "intrins.h"
- #define u8 unsigned char
- #define u16 unsigned int
- #define u32 unsigned long
- #define s8 signed char
- #define s16 signed int
- #define s32 signed long
- #define KEY_TIME 25 //按鍵消抖時間 (毫秒)
- #define reset() IAP_CONTR |= 0x20 //芯片復位
- #define feed_dog() WDT_CONTR |= 0x10 //看門狗喂狗
- u8 code nbr[16] = { //共陰數碼管段碼16進制
- 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
- };
- u8 show[4]; //4位數碼管當前顯示的段碼 更改數碼管顯示的段碼 只需更改此數組
- u8 wink; //閃爍的數碼管段碼 0x01: 第一位閃爍 0x02:第二位閃爍 0x04: 第三位閃爍 0x0F:全閃爍 0x00:全不閃爍
- sbit P3_0 = P3 ^ 0; //按鍵S1 (I/O口定義的按鍵未經消抖,請勿在中斷外直接使用)
- sbit P3_1 = P3 ^ 1; //按鍵S2
- sbit P3_2 = P3 ^ 2; //有源蜂鳴器 低電平鳴叫
- sbit P3_3 = P3 ^ 3; //繼電器或MOS管 低電平吸合(導通)
- u16 S1_ms, S2_ms; //按鍵0、按鍵1連續按下的時間 定時器中斷計數此變量 最長65535毫秒 松開清零
- u16 delay_ms; //定時器中斷延時 (毫秒)
- u16 time; //定時時間 (秒)
- u16 beep_ms; //蜂鳴器鳴叫時間 (毫秒)
- u16 bdata Bit16 = 0; //定義16位可位尋址變量
- sbit delay = Bit16 ^ 0; //定時器中斷延時毫秒開關 中斷外置1 延時完中斷內清0
- sbit test = Bit16 ^ 1; //此值為1數碼管全亮 蜂鳴器響 所有按鍵無效 否則正常
- sbit S1 = Bit16 ^ 2; //按鍵0 連續按下N毫秒清0, 松開置1(定時器0中斷消抖)
- sbit S2 = Bit16 ^ 3; //按鍵1 (處理方式與按鍵0相同)
- sbit hz10 = Bit16 ^ 4; //10Hz信號源 (定時器0中斷產生,用于控制數碼管閃爍)
- sbit bak = Bit16 ^ 5; //按鍵長按識別處理用
- sbit Beep = Bit16 ^ 6; //有源蜂鳴器 低電平響
- sbit start = Bit16 ^ 7; //倒計時開關 置1倒計時開始 清0則結束
- sbit pause = Bit16 ^ 8; //1暫停倒計時 0正常
- sbit relay = Bit16 ^ 9; //繼電器或MOS管 低電平吸合(導通) 1秒只能吸合或釋放1次
- void InitTimer0() { //初始化定時器0中斷
- TMOD = 0x01;
- TH0 = 0xFC;
- TL0 = 0x18;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- void beep(u16 ms) { //蜂鳴器鳴叫 參數:鳴叫毫秒
- beep_ms = ms;
- Beep = 0;
- }
- u16 set_time() { //設定定時時間
- u8 n = 0; //0:編輯千位 1:百位 2:十位 3:個位
- u8 o[4];
- o[0] = 0; o[1] = 0; o[2] = 0; o[3] = 0;
- while (1) {
- feed_dog();
- wink = 8 >> n;
- show[0] = nbr[o[0]];
- show[1] = nbr[o[1]];
- show[2] = nbr[o[2]];
- show[3] = nbr[o[3]];
- if (S2 == 0) { //S2按下 短按加1
- beep(50);
- if (o[n]++ >= 9) o[n] = 0;
- show[n] = nbr[o[n]];
- delay_ms = 500; delay = 1;
- while (delay && S2 == 0); //長按延時等待
- while (S2_ms >= 500) { //按鍵長按,開始連加
- feed_dog();
- delay_ms = 125; delay = 1; //0.125秒連加一次
- while (delay && S2 == 0);
- beep(50);
- if (o[n]++ >= 9) o[n] = 0;
- show[n] = nbr[o[n]];
- }
- delay = 0;
- delay_ms = 0;
- }
- if (S1 == 0) { //S1按下
- beep(50);
- n++; //輸入下一位
- while (S1 == 0) {
- feed_dog();
- if (S1_ms >= 1000 && !bak) { //長按退回編輯
- beep(50);
- n = 0;
- wink = 8 >> n;
- show[0] = nbr[o[0]];
- show[1] = nbr[o[1]];
- show[2] = nbr[o[2]];
- show[3] = nbr[o[3]];
- bak = 1;
- }
- }
- if (bak) {
- bak = 0;
- continue;
- }
- if (n >= 4) { //個位輸入完成
- wink = 0;
- return o[0] * 1000 + o[1] * 100 + o[2] * 10 + o[3];
- }
- }
- }
- return 0;
- }
- void main() {
- u8 i = 0;
- Beep = 1;
- WDT_CONTR = 0x27; //初始化看門狗
- P1M0 = 0x0F; P1M1 = 0x00; //P1.0~P1.3強推挽
- P2M0 = 0xFF; P2M1 = 0x00; //P2.0~P2.7強推挽
- //上電1秒數碼管全亮 蜂鳴器響
- test = 1;
- InitTimer0();
- delay_ms = 1000; delay = 1;
- while (delay);
- test = 0;
- show[0] = nbr[0];
- show[1] = nbr[0];
- show[2] = nbr[0];
- show[3] = nbr[0];
- while (1) {
- relay = 1;
- pause = 0;
- do { //時間設定
- time = set_time();
- } while (!time);
- time -= 1;
- start = 1;
- relay = 0;
- while (start) {
- feed_dog();
- if (S1 == 0) { //S1按下蜂鳴器響1下
- beep(50);
- while (S1 == 0) {
- feed_dog();
- }
- }
- if (S2 == 0) { //S2按下暫停倒計時
- beep(50);
- pause = !pause;
- relay = pause;
- while (S2 == 0) {
- feed_dog();
- if (pause && S2_ms >= 3000) { //長按3秒復位
- _nop_(); _nop_(); _nop_(); _nop_();
- reset();
- _nop_(); _nop_(); _nop_(); _nop_();
- }
- }
- }
- }
- //倒計時結束
- show[0] = 0x79; //E
- show[1] = 0x54; //n
- show[2] = 0x5E; //d
- show[3] = 0x00;
- for (i = 0; i < 6; i++) { //蜂鳴器響6下
- delay_ms = 500; delay = 1; while (delay);
- beep(500);
- while (!Beep);
- feed_dog();
- }
- while (1) {
- feed_dog();
- if (S1 == 0 || S2 == 0) {
- beep(50);
- while (S1 == 0 || S2 == 0) {
- feed_dog();
- }
- break;
- }
- }
- }
- }
- void Timer0Interrupt() interrupt 1{ //12Mhz 1mS定時器中斷
- static u8 seg = 0; //當前正在掃描的數碼管段碼 4位數碼管 范圍:0~3
- static u8 ms1 = 0;
- static u16 ms = 0, ms2 = 0;
- TH0 = 0xFC;
- TL0 = 0x18;
- if (delay && !--delay_ms) { //延時任意毫秒
- delay = 0;
- }
- //數碼管動態掃描處理
- P1 |= 0xF; //消影
- P2 = test ? 0xFF : (wink & (1 << (3 ^ seg)) && !hz10 ? 0 : show[seg]); //段碼
- P1 &= ~(1 << seg); //位碼
- if (++seg >= 4) seg = 0;
- if (test) { //測試模式
- S1 = 1; S2 = 1;
- P3_2 = 0;
- return;
- }
- //蜂鳴器處理
- P3_2 = Beep;
- if (!Beep && !--beep_ms) {
- Beep = 1;
- }
- if (++ms1 >= 50) {
- ms1 = 0;
- hz10 = !hz10;
- }
- //按鍵處理
- if (P3_0 == 0) {
- if (S1_ms != 0xFFFF) S1_ms++;
- }
- else {
- S1_ms = 0;
- }
- if (P3_1 == 0) {
- if (S2_ms != 0xFFFF) S2_ms++;
- }
- else {
- S2_ms = 0;
- }
- S1 = !(S1_ms >= KEY_TIME);
- S2 = !(S2_ms >= KEY_TIME);
- //繼電器處理
- if (++ms2 >= 1000) { //繼電器1秒只能進行1次吸合或釋放,防止頻繁開關導致設備損壞
- ms2 = 0;
- P3_3 = relay;
- }
- //時間倒計時處理
- if (start) {
- if (pause) {
- wink = 0xF;
- }
- else {
- wink = 0;
- if (++ms >= 1000) {
- ms = 0;
- show[0] = nbr[time / 1000 % 10];
- show[1] = nbr[time / 100 % 10];
- show[2] = nbr[time / 10 % 10];
- show[3] = nbr[time % 10];
- if (!time--) { //倒計時結束
- start = 0;
- relay = 1;
- }
- }
- }
- }
- }
復制代碼 |
評分
-
查看全部評分
|