目录

  • 1 要实现的功能
  • 2 数码管的原理
    • 2.1 数码管发光显示原理
    • 2.2 数码管控制原理
  • 3 功能实现过程
    • 3.1 GPIO配置
    • 3.2 数字显示
    • 3.3 显示控制
    • 3.4 其他代码
  • 4 调试修改
  • 5 最终效果
  • 6 后语

最近买了一些电子元件,打算配合手头上的F28335开发板一起玩一玩。其中有一个四位共阳的数码管,虽然比较简单,但有些细节还是需要注意,所以写一篇东西来记录一下这个过程。

1 要实现的功能

直接利用F28335的GPIO口来驱动控制数码管,将输入的数字显示出来。

2 数码管的原理

2.1 数码管发光显示原理


如图所示为本次所用的数码管的结构尺寸以及电路原理图。由右上角的示意图可以看到,一个数字有8个发光位置,分别是组成数字的A到G段以及组成小数点的DP段,令相应的段发光就可以组成各个数字。而段的发光是通过发光二极管实现的,由下方的这个电路原理图可以看到,每一个数位都有各自的8段发光二极管,而每个数位的8段发光二极管的阳极都是连在一块的,所以这种叫共阳极数码管,而如果二极管的方向调换,各段二极管的阴极连在一块的就叫共阴极数码管。因此,由这个电路图我们可以知道,举个例子,如果我们把12脚接上高电平,而将4/7脚接上低电平,那么最左边一位数字的B/C段就会被点亮,就可以在最左边一位上显示出“1”。

2.2 数码管控制原理

开始之前,首先可以看到,四位数码管一共有12个管脚,其中6/8/9/12脚分别控制着四位数字其中的一位,而剩余的8个管脚分别控制着8段发光二极管的其中一段,为了方便描述,将6/8/9/12脚称为位管脚,而将其余管脚称为段管脚
在上一部分中,我们搞清楚了怎么让数码管显示数字,但是仔细观察电路原理图可以发现,虽然每个数位都有自己的8段发光二极管,但是各个数位相同的段对应的发光二极管,比如每个数字的A段,它们的阴极是连在一块的。这就意味着,我们不能同时控制2个或以上的数位,因为如果我们同时给2个或以上的位管脚接上高电平,那么这些数位将显示一样的数字。
为了解决这个问题,我们可以采用动态扫描的方式,也就是快速轮流点亮各个数位,当轮换速度超过一定程度时,人眼就无法分辨,就会认为各个数位是同时点亮的。

3 功能实现过程

3.1 GPIO配置

由于四位数码管共有12个管脚,而手头上又没有其他器件,所以这里打算直接用F28335的12个GPIO来驱动控制数码管。

根据数据手册,选取了JP1接口上的1-6脚以及9-14脚作为输出管脚(如果不是接口上针孔之间间隔太密,我也想选1-12脚)。管脚初始化代码如下:

void Init_DT_Gpio()
{EALLOW;// configure the corresponding pins to be GPIOGpioCtrlRegs.GPBMUX1.bit.GPIO40 = 0x00;GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 0x00;GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 0x00;GpioCtrlRegs.GPBMUX1.bit.GPIO43 = 0x00;GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 0x00;GpioCtrlRegs.GPBMUX1.bit.GPIO45 = 0x00;GpioCtrlRegs.GPCMUX2.bit.GPIO80 = 0x00;GpioCtrlRegs.GPCMUX2.bit.GPIO81 = 0x00;GpioCtrlRegs.GPCMUX2.bit.GPIO82 = 0x00;GpioCtrlRegs.GPCMUX2.bit.GPIO83 = 0x00;GpioCtrlRegs.GPCMUX2.bit.GPIO84 = 0x00;GpioCtrlRegs.GPCMUX2.bit.GPIO85 = 0x00;// configure the corresponding pins as output pinsGpioCtrlRegs.GPBDIR.bit.GPIO40 = 1;GpioCtrlRegs.GPBDIR.bit.GPIO41 = 1;GpioCtrlRegs.GPBDIR.bit.GPIO42 = 1;GpioCtrlRegs.GPBDIR.bit.GPIO43 = 1;GpioCtrlRegs.GPBDIR.bit.GPIO44 = 1;GpioCtrlRegs.GPBDIR.bit.GPIO45 = 1;GpioCtrlRegs.GPCDIR.bit.GPIO80 = 1;GpioCtrlRegs.GPCDIR.bit.GPIO81 = 1;GpioCtrlRegs.GPCDIR.bit.GPIO82 = 1;GpioCtrlRegs.GPCDIR.bit.GPIO83 = 1;GpioCtrlRegs.GPCDIR.bit.GPIO84 = 1;GpioCtrlRegs.GPCDIR.bit.GPIO85 = 1;EDIS;
}

