有网站的源代码怎么生成网站,邢台哪里可以做网站,长沙今天最新招聘信息,网站建设需要什么呢软件定时器允许设置一段时间#xff0c;当设置的时间达到后就执行指定的功能函数#xff0c;被软件定时器调用的功能函数叫做定时器的回调函数。软件定时器的回调函数是在定时器服务任务中执行的#xff0c;所以一定不能在回调函数中调用任何阻塞任务的API函数#xff0c;比…软件定时器允许设置一段时间当设置的时间达到后就执行指定的功能函数被软件定时器调用的功能函数叫做定时器的回调函数。软件定时器的回调函数是在定时器服务任务中执行的所以一定不能在回调函数中调用任何阻塞任务的API函数比如VTaskDelay。 软件定时器分为两种单次定时器和周期定时器单次定时器就执行一次然后停止运行不能自动重启但我们可以手动重新启动周期定时器就是执行完回调函数以后自动的重新启动这样回调函数就会周期性的执行。
0x01 定时器相关配置
定时器的配置在FreeRTOSConfig.h中 configUSE_TIMES 如果要使用软件定时器configUSE_TIMES要设置为1。 configTIMER_TASK_PRIORITY 设置软件定时器服务任务的任务优先级 configTIMER_QUEUE_LENGTH 设置定时器命令队列的队列长度 configTIMER_TASK_STACK_DEPTH 设置定时器任务的任务堆栈大小单位为字对于STM32来说一个字是4字节
0x02 创建定时器
使用软件定时器首先要创建创建定时器分为动态和静态两种创建方法。
xTimerCreate()使用动态方法创建软件定时器xTimerCreateStatic()使用静态方法创建软件定时器 TimerHandle_t xTimerCreate( const char * const pcTimerName,const TickType_t xTimerPeriodInTicks,const UBaseType_t uxAutoReload,void * const pvTimerID,TimerCallbackFunction_t pxCallbackFunction ) const char * const pcTimerName软件定时器名字const TickType_t xTimerPeriodInTicks软件定时器的定时周期单位是时钟节拍数可以借助portTICK_PERIOD_MS将ms单位转换为时钟节拍数比如定时器的周期为100个时钟节拍的话那么xTimerPeriodInTicks100当定时器周期为500ms的时候xTimerPeriodInTicks 500/portTICK_PERIOD_MSconst UBaseType_t uxAutoReload设置定时器模式但是定时器还是周期定时器当uxAutoReloadpdTRUE的时候创建的是周期定时器uxAutoReloadpdFALSE是单次定时器。void * const pvTimerID定时器ID号。TimerCallbackFunction_t pxCallbackFunction 定时器回调函数当定时器周期到了以后就会调用这个函数。 TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,const TickType_t xTimerPeriodInTicks,const UBaseType_t uxAutoReload,void * const pvTimerID,TimerCallbackFunction_t pxCallbackFunction,StaticTimer_t *pxTimerBuffer )const char * const pcTimerName软件定时器名字const TickType_t xTimerPeriodInTicks软件定时器的定时周期单位是时钟节拍数可以借助portTICK_PERIOD_MS将ms单位转换为时钟节拍数比如定时器的周期为100个时钟节拍的话那么xTimerPeriodInTicks100当定时器周期为500ms的时候xTimerPeriodInTicks 500/portTICK_PERIOD_MSconst UBaseType_t uxAutoReload设置定时器模式但是定时器还是周期定时器当uxAutoReloadpdTRUE的时候创建的是周期定时器uxAutoReloadpdFALSE是单次定时器。void * const pvTimerID定时器ID号。TimerCallbackFunction_t pxCallbackFunction 定时器回调函数当定时器周期到了以后就会调用这个函数。StaticTimer_t *pxTimerBuffer参数指向一个StaticTimer_t类型的变量用来保存定时器结构体
0x03 开启软件定时器
如果软件定时器停止运行的话可以使用FreeRTOS提供的两个开启函数来重新启动软件定时器
xTimerStart()开启软件定时器用于任务中xTimerStartFromISR()开启软件定时器用于中断中
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait )TimerHandle_t xTimer要开启的软件定时器的句柄TickType_t xTicksToWait 设置阻塞时间
BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );TimerHandle_t xTimer开启的软件定时器的句柄BaseType_t *pxHigherPriorityTaskWoken 标记退出此函数以后是否进行任务切换这个变量的值函数会自动设置的用户不用进行设置当此值为pdTURE的时候在退出中断服务函数之前一定要进行一次任务切换。
0x04 复位软件定时器
复位一个软件定时器会重新计算定时周期达到的时间点这个新的时间点是相对于复位定时器的那个时刻开始的比如说我们有个timer1单次定时器定时周期是5s从0s到5s如果没有干预的话timer1在5s会停止运行如果我们在3s时刻进行复位则timer1会从3s开始中间如果没有干预的话会到8s停止运行有复位的话会从复位时刻继续运行5s。复位相关函数如下
xTimerReset复位软件定时器用在任务中xTimerResetFromISR复位软件定时器用在中断服务函数中
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait )TimerHandle_t xTimer要复位的软件定时器句柄TickType_t xTicksToWait设置阻塞时间
BaseType_t xTimerResetFromISR( TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );TimerHandle_t xTimer要复位的软件定时器句柄BaseType_t *pxHigherPriorityTaskWoken设置退出此函数是否进行任务切换
0x05 停止软件定时器
停止软件定时器相关中断如下
xTimerStop()停止软件定时器用于任务中xTimerStopFromISR()停止软件定时器用在中断服务函数中
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait )TimerHandle_t xTimer要停止的软件定时器句柄TickType_t xTicksToWait设置阻塞时间
BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken )TimerHandle_t xTimer要停止的软件定时器句柄BaseType_t *pxHigherPriorityTaskWoken 标志退出此函数是否要进行任务切换
实验
设计两个任务
start_task用来创建timercontrol_task和两个软件定时器这两个定时器分别为周期定时器和单次定时器定时周期一个为1s另一个为2stimercontrol_task控制两个软件定时器的开启和停止
main函数中创建start_task任务
int main(void)
{HAL_Init(); //初始化HAL库 Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhzdelay_init(180); //初始化延时函数uart_init(115200); //初始化串口LED_Init(); //初始化LED KEY_Init(); //初始化按键BEEP_Init(); //初始化蜂鸣器SDRAM_Init(); //初始化SDRAMLCD_Init(); //初始化LCDmy_mem_init(SRAMIN); //初始化内部内存池POINT_COLOR RED;LCD_ShowString(30,10,200,16,16,Apollo STM32F4/F7); LCD_ShowString(30,30,200,16,16,FreeRTOS Examp 15-1);LCD_ShowString(30,50,200,16,16,KEY_UP:Start Tmr1);LCD_ShowString(30,70,200,16,16,KEY0:Start Tmr2);LCD_ShowString(30,90,200,16,16,KEY1:Stop Tmr1 and Tmr2);LCD_DrawLine(0,108,239,108); //画线LCD_DrawLine(119,108,119,319); //画线POINT_COLOR BLACK;LCD_DrawRectangle(5,110,115,314); //画一个矩形 LCD_DrawLine(5,130,115,130); //画线LCD_DrawRectangle(125,110,234,314); //画一个矩形 LCD_DrawLine(125,130,234,130); //画线POINT_COLOR BLUE;LCD_ShowString(6,111,110,16,16, AutoTim:000);LCD_ShowString(126,111,110,16,16,OneTim: 000);//创建开始任务xTaskCreate(start_task,start_task,256,NULL,1,StartTask_Handler);//启动任务调度器vTaskStartScheduler();
}start_task来创建timercontrol_task和两个软件定时器
void start_task(void *pvParameters)
{taskENTER_CRITICAL();//创建软件周期定时器周期定时器周期为1s1000个时钟节拍AutoReloadTimer_HandlerxTimerCreate(AutoReloadTimer,1000,pdTRUE,(void *)1,AutoReloadCallback);//创建单词定时器OneShotTimer_Handler xTimerCreate(OneShotTimer,2000,pdFALSE,(void*)2,OneShotCallback);xTaskCreate(timercontrol_task,timercontrol_task,256,NULL,2,TimerControlTask_Handler);taskEXIT_CRITICAL();vTaskDelete(StartTask_Handler);
}AutoReloadCallback和OneShotCallback是两个定时器的回调函数内容为
void AutoReloadCallback(TimerHandle_t xTYimer)
{static u8 tmr1_num0;tmr1_num;LCD_ShowxNum(70,111,tmr1_num,3,16,0x80); //显示执行次数LCD_Fill(6,131,114,313,lcd_discolor[tmr1_num%14]);
}
void OneShotCallback(TimerHandle_t xTYimer)
{static u8 tmr2_num 0;tmr2_num;LCD_ShowxNum(190,111,tmr2_num,3,16,0x80);LCD_Fill(126,131,233,313,lcd_discolor[tmr2_num%14]);LED1 !LED1;printf(定时器2运行结束\r\n);
}timercontrol_task内容
void timercontrol_task(void *pvParameter)
{u8 key,num;while(1){if((AutoReloadTimer_Handler!NULL)(OneShotTimer_Handler!NULL)){key KEY_Scan(0);switch(key){case WKUP_PRES:xTimerStart(AutoReloadTimer_Handler,0);printf(开启定时器1\r\n);break;case KEY0_PRES:xTimerStart(OneShotTimer_Handler,0);printf(开始定时器2\r\n);break;case KEY1_PRES:xTimerStop(AutoReloadTimer_Handler,0);xTimerStop(OneShotTimer_Handler,0);printf(关闭定时器1和2\r\n);break;}}num;if(num50){num 0;LED0 !LED0;}vTaskDelay(10);//延时10ms}
}
start_task只是创建了定时器并没有开启在timercontrol_task中如果按下KEY_UP按键就会开启AutoReloadTimer_Handler定时器按下KEY0就会启动OneShotTimer_Handler定时器按下KEY1停止两个定时器
串口输出内容