【国产高性能运动控制MCU 先楫HPM5361】定时器+中断 寄存器编程测试
[复制链接]
前言
定时器和中断是最常使用的资源,这一篇继续测试定时器和中断的代码编写,为了简单还是直接基于寄存器操作。
定时器
参考手册42 43章
寄存器比较简单,不同通道CH0,CH1,CH2,CH3的寄存器一样
后面
SR,IRQEN,GCR公用。
根据寄存器描述很容易写出相关代码
详见注释
#include <rtthread.h>
#include <rtdevice.h>
#include "rtt_board.h"
#include <drv_gpio.h>
#include <drv_gpio.h>
void timer_cb(void)
{
HPM_GPIO0->DO[GPIO_DI_GPIOA].TOGGLE = 1u << 27;
}
void timer_init(void)
{
HPM_IOC->PAD[IOC_PAD_PA27].FUNC_CTL = IOC_PA27_FUNC_CTL_GPIO_A_27;
HPM_GPIO0->OE[GPIO_DI_GPIOA].SET = 1u << 27;
install_isr(IRQn_GPTMR0,(uint32_t)timer_cb);
intc_m_enable_irq(IRQn_GPTMR0);
}
void timer_set_period(uint32_t period)
{
HPM_GPTMR0->CHANNEL[0].CR |= (1u << 14); /* 复位 */
HPM_GPTMR0->CHANNEL[0].CR &= ~(1u << 14); /* 释放复位 */
HPM_GPTMR0->CHANNEL[0].CR |= (1u << 3); /* 调试时定时器停止 */
HPM_GPTMR0->CHANNEL[0].RLD = period; /* 重载值 计数器从0开始运行到重载值恢复到0重新计数 */
HPM_GPTMR0->SR = 0xFFFF; /* 写1清除标志 */
HPM_GPTMR0->IRQEN |= 0x01; /* 通道0重载中断使能 */
}
void timer_start(void)
{
HPM_GPTMR0->CHANNEL[0].CR |= (1u << 10); /* 使能 */
}
void timer_stop(void)
{
HPM_GPTMR0->CHANNEL[0].CR &= ~(1u << 10); /* 停止 */
}
中断
中断相关操作接口位于hpm_interrupt.h
其中install_isr用于注册中断回调函数,即对应的数组__vector_table
intc_m_enable_irq用于使能中断,其他接口参考h文件。
其中中断号在hpm_soc.h中定义,比如定时器0即IRQn_GPTMR0。
使能定时器中断两句搞定
install_isr(IRQn_GPTMR0,(uint32_t)timer_cb);
intc_m_enable_irq(IRQn_GPTMR0);
中断处理过程
trap_entry->
case IRQ_M_EXT:
调用之前注册的回调函数
((isr_func_t) __vector_table[irq_index])();
时钟
默认时钟是100MHz,即800MHz主频8分频,后面可以测试出来
EEWORLDIMGTK2
测试
为了方便测试使用IO在中断中反转
timer_init中初始化IO
HPM_IOC->PAD[IOC_PAD_PA27].FUNC_CTL = IOC_PA27_FUNC_CTL_GPIO_A_27;
HPM_GPIO0->OE[GPIO_DI_GPIOA].SET = 1u << 27;
中断回调中翻转IO
void timer_cb(void)
{
HPM_GPIO0->DO[GPIO_DI_GPIOA].TOGGLE = 1u << 27;
}
测试代码
void thread_entry(void *arg)
{
timer_init();
timer_set_period(10000);
timer_start();
while(1){
rt_thread_mdelay(200);
}
}
10000对应100uS
1000对应10uS
可知时钟频率是1对应1/100uS即100MHz。
timer_set_period(10000);
timer_set_period(1000);
总结
可以看到定时器和中断操作比较简单,直接寄存器操作也很快捷。时钟频率比较高所以精度也可以很高。
|