記事ディレクトリ
1. デジタル管のダイナミックリフレッシュの原理
上図は引用元:51 マイコン入門 2 - デジタル管のダイナミックスキャンでは、
セグメントコードを制御するポートの列が使用されており、表示する必要のあるセグメントが点灯しており、映画を見るのと同じように、1 つずつ開いたり閉じたりします。写真はアニメーションで構成されています。
2. 動的リフレッシュの原理
具体的な制御プロセスは図に示すとおりで、N はデジタル管の数を表します。
各遅延は短すぎないことに注意してください。ここでのプログラムは 1ms に基づいており、人間の目では上記の動的リフレッシュを簡単に区別できないため、サイクルの合計終了時間が 20ms を超えないようにする必要があります。 50Hz。
一定の遅延時間を与えてから 2 番目の位置に切り替え、ビットコードを開いて順番に繰り返すと、8 つのチューブが同時に点灯します。
3.8桁デジタル管が同時点灯
1. 前のレッスンに基づいて、ビット コード選択配列を追加します。
前のセクションのプロジェクト 5.seg をテンプレートとして使用して、6.seg-active を作成します。
元の静的表示コードをシールドし、4 桁のデジタル チューブを追加します。コード:
//第1位的数码管显示0
P7 = COM_Tab[0];
P6 = SEG_Tab[0]; //这个数码管输出段码
delay_ms(1);
//第2位的数码管显示1
P7 = COM_Tab[1];
P6 = SEG_Tab[1]; //这个数码管输出段码
delay_ms(1);
//第3位的数码管显示2
P7 = COM_Tab[2];
P6 = SEG_Tab[2]; //这个数码管输出段码
delay_ms(1);
//第4位的数码管显示3
P7 = COM_Tab[3];
P6 = SEG_Tab[3]; //这个数码管输出段码
delay_ms(1);
コンパイルとダウンロード、メイン周波数は 24MHZ、各ダウンロードの前にカスタム コマンドを送信すると、デジタル チューブには 0123 が表示されます。
遅延を 200ms に変更し、ファイル ヘッダー マクロで最大遅延時間を定義します。
#define SEG_DELAY 200 //延时ms
//while主循环中使用宏定义,可实现批量修改延迟时间
delay_ms(SEG_DELAY);
明らかなちらつきが見られます。
デジタル チューブに 1 から 8 までを表示するだけが必要な場合は、コード内のセグメント コードとビット コードのパラメータ変数を確認し、値が同じであれば、num 変数を使用できます。num の最大値は 7 で、デジタル管は 8 ビットのみです。
資格を得るには、判決を追加する必要があります。
P7 = COM_Tab[num];
P6 = SEG_Tab[num+1]; //这个数码管输出段码,从1 开始显示到8
delay_ms(SEG_DELAY);
num++;
if(num>7)
{
num = 0;
}
新しい配列を作成して、各ビットに表示する内容を選択します
表示するデータが不規則な場合は、ビットごとに表示する内容を選択する新しい配列を作成する必要があります。
新しい配列を作成します: u8 Show_Tab[8] = {1,5,0,3,5,7,3,3};
表示関数の関連する内容を変更します:
P7 = COM_Tab[num]; //位码选择
P6 = SEG_Tab[Show_Tab[num]]; //需要显示的数组内容,如果 num =0 ->Show_Tab[num] = 1->P6 =0xf9
delay_ms(SEG_DELAY);
num++;
if(num>7)
{
num = 0;
}
実践編:簡単な10秒無料オーダーカウンター
1. ターゲットタイムは最初の 4 つのデジタル管に表示されます。つまり、「10.00」はタイミング時間が 10 秒であることを意味します。 2. 最後の 4 桁は
現在のタイミング 00.00 を表示し、最小単位は 10ms です
。スタートボタンを押すと最後の10msごとに+1され、終了ボタンを押すとカウントが停止します。
まず、小数点を点灯させるにはどうすればよいでしょうか?デフォルトでは、配列の小数点は点灯せず、小数点が追加されます。
元のセグメント コードをコピーし、コピーした部分から 0x80 を減算します。
u8 SEG_Tab[20] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //0-9段码选择,添加0-9带小数点的段码
//定义基础显示代码
Show_Tab[0] = 1; //选择1
Show_Tab[1] = 10; //选择“0.”
Show_Tab[2] = 0; //选择0
Show_Tab[3] = 0; //选择0
効果を見ると、最初の 4 桁は 10.00 で、次の桁は 5733 のままです (以前のコードは変更されていません)。元の表示コードを変更して、すべて 0 を表示することができます。
u8 Show_Tab[8] = {0,0,0,0,0,0,0,0};
新しいタイミング変数を作成します。サイズは u32, u32 TimCount = 0; //カウント単位はミリ秒です。1 が増えるごとに 1 ミリ秒が経過したことを意味します。4 ~ 7 桁の表示コードは次のとおりです
。
if(RUN_state == 1)
{
TimCount++; //每执行完1次,加1
Show_Tab[4] = TimCount/10000%10; //取万位,
Show_Tab[5] = TimCount/1000%10; //取千位,
Show_Tab[6] = TimCount/100%10; //取百位,
Show_Tab[7] = TimCount/10%10; //取10位,除以10即舍去最低位,103%10 = 3,1030/10%10=3
}
コンパイルと書き込み後、データはビートしていますが、表示がまだ異常です:
1. 一時停止を押しても、0 から再開しません。データは最初に 0 にクリアされません。コードを修正します。
if( RUN_State == 0 )
TimCount = 0;
2. 百の位の小数点が表示されないので、次のように変更します: Show_Tab[5] = TimCount/1000%10+10; //千の位を取得して小数点を表示します 再コンパイルしてダウンロードします
。10.000000 が表示され、00.00 が表示されません。変更: Show_Tab[8] の対応する位置に元のデータ + 10:
u8 Show_Tab[8] = {0,0,0,0,0,10,0,0}; //数码管均重置为0,10代表第10位(0x40),带小数点。显示0.00。
//即要想显示数字+小数点,只要在数字前面加1,变成10几,就可以了
コンパイルして書き込み、表示: 10.0000.00、効果は正常です。キー 1 を押して 0 からカウントを開始すると、数値がジャンプします。もう一度押して停止し、もう一度キーを押して、再び 0 からカウントを開始します。
key1 を押すと 1 桁しか表示されません。コードを調整する必要があります。key1
が押されたときに実行される場所を見てください。「while(KEY1 == 0);」はキーが離されるのを待つので、ここでは表示は移動しません。
したがって、問題を解決する鍵は、ボタンが放されるまでデジタル管を常に表示し続けることです。
次に、デジタル チューブの表示コードを移動し、待機プロセス中に再度表示する必要があります。データもループ中に追加されます。
while(KEY1 == 0) //增加重复显示代码,防止等待KEY1按下的过程中只显示1位0
{
P7 = COM_Tab[num]; //位码选择
P6 = SEG_Tab[Show_Tab[num]]; //需要显示的数组内容,如果 num =0 ->Show_Tab[num] = 1->P6 =0xf9
delay_ms(SEG_DELAY);
num++;
if(num>7)
{
num = 0;
}
}
コンパイルして実行した後、key1 を押すとパラメータが移動し続けます。
更新アクションを関数として記述します。
繰り返されるリフレッシュ作業は関数で置き換えることができます。
最初に宣言: void SEG_Fre(void); //デジタル チューブのリフレッシュに特別に使用され、
次に実装:
void SEG_Fre(void) //专门用于数码管刷新
{
//---------------------------数码管刷新---------------------------------
u8 num = 0;
P7 = COM_Tab[num]; //位码选择
P6 = SEG_Tab[Show_Tab[num]]; //需要显示的数组内容,如果 num =0 ->Show_Tab[num] = 1->P6 =0xf9
delay_ms(SEG_DELAY);
num++;
if(num>7)
{
num = 0;
}
}
コードで使用されている完全なコードは次のとおりです。
#include "COMM/stc.h" //调用头文件
#include "COMM/usb.h"
#define KEY1 P32 //定义一个按键 引脚选择P32
#define KEY2 P33 //定义一个按键 引脚选择P33
#define BEEP P54 //定义一个按键 引脚选择P54
#define SEG_Delay 1 //延时多少ms
#define MAIN_Fosc 24000000UL //定义主时钟
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
u8 SEG_Tab[20] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //0-9段码,0-9带小数点
u8 COM_Tab[8] = { 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe }; //0-7的位码数组
u8 Show_Tab[8] = {3,0,0,0,0,10,0,0};
u32 TimCount = 0; //计数单位1ms
bit RUN_State = 0; //开始运行/结束运行
u8 num = 0;
void sys_init(); //函数声明
void delay_ms(u16 ms); //unsigned int
void SEG_Fre( void ); //专门用于数码管刷新
void main() //程序开始运行的入口
{
sys_init(); //USB功能+IO口初始化
usb_init(); //usb库初始化
EA = 1; //CPU开放中断,打开总中断。
while(1) //死循环
{
if( DeviceState != DEVSTATE_CONFIGURED ) //
continue;
if( bUsbOutReady )
{
usb_OUT_done();
}
//------------------------------------------------数码管刷新-------------------------------------------------
Show_Tab[0] = 1; //选择 1
Show_Tab[1] = 10; //选择 0.
Show_Tab[2] = 0; //选择 0
Show_Tab[3] = 0; //选择 0
if( RUN_State==1 )
{
TimCount++;
Show_Tab[4] = TimCount/10000%10;
Show_Tab[5] = TimCount/1000%10+10;
Show_Tab[6] = TimCount/100%10;
Show_Tab[7] = TimCount/10%10; //取10位
}
SEG_Fre();
if( KEY1 ==0 )
{
delay_ms(10);
if( KEY1 ==0 )
{
BEEP = 0;
delay_ms(10);
BEEP = 1;
while( KEY1 ==0 )
{
SEG_Fre();
}
if( RUN_State==0 )
TimCount = 0;
RUN_State = !RUN_State;
}
}
}
}
/*
11111110 0XFE
11111101 0XFD
11111011 0XFB
11110111 0XF7
11101111 0XEF
11011111 0XDF
10111111 0XBF
01111111 0X7F
*/
void sys_init() //函数定义
{
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03;
P3M1 |= 0x03;
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01)); //等待时钟稳定
USBCLK = 0x00; //使用CDC功能需要使用这两行,HID功能禁用这两行。
USBCON = 0x90;
}
void delay_ms(u16 ms) //unsigned int
{
u16 i;
do
{
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}
void SEG_Fre( void )
{
//位码选择第一位,段码选择0
u8 num = 0; //也可以放在main函数前,作为全局变量
P7 = COM_Tab[num]; //位码的选择
P6 = SEG_Tab[Show_Tab[num]];//需要显示的数字的内码 赋给 P6 NUM =0 -> Show_Tab[num]] = 1 -> p6 = oxF9
delay_ms(SEG_Delay);
num++;
if( num >7 )
num = 0;
}
宿題:
1. 次の関数を備えた単純な時計を作成します:
1. 初期状態では、それぞれ時、分、秒として 00 - 00 - 00 が表示されます;
2. 毎秒、秒 + 1、毎分、分 + 1 など;
3. 時間が 00-00-30 になると、目覚まし時計を示すブザーが 3 秒間鳴り続けます。