2815|0

1304

帖子

0

TA的资源

纯净的硅(高级)

楼主
 

【GD32L233C-START评测】第5篇 动态扫描实现直驱4位时钟数码管 [复制链接]

本帖最后由 yang_alex 于 2022-2-21 17:56 编辑

        单片机驱动多位数码管时有共阳和共阴两种接法,我们这里使用的是共阳4位时钟数码管。下面是他的外观图、段位图和引脚图:

       先来说明一下我们的硬件电路:数码管的位引脚DIG1、DIG2、DIG3、DIG4分别接评估板的PB9、PB6、PB5、PB1,数码管的段引脚A、B、C、D、E、F、G、DP分别接评估板的PB8、PB4、PB12、PB14、PB13、PB7、PB0、PB15。这里没有接限流电阻,主要是考虑到:都是用杜邦线连接的,加电阻不方便(实际做板子的时候最好在每个位引脚和MCU的GPIO之间加个限流电阻),另外就是因为采用了动态扫描以及3.3V电压本来就不高。注意,如果LED的驱动电流比较大的时候就不能直接用MCU的GPIO去驱动数码管的位引脚了,而是需要去驱动一个PNP三极管,通过控制这个PNP三极管的导通与否去控制数码管的位引脚是否接到正电源。

       软件方面:驱动方法是评估板上接数码管位引脚的GPIO输出高电平去推数码管中的LED,评估板上接数码管段引脚的GPIO输出低电平去拉数码管中的LED,这样对应的LED就会亮。动态扫描的原理是:评估板上接数码管位引脚的GPIO轮流输出扫描信号,使每一瞬间只有一个数码管被选通(输出高电平,数码管该位共阳极被高电平驱动),然后由评估板上接数码管段引脚的7个GPIO(这个4位时钟数码管上每个数码右下角的点是空的,没有LED,不需要驱动)送入该位要显示的字形码(输出低电平),点亮该位字形段显示字形。这样在的段码驱动和位选线配合控制下,就可以使各数码管轮流点亮显示各自的字符。DP1和DP2另外控制。扫描频率恰当的情况下,由于人眼的暂留效应,4位时钟数码是同时显示的。

      工作原理和电路说清楚了,我们来看一下代码:

      首先,对用到的GPIO做初始化,这里利用了评估板所带的gd32l233c_start.c程序,所以项目重要添加这个程序,并且在相应的头文件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)在gd32l233c_start.c程序中有定义,我们直接拿来初始化数码管相关驱动引脚:

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

        我们利用一个定时器实现4位时钟数码管的动态扫描,所以要先配置这个定时器(定时3毫秒):

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

        再在定时器的中断程序中更新4位时钟数码管各位要显示的数:

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

        接下来就是主程序中给定要时钟数码管要显示的数,已经秒脉冲的显示(500毫秒翻转一次)

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

         好了。编译下载,跑起来看看我们的成果吧:

此帖出自GD32 MCU论坛
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
电子大赛历届题目方案分析及讲解

电子大赛历届题目方案分析及讲解.rar

诺基亚N92(DVB-H手机).pdf

诺基亚N92(DVB-H手机).pdf

数控电源

单片机控制开关电源有没有可能实现频率在10Hz到500KHz连续可调 做过的讲下啊 我看报道说没有办法控制精度 都是采用DDS专用芯 ...

TI应用工程师带你玩转智能插座!!!(多图)

http://player.youku.com/player.php/sid/XMjg3MzExMzcy/v.swf都说笔记本耗电少?但是不是真的少?谁也没有仔细去量过。这一次, ...

beaglebone linux 3g网卡驱动笔记。

beaglebone linux 3g网卡驱动笔记。 配有截图,比较详细 不同的网卡主要区别在于ppp的那个脚本中的串号 如果找不到与网 ...

TPS5450

515613 先上图,电感标错了。 对此设计,RMS电感电流为3.003A,峰值为3.31A,选L1=15μH,饱和电流要大于3. ...

据说,噪声频谱密度比信噪比更有用?

以下文章来源于亚德诺半导体,作者ADI 大家有木有发现,在比较在不同速度下工作的系统、或者查看软件定义系统如何处理不 ...

【平头哥RVB2601创意应用开发】 二、CDK开发环境安装及helloworld体验

本帖最后由 kit7828 于 2022-3-10 13:59 编辑 下载剑池CDK后过了几天才安装的,是在电脑重装系统后安装的(C盘扩容导致时不时 ...

【雅特力AT-START-F435开发板试用】1-构建RTT-Stdio开发环境

【雅特力AT-START-F435开发板试用】1-构建RTT-Stdio开发环境 首先真诚感谢电子工程师世界、雅特力科技举办【雅特力AT-STA ...

【Raspberry Pi 5测评】树莓派5学习笔记03(PWM应用)

树莓派5(Raspberry Pi 5)是一款功能强大且价格实惠的小型计算机,可以广泛应用于各种硬件控制项目。通过树莓派的GPIO引脚 ...

关闭
站长推荐上一条 1/10 下一条
有奖直播:当AI遇见仿真,会有什么样的电子行业革新之路?
首场直播:Simcenter AI 赋能电子行业研发创新
直播时间:04月15日14:00-14:50

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 12

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表