本帖最后由 wangjj19950516 于 2021-1-28 09:48 编辑
定时器是非常常用的一个模块,一般用于定时,设定好需要的时间后,当计数器达到设定值后就会产生中断,在中断函数中将时间标志置位。一般用这种方式做主函数的定时循环处理。 但有些产品或应用,为了保证运行的可靠性,要尽可能的减少中断数目,因为中断会打断正在处理的操作,可能会导致数据丢失或错误。中断数目越大,发生错误的概率就越大。因此,为了减少中断数目,这里介绍一种定时器查询方式实现定时循环。
硬件:AC7801开发板
软件:keil 5.23
功能:查询定时器实现1ms定时
1.AC7801系统默认时钟为48M,若需要配置时钟为其他频率可以参考以下代码:
void CLOCK_Config (void)
{
SPM_XOSCOKBypassSet(DISABLE);
SPM->PWR_MGR_CFG1 |= 1<<29;//外部高速时钟使能
while((SPM->PWR_MGR_CFG1 &(0X80000000))==0)//等待XOSC时钟就绪
{}
SPM->PWR_MGR_CFG1 |= (1<<27);//SYSPLL使能
while((SPM->PWR_MGR_CFG1 &(0X40000000))==0)//等待PLL时钟就绪
{}
CKGEN->CTRL |= (1<<20);//PLL参考时钟选择外部振荡器
/*
PLLCLOCK = HSE*FBKDIV/(POSDIV*2)/PREDIV = 8*96/16=48M
SYSCLOCK = PLLCLOCK/SYSCLK_DIV = 48/1 = 48M
*/
CKGEN->SYSPLL1_CFG0 = ((CKGEN->SYSPLL1_CFG0 & (~(uint32_t)(0x3<<30)))|(0<<30)); //PREDIV
CKGEN->SYSPLL1_CFG0 = ((CKGEN->SYSPLL1_CFG0 & (~(uint32_t)(0x1f<<25)))|(8<<25)); //POSDIV
CKGEN->SYSPLL1_CFG0 = ((CKGEN->SYSPLL1_CFG0 & (~(uint32_t)(0xff<<15)))|(96<<15)); //FBKDIV
CKGEN->CTRL |= ((CKGEN->CTRL & (~(3<<4)))|(0<<4)); //SYSCLK_DIV=1
CKGEN->CTRL |= (1<<0);//系统时钟源选择
CKGEN->CTRL = ((CKGEN->CTRL & (~(uint32_t)(0x3<<8)))|(1<<8)); //APB分频系数
}
2.定时器配置
配置TIMER0,装载值为最大0XFFFFFFFF,不使能中断。
void Timer0_Config(void)
{
TIMER_ConfigType timerConfig = {0};
memset(&timerConfig, 0, sizeof(timerConfig));
timerConfig.periodValue = 0xffffffff;
timerConfig.interruptEn = DISABLE;
timerConfig.linkModeEn = DISABLE;
timerConfig.timerEn = ENABLE;
TIMER_Init(TIMER_CHANNEL0, &timerConfig);
}
3.定义宏定义操作#define TIMER_VALUE (TIMER_CHANNEL0->CVAL)
读取定时器的计数值
4.main()函数处理
在main()函数中,读取到定时器的计数值,因为定时器时钟为48/2=24M,所以定时器的一个计数值对应的时间为1/24us,要定时1ms,则需要计24000个数。但需要注意的是,AC7801的定时器是向下计数的,即从0XFFFFFFFF向下递减直至0。实际计数值为上次读到的计数值减去当前读到的计数值,当两次的差值大于24000,则认为1ms时间到,可执行相应的操作。这里是翻转IO口,同时需要将上次读到的计数值更新,减去24000.
int main(void)
{
CLOCK_Config();
Timer0_Config();
//配置PC9为输出
GPIO_SetFunc(GPIOC,GPIO_PIN9, 0);
GPIO_SetDir(GPIOC,GPIO_PIN9, 1);
GPIO_SetPinLevel(GPIOC, GPIO_PIN9, GPIO_LEVEL_LOW);
Base_time = TIMER_VALUE;
while(1)
{
Data_time = Base_time - TIMER_VALUE;
if (Data_time >= 24000)
{
GPIOC->ODR ^= 1<<9;
Base_time -= 24000;
}
}
}
通过测量PC9端口波形,确实为1ms翻转一次,功能正确。
附上调试代码
timer.rar
(1.66 MB)
|