本文介绍的是使用 GPT1 定时器实现定时中断,达到和 EPIT 定时器一样的效果,每隔 500ms 切换LED灯的状态。
目录
一、GPT1 定时器初始化
因为使用GPT的定时中断来切换LED灯的状态,所以这里的配置主要包含:定时器配置、中断配置
- 定时器配置
- 设置复位,并等待复位结束(关于复位的详细内容,参考上一篇:GPT 寄存器解析)
- 定时器配置(选择计数器初始值、选择时钟源、选择工作模式)
- 设置分频数
- 中断配置
- 设置比较值(当计数器的值 == 比较值时,触发中断)
- 中断使能(GIC 使能、GPT 使能、注册中断服务函数)
/*
* @description : gpt 定时初始化
* @param : 定时间隔,单位: ms
* @return : 无
*/
void delay_init(unsigned int interval)
{
// 设置复位(设为复位状态后,除了bit 0、1、2、3、5外,其他位都会被重置为默认值)
GPT1_CR = 0;
GPT1_CR |= (1 << 15);
while((GPT1_CR >> 15) & 0x01); // 等待复位完成
/*
* 配置GPT定时器
* bit 1: 1 设置计数器初始值问为 0
* bit 8-6: 001 选择时钟源为 ipg_clk
* bit 9: 0 选择工作模式 restart mode
*/
GPT1_CR |= ((1 << 1) | (1 << 6)); // bit 1、6
GPT1_CR &= ~(1 << 9); // bit 9
// 分频
GPT1_PR &= ~(0xFFF << 0); // 低 12 bit 清零
GPT1_PR |= (65 << 0); // 66 分频
// 设置通道1 的比较值
unsigned int val = 1000000 * interval / 1000;
GPT1_OCR1 = (val << 0);
// 输出比较通道1中断使能
GPT1_IR |= (1 << 0);
// 使能 GIC 中相应中断
GIC_EnableIRQ(87);
// 注册中断服务函数(中断ID = 55 + 32 = 87)
register_irqhandler(87, delay_irqhandler);
// 启动定时器
GPT1_CR |= (1 << 0);
}
注意:设为复位状态后,除了bit 0、1、2、3、5外,其他位都会被重置为默认值。在复位结束之前,bit 15 会一直被置 1;只有当复位结束以后,才会自动置 0,此时我们需要等待复位结束
二、GPT1 中断服务函数
GPT1 包含 2 个捕获中断 Input Capture1~2 和 3 个输出比较中断 Output Compare1~3,他们触发的是同一个中断服务函数,我们需要根据 GPT1_SR 判断是哪一个中断被触发了。
/*
* @description : gpt 延时中断服务函数
* @param : 无
* @return : 无
*/
void delay_irqhandler(void* userParams)
{
// 判断是谁产生的中断(输入捕获还是输出比较?哪个通道?)
// 读取 GPT1_SR
if ((GPT1_SR >> 0) & 0x01) // 说明是输出比较通道1的中断事件发生了
{
extern unsigned int status;
switch_led(status); // 切换LED状态
status = !status;
}
GPT1_SR |= (1 << 0); // 清除中断标志位
}