这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » TI » 【TIMSPM0MCU焕新大作战】+非定时器方式完成数码管递减显示数字

共1条 1/1 1 跳转至

【TIMSPM0MCU焕新大作战】+非定时器方式完成数码管递减显示数字

专家
2024-04-16 21:03:30     打赏

在进行课程2之前,先补一补数码管相关的知识。数码管,可以理解成摆成数字8形状的几个发光二极管组成的器件,在显示原理上,其实就是点亮对应的笔段的LED,实现不同数字的表示。点亮LED,需要根据LED的压降、电源电压,计算出需要的限流电阻的大小。切记,不能像点白炽灯那样直接把电压是加到LED上,很容易瞬间烧毁LED。对数码管也是一样的道理。根据驱动方式的不同,数码管有两种模式,共阴和共阳。共阴模式,表示所有笔段共用阴极,点亮不同笔段时,需要控制输出高电平给各个笔段的阳极;共阳模式,表示所有笔段共用阳极,点亮时不同笔段时,需要控制输出低电平给各个笔段的阴极;

为了方便驱动数码管,人们做出了对应的驱动集成块,典型的如4511,74HC595,前者是CMOS电路,输出能力有限,驱动数码管时需要加功率器件作为缓冲。而74HC595是高速硅栅CMOS器件和引脚兼容低功耗肖特基TTL(LSTTL),是8级串行移位寄存器与存储寄存器和三态输出。在SCK的上升沿,串行数据由SDL输入到内部的8位位移缓存器,并行输出则是在LCK的上升沿将在8位位移缓存器的数据存入到8位并行输出缓存器。当串行数据输入端OE的控制信号为低使能时,并行输出端的输出值等于并行输出缓存器所存储的值。

74HC595的引脚说明:

图片1.png74HC595的处理逻辑真值表:

图片2.png

74HC595的工作方式:

第一步:目的:将要准备输入的位数据移入74HC595数据输入端上。

方法:送位数据到_595。

第二步:目的:将位数据逐位移入74HC595,即数据串入

方法:SH_CP产生一上升沿,将DS上的数据移入74HC595移位寄存器中,先送低位,后送高位。

第三步:目的:并行输出数据。即数据并出

方法:ST_CP产生一上升沿,将由DS上已移入数据寄存器中的数据送入到输出锁存器。

说明: 从上可分析:从SH_CP产生一上升沿(移入数据)和ST_CP产生一上升沿(输出数据)是二个独立过程,实际应用时互不干扰。即可输出数据的 同时移入数据。

用74HC595点亮数码管,只需要将合适的数据输出给75HC595,开放输出,完成对数码管各个笔段的控制,实现自己想要的数字显示效果。

图片3.png

活动中配套的数码管显示模块,使用了两组数码管模块和两个74HC595。数码管模块型号为3461BS1-7.3

图片4.png

原理图为

图片5.png

由原理图看,这是共阳数码管,显示数字0-9的段位码为:

0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90

笔段输出高电平,笔段不亮;笔段输出低电平,笔段被点亮。

配套的数码管显示模组的原理图:

图片6.png

这个显示模组的构思很巧妙,一用一个74HC595的输出控制笔段,另一个74HC595控制数码管的位,只要配合好船型数据,就可以动态显示8个数字。而且模组的构成上,是可以做很多级联的。由于所有数码管共用A~G、小数点这个八个字段,因此一次只能显示一种字符。理论上可以同时点亮所有数码管为同一个字符

这个模块需要提供三个信号:

1、SCLK

这个是串行时钟信号,在时钟的上升沿,把串行数据送入移位寄存器。

2、RCLK

这个是锁存信号,在时钟的上升沿,将数据从移位寄存器存入存储寄存器,呈现到74HC595的Qn输出引脚上。

3、DIO

这个是串行数据输入端

这三个信号都是输入信号,对于开发板而言就是输出信号,刚好可以利用上次试验使用到的那三个驱动LED的信号,也就是PA13,PA26,PA27三个GPIO口。程序的处理逻辑如下:

图片7.png

实际上就是循环显示10 到0 的过程。由于8个笔段对所有数码管是共用的,所以显示10时,不能同时在两个数码管上显示,只能通过动态扫描方式显示。

主程序代码如下:



