[学习笔记] AC7801定时器实现查询定时

[复制链接]
 楼主| wangjj19950516 发表于 2021-1-27 20:33 | 显示全部楼层 |阅读模式
本帖最后由 wangjj19950516 于 2021-1-28 09:48 编辑

      定时器是非常常用的一个模块,一般用于定时,设定好需要的时间后,当计数器达到设定值后就会产生中断,在中断函数中将时间标志置位。一般用这种方式做主函数的定时循环处理。           但有些产品或应用,为了保证运行的可靠性,要尽可能的减少中断数目,因为中断会打断正在处理的操作,可能会导致数据丢失或错误。中断数目越大,发生错误的概率就越大。因此,为了减少中断数目,这里介绍一种定时器查询方式实现定时循环。
硬件:AC7801开发板
软件:keil 5.23
功能:查询定时器实现1ms定时

1.AC7801系统默认时钟为48M,若需要配置时钟为其他频率可以参考以下代码:
  1. void CLOCK_Config (void)
  2. {        
  3.         SPM_XOSCOKBypassSet(DISABLE);
  4.         SPM->PWR_MGR_CFG1 |= 1<<29;//外部高速时钟使能
  5.         while((SPM->PWR_MGR_CFG1 &(0X80000000))==0)//等待XOSC时钟就绪
  6.         {}
  7.   
  8.         SPM->PWR_MGR_CFG1 |= (1<<27);//SYSPLL使能
  9.         while((SPM->PWR_MGR_CFG1 &(0X40000000))==0)//等待PLL时钟就绪
  10.         {}
  11.         CKGEN->CTRL |= (1<<20);//PLL参考时钟选择外部振荡器
  12.                
  13.   /*
  14.                 PLLCLOCK = HSE*FBKDIV/(POSDIV*2)/PREDIV = 8*96/16=48M
  15.                 SYSCLOCK = PLLCLOCK/SYSCLK_DIV = 48/1 = 48M
  16.         */
  17.         CKGEN->SYSPLL1_CFG0 = ((CKGEN->SYSPLL1_CFG0 & (~(uint32_t)(0x3<<30)))|(0<<30));          //PREDIV
  18.         CKGEN->SYSPLL1_CFG0 = ((CKGEN->SYSPLL1_CFG0 & (~(uint32_t)(0x1f<<25)))|(8<<25));        //POSDIV
  19.         CKGEN->SYSPLL1_CFG0 = ((CKGEN->SYSPLL1_CFG0 & (~(uint32_t)(0xff<<15)))|(96<<15));        //FBKDIV
  20.                
  21.   CKGEN->CTRL |= ((CKGEN->CTRL & (~(3<<4)))|(0<<4));        //SYSCLK_DIV=1
  22.         CKGEN->CTRL |= (1<<0);//系统时钟源选择
  23.         CKGEN->CTRL = ((CKGEN->CTRL & (~(uint32_t)(0x3<<8)))|(1<<8));        //APB分频系数
  24. }
2.定时器配置
  配置TIMER0,装载值为最大0XFFFFFFFF,不使能中断
  1. void Timer0_Config(void)
  2. {
  3.     TIMER_ConfigType timerConfig = {0};
  4.     memset(&timerConfig, 0, sizeof(timerConfig));
  5.     timerConfig.periodValue = 0xffffffff;
  6.     timerConfig.interruptEn = DISABLE;
  7.     timerConfig.linkModeEn = DISABLE;
  8.     timerConfig.timerEn = ENABLE;
  9.     TIMER_Init(TIMER_CHANNEL0, &timerConfig);
  10. }
3.定义宏定义操作#define TIMER_VALUE (TIMER_CHANNEL0->CVAL)
  读取定时器的计数值
4.main()函数处理
   在main()函数中,读取到定时器的计数值,因为定时器时钟为48/2=24M,所以定时器的一个计数值对应的时间为1/24us,要定时1ms,则需要计24000个数。但需要注意的是,AC7801的定时器是向下计数的,即从0XFFFFFFFF向下递减直至0。实际计数值为上次读到的计数值减去当前读到的计数值,当两次的差值大于24000,则认为1ms时间到,可执行相应的操作。这里是翻转IO口,同时需要将上次读到的计数值更新,减去24000.
  1. int main(void)
  2. {
  3.         CLOCK_Config();
  4.         Timer0_Config();
  5.         //配置PC9为输出
  6.         GPIO_SetFunc(GPIOC,GPIO_PIN9, 0);
  7.         GPIO_SetDir(GPIOC,GPIO_PIN9, 1);
  8.         GPIO_SetPinLevel(GPIOC, GPIO_PIN9, GPIO_LEVEL_LOW);
  9.        
  10.         Base_time = TIMER_VALUE;
  11.         while(1)
  12.         {
  13.                  Data_time = Base_time - TIMER_VALUE;
  14.                                 if (Data_time >= 24000)
  15.                                 {               
  16.                                                 GPIOC->ODR ^= 1<<9;                               
  17.                                                 Base_time -= 24000;
  18.                                 }       
  19.         }       
  20. }

通过测量PC9端口波形,确实为1ms翻转一次,功能正确。

附上调试代码 timer.rar (1.66 MB, 下载次数: 62)





ayb_ice 发表于 2022-11-8 13:59 | 显示全部楼层
这个方法是可行的,而且效率高
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

86

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部

24

主题

86

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部