这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » TI » 课程2+"任务1"+"用定时器实现数码管从10到0的递减,步长为1"

共1条 1/1 1 跳转至

课程2+"任务1"+"用定时器实现数码管从10到0的递减,步长为1"

菜鸟
2024-05-13 09:42:19     打赏

前言 :这里我使用的是keil5.39keil版本必须在5.38A以上),编译器使用的是6.21版本,安装教程官网上面有详细的介绍,这里就不过多的说明了,如果说在使用keil版本出现问题的话,还是建议大家学习一下ccs编译环境,真的很好用。

一:任务目标:

1:利用74HC595驱动单个数码管

2:利用按键实现数码管数据增加变化

3:利用定时器T0实现一个数字秒表

4:课后练习 :用定时器中断实现数码管数值的递减

时间范围(10 ~ 0)

递减步长1000ms

二:使用工具:

1LP-MSPM0L1306开发板;

2Mic USB线

374HC595数码管模块

4:杜邦线 5

三:硬件介绍:

1:数码管介绍

数码管,也称作辉光管,是一种可以显示数字和其他信息的电子设备。玻璃管中包括一个金属丝网制成的阳极和多个阴极。大部分数码管阴极的形状为数字

这里我们使用的是七段数码管外加DP引脚,可以显示09的数字和一些字母信息。 数码管的工作原理:

按发光二极管单元连接方式可分为共阳极数码管和共阴极数码管。共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮

数码管图片:

数码管.png 

大家可以根据PPT去查找共阳和共阴极的编码方式,这里就不做说明了。

274HC595介绍

该芯片是一个8位串行输入、并行输出的位移缓存器。该缓存器在控制数码管中具有重要作用。

芯片引脚图:

595引脚图.png 

引脚说明:

引脚说明.png 

芯片的时序图:

时序图.png 

四:硬件连接

硬件连接.png 

 74HC595模块的VCCGND连接开发板的5VGND引脚;

DI连接开发板的PA27

SCLK连接开发板的PA26

RCLK连接开发板的PA13.

:软件开发过程:

为了开发方便,这里我是用CCS软件配置了一下使用到的IO口定义部分,配置图如下所示:以DIO口为例进行介绍

DIO口.png 

5.2 驱动步骤

1、首先将8位需要的传输的数据从引脚PA27(数据引脚)DI输入到芯片74HC595

2、将从DI上的数据串行移入移位寄存器,需要时钟驱动,即引脚11(SHCP)每产生一个上升沿,DI上的数据往移位寄存器送入一位,先送高位,后送低位,经过8个上升沿后,8bit全部送入移位寄存器了。

3、将移位寄存器里的数据送入存储寄存器,引脚12(STCP)产生一个上升沿后,该操作就完成了

4、引脚13(OE)为低电平,则步骤3送入存储寄存器的8bit数据(一个字节)就在Q7-Q0并行输出,并输出的数据会被所存起来。

注意:数据并行输出后,只要没有数据更新进来,原输出的数据保持不变,就是所谓的锁存(数据被锁存住)。在完成步骤123后,只要步骤4还没使能,输出都是保持不变的,当OE一使能,新的数据就输出覆盖旧输出。

我们的是8位共阳极数码管,原理图如下。两颗74HC595,一个是实现片选,一个输出8位并行数据。

5.3函数介绍:

//========================================================================

// 函数: void HC595_WriteData(uint8_t data)

// 描述: HC595芯片写入数据

// 参数:

// 返回: none.

// 版本: VER1.0

// 日期: 2024-5-8

// 备注:

//========================================================================

void HC595_WriteData(uint8_t data)

{

    uint8_t i;

    for(i = 0; i < 8; i++)

    {

        if((data & 0x80)>0)

{

    HC595_DAT(1);

        }

        else

{

            HC595_DAT(0);

        }

        HC595_CLK(0);

delay_cycles(32);

        HC595_CLK(1);

delay_cycles(32);  

data <<= 1;

    }

}

函数解析:

作用:发送字节到74HC595芯片的缓冲器中。
分析:发送的过程很重要,需要搞清所使用的芯片是先低位发送还是先高位。这里的延时很重要,如果延时不准确的话,74HC595根本不能用。

这个芯片是先写入最高位,再依次发送到最低位。所以在该段函数中,我们通过该数据与(&0x80,取出最高位,通过DIO口输入1/0,由于之前所提到的,唯有SCLK到达上升沿的时候,数据才能传入,于是我们在每次循环输入数据的时候,都将SCLKPB13)拉高10us ,然后再将所要输入的byte左移一位,继续循环。

由于两片74HC595芯片的作用,当第一片74HC595芯片的缓冲区八位都存在数据的时候,此时DIO口继续输入数据,则将会将已有数据顶置到下一片74HC595的缓冲区。

因此所要显示数字的数据传入完成后,继续传入其所要求显示的数码管位置,该过程也同理于数字数据的传输过程。

//========================================================================

// 函数: void HC595_SEND_DATA(uint8_t Value, uint8_t BIT)

// 描述: HC595芯片写入数据和需要显示的位选

// 参数:

// 返回: none.

// 版本: VER1.0

// 日期: 2024-5-8

// 备注:

//========================================================================

void HC595_SEND_DATA(uint8_t Value, uint8_t BIT)

{

    HC595_WriteData(Value);

    HC595_WriteData(1<<BIT);

    Display_Out();

}

作用:控制4位数码管的显示位置以及显示的数字
分析:该函数使用之前所定义和编写的void HC595_Send_Byte(unsigned char byte)函数继续工作,需要注意的是,当数据和位置全部输入后,需要拉高RCLKPB12)的电平,使其完成显示

 

显示代码:

//========================================================================

// 函数: void Disp_Data(uint16_t DATA1, uint16_t DATA2)

// 描述: 数码管显示数字0-9

// 参数: DATA1:第一个数码管 数据  DATA2:第一个数码管 数据

// 返回: none.

// 版本: VER1.0

// 日期: 2024-5-8

// 备注:

//========================================================================

void Disp_Data(uint16_t DATA1, uint16_t DATA2)

{

    uint16_t Temp_H,Temp_l;

    uint8_t NUM_Q, NUM_B,NUM_S,NUM_G;

 

    Temp_l = DATA2;

    NUM_Q = Temp_l/1000;

    NUM_B = Temp_l/100%10;

    NUM_S = Temp_l/10%10;

    NUM_G = Temp_l%10;

    HC595_SEND_DATA(Disp_DX[NUM_Q]+0x80,3);

    HC595_SEND_DATA(Disp_DX[NUM_B],2);

    HC595_SEND_DATA(Disp_DX[NUM_S],1);

    HC595_SEND_DATA(Disp_DX[NUM_G],0);

 

    Temp_H = DATA1;

    NUM_Q = Temp_H/1000;

    NUM_B = Temp_H/100%10;

    NUM_S = Temp_H/10%10;

    NUM_G = Temp_H%10;

    HC595_SEND_DATA(Disp_DX[13],7);

    HC595_SEND_DATA(Disp_DX[12],6);

    HC595_SEND_DATA(Disp_DX[11],5);

    HC595_SEND_DATA(Disp_DX[10],4);

}

一次只能显示一个位置的数字,因此需要搭配主函数中的while(1){ }继续循环显示,利用人眼捕获的时间差,从而动态显示全部的数字。

//========================================================================

// 函数: void DispCheckLed(void)

// 描述: 程序开始时用于自检各个数码管的段选,判断数码管是否正常.

// 参数: None.

// 返回: None.

// 版本: V1.0, 2023-07-01

//========================================================================

void DispCheckLed(void)

{

uint8_t i;

/*数码段测试*/

for(i=0;i<9;i++)      //数码管自检,

{                                          

HC595_SEND_DATA( LED_START[i],0);

delay_ms(200);

}

}

作用主要为了检测使用个某个数码管上的段选是否正常。

主程序:

    SYSCFG_DL_init();


  NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);


 

if(Function == 0)

{

DispCheckLed();  


}

    while (1)

{

 

/*该处代码为了检测最右面的数码管是否正常,自检完成后显示 数字 8*/

if(Function == 0)

{

HC595_SEND_DATA(0x00,0);


}

实现现象:上电之后右侧数码管自检,自检完成后将数码全部点亮,效果如下:

 LED自检 00_00_00-00_00_30.gif


课程2-2: 利用按键实现数码管数据变化

主程序:

 

/*定义按下 和 抬起时按键的标志位 */

int KeyUp = 0 ;

int KeyDown= 0 ;

int work2 = 99 ;

KeyValue = DL_GPIO_readPins(Blinky_PORT,GPIO_LEDS_USER_KEY_01_PIN);   // Read the state of key input

if(KeyValue == 0)

{

DL_GPIO_clearPins(Blinky_PORT, GPIO_LEDS_USER_Twinkle_LED_PIN); //PA0= 0;turn on led

KeyDown = 1 ;

KeyUp = 0 ;


}

else

{

DL_GPIO_setPins(Blinky_PORT, GPIO_LEDS_USER_Twinkle_LED_PIN);   //PA0= 1;turn off led

KeyUp = 1 ;

}  


Disp_Data_worK2(work2);

 

if(( KeyDown== 1) && (KeyUp == 1) )

{

KeyDown = 0 ;

work2 -- ;

}

说明:这里我定义了按键按下和抬起的两个状态位,防止在按下按键时,数据变化的太快,这样每次按下按键时,数据减少一个,试验效果如下:

LED减1 00_00_00-00_00_30.gif

课程2-3定时器实现数字秒表

M0L1306定时器介绍:

具有重复重新加载模式的 16 位或 32 位向上、向下或向上/向下计数器

用于对计数器时钟频率进行分频的 8 位可编程预分频器

最多两个独立通道,用于:

       – 输出比较

       – 输入捕捉

       PWM 输出(边沿对齐和中心对齐)

       – 单次触发模式

定时器配置部分:

定时器.png 

软件代码:

定时器初始化:

SYSCONFIG_WEAK void SYSCFG_DL_TIMER_0_init(void) {

 

    DL_TimerG_setClockConfig(TIMER_0_INST,

        (DL_TimerG_ClockConfig *) &gTIMER_0ClockConfig);

 

    DL_TimerG_initTimerMode(TIMER_0_INST,

        (DL_TimerG_TimerConfig *) &gTIMER_0TimerConfig);

    DL_TimerG_enableInterrupt(TIMER_0_INST , DL_TIMERG_INTERRUPT_ZERO_EVENT);

    DL_TimerG_enableClock(TIMER_0_INST);

 

 

}

定时器配置:10MS中断一次,并在中断函数里面对数据做处理:::

void TIMER_0_INST_IRQHandler(void)

{

switch (DL_TimerG_getPendingInterrupt(TIMER_0_INST))   

{

        case DL_TIMER_IIDX_ZERO:

{

count++ ;

if(count >= 100)

{  

count = 0 ;

Disp_num--;          

if(Disp_num ==0)

{

 Disp_num = 10 ;

}

}

           }

            break;

        default:

            break;

    }

}

在主函数中,直接调用显示部分就可以:

        Disp_Data(0000,Disp_num);  

 

试验效果如下:

秒表 00_00_00-00_00_30.gif


 

课后作业:

要求:

用定时器中断实现数码管数值的递减

时间范围(10 ~ 0)

递减步长1000ms

 

这里与2-3类似,唯一不同的是做减法,这里就不再重复介绍:

 只需在定时器中断函数里面,写如下,然后再主函数中,显示变量 Disp_num 即可。

Disp_num--;          

if(Disp_num ==0)

{

 Disp_num = 10 ;

}

效果图如下::

LED10-0 00_00_00-00_00_30.gif





关键词: MSPM0L1306    

共1条 1/1 1 跳转至

回复

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