入门第三步——循环点亮LED
上一节,我们学习了循环点亮一个LED,但是使用的是延时函数,这样非常的不友好,既浪费了单片机的资源,又显得的没有水平。这一节我们来点不一样的操作,采用定时器中断来点亮LED。
先建立一个Timer0_Init.c和Timer0_Init.h,单独封装一下。
再新建一个中断处理函数,App_interrupts.c和App_interrupts.h
看代码:
main.c
#include "main.h"
int main()
{
App_LedInit();
Timer0_Init();
Bt_M0_Cnt16Set(TIM0,3036); //重载值,1s/(4M/32)=1*10^6 / (4*1*10^6/32) =8us 500ms/8us = 62500 65536-62500=3036
Bt_M0_Run(TIM0);
while(1);
}
App_Gpio_Init.c
#include "App_Gpio_Init.h"
void App_LedInit(void)
{
stc_gpio_cfg_t stcGpioCfg; ///定义结构体变量
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); ///< 打开GPIO外设时钟门控
stcGpioCfg.enDir = GpioDirOut; ///< 端口方向配置->输出(其它参数与以上(输入)配置参数一致)
stcGpioCfg.enPu = GpioPuDisable; ///< 端口上拉配置->不使能
stcGpioCfg.enPd = GpioPdDisable; ///< 端口下拉配置->不使能
stcGpioCfg.bOutputVal=TRUE; ///< 端口低电平驱动,初始化为高电平,使LED处于熄灭状态
Gpio_Init(GpioPortA, GpioPin0, &stcGpioCfg); ///< GPIO IO LED端口初始化
}
Timer0_Init.c
#include "Timer0_Init.h"
void Timer0_Init(void)
{
stc_bt_mode0_cfg_t stcBtConfig;
DDL_ZERO_STRUCT(stcBtConfig);
Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE);
stcBtConfig.enWorkMode = BtWorkMode0; ///< 定时器模式
stcBtConfig.bEnGate = FALSE; ///< 门控极性控制->关闭
stcBtConfig.enPRS = BtPCLKDiv32; ///< 预除频配置
stcBtConfig.bEnTog = FALSE; ///< 翻转输出使能
stcBtConfig.enCT = BtTimer; ///< 定时功能
stcBtConfig.enCntMode = Bt16bitArrMode; ///< 自动重载16位定时器
Bt_Mode0_Init(TIM0, &stcBtConfig);
Bt_M0_ARRSet(TIM0,3036); //重载值,1s/(4M/32)=1*10^6 / (4*1*10^6/32) =8us 500ms/8us = 62500 65536-62500=3036
Bt_ClearIntFlag(TIM0,BtUevIrq); //中断清除
Bt_Mode0_EnableIrq(TIM0); //中断使能
EnableNvic(TIM0_IRQn,IrqLevel3,TRUE); //NVIC使能
}
App_interrupts.c
#include "App_interrupts.h"
//Tim0中断服务函数
void Tim0_IRQHandler(void)
{
static boolean_t Flag=0;
if(TRUE == Bt_GetIntFlag(TIM0,BtUevIrq))
{
Bt_ClearIntFlag(TIM0,BtUevIrq);
Gpio_WriteOutputIO(GpioPortA, GpioPin0, Flag);
Flag ^= 1;
}
}
本节采用定时器实现LED电平翻转,实现了去除delay延时函数,让代码更加可靠,可读性更强。