[GD32L233C-START Review] Chapter 5 Dynamic Scanning to Directly Drive 4-Bit Clock Digital Tube
[Copy link]
This post was last edited by yang_alex on 2022-2-21 17:56
There are two ways to connect a single-chip microcomputer to drive a multi-digit digital tube: common anode and common cathode. Here we use a common anode 4-digit clock digital tube. The following is its appearance, segment diagram and pin diagram:
Let's first explain our hardware circuit: the bit pins DIG1, DIG2, DIG3, and DIG4 of the digital tube are connected to PB9, PB6, PB5, and PB1 of the evaluation board respectively, and the segment pins A, B, C, D, E, F, G, and DP of the digital tube are connected to PB8, PB4, PB12, PB14, PB13, PB7, PB0, and PB15 of the evaluation board respectively. There is no current limiting resistor here, mainly because: they are all connected with DuPont wires, and it is inconvenient to add resistors (when actually making the board, it is best to add a current limiting resistor between each bit pin and the GPIO of the MCU), and because of the use of dynamic scanning and the low voltage of 3.3V. Note that if the driving current of the LED is relatively large, the MCU's GPIO cannot be used directly to drive the bit pin of the digital tube, but it is necessary to drive a PNP transistor, and control whether the bit pin of the digital tube is connected to the positive power supply by controlling the conduction of this PNP transistor.
Software: The driving method is that the GPIO connected to the digital tube bit pin on the evaluation board outputs a high level to push the LED in the digital tube, and the GPIO connected to the digital tube segment pin on the evaluation board outputs a low level to pull the LED in the digital tube, so that the corresponding LED will light up. The principle of dynamic scanning is: the GPIO connected to the digital tube bit pin on the evaluation board outputs the scanning signal in turn, so that only one digital tube is selected at each moment (outputs a high level, and the common anode of the digital tube is driven by a high level), and then the 7 GPIOs connected to the digital tube segment pins on the evaluation board (the dot in the lower right corner of each digit on this 4-bit clock digital tube is empty, there is no LED, and no driving is required) send the glyph code to be displayed in that bit (output low level), and light up the glyph segment to display the glyph. In this way, under the control of the segment code drive and the bit select line, each digital tube can be lit up in turn to display its own character. DP1 and DP2 are controlled separately. When the scanning frequency is appropriate, due to the persistence effect of the human eye, the 4-bit clock digital is displayed simultaneously.
Now that the working principle and circuit are clear, let's take a look at the code:
First, initialize the GPIO used. Here, the gd32l233c_start.c program provided by the evaluation board is used. Therefore, it is important to add this program to the project and add the definition of the corresponding pins to the corresponding header file gd32l233c_start.h:
#define LED_A_PIN GPIO_PIN_8
#define LED_A_GPIO_PORT GPIOB
#define LED_A_GPIO_CLK RCU_GPIOB
#define LED_B_PIN GPIO_PIN_4
#define LED_B_GPIO_PORT GPIOB
#define LED_B_GPIO_CLK RCU_GPIOB
#define LED_C_PIN GPIO_PIN_12
#define LED_C_GPIO_PORT GPIOB
#define LED_C_GPIO_CLK RCU_GPIOB
#define LED_D_PIN GPIO_PIN_14
#define LED_D_GPIO_PORT GPIOB
#define LED_D_GPIO_CLK RCU_GPIOB
#define LED_E_PIN GPIO_PIN_13
#define LED_E_GPIO_PORT GPIOB
#define LED_E_GPIO_CLK RCU_GPIOB
#define LED_F_PIN GPIO_PIN_7
#define LED_F_GPIO_PORT GPIOB
#define LED_F_GPIO_CLK RCU_GPIOB
#define LED_G_PIN GPIO_PIN_0
#define LED_G_GPIO_PORT GPIOB
#define LED_G_GPIO_CLK RCU_GPIOB
#define LED_1_PIN GPIO_PIN_9
#define LED_1_GPIO_PORT GPIOB
#define LED_1_GPIO_CLK RCU_GPIOB
#define LED_2_PIN GPIO_PIN_6
#define LED_2_GPIO_PORT GPIOB
#define LED_2_GPIO_CLK RCU_GPIOB
#define LED_3_PIN GPIO_PIN_5
#define LED_3_GPIO_PORT GPIOB
#define LED_3_GPIO_CLK RCU_GPIOB
#define LED_4_PIN GPIO_PIN_1
#define LED_4_GPIO_PORT GPIOB
#define LED_4_GPIO_CLK RCU_GPIOB
#define LED_DP_PIN GPIO_PIN_15
#define LED_DP_GPIO_PORT GPIOB
#define LED_DP_GPIO_CLK RCU_GPIOB
void gd_eval_led_init(led_typedef_enum lednum) is defined in the gd32l233c_start.c program. We use it to initialize the digital tube related driver pins directly:
void gpio_config(void)
{
/* initilize the LEDs*/
gd_eval_led_init(LED1);
gd_eval_led_init(LED_A);
gd_eval_led_init(LED_B);
gd_eval_led_init(LED_C);
gd_eval_led_init(LED_D);
gd_eval_led_init(LED_E);
gd_eval_led_init(LED_F);
gd_eval_led_init(LED_G);
gd_eval_led_init(LED_1);
gd_eval_led_init(LED_2);
gd_eval_led_init(LED_3);
gd_eval_led_init(LED_4);
gd_eval_led_init(LED_DP);
}
We use a timer to realize the dynamic scanning of the 4-bit clock digital tube, so we need to configure this timer first (timing 3 milliseconds):
void timer_config(void)
{
timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;
/* enable the peripherals clock */
rcu_periph_clock_enable(RCU_TIMER5);
/* deinit a TIMER */
timer_deinit(TIMER5);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER5 configuration */
timer_initpara.prescaler = 63;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 3000; //3ms
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER5, &timer_initpara);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER5);
/* clear channel 0 interrupt bit */
timer_interrupt_flag_clear(TIMER5, TIMER_INT_FLAG_UP);
/* channel 0 interrupt enable */
timer_interrupt_enable(TIMER5, TIMER_INT_UP);
/* enable a TIMER */
timer_enable(TIMER5);
}
Then update the number to be displayed on each digit of the 4-digit clock digital tube in the timer interrupt program:
void TIMER5_IRQHandler(void)
{
uint16_t seg6,seg5,seg1,seg3,seg4,seg2 = 0x7191;// seg2段处理 0xf191不显示DP,DP置1 0x7191显示DP DP单独控制 // seg3 位处理 // seg4 段数据 // seg5 输出数据
if(SET == timer_interrupt_flag_get(TIMER5, TIMER_INT_FLAG_UP))
{
/* clear channel 1 interrupt bit */
timer_interrupt_flag_clear(TIMER5, TIMER_INT_FLAG_UP);
seg2 = 0x7191;
if(Times < 4)
{
switch(Times)
{
case 0: seg4 = display_clock[hour1]|0x8000 ; //显示第一位
seg3 = 0x0200; //第一位 0x0200
break;
case 1: seg4 = display_clock[hour2]|0x8000 ; //显示第二位
seg3 = 0x0040; //第二位 0x0040
break;
case 2: seg4 = display_clock[min1]|0x8000 ; //显示第三位
seg3 = 0x0020; //第三位 0x0020
break;
case 3: seg4 = display_clock[min2]|0x8000 ; //显示第四位
seg3 = 0x0002; //第四位 0x0002
break;
default : break;
}
seg1 = gpio_output_port_get(GPIOB);
seg5 = (seg2 | seg1 )& 0xfd9d;
gpio_port_write(GPIOB,seg5 ); //去拖影
seg5 = (seg4 & seg5 )| seg3;
gpio_port_write(GPIOB,seg5 );
Times++;
}
else
{
Times = 0;
}
}
}
Next, the main program gives the number to be displayed on the clock digital tube, and the display of the second pulse (flip once every 500 milliseconds)
#include "gd32l23x.h"
#include "gd32l233c_start.h"
#include "systick.h"
uint16_t hour1,hour2,min1,min2,sec1,sec2;
uint32_t display_clock[] = {0x8263, 0xE3E3,0x92E2,0xA2E2,0xE362,0xA272,0x8272,0xE081,0x8262,0xA000};
uint16_t Times = 0,pwm_pulse_value = 20;
void gpio_config(void);
void nvic_config(void);
void timer_config(void);
int main(void)
{
systick_config();
gpio_config();
nvic_config();
timer_config();
hour1 = 1;
hour2 = 8;
min1 = 5;
min2 = 6;
while(1)
{
gd_eval_led_toggle(LED_DP); //秒闪烁
delay_1ms(500);
}
}
OK. Compile and download, run and see our results:
|