这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » TI » 【MSP焕新大作战】课程二+任务一---MSPM01306实现数码管从10到0的

共2条 1/1 1 跳转至

【MSP焕新大作战】课程二+任务一---MSPM01306实现数码管从10到0的递减

助工
2024-05-10 23:43:38     打赏

    本文的主要开发内容是对8位数码管的编程驱动以及实现数码管从10到0的递减显示,首先需要设置数码管与MCU的引脚连接。下图为8位数码管的电路原理图、引脚功能定义,所用到的数码管驱动芯片是HC595,这是一颗高速串行数据转并行输出芯片。HZ@3QEL$VGNE2O`N{_AIM3O.png

GUWXR2C0%~US{JPS{SQZ`5L.png

    从以上电路原理图知,8位数码管由两片HC595芯片组成,其中第一片HC595芯片负责接收串行数据输入,并将低八位串行数据用于驱动单个数码管,高八位数据串行输入到第二片HC595芯片,用于驱动第几位数码管显示。当低八位数据和高八位串行数据传输完毕,在RCLK引脚上给予不小于2us的上升沿,此时将有一位数码管被点亮。

    按照以上说明,那么每次只能点亮一位数码管,这可无法实现多位数码管同时点亮呢。然而非也非也,由于人眼都会存在一个视觉暂留性,在极短的时间内,快速循环点亮多位数码管,那么我们看到的就是多位数码管"同时点亮"了。这个和手机屏幕显示也是类似的,手机屏幕的各个显示点也并非同时点亮,而是以超快的频率循环点亮来实现整个屏幕内容的显示。

    一位数码管示意图

QQ图片20240510231639.png

    数码管模块由八段LED组成,均为共阳极,那么驱动LED显示就需要锁存器中的数据为低电平数据,LED段驱动顺序为a-b-c-d-e-f-g-h,然而对应的HC595内部锁存器是数据存储顺序为LED段驱动顺序的倒序。

    例如,数码管驱动显示数字6(小数点不显示),对应LED段驱动数据为01000001,而锁存器存储数据为10000010。对于一位数码管来说,它能够显示的数字范围是0~9,因此可以将0~9的锁存器数据封装在一个数组中,方便数码管显示0~9中任一位数据时直接调用。

    根据以上原理,在程序开发中实现了数码管从10到0递减显示,并且额外增加了一个秒表计时器功能,开机默认运行倒计时模式,循环从10递减到0。按下按键1实现功能切换,切换至秒表计时器模式,数码管显示0,按下按键1实现计算功能,理论上可以计时的时间为2^32秒,实际上应该用不了计时这么久的。再一次按下按键实现计时终止,当前数码管显示最终的计时时间,再次按下按键1,实现计时清零重新返回计时启动模式。

    无论是倒计时模式还是计时器模式,数码管数字刷新显示操作均由定时器0的中断回调函数完成,而精确延时操作由定时器1完成。定时器中断的机制是定时器在每隔设定的间隔内触发一次中断,中断可以暂停当前CPU的执行任务,转向执行定时器中断回调函数的任务,执行完毕后返回执行上一次CPU暂停执行的任务。因此在程序中需要指定中断优先级别,中断级别是数字越小优先级越高,程序中设定按键中断完成功能模式切换,将按键中断优先级设为最高,其次是定时器1精确延时中断优先级为次高,定时器0数码管刷新中断优先级最低。

QQ图片20240511003435.png

    syscfg文件下载链接:syscfg.zip

    源代码:

#include "ti_msp_dl_config.h"
#include <math.h>
#define NUM_MAXLENGTH 8
#define delay_us 32
typedef struct{
    uint32_t Num_start;
    uint8_t  Num_polarity;
    uint8_t  polarity_flag;
    uint8_t  func_mode;//0表示倒计时模式,1表示秒表模式
    uint8_t  stopwatch_status;//0表示等待启动秒表,1表示正在计时,2表示停止计时
}LED_Segment_Mode;
LED_Segment_Mode LS_Mode;
uint8_t Num_List[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf};
int32_t Num_Decrease=1;

/**
 *  @brief      时钟上升沿配置
 *
 *  @param[in]  外设端口PORTx、t1、t2
 *
 */
void HC595_CLKRisingEdge_Config(GPIO_Regs* PORTx,uint32_t PINx,uint32_t t1,uint32_t t2){
        DL_GPIO_clearPins(PORTx, PINx);
        delay_cycles(delay_us*t1);
        DL_GPIO_setPins(PORTx, PINx);
        delay_cycles(delay_us*t2);
}
/**
 *  @brief      HC595输入1字节数据
 *
 *  @param[in]  byte字节数据
 *
 */
void LED_Segment_WriteByte(uint8_t byte){
    for(uint8_t i=1;i<=8;i++){
        if(byte&0x80){
            DL_GPIO_setPins(PORT_HC595_PORT,PORT_HC595_PIN_HC595_DIO_PIN);
        }
        else
        {
            DL_GPIO_clearPins(PORT_HC595_PORT,PORT_HC595_PIN_HC595_DIO_PIN);
        }
        HC595_CLKRisingEdge_Config(PORT_HC595_PORT,PORT_HC595_PIN_HC595_SCLK_PIN,2,2);
        byte<<=1;
    }

}
/**
 *  @brief      数码管显示一位数字
 *
 *  @param[in]  Num_one数字,index显示位置
 *
 */
