【WCH蓝牙系列芯片】-基于CH585开发板—系统 SysTick 定时器应用
------------------------------------------------------------------------------------------------------------------------------------
CH592的嘀嗒定时器是内核自带的64位计数器。

设置好嘀嗒时间后,计数满会进入到中断并需要手动清除标志
SysTick中断触发程序
#include "CH58x_common.h" volatile uint32_t systick_irq_count = 0; /********************************************************************** @fn DebugInit* @brief 调试初始化* @return none*/ void DebugInit(void) {GPIOA_SetBits(GPIO_Pin_14);GPIOPinRemap(ENABLE, RB_PIN_UART0);GPIOA_ModeCfg(GPIO_Pin_15, GPIO_ModeIN_PU);GPIOA_ModeCfg(GPIO_Pin_14, GPIO_ModeOut_PP_5mA);UART0_DefInit(); } /********************************************************************** @fn main* @brief 主函数* @return none*/ int main() {HSECFG_Capacitance(HSECap_18p);SetSysClock(SYSCLK_FREQ);/* 配置串口调试 */DebugInit();PRINT("Start @ChipID=%02X\n", R8_CHIP_ID);printf("\r\n============================================\r\n");printf(" Build Date: %s\r\n", __DATE__);printf(" Build Time: %s\r\n", __TIME__);printf("============================================\r\n");SysTick_Config(FREQ_SYS*10); //设置为FREQ_SYS/1000,则1ms进入一次中断。这个地方设置10秒while(1){PRINT("SYS_GetSysTickCnt = %d\r\n", SYS_GetSysTickCnt()); //获取计数时间,计数满会进入中断并清0。mDelaymS(200);} } __INTERRUPT __HIGH_CODE /*嘀嗒定时器中断函数*/ void SysTick_Handler() {systick_irq_count++;PRINT("\r\n---------------------------------------\r\n");PRINT("[SysTick IRQ] count = %d\r\n", systick_irq_count);PRINT("---------------------------------------\r\n\r\n");SysTick->SR = 0; //清除中断标志 }

为了功能验证测试,在systick中断加了打印,来观察systick计数值满了之后,进入中断后,清除中断标志位。CPU 正在执行主循环(while(1)),当 10 秒时间到达时,硬件强制打断了主循环,跳到了 SysTick_Handler() 中执行打印,将systick_irq_count+1,并且将数值打印出来,执行完清理标志位后,又回到了主循环继续干活,观察打印的数据之后,基本是在运行10秒左右就会进入systick中断。
可以利用 SysTick 计数来测量程序的运行时间,作为调试程序的方式。
在蓝牙从机中建立一个用于ADC+DMA采集的任务事件,用TMOS任务1秒执行一次这个任务事件,通过记录SysTick计数值来计算出ADC+DMA运行一次所需要的时间大概在多少。
先在主函数中,注册一个新的TMOS的任务函数,设定一个任务时间,启动1秒的SBP_ADC_DMA_TEST_EVT的任务事件

在TMOS任务处理函数中,调用ADC_DMA_TEST()启动ADC的DMA采集,并且打印出计数值计算出的时间参数。
/* TMOS 定时任务处理函数:每1000ms执行一次 */ uint16_t TEST_ProcessEventtt(uint8_t task_id, uint16_t events) {if(events&SBP_ADC_DMA_TEST_EVT){// 打印出总耗时PRINT("--> Task execution time: %d us\r\n\r\n", time_us);ADC_DMA_TEST(); // 启动新一轮的ADC DMA采集,通道3tmos_start_task(ttTaskId, SBP_ADC_DMA_TEST_EVT, 1600);return events ^ SBP_ADC_DMA_TEST_EVT;} }
在ADC_DMA_TEST函数中,对ADC引脚进行初始化后,直接通过 t_start = SysTick->CNT;记录ADC开始的SysTick的值


当ADC测量完后,DMA数据搬运结束之后,调用 stop_ADC()停止ADC采集,在调用t_end = SYS_GetSysTickCnt();记录任务结束时的 SysTick 计数值。t_diff = t_end - t_start; 然后将开启记录的数据和结束记录的数据相减,将用time_us = t_diff / (FREQ_SYS / 1000000);计算出本次ADC采集所需要的时间

最后在TMOS任务事件中,将计算出来的时间

通过打印可以看到差不多运行ADC+DMA的采集之后,差不多在651uS左右。

除此之后,还可以利用定时器计数的方式来计算出程序运行的时间参数,