3.2 数字显示

经过上面的配置之后,我们就可以通过对GPIO口的操作来实现数字的显示。首先进行相关的宏定义以方便理解和编程:

// macro definition of the output pins of digital tube
#define     DT_E        GpioDataRegs.GPBDAT.bit.GPIO40
#define     DT_D        GpioDataRegs.GPBDAT.bit.GPIO41
#define     DT_DP       GpioDataRegs.GPBDAT.bit.GPIO42
#define     DT_C        GpioDataRegs.GPBDAT.bit.GPIO43
#define     DT_G        GpioDataRegs.GPBDAT.bit.GPIO44
#define     DT_BIT4     GpioDataRegs.GPBDAT.bit.GPIO45
#define     DT_B        GpioDataRegs.GPCDAT.bit.GPIO80
#define     DT_BIT3     GpioDataRegs.GPCDAT.bit.GPIO81
#define     DT_BIT2     GpioDataRegs.GPCDAT.bit.GPIO82
#define     DT_F        GpioDataRegs.GPCDAT.bit.GPIO83
#define     DT_A        GpioDataRegs.GPCDAT.bit.GPIO84
#define     DT_BIT1     GpioDataRegs.GPCDAT.bit.GPIO85

然后定义了三个函数,分别是 Sel_BitSel_NumOutput ,其中 Sel_BitSel_Num 是根据输入的期望点亮的数位和期望显示的数字来分别对位管脚和段管脚进行操作,而 Output 则是调用 Sel_BitSel_Num 来在相应的数位上显示相应的数字。其代码分别如下:

void Sel_Bit(Uint16 bit)
{switch (bit){case 1:DT_BIT2 =   0; DELAY_US(10);DT_BIT3 =   0; DELAY_US(10);DT_BIT4 =   0; DELAY_US(10);DT_BIT1 =   1; DELAY_US(10);break;case 2:DT_BIT1  =   0; DELAY_US(10);DT_BIT3 =   0; DELAY_US(10);DT_BIT4 =   0; DELAY_US(10);DT_BIT2 =   1; DELAY_US(10);break;...}
}
void Sel_Num(Uint16 num)
{switch (num){case 0:DT_A    =   0; DELAY_US(10);DT_B    =   0; DELAY_US(10);DT_C    =   0; DELAY_US(10);DT_D    =   0; DELAY_US(10);DT_E    =   0; DELAY_US(10);DT_F    =   0; DELAY_US(10);DT_G    =   1; DELAY_US(10);DT_DP   =   1; DELAY_US(10);break;case 1:DT_A =   1; DELAY_US(10);DT_B    =   0; DELAY_US(10);DT_C    =   0; DELAY_US(10);DT_D    =   1; DELAY_US(10);DT_E    =   1; DELAY_US(10);DT_F    =   1; DELAY_US(10);DT_G    =   1; DELAY_US(10);DT_DP   =   1; DELAY_US(10);break;...}
}
void Output(Uint16 bit, Uint16 num)
{Sel_Bit(bit);Sel_Num(num);
}

其中DELAY_US(10)是延时语句,这是因为不能连续对GPxDAT寄存器进行操作。而为了避免位管脚同时接通,在某个位管脚输出高电平时将其余位管脚输出低电平。

3.3 显示控制

现在我们可以在选定的数位上显示选定的数字了,下面的问题就是将输入的数字转换成各个数位要显示的数字,也就是要分别提取数字的个、十、百、千位。这通过 DT_Show 函数来实现,代码如下:

void DT_Show(Uint16 num)
{Uint16 remain;remain = num % 10000;Bits[0] = remain / 1000;remain = remain % 1000;Bits[1] = remain / 100;remain %= 100;Bits[2] = remain / 10;remain %= 10;Bits[3] = remain;
}

其中Bits数组的元素就是对应数位要显示的数字,Bits[0]为最左位。

3.4 其他代码

主函数中的while循环如下:

while(1){Output(1,Bits[0]);Output(2,Bits[1]);Output(3,Bits[2]);Output(4,Bits[3]);}

以此来实现数码管的轮流点亮。而输入数字的更新代码放在了定时器中断中:

interrupt void ISRTimer0()
{PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;CpuTimer0Regs.TCR.bit.TIF = 1;CpuTimer0Regs.TCR.bit.TRB = 1;if (DT_count == 9999)DT_count = 0;elseDT_count++;DT_Show(DT_count);
}

4 调试修改

