GPIO输出应用:数码管

数码管原理

共阴/共阳结构

  • 一位8段数码管集成了8个发光二极管(包括一个方形数字8与一个小数点)若是按一个二极管两个引脚的传统方式进行设计,将会使制造与控制变得很繁琐
  • 为了化繁为简,数码管使用共阳极/共阴极结构,一个数码管的8个二极管的阳极/阴极被接在公共端
  • 以共阳极结构为例,8个发光二极管的阳极被接在一起,并连接到一个正电源;若某个发光二极管的负极被置为低电平,该发光二极管就会被点亮,共阴结构原理一致,配置相反

段选码

  • 由上文可知,通过配置连接数码管中各个二极管的GPIO端口输出高低电平,即可操控数码管中对应二极管亮灭,组成数码字符

  • 为保证显示同一数码的引脚电平取值相同,数码管有统一的排列规则:

    最上方为a,按顺时针方向排列至f,中间的横杠为g,下方的小数点为dp

  • 以共阳结构为例,当与数码管连接的GPIO端口组某一位被配置为0(输出低电平)时,对应二极管亮起:

    比如需要显示数字1,即需要b、c段亮起,对应的段选码是0xF9(1111 1001)

    为免去重复写入各种配置用十六进制数的麻烦,往往将各个情况对应的位选码、段选码写入数组中,使用时直接选择

    unsigned char num[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xa0,0x83,0xc6,0xa1,0x86,0x8e};
    //与数字0-9相对应的段选码
    

显示多位数码管

  • 位选码

    对于有多位数码管的情况,借助位选信号,开启指定的那一位数码管

    例如PE0至PE3连接至数码管的0至3位,想要在第一位显示数字,应该配置PE组输出寄存器位选码为0xFE(1111 1110),使能第一位数码管

    与段选码同理,也写成数组,方便选用:

    unsigned char bit[] = {0xFE,0xFD,0xFB,0xF7};
    //位选码,分别对应1111 1110等数,用以控制数码管不同位,例如OxFE就打开了第0位数码管
    
  • 刷新数码管

    位选信号一次只能使能一位数码管,为了显示多位数字,使用刷新数码管的方式:

    在主程序中让各位数字轮流循环显示,而切换位的时间得极短,让人难以察觉


代码实现

  • 初始化函数

    具体的配置取决于电路结构:哪些引脚连接数码管的段选端(一般用字母A-F标记),哪些连接至位选端

    void Digit_GPIO_Init()
    {
      //位选初始化
      PE_DDR = 0x0F;//配置为输出
      PE_CR1 = 0x0F;//推挽输出
      PE_ODR = 0x0F;//先关闭
      //段选初始化
      PB_DDR = 0xFF;
      PB_CR1 = 0xFF;
      PB_ODR = 0xFF;
    }
    
  • 刷新数码管

    void Display(unsigned char xbit,unsigned char xnum)
    {
      PE_ODR |= 0X0F;
      PE_ODR &= bit[xbit];
      PB_ODR = num[xnum];
      //传入数字以选择对应要进行显示的位与要显示的数
      delay(2);
      //切换位的时间设定得极短,让人难以察觉,在视觉上认为各个数码管是一齐显示的
      PB_ODR = 0xFF;//在显示完成后清除以防残影
    }
    
  • 使用方法

    //在写好函数后,可以在主程序中直接调用,比如希望显示从第3位到第0位数码管显示2333
    unsigned char bit[] = {0xFE,0xFD,0xFB,0xF7};
    //位选码,分别对应1111 1110等数,用以控制数码管不同位,例如OxFE就打开了第0位数码管
    unsigned char num[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xa0,0x83,0xc6,0xa1,0x86,0x8e};
    //与数字0-9相对应的段选码
    void Display(unsigned char xbit,unsigned char xnum);
    main()
    {
    //省略具体代码
    Display(3,2);
    Display(2,3);
    Display(1,3);
    Display(0,3);
    while(1);
    }
    

posted on   无术师  阅读(31)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?

统计

点击右上角即可分享
微信分享提示