void LED_Segment_Display_Num_One(uint8_t Num_one,uint8_t index){
//    switch(Num_one){
//    case 0:
//        break;
//    }
    LED_Segment_WriteByte(Num_List[Num_one]);
    LED_Segment_WriteByte(1<<index);
    HC595_CLKRisingEdge_Config(PORT_HC595_PORT,PORT_HC595_PIN_HC595_RCLK_PIN,2,2);
}
/**
 *  @brief      数码管显示小数点
 *
 *  @param[in]  Num_one小数点,index显示位置
 *
 */
void LED_Segment_Display_point(uint8_t Num_one,uint8_t index){
//    switch(Num_one){
//    case 0:
//        break;
//    }
    LED_Segment_WriteByte(Num_one);
    LED_Segment_WriteByte(1<<index);
    HC595_CLKRisingEdge_Config(PORT_HC595_PORT,PORT_HC595_PIN_HC595_RCLK_PIN,2,2);
}
/**
 *  @brief      数码管显示处理
 *
 *  @param[in]  Num数字
 *
 */
void Num_LED_Segment_Process(uint32_t Num){
    uint8_t num_lsb=0;
    uint8_t i;
    for(i=0;i<NUM_MAXLENGTH;i++)
    {
        num_lsb=Num%10;
        Num/=10;
        LED_Segment_Display_Num_One(num_lsb,i);
        if(Num==0)break;
    }

    if(LS_Mode.Num_polarity==0){
        LED_Segment_WriteByte(0xbf);
        LED_Segment_WriteByte(0x01<<(i+1));
        HC595_CLKRisingEdge_Config(PORT_HC595_PORT,PORT_HC595_PIN_HC595_RCLK_PIN,2,2);
    }
}


int main(void)
{
    SYSCFG_DL_init();
    NVIC_SetPriority(TIMER_0_INST_INT_IRQN, 2);
    NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);
    DL_TimerG_startCounter(TIMER_0_INST);
//
    NVIC_SetPriority(TIMER_1_INST_INT_IRQN, 1);
    NVIC_EnableIRQ(TIMER_1_INST_INT_IRQN);
    DL_TimerG_startCounter(TIMER_1_INST);

    NVIC_SetPriority(GPIO_MULTIPLE_GPIOA_INT_IRQN, 0);
    NVIC_EnableIRQ(GPIO_MULTIPLE_GPIOA_INT_IRQN);

    LS_Mode.Num_start=10;
    LS_Mode.polarity_flag=1;
    LS_Mode.Num_polarity=1;//默认显示正数
    LS_Mode.func_mode=0;
    LS_Mode.stopwatch_status=0;
    while (1) {
        delay_cycles(10);
//        LED_Segment_Display_Num_One(0x7f,0x01<<5);
//        LED_Segment_Display_point(0x7f,5);
//        Num_LED_Segment_Process_Float(0.356,2);
    }
}
void TIMER_0_INST_IRQHandler(void)
{
    switch (DL_TimerG_getPendingInterrupt(TIMER_0_INST))
    {
        case DL_TIMER_IIDX_ZERO:
            Num_LED_Segment_Process(Num_Decrease);
            break;
        default:
            break;
    }
}
void TIMER_1_INST_IRQHandler(void)
{
    switch (DL_TimerG_getPendingInterrupt(TIMER_1_INST)) {
        case DL_TIMER_IIDX_ZERO:
//            DL_GPIO_togglePins(GPIO_LEDS_PORT,GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN);
            if(LS_Mode.func_mode==0){
                if(LS_Mode.polarity_flag==1){
                    Num_Decrease--;
                    if(Num_Decrease<0)
                    Num_Decrease=LS_Mode.Num_start;
                }
    //            else
    //            {
    //
    //                if(LS_Mode.Num_polarity==1){
    //                    Num_Decrease--;
    //                    if(Num_Decrease<0)
    //                        LS_Mode.Num_polarity=0;
    //                }
    //                else{
    //                    Num_Decrease++;
    //                    if(Num_Decrease==LS_Mode.Num_start)
    //                        LS_Mode.Num_polarity=1;
    //                }
    //            }
            }
            else
            {
                if(LS_Mode.stopwatch_status==0)
                    Num_Decrease=0;
                else if(LS_Mode.stopwatch_status==1)
                    Num_Decrease++;
                else
                {
                }
            }
            break;
        default:
            break;
    }
}
void GROUP1_IRQHandler(void)
{
    switch (DL_GPIO_getPendingInterrupt(PORT_Key2_PORT)) {
        case PORT_Key2_PIN_Key2_IIDX:

            switch(LS_Mode.stopwatch_status){

            case 0:
                LS_Mode.stopwatch_status++;
                break;
            case 1:
                LS_Mode.stopwatch_status++;
                break;
            case 2:
                LS_Mode.stopwatch_status=0;
                break;
            default:
                LS_Mode.stopwatch_status=0;
            break;
            }
         break;
         case PORT_Key1_PIN_Key1_IIDX:
             DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
             if(LS_Mode.func_mode==0)
             {
                 Num_Decrease=0;
                 LS_Mode.stopwatch_status=0;
                 LS_Mode.func_mode++;

             }
             else if(LS_Mode.func_mode==1)
             {
                 LS_Mode.func_mode--;
                 Num_Decrease=LS_Mode.Num_start;
             }
             else
             {
                 LS_Mode.func_mode=0;
                 Num_Decrease=LS_Mode.Num_start;
             }
         break;
         default:
//             DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
             break;
    }
}

效果图:





关键词: MSPM01306     数码管驱动          课程二    

专家
2024-05-11 08:22:22     打赏
2楼

不错啊


共2条 1/1 1 跳转至

回复

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