配置延时函数
GPT 是一款 32 位多功能定时器,输入时钟经 12 位预分频器(1~4096 分频)后驱动 32 位计数器自由计数;它同时支持输入捕获 与输出比较两大核心功能:输入捕获通道可在引脚电平跳变时(如 GPT_CAPTURE1 的上升沿),将当前计数值锁存到对应 Timer Input Reg 并触发捕获中断;输出比较通道则通过将计数器值与 3 组 Timer Output Reg 比对,匹配后触发输出中断并通过输出模块控制引脚电平变化;此外计数器溢出时也可触发溢出中断,所有中断经汇总后发送给处理器,整体可实现精准定时、脉冲测量、PWM 输出等多种场景,且支持自由运行模式,无需 CPU 频繁干预。
这次用通用定时器进行delay函数的编写
该定时器的计数器Timer Counter 32-bit是往上加的,当计数器的值等于Timer Output Reg1 32-bit/Timer Output Reg 2 32-bit/Timer Output Reg3 32-bit这三个时,其对应的GPT_COMPARE的引脚便会发生变化(电平如何变化自己设置)。
进行寄存器的配置

1、GPT Control Register (GPTx_CR)
GPTx_CR 是 GPT 定时器的核心控制寄存器,用于全局启停、模式选择、时钟源配置、中断控制及功能使能,是 GPT 初始化和运行控制的关键入口。
本次由于只是当成计数器使用,CR寄存器IM/OM这些关于捕获的都不使用,此次仅配置FRR,选择free-run模式,CLCKSRC选择外设时钟(66M),ENMODE定时器失能后保留原来的值,以及EN使能寄存器
2、GPT Prescaler Register (GPTx_PR)
GPTx_PR 是 12 位可读可写寄存器,用于配置 GPT 定时器的预分频系数,对输入时钟源进行分频,从而得到驱动 32 位计数器的最终计数时钟。
本次将其配置为66分频
cpp
void gpt1_init(void)
{
gpt1_reset();
unsigned int tmp = GPT1->CR;
tmp &= ~(0x1ff<<20);
tmp &= ~(0xf << 16);
tmp |= (1 << 9);
tmp &= ~(0x7 << 6);
tmp |= (1 << 6);
tmp &= ~(1 << 1);
GPT1->CR = tmp;
tmp = GPT1->PR;
tmp &= ~(0xfff << 0);
tmp |= (65 << 0);
GPT1->PR = tmp;
GPT1->CR |= (1 << 0);
}
编写延时函数
GPTx_CNT 是 GPT 定时器的32 位只读计数寄存器,专门用于实时存放计数器当前的计数值;定时器使能后,它会在分频后的时钟驱动下持续递增计数,自由运行模式下计满溢出后自动从 0 重新开始,输入捕获触发时硬件会自动将该寄存器的值锁存到输入捕获寄存器,输出比较则实时将它与比较寄存器的值进行比对,匹配后触发对应动作,读取该寄存器可直接获取当前计时数值。

GPT1->CNT 就是一个一直在自己数数的计数器
刚进函数 → 记起点(old)
过一会儿 → 看现在(cur)
现在 - 起点 = 过去了多少时间
把过去的时间累加起来
累加到你要的数值 → 延时结束
处理溢出
定时器会从很大的数突然变回 0,所以你要补上一圈的长度,让差值正确
cpp
void inline delay_us(unsigned int num)
{
unsigned int counter = 0;
unsigned int old_counter = GPT1->CNT;
unsigned int cur_counter = 0;
while(1)
{
cur_counter = GPT1->CNT;
if(cur_counter == old_counter)
continue;
if(cur_counter > old_counter)
counter += cur_counter - old_counter;
else if(cur_counter < old_counter)
counter += cur_counter + 0xffffffff - old_counter;
if(counter >= num)
return;
old_counter = cur_counter;
}
}
void delay_ms(unsigned int num)
{
while(num--)
{
delay_us(1000);
}
}