硬件连接、代码编写都完成后进行烧录调试,发现显示效果上有很大的问题。虽然能辨认出数码管有在按照输入数字的改变而改变,但是除此之外还有一些不该被点亮的发光二极管被点亮了,导致仿佛有两个数字重叠在同一个数位上。经过仔细辨认,发现最右边一位数位的变化能引起最左边一位数位的相同变化,举个例子,比如1234,本来应该只有最右边一位是4,但实际上能看到最左边一位也显示出一个淡淡的4。
经过思考和调(xia)试(gai),我发现,这是由于各个管脚不是同时变化而造成的,还是用之前的1234举例子,最右边一位显示完4之后应该轮到最左边一位显示1,这个时候先调用 Sel_Bit 函数改变位管脚的输出,由6管脚输出高电平变成12管脚输出高电平,但这个时候,段管脚的电位还没有改变,还是显示“4”的状态,所以就导致最左边一位上也显示出“4”,同时由于经过短暂延时之后段管脚的状态就改变了,所以4的持续时间不长,显示出的效果就是淡淡的。
为了解决这个问题,做了以下三方面的改进,首先是对驱动函数进行修改,利用GPxSET寄存器和GPxCLEAR寄存器的操作代替GPXDAT寄存器的操作,这样可以不进行延时,提高操作的实时性,修改之后的宏定义如下:

#define     DT_E_ON         GpioDataRegs.GPBCLEAR.bit.GPIO40    =   1
#define     DT_E_OFF        GpioDataRegs.GPBSET.bit.GPIO40      =   1
#define     DT_D_ON         GpioDataRegs.GPBCLEAR.bit.GPIO41    =   1
#define     DT_D_OFF        GpioDataRegs.GPBSET.bit.GPIO41      =   1
#define     DT_DP_ON        GpioDataRegs.GPBCLEAR.bit.GPIO42    =   1
#define     DT_DP_OFF       GpioDataRegs.GPBSET.bit.GPIO42      =   1
#define     DT_C_ON         GpioDataRegs.GPBCLEAR.bit.GPIO43    =   1
#define     DT_C_OFF        GpioDataRegs.GPBSET.bit.GPIO43      =   1
#define     DT_G_ON         GpioDataRegs.GPBCLEAR.bit.GPIO44    =   1
#define     DT_G_OFF        GpioDataRegs.GPBSET.bit.GPIO44      =   1
#define     DT_BIT4_ON      GpioDataRegs.GPBSET.bit.GPIO45      =   1
#define     DT_BIT4_OFF     GpioDataRegs.GPBCLEAR.bit.GPIO45    =   1#define     DT_B_ON         GpioDataRegs.GPCCLEAR.bit.GPIO80    =   1
#define     DT_B_OFF        GpioDataRegs.GPCSET.bit.GPIO80      =   1
#define     DT_BIT3_ON      GpioDataRegs.GPCSET.bit.GPIO81      =   1
#define     DT_BIT3_OFF     GpioDataRegs.GPCCLEAR.bit.GPIO81    =   1
#define     DT_BIT2_ON      GpioDataRegs.GPCSET.bit.GPIO82      =   1
#define     DT_BIT2_OFF     GpioDataRegs.GPCCLEAR.bit.GPIO82    =   1
#define     DT_F_ON         GpioDataRegs.GPCCLEAR.bit.GPIO83    =   1
#define     DT_F_OFF        GpioDataRegs.GPCSET.bit.GPIO83      =   1
#define     DT_A_ON         GpioDataRegs.GPCCLEAR.bit.GPIO84    =   1
#define     DT_A_OFF        GpioDataRegs.GPCSET.bit.GPIO84      =   1
#define     DT_BIT1_ON      GpioDataRegs.GPCSET.bit.GPIO85      =   1
#define     DT_BIT1_OFF     GpioDataRegs.GPCCLEAR.bit.GPIO85    =   1

然后,对切换的动作进行修改,原来是先切换位管脚的电平分布,再切换段管脚的电平分布。现在改成先将位管脚全部拉低,使得数码管全灭,然后切换段管脚的电平分布,最后切换位管脚的电平分布。
最后的话,切换过程完成之后延时10微秒,使得每个数位能持续亮一段时间,避免频繁切换造成的亮度降低。修改之后的 Sel_BitSel_NumOutput 函数代码如下:

void Sel_Bit(Uint16 bit)
{switch (bit){case 1:DT_BIT1_ON;DT_BIT2_OFF;DT_BIT3_OFF;DT_BIT4_OFF;break;case 2:DT_BIT1_OFF;DT_BIT2_ON;DT_BIT3_OFF;DT_BIT4_OFF;break;...}
}
void Sel_Num(Uint16 num)
{DT_BIT1_OFF;DT_BIT2_OFF;DT_BIT3_OFF;DT_BIT4_OFF;switch (num){case 0:DT_A_ON;DT_B_ON;DT_C_ON;DT_D_ON;DT_E_ON;DT_F_ON;DT_G_OFF;DT_DP_OFF;break;case 1:DT_A_OFF;DT_B_ON;DT_C_ON;DT_D_OFF;DT_E_OFF;DT_F_OFF;DT_G_OFF;DT_DP_OFF;break;...}
}
void Output(Uint16 bit, Uint16 num)
{Sel_Num(num);Sel_Bit(bit);DELAY_US(10);
}

5 最终效果

数码管效果

6 后语

至此,利用F28335控制四位共阳数码管的小实验就完成了。不过本人水平有限,这个实验各个方面肯定都还有可以改进的地方,欢迎大家批评指正。

使用TMS320F28335控制四位共阳数码管相关推荐

  1. 利用四位共阳数码管显示小数

    目录 前言 实现过程 思路 具体方法 其他代码 效果 利用数码管显示舵机的实际转速 总结 前言 前段时间利用TMS320F2335实现了对四位共阳数码管的控制(链接在这),不过当时只实现了利用数码管显 ...

  2. 四位共阳极数码管显示函数_新手求助四位共阳数码管显示函数

    #include #include "DS1302.H" sbit K_S = P1^0;    //显示模式sbit K_M = P1^1;    //修改sbit K_I = ...

  3. 74HCD164实现四位共阳数码管的动态扫描与六个按键实现继电器的通断程序

    #include<stc89.h>  #include<intrins.h> #define uchar unsigned char #define uint unsigned ...

  4. STM32共阳数码管编程分享

    开篇简介 相信玩过单片机的人都不会对数码管感到陌生!这次的分享也是近期在做的一个小项目里面用到的实例,代码均是自编.自测,保质保量?相信对各位初学者能起到快速上手的作用.(主控基于STM32F103Z ...

  5. 物联网开发笔记(80)- 使用Micropython开发ESP32开发板之通过IIC接口控制TM1650四位共阴数码管模块

    一.目的 这一节我们学习如何使用我们的ESP32开发板来通过IIC接口控制TM1650四位共阴数码管模块.  二.环境 ESP32 + Thonny + TM1650四位共阴数码管模块 + 几根杜邦线 ...

  6. stm32用库函数控制一位共阳数码管以及共阴数码管

    一.数码管原理: 见上图,上图是一个数码管的内部示意图,它们的发光原理和普通发光二极管是一样的,所以可将数码管的亮段当成几个发光二极管.根据内部发光二极管的共连接端不同,可以分为共阳极接法和共阴极接法 ...

  7. stm32控制共阳数码管以及共阴数码管

    共阳数码管 #include "stm32f10x.h" u8table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80};//共阳 ...

  8. c语言一位共阳数码管编程,求一个共阳四位数码管滚动显示1234的程序

    /******************************************************************************* * 文件名: 数码管 * 描  述: ...

  9. 共阴共阳数码管(及74HC595控制)

    一.共阳数码管 共阳数码管段表  0xc0,/*0*/                             0xF9,/*1*/                             0xA4, ...

最新文章

  1. 老谢oracle视频笔记_day02
  2. [Head First设计模式]身边的设计模式——适配器模式
  3. Volley框架学习
  4. 从命令行列出所有环境变量?
  5. 在python语言中下列是二进制整数_Python从菜鸟到高手(5):数字
  6. 【SpringMVC】登录状态验证
  7. fir.im Weekly - 1000 个 Android 开源项目集合
  8. 《Python Cookbook 3rd》笔记(5.17):将字节写入文本文件
  9. 元类及创建元类的方法(面试用
  10. android开发模仿文件管理器_2020 Web界面开发:DevExtreme全新的Diagram控件、文件管理器...
  11. 使用json对象要注意的地方
  12. 2021-02-02 天地图图层类型
  13. mysql5.5数据备份_MySql5.5备份和还原
  14. vb杨辉三角代码编写_如何用VB编程输出杨辉三角?
  15. php输入框形式,文本框有哪两种方式
  16. Linux常用命令:scp命令
  17. php文件更名,php如何批量给文件改名
  18. 【Linux进程间通信】二、pipe管道
  19. 英飞凌芯片支持计划第二阶段申请计划(硅麦芯片已开启)
  20. Fabric 系统链码

热门文章

  1. un1que成员介绍
  2. 新手使用python易踩坑语法:if语句中or 与in连用
  3. IT程序员的就业前景究竟如何?
  4. 大数据Saprk----Spark基础-scala的隐式转换
  5. jadx动态调试安卓apk
  6. Greenplum在HTAP场景下的优化和应用
  7. 使用 kubeadm 初始化 worker节点出现 not ready 故障
  8. 正则表达式匹配英文和法文
  9. c语言分离个位十位百位_用c语言如何表示出一个数的个位,百位,十位
  10. python百位数千位数取整