声明:以下内容为本人学习心得。
一、基础知识
HC32F460的Timer0提供了2个单元,每个单元下有A、B通道,即Time0一共有4个通道,具有同步计数和异步计数方式,特别注意的是:单元1通道A的比较匹配中断TMR_U1_GCMA仅在异步计数方式时使用。
二、代码分析
本实验设置Timer0时钟源为XTAL32,使能计数匹配中断,每0.5S中断一次并切换LED_BLUE的亮灭状态;同时使能按键K10的下降沿产生内部触发事件,该事件可以使定时器停止计数。
main.c
①定义变量声明,具体解释在后面。
#define EXAMPLE_PERIPH_WE (LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | \
LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_SRAM)
#define EXAMPLE_PERIPH_WP (LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_SRAM)
/* TMR0 unit and channel definition */
#define TMR0_UNIT (CM_TMR0_1)//Timer0通道1基地址
#define TMR0_CLK (FCG2_PERIPH_TMR0_1)//使能Timer0时钟,通过寄存器PWC_FCG2(功能时钟控制器2)设置
#define TMR0_CH (TMR0_CH_B)//使用Timer0的CH_B通道
#define TMR0_TRIG_CH (AOS_TMR0)//AOS:自动运行系统,TMR0_HTSSR(Timer0硬件触发事件选择寄存器)地址
#define TMR0_CH_INT (TMR0_INT_CMP_B)//设置CH_B通道 比较匹配中断使能
#define TMR0_CH_FLAG (TMR0_FLAG_CMP_B)//设置 比较匹配中断完成标志位,通过TMRO_STFLR(状态标志寄存器),第16位置1
#define TMR0_INT_SRC (INT_SRC_TMR0_1_CMP_B)//中断序号65
#define TMR0_IRQn (INT006_IRQn)//中断源
/* Period = 1 / (Clock freq / div) * (Compare value + 1) = 500ms */
#define TMR0_CMP_VALUE (XTAL32_VALUE / 16U / 2U - 1U)//设置基准值 2048
②Time0定时器配置
static void TMR0_Config(void)
{
stc_tmr0_init_t stcTmr0Init;//定时器0配置结构体
stc_irq_signin_config_t stcIrqSignConfig;//中断配置结构体
/* Enable timer0 and AOS clock */
FCG_Fcg2PeriphClockCmd(TMR0_CLK, ENABLE);//打开TIME0使能时钟
FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_AOS, ENABLE);//打开AOS使能时钟
/* TIMER0 configuration */
(void)TMR0_StructInit(&stcTmr0Init);
stcTmr0Init.u32ClockSrc = TMR0_CLK_SRC_XTAL32;//选择XTAL32为时钟源
stcTmr0Init.u32ClockDiv = TMR0_CLK_DIV16;//设置16分频
stcTmr0Init.u32Func = TMR0_FUNC_CMP;//设置为 比较匹配中断模式
stcTmr0Init.u16CompareValue = (uint16_t)TMR0_CMP_VALUE;//基准值为2048
(void)TMR0_Init(TMR0_UNIT, TMR0_CH, &stcTmr0Init);
/* Asynchronous clock source, writing to TMR0 register requires waiting for three asynchronous clocks. */
DDL_DelayMS(1U);
TMR0_HWStopCondCmd(TMR0_UNIT, TMR0_CH, ENABLE);
/* Asynchronous clock source, writing to TMR0 register requires waiting for three asynchronous clocks. */
DDL_DelayMS(1U);
TMR0_IntCmd(TMR0_UNIT, TMR0_CH_INT, ENABLE);
/* Asynchronous clock source, writing to TMR0 register requires waiting for three asynchronous clocks. */
DDL_DelayMS(1U);
AOS_SetTriggerEventSrc(TMR0_TRIG_CH, BSP_KEY_KEY10_EVT);
/* Interrupt configuration */
stcIrqSignConfig.enIntSrc = TMR0_INT_SRC;
stcIrqSignConfig.enIRQn = TMR0_IRQn;
stcIrqSignConfig.pfnCallback = &TMR0_CompareIrqCallback;
(void)INTC_IrqSignIn(&stcIrqSignConfig);
NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);
}
中断结构体成员的详解在之前发布的文章有说过,这里就不多细节了,直接看定时器0结构体成员有哪些:
typedef struct {
uint32_t u32ClockSrc; /*!< 选择时钟源 */
uint32_t u32ClockDiv; /*!< 设置时钟源分频*/
uint32_t u32Func; /*!< 设置定时器0功能:计数 or 输入捕获 */
uint16_t u16CompareValue; /*!< 设置基准值 */
} stc_tmr0_init_t;
特别注意的是:
DDL_DelayMS(1U); 在Timer0配置中的作用是:等待3个异步计数时钟。
这是因为HC32F460规定使用Timer0模块时,在选择异步计数的情况下,修改计数值、基准值、启动位、状态位时Timer()从接收到写动作后经过3个异步计数时才将修改值写入对应的寄存器。
TMR0_HWStopCondCmd(TMR0_UNIT, TMR0_CH, ENABLE);设置TMR0_BCONR(基本控制寄存器)第b29位HSTPB为1,置1:条件匹配时,定时器停止有效。
TMR0_IntCmd(TMR0_UNIT, TMR0_CH_INT, ENABLE);使能中断,设置TMR0_BOCNR(基本控制寄存器)的b18位 INTENB为1,置1:CMPBR寄存器和计数值相等时,或者发生捕获输入事件时,该中断使能。
AOS_SetTriggerEventSrc(TMR0_TRIG_CH, BSP_KEY_KEY10_EVT); 写入硬件触发的事件编号。
BSP_KEY_KEY10_EVT:对应PORT_EIRQ1外部中断,下降沿触发。
剩下的代码是中断配置,之前文章讲过,这里不多说,看看XTAL32配置和Timer0_1的通道B比较匹配中断回调函数
static void XTAL32_Config(void)
{
stc_clock_xtal32_init_t stcXtal32Init;
GPIO_AnalogCmd(BSP_XTAL32_PORT, BSP_XTAL32_IN_PIN | BSP_XTAL32_OUT_PIN, ENABLE);
(void)CLK_Xtal32StructInit(&stcXtal32Init);
/* Configure Xtal32 */
stcXtal32Init.u8State = CLK_XTAL32_ON;
stcXtal32Init.u8Drv = CLK_XTAL32_DRV_MID;
stcXtal32Init.u8Filter = CLK_XTAL32_FILTER_OFF;
(void)CLK_Xtal32Init(&stcXtal32Init);
}
static void TMR0_CompareIrqCallback(void)
{
BSP_LED_Toggle(LED_BLUE);
TMR0_ClearStatus(TMR0_UNIT, TMR0_CH_FLAG);
}
也都是之前文章讲过,直接看主函数:
int32_t main(void)
{
/* Peripheral registers write unprotected */
LL_PERIPH_WE(EXAMPLE_PERIPH_WE);
/* Configure XTAL32 */
XTAL32_Config();
/* BSP init */
BSP_LED_Init();
BSP_KEY_Init();
/* Configure TMR0 */
TMR0_Config();
/* TMR0 start counting */
TMR0_Start(TMR0_UNIT, TMR0_CH);
/* Asynchronous clock source, writing to TMR0 register requires waiting for three asynchronous clocks. */
DDL_DelayMS(1U);
/* Peripheral registers write protected */
LL_PERIPH_WP(EXAMPLE_PERIPH_WP);
for (;;) {
;
}
TMR0_Start(TMR0_UNIT, TMR0_CH); 目的是通过设置基本控制就寄存器(TMR0_BCONR)中的第b16位CSTB为1,置1时:通道B定时器启动。
到此定时器0计数实验就结束了,有什么疑问的可以私信我~