STM32F103VET6基于Arduino开发框架下FreeRTOS串口1不能正常工作解决方案
✨通过搜索发现这个bug存在了这么多年了,在百度经验《STM32F103+FreeRTOS串口模块不能正常工作》就记录了
STM32F10x
外设固件库v3.5 + FreeRTOS v7.0.2存在这个问题,没想到今天在Arduino框架下还是遇到了同样的一个问题。
🛠解决方案
🔨1. 不能使用串口1作为调试信息输出。
🍁像STM32F103VET6芯片有4个串口,在Arduino框架下,可以根据使用情况调整到其他串口上。
HardwareSerial Serial1(PC11,PC10);
HardwareSerial Serial3(PA3,PA2);
HardwareSerial Serial4 (PC11, PC10);
......
HardwareSerial Serial10 (PC11, PC10);
✅串口和引脚号可以任意指定,只要不使用
Serial
,可以使用Serial1 - Serial10
.
🔧2. 不使用基于FreeRTOS提供的延时函数。
可以使用
delay()
来替代vTaskDelay((200L * configTICK_RATE_HZ);//200ms
延时函数。
🔑经测试,以上两种方法都可行。
FreeRTOS依赖库
STM32FreeRTOS
:- 在IDE里面打开管理库(Ctrl + Shift + I)页面搜索FreeRTOS
关键字
🌼示例代码
#include <STM32FreeRTOS.h>//点击这里会自动打开管理库页面: http://librarymanager/All#FreeRTOS
HardwareSerial Serial3(USART3);
// Define the LED pin is attached
const uint8_t LED_PIN = PE5;
extern "C" void SystemClock_Config(void){
RCC_OscInitTypeDef RCC_OscInitStruct = {};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {};//新增内容
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();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
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();
}
}
// Declare a semaphore handle.
SemaphoreHandle_t sem;
//------------------------------------------------------------------------------
/*
* Thread 1, turn the LED off when signalled by thread 2.
*/
// Declare the thread function for thread 1.
static void Thread1(void* arg) {
UNUSED(arg);
pinMode(PB5, OUTPUT);
while (1) {
digitalToggle(PB5);
Serial3.println("PB5 LED TURN Toggle");
vTaskDelay((200L * configTICK_RATE_HZ) / 1000L);//200ms
// delay(500);
// Wait for signal from thread 2.
xSemaphoreTake(sem, portMAX_DELAY);
// Turn LED off.
// digitalWrite(LED_PIN, LOW);
}
}
//------------------------------------------------------------------------------
/*
* Thread 2, turn the LED on and signal thread 1 to turn the LED off.
*/
// Declare the thread function for thread 2.
static void Thread2(void* arg) {
UNUSED(arg);
pinMode(LED_PIN, OUTPUT);
while (1) {
// Turn LED on.
// digitalWrite(LED_PIN, HIGH);
digitalToggle(LED_PIN);
// delay(500);
// Sleep for 200 milliseconds.
vTaskDelay((200L * configTICK_RATE_HZ) / 1000L);
Serial3.println("PE5 LED TURN Toggle");
// Signal thread 1 to turn LED off.
xSemaphoreGive(sem);
// Sleep for 200 milliseconds.
// vTaskDelay((200L * configTICK_RATE_HZ) / 1000L);
}
}
//------------------------------------------------------------------------------
void setup() {
portBASE_TYPE s1, s2;
Serial3.setRx(PC11); // using pin name PY_n
Serial3.setTx(PC10); // using pin number PYn
Serial3.begin(115200);
delay(3000);
Serial3.println("STM32F103VET6");
// initialize semaphore
sem = xSemaphoreCreateCounting(1, 0);
// create task at priority two
s1 = xTaskCreate(Thread1, NULL, configMINIMAL_STACK_SIZE, NULL, 2, NULL);
// create task at priority one
s2 = xTaskCreate(Thread2, NULL, configMINIMAL_STACK_SIZE, NULL, 1, NULL);
// check for creation errors
if (sem== NULL || s1 != pdPASS || s2 != pdPASS ) {
Serial3.println(F("Creation problem"));
while(1);
}
// start scheduler
vTaskStartScheduler();
Serial3.println("Insufficient RAM");
while(1);
}
//------------------------------------------------------------------------------
// WARNING idle loop has a very small stack (configMINIMAL_STACK_SIZE)
// loop must never block
void loop() {
// Not used.
}