提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
嘿嘿学习一下FreeRTOS低功耗模Tickless。
一、TIckless是什么?
二、API介绍
1.配置
打开Tickless宏
#ifndef configUSE_TICKLESS_IDLE
#define configUSE_TICKLESS_IDLE 1
#endif
下一步改代码
在FreeRTOS.h文件的第810行开始
#ifndef configPRE_SLEEP_PROCESSING
//#define configPRE_SLEEP_PROCESSING( x )
extern void PreSleepProcessing(uint32_t ulExpectedldleTime);
#define configPRE_SLEEP_PROCESSING PreSleepProcessing
#endif
#ifndef configPOST_SLEEP_PROCESSING
//#define configPOST_SLEEP_PROCESSING( x )
extern void PostSleepProcessing(uint32_t ulExpectedldleTime);
#define configPOST_SLEEP_PROCESSING PostSleepProcessing
#endif
然后主函数添加PreSleepProcessing和PostSleepProcessing的源文件
//进入低功耗模式执行任务
void PreSleepProcessing(uint32_t ulExpectedldleTime){
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOD_CLK_DISABLE();
__HAL_RCC_GPIOE_CLK_DISABLE();
}
//退出低功耗模式执行任务
void PostSleepProcessing(uint32_t ulExpectedldleTime){
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
}
这样低功耗就配置成功了
2.串口回调函数+NVIC
串口回调
usart.c
#include "usart.h"
UART_HandleTypeDef huart1;
uint8_t Rxbuff[64];
uint16_t Rx_Len;
uint8_t DateBuff[1];
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
HAL_NVIC_SetPriority(USART1_IRQn,4,3);
HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_UART_Receive_IT(&huart1,(uint8_t*)&DateBuff,1);
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
}
}
void USART1_IRQHandler (void) {
HAL_UART_IRQHandler(&huart1);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if(huart->Instance==USART1){
if(DateBuff[0]=='\n'){
Rxbuff[Rx_Len]='\n';
Rx_Len=0;
//HAL_UART_Transmit(&huart1,(uint8_t*)&Rxbuff,strlen(Rxbuff) * sizeof(char),HAL_MAX_DELAY);
}else{
Rxbuff[Rx_Len]=DateBuff[0];
Rx_Len++;
}
HAL_UART_Receive_IT(&huart1,(uint8_t *)&DateBuff,1);
}
}
3.案例
main.h
通过串口输入‘1’来控制任务2
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "Timers.h"
#include "event_groups.h"
#include "stdio.h"
#include "Key.h"
#ifdef __GNUC__ //printf重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t*)&ch,1,HAL_MAX_DELAY);
return ch;
}
TaskHandle_t HandlerTask1;
TaskHandle_t Task_Name4;
BaseType_t xReturn;
SemaphoreHandle_t Task1semaphore;
TimerHandle_t AutoTimerTask;
TimerHandle_t OneTimerTask;
SemaphoreHandle_t semaphoreTask;
void SystemClock_Config(void);
StackType_t xTask3Static[128];
StaticTask_t xTaskTCB;
StackType_t xIdle3Static[128];
StaticTask_t xIdleTCB;
StackType_t xTimerStatic[526];
StaticTask_t xTimerTCB;
//进入低功耗模式执行任务
void PreSleepProcessing(uint32_t ulExpectedldleTime){
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOD_CLK_DISABLE();
__HAL_RCC_GPIOE_CLK_DISABLE();
}
//退出低功耗模式执行任务
void PostSleepProcessing(uint32_t ulExpectedldleTime){
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
}
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize ){
*ppxIdleTaskTCBBuffer=&xIdleTCB;
*ppxIdleTaskStackBuffer=xIdle3Static;
*pulIdleTaskStackSize=128;
}
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
StackType_t ** ppxTimerTaskStackBuffer,
uint32_t * pulTimerTaskStackSize ){
* ppxTimerTaskTCBBuffer=&xTimerTCB;
* ppxTimerTaskStackBuffer=xTimerStatic;
* pulTimerTaskStackSize=526;
}
void Task1Function( void * param){
for(;;){
printf("TASK1..\r\n");
vTaskDelay(1000);
}
}
void Task2Function(void* param){
int num;
BaseType_t err;
for(;;)
{
xSemaphoreGive(semaphoreTask);
err=xSemaphoreTake(semaphoreTask,0);
num =atoi(Rxbuff);
//printf("NUM=%d\r\n",num);
if(num==1){
printf("NUM=%d\r\n",num);
vTaskDelay(1000);
}
vTaskDelay(10);
}
}
void Task3Funtion(void* param){
TickType_t st_time=xTaskGetTickCount();
while(1){
uint32_t num =1;
xTaskDelayUntil(&st_time,30);
}
}
void Task4Funtion(void* param){
taskENTER_CRITICAL();
//创建标志位
semaphoreTask=xSemaphoreCreateBinary();
//创建任务
xReturn=xTaskCreate(Task1Function,"Task1",128,NULL,2,&HandlerTask1);
xTaskCreate(Task2Function,"Task2",128,NULL,2,NULL);
xTaskCreateStatic(Task3Funtion,"Task3",128,NULL,2,xTask3Static,&xTaskTCB);
if(xReturn == pdPASS){
uint8_t buffS[20]="Task1 Create OK..\r\n";
HAL_UART_Transmit(&huart1,(uint8_t*)buffS,strlen(buffS)*sizeof(char),HAL_MAX_DELAY);
}
vTaskDelete(Task_Name4);
taskEXIT_CRITICAL();
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
xTaskCreate(Task4Funtion,"Task4",600,NULL,1,&Task_Name4);
vTaskStartScheduler();
while (1)
{
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */
总结
今天又是充足的一天
心在九天仙阙前,身在万丈红尘中 --《长生界》