#include "ti_msp_dl_config.h"
void delay(uint32_t cnt);
void DispNum(unsigned char num, unsigned char pos);
/* This results in approximately 0.5s of delay assuming 32MHz CPU_CLK */
#define DELAY (16000000)   // 500ms
#define ms50 (1600000)   // 50ms
#define s1 (32000000)   // 1s
#define ms1 (320)   // 0.01ms模式延迟
// 16进制数字显示信史段码(0-9,A-F),段码位=1时,数码管的对应的笔段不会被点亮
unsigned char TAB_SEG[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x77, 0x83, 0xC6, 0xA1, 0x86, 0x8E, 0xFF, 0xBF };
// 数码管模块的显示位置,自左向右
unsigned char TAB_POS[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
// 发送数据给数码管模块用的串行时钟,时钟上升沿有效
#define SCLK_0 DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN)
#define SCLK_1 DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN)
// 使数码管唯一寄存器数据被锁存到存储寄存器用的锁存信号,上升沿有效
#define RCLK_0 DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_2_PIN)
#define RCLK_1 DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_2_PIN)
// 发送数据给数码管模块用的串行数据位
#define DIO_0 {DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_3_PIN);}
#define DIO_1 {DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_3_PIN);}
void delay(uint32_t cnt) {
    uint32_t d=cnt;
    while(d--);
}
/**
 * 显示一位数码管数据
 * chr : 显示的数值字符(‘0’-‘9’,‘A’-‘F’)
 * pos :显示的位置(最左侧开始:0-7, 对应的位置数据:0x80, 0x40,0x20,0x10,0x08,0x04,0x02,0x01)
 * 暂时不考虑小数点的处理。数字后面有小数点的场合,相当于该数字的小数点笔段位清0
 */
void DispNum(unsigned char chr, unsigned char pos) {
    unsigned char i, num;
    // 根据字符,获取对应的段位码数据
    if (chr>=0 && chr<16) {
        num=TAB_SEG[chr];
    } else if (chr>=' ') {
        // 空格,所有笔段都不显示
        num = 0xFF;
    } else if (chr>='-') {
        num = 0xBF;
    } else {
      return;
    }
    // 将段位码数据以串行方式发送给数码管显示模块
    // 每个字符有八个笔段,小数点通常不用
    for(i=0;i<8;i++) {
      // 输出笔段对应的数据位
      if ((num & 0x80)>0) {
          // 笔段数据为1 的,DIO对应GPIO口输出高电平
          DIO_1;
      } else {
          // 笔段数据为0 的,DIO对应GPIO口输出低高电平
          DIO_0;
      }
      // 下一个笔段
      num<<=1;
      // 发出移位用串行时钟上升沿脉冲
      SCLK_0;
      delay_cycles(ms1);
      SCLK_1;
      delay_cycles(ms1);
    }
    // 发送完笔段数据,发送显示位置数据
    num = TAB_POS[pos%8];
    for(i=0;i<8;i++) {
      // 输出对应的数据位
        if ((num & 0x80)>0) {
          DIO_1;
      } else {
          DIO_0;
      }
      // 下一个数码管位置
      num<<=1;
      // 发出移位用串行时钟上升沿脉冲
      SCLK_0;
      delay_cycles(ms1);
      SCLK_1;
      delay_cycles(ms1);
    }
    // 发出锁存信号,点亮数码管
    RCLK_0;
    delay_cycles(ms1);
    RCLK_1;
    delay_cycles(ms1);
}
int main(void) {
    uint32_t i=0, j=0;
    /* Power on GPIO, initialize pins as digital outputs */
    SYSCFG_DL_init();
    /* Default: LED1 and LED3 ON, LED2 OFF */
    DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_2_PIN);
    DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN |
                                        GPIO_LEDS_USER_LED_3_PIN |
                                        GPIO_LEDS_USER_TEST_PIN);
    DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_LED_3_PIN | GPIO_LEDS_USER_TEST_PIN);
    while (1) {
        // 循环显示10递减到0 的过程
        for (i=0; i<11; i++) {
            if (i==0) {
                // 因为笔段共用,10的显示不同于其他数字,只能通过动态扫描方式显示
                for (j=0; j<1400; j++) {
                    DispNum(1, 6);
                    DispNum(0, 7);
                }
            } else {
                // 显示字符9-0
                DispNum(10-i, 7);
                // 保持显示时长为1秒
                delay_cycles(s1);
            }
        }
    }
}

运行效果

课程2.gif




关键词: MSPM0焕新大作战     课程2     任务1    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]