1. 前に書く
この実験では、主にタイマーを使用して独立したボタンとデジタル チューブを定期的にスキャンし、2 つのモジュール機能の遅延機能を置き換えます。スケジュールされたスキャンにタイマーを使用する利点は、メイン機能の遅延がボタンの検出やデジタル チューブのスキャンには影響せず、応答速度にのみ影響することです。タイマーがオーバーフローしたため、スケジュール スキャンである割り込みプログラムが実行されます。
2. メインモジュールの改善
改善のための一般的なアイデアは次のとおりです。
- タイマーを使用して遅延機能を置き換えるだけで、元の機能が変更されないことが保証されます。
- スケジュールされた割り込み関数によって呼び出されるループ関数を定義します。
- main 関数によって呼び出される新しい関数を定義します。この関数には、元の関数と同じパラメータと戻り値があります。
2.1 独立したボタンモジュール
前の独立したボタン モジュールの機能は、リリース信号が検出された場合はボタンの値を返し、ボタンが押されていない場合は 0 を返します。中央にはディレイ機能があり、キーのジッターを排除します。
#include <REGX52.H>
unsigned char Keynum;
unsigned char key()
{
unsigned char temp=0;
temp=Keynum;
Keynum=0;
return temp;
}
unsigned char Independentkey()
{
unsigned char keynum=0;
if(P3_1==0){keynum=1;}
if(P3_0==0){keynum=2;}
if(P3_2==0){keynum=3;}
if(P3_3==0){keynum=4;}
return keynum;
}
void Key_Loop()
{
static unsigned char Last_state,Now_state;
Last_state=Now_state;
Now_state=Independentkey();
if(Last_state==1&&Now_state==0)//松手检测
{
Keynum=1;
}
if(Last_state==2&&Now_state==0)//松手检测
{
Keynum=2;
}
if(Last_state==3&&Now_state==0)//松手检测
{
Keynum=3;
}
if(Last_state==4&&Now_state==0)//松手检测
{
Keynum=4;
}
}
2.2 デジタル管表示モジュール
以前は、デジタル管の機能は表示する桁を指定することでした。デジタルチューブは、セグメント選択のクリアまたはビット選択のクリアを実行する前に短い遅延があることを示しますが、これは遅延機能によって完了します。
#include"Displaytube.h"
unsigned char Nixie_segs[9]={0,10,10,10,10,10,10,10,10};
void Set_Nixiesegs(unsigned char bits,number)//设置数组
{
Nixie_segs[bits]=number;
}
void Displaytube(unsigned char bits,segs)//bits:位选 segs:段选
{
static unsigned char tube[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40}; //0~9,不显示,-
//位选
P0=0x00;
switch(bits)
{
case 1:P2_4=0;P2_3=0;P2_2=0;
break;
case 2:P2_4=0;P2_3=0;P2_2=1;
break;
case 3:P2_4=0;P2_3=1;P2_2=0;
break;
case 4:P2_4=0;P2_3=1;P2_2=1;
break;
case 5:P2_4=1;P2_3=0;P2_2=0;
break;
case 6:P2_4=1;P2_3=0;P2_2=1;
break;
case 7:P2_4=1;P2_3=1;P2_2=0;
break;
case 8:P2_4=1;P2_3=1;P2_2=1;
break;
default:
break;
}
//段选
P0=tube[segs];
}
void Nixie_Loop()
{
static unsigned char i=1;
Displaytube(i,Nixie_segs[i]);
i++;
if(i>8)i=1;
}
3. テストファイルtest.c
#include <REGX52.H>
#include"IndependentKey.h"
#include"Displaytube.h"
#include"Timer0_Init.h"
#include"AT24C02.h"
#include"Delay.h"
unsigned char millsec,sec,min;
unsigned char Stopmode=1;
void watch_show()
{
Set_Nixiesegs(8,min/10);
Set_Nixiesegs(7,min%10);
Set_Nixiesegs(6,11);
Set_Nixiesegs(5,sec/10);
Set_Nixiesegs(4,sec%10);
Set_Nixiesegs(3,11);
Set_Nixiesegs(2,millsec/10);
Set_Nixiesegs(1,millsec%10);
if(millsec>99)
{
sec++;
if(sec>59)
{
min++;
sec=0;
}
millsec=0;
}
}
int main()
{
unsigned char keynum=0;
Timer0_Init();
while(1)
{
keynum=key();
if(keynum!=0)
{
if(keynum==1) //暂停
{
Stopmode=!Stopmode;
}
if(keynum==2) //复位
{
millsec=0;
min=0;
sec=0;
}
if(keynum==3) //保存到AT24C02
{
AT24C02_Writebyte(0x01,min);
Delay(5);//写周期
AT24C02_Writebyte(0x02,sec);
Delay(5);
AT24C02_Writebyte(0x03,millsec);
Delay(5);
}
if(keynum==4) //读出数据
{
min=AT24C02_Readbyte(0x01);
sec=AT24C02_Readbyte(0x02);
millsec=AT24C02_Readbyte(0x03);
}
}
watch_show();
}
}
void Timer0_ISR() interrupt 1
{
static int count1,count2,count3=0;
count1++;
count2++;
count3++;
TH0=0xfc;
TL0=0x18;
if(count1==20) //20ms
{
count1=0;
Key_Loop();
}
if(count2==2) //2ms
{
count2=0;
Nixie_Loop();
}
if(count3==10) //10ms
{
count3=0;
if(Stopmode==0)
millsec++;
}
}
4. 効果の簡単な説明
- 起動するとデジタル管には「00-00-00」が表示されます。
- key1 ボタンを押すと、ストップウォッチが計時を開始します。
- ストップウォッチを一時停止するには、キー 1 をもう一度押します。
- キー 2 を押してストップウォッチをクリアします。
- key3 キーを押してデータを AT24C02 に保存します。
- key4 キーを押して、AT24C02 に保存されているデータを読み取ります (停電してもデータは失われません)。