打印
[学习笔记]

AC7801定时器实现查询定时

[复制链接]
2042|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wangjj19950516|  楼主 | 2021-1-27 20:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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)





使用特权

评论回复

相关帖子

沙发
ayb_ice| | 2022-11-8 13:59 | 只看该作者
这个方法是可行的,而且效率高

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

86

帖子

2

粉丝