Study notes | Decimal point control principle | Digital tube dynamic display | Segment code and bit code | STC32G microcontroller video development tutorial (Brother Chong) | Episode 10: Digital tube dynamic display

1. Principle of dynamic refresh of digital tube

Insert image description here

Insert image description here
Insert image description here
The above picture is quoted from: 51 Microcontroller Beginner 2 - Digital tube dynamic scanning
uses a row of ports to control segment codes. Which segments need to be displayed are lit. Just like watching a movie, they are opened and closed one by one. The pictures are composed of animations.
Insert image description here

2. Dynamic refresh principle

The specific control process is as shown in the figure, N represents how many digital tubes there are!
Insert image description here

It should be noted that each delay cannot be too short. Our program here is based on 1ms, and it is necessary to ensure that the total end time of a cycle cannot be greater than 20ms, because the human eye cannot easily distinguish dynamic refreshes above 50HZ.
Give it a certain delay time and then switch to the second position, then open the bit code, cycle in sequence, and the 8 tubes will light up at the same time.

3.8-digit digital tubes light up at the same time

1. Based on the previous lesson, add a bit code selection array. Use the
project 5.seg in the previous section as a template to create 6.seg-active:
shield the original static display code and add a 4-digit digital tube display. Code:

		//第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);

Compile and download, the main frequency is 24MHZ, send a custom command before each download, and the digital tube displays 0123.
Change the delay to 200ms, and define the maximum time delay in the file header macro:

#define SEG_DELAY 200	//延时ms
//while主循环中使用宏定义,可实现批量修改延迟时间
delay_ms(SEG_DELAY);

Obvious flickering is visible.
If you only need the digital tube to display from 1 to 8, observe the segment code and bit code parameter variables in the code. If the values ​​are the same, you can use the num variable. The maximum value of num is 7, and there are only 8-bit digital tubes.
A judgment needs to be added to qualify:

		P7 = COM_Tab[num];
		P6 = SEG_Tab[num+1];	//这个数码管输出段码,从1 开始显示到8
		delay_ms(SEG_DELAY);

		num++;

		if(num>7)
		{
			num = 0;
		}

Create a new array to select the content to be displayed for each bit

If the data to be displayed is irregular, you need to create a new array to select the content to be displayed for each bit!
Create a new array: u8 Show_Tab[8] = {1,5,0,3,5,7,3,3};
modify the relevant content of the display function:

		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;
		}

Practical practice: simple 10-second free order counter

Insert image description here

1. Display the target time on the first four digital tubes, that is, "10. 00" means the timing time is 10 seconds.
2. The last four digits display the current timing 00.00, and the minimum unit is 10ms.
3. After pressing the start button, each time The last number of 10ms is +1; the count stops after pressing the end button.
First of all, how to light up the decimal point? By default, the decimal point in the array is not lit, and a decimal point is added.
Copy the original segment code, and then subtract 0x80 from the copied part:

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

Looking at the effect, the first 4 digits are 10.00, and the following digits are still 5733 (the previous code has not been modified). You can modify the original display code and all display 0.

u8 Show_Tab[8] = {0,0,0,0,0,0,0,0};

Create a new timing variable, the size is u32, u32 TimCount = 0; //The counting unit is ms. Each increment of 1 means that 1ms has passed. The
4-7 digit display code is:

		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
		}

After compiling and burning, the data is beating, but the display is still abnormal:
1. After pressing pause, it does not restart from 0. The data is not cleared to 0 at the beginning. Modify the code:

if( RUN_State == 0 )
					TimCount = 0;

2. The decimal point on the hundreds digit is not displayed. Change it to: Show_Tab[5] = TimCount/1000%10+10; //Take the thousands digit and display the decimal point. Recompile and download
. 10.000000 is displayed, 00.00 is not displayed, modification: original data + 10 at the corresponding position of Show_Tab[8]:

u8 Show_Tab[8] = {0,0,0,0,0,10,0,0};  //数码管均重置为0,10代表第10位(0x40),带小数点。显示0.00。
									  //即要想显示数字+小数点,只要在数字前面加1,变成10几,就可以了

Insert image description here

Compile and burn, display: 10.0000.00, the effect is normal, press key1 to start counting from 0, the number jumps, press it again, stop, press the key again, and start counting from 0.
When key1 is pressed, only 1 digit is displayed. The code needs to be adjusted:
take a look at where key1 is executed when pressed? "while(KEY1 == 0);" waits for the key to be released, so the display does not move here.
So the key to solving the problem is to keep the digital tube constantly displaying while waiting for the button to be released.
Then you need to move the display code of the digital tube and display it again during the waiting process. The data will also be added during the loop:

				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;
                    }
				}

After compiling and running, the parameters keep moving when key1 is pressed.

Write the refresh action as a function

Repeated refresh work can be replaced by a function.
First declare: void SEG_Fre(void); //Specially used for digital tube refresh,
and then implement:

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;
	}
}

Used in the code, the complete code is:

#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;
}

Homework:

1. Make a simple clock with the following functions:
1. The initial state displays 00 - 00 - 00, as hours, minutes, and seconds respectively;
2. Every second, seconds + 1, every minute, minutes + 1, and so on. ;
3. When the time reaches 00-00-30, the buzzer will sound for 3 seconds to indicate the alarm clock.

Guess you like

Origin blog.csdn.net/Medlar_CN/article/details/132694178