STM32的串口FIFO发送和接收使用FreeRTOS实时操作系统

文章介绍了如何使用FreeRTOS和STM32开发一个包含发送和接收功能的串口程序,通过FIFO机制管理数据,并展示了中断处理和队列操作的实现。

以下是一个带有串口接收中断的使用FreeRTOS和STM32的串口FIFO发送和接收程序的示例代码,包含了每个功能函数的详细实现:

#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#define UART_TX_BUFFER_SIZE 128
#define UART_RX_BUFFER_SIZE 128

// 串口发送和接收的队列句柄
QueueHandle_t xTxQueue;
QueueHandle_t xRxQueue;

// 串口发送任务的函数
void vUartTxTask(void *pvParameters)
{
    uint8_t txData;
    
    while (1)
    {
        // 从发送队列中接收数据
        if (xQueueReceive(xTxQueue, &txData, portMAX_DELAY) == pdTRUE)
        {
            // 发送数据
            USART_SendData(USART1, txData);
            
            // 等待发送完成
            while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        }
    }
}

// 串口接收任务的函数
void vUartRxTask(void *pvParameters)
{
    uint8_t rxData;
    
    while (1)
    {
        // 接收数据
        if (xQueueReceive(xRxQueue, &rxData, portMAX_DELAY) == pdTRUE)
        {
            // 处理接收到的数据
            // 在这里可以执行相应的操作,比如将数据发送到其他任务
            
            // 示例:打印接收到的数据
            printf("Received data: %c\n", rxData);
        }
    }
}

// 初始化串口
void UART_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    // 使能串口和GPIO的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置UART引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // TX引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // RX引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置USART参数
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    
    // 使能串口接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    
    // 配置串口中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // 使能串口
    USART_Cmd(USART1, ENABLE);
}

// 初始化串口发送和接收的队列
void UART_QueueInit(void)
{
    xTxQueue = xQueueCreate(UART_TX_BUFFER_SIZE, sizeof(uint8_t));
    xRxQueue = xQueueCreate(UART_RX_BUFFER_SIZE, sizeof(uint8_t));
}

// 从串口发送一个字节
void UART_SendByte(uint8_t data)
{
    // 发送数据到发送队列
    if (xQueueSendToBack(xTxQueue, &data, 0) != pdTRUE)
    {
        // 发送队列已满,处理溢出错误
    }
}

// 串口接收中断处理函数
void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        // 读取接收到的数据
        uint8_t rxData = USART_ReceiveData(USART1);
        
        // 将接收到的数据发送到接收队列中
        if (xQueueSendToBackFromISR(xRxQueue, &rxData, NULL) != pdTRUE)
        {
            // 接收队列已满,处理溢出错误
        }
        
        // 清除接收中断标志位
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
}

int main(void)
{
    // 初始化硬件和FreeRTOS内核
    
    // 初始化串口
    UART_Init();
    
    // 初始化串口发送和接收的队列
    UART_QueueInit();
    
    // 创建串口发送任务
    xTaskCreate(vUartTxTask, "UART_TX", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
    
    // 创建串口接收任务
    xTaskCreate(vUartRxTask, "UART_RX", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
  
// 在main函数中,我们首先初始化了硬件和FreeRTOS内核,然后调用UART_Init函数初始化串口,接着调用UART_QueueInit函数初始化串口发送和接收的队列。

接下来,我们创建了串口发送任务(vUartTxTask)和串口接收任务(vUartRxTask)。

在UART_SendByte函数中,我们将要发送的数据发送到发送队列中。如果发送队列已满,则可能会发生溢出错误。

在UART_ReceiveByte函数中,我们从接收队列中接收数据。如果接收队列为空,则可能会发生错误。

在USART1_IRQHandler函数中,我们处理串口接收中断。当接收到数据时,我们将数据发送到接收队列中。如果接收队列已满,则可能会发生溢出错误。

以上是一个带有串口接收中断的串口FIFO发送和接收程序的示例代码。您可以根据自己的需求进行修改和扩展。请注意,该示例中的错误处理部分需要根据具体的应用场景进行适当的修改。

### STM32 FreeRTOS 实现串口通信的收发功能 #### 1. 工程配置 为了在STM32使用FreeRTOS实现串口通信,首先需要完成基本的硬件软件环境搭建。通过CubeMX工具生成基础代码框架,并确保FreeRTOS库已正确集成到项目中[^1]。 - **CubeMX配置**: 在STM32CubeMX中选择目标芯片(如STM32F103ZET6),启用USART外设并设置波特率、数据位、停止位以及校验模式等参数。同时,在中间件选项中勾选FreeRTOS支持。 - **FreeRTOS任务管理**: 创建两个独立的任务分别用于处理串口发送接收逻辑。这有助于提高系统的实时性可维护性[^3]。 #### 2. UART初始化与DMA配置 对于高效的串口通信,推荐使用DMA方式进行数据传输以减轻CPU负担。以下是UART初始化的关键步骤: ```c // USART DMA Initialization Code Example void MX_USARTx_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; // 设置波特率为115200bps huart1.Init.WordLength = UART_WORDLENGTH_8B; // 数据长度为8位 huart1.Init.StopBits = UART_STOPBITS_1; // 停止位数为1 huart1.Init.Parity = UART_PARITY_NONE; // 无奇偶校验 huart1.Init.Mode = UART_MODE_TX_RX; // 启用TX/RX模式 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 不使用硬件流控制 HAL_UART_MspInit(&huart1); // 初始化GPIO及相关资源 __HAL_UART_ENABLE_DMA(&huart1, UART_DMAReq_Rx); } ``` 上述代码片段展示了如何利用HAL库来初始化USART模块,并启用了RX方向上的DMA请求[^2]。 #### 3. 接收线程设计 创建一个专门负责读取来自PC端命令或其他设备消息的任务。此任务会周期性地检查是否有新到达的数据包等待处理。 ```c #include "FreeRTOS.h" #include "task.h" #define RX_BUFFER_SIZE 256 uint8_t rxBuffer[RX_BUFFER_SIZE]; QueueHandle_t xRxQueue; void vUARTRxTask(void *pvParameters){ uint8_t chData; while (1){ if(xQueueReceive(xRxQueue,&chData,portMAX_DELAY)){ /* Process received character here */ printf("Received Char:%c\n",chData); } } } BaseType_t xStartUARTRxTask(){ static QueueHandle_t xCreatedQueue; BaseType_t xReturn; xCreatedQueue=xQueueCreate(RX_BUFFER_SIZE,sizeof(uint8_t)); if(NULL != xCreatedQueue){ xTaskCreate(vUARTRxTask,"rx_task",configMINIMAL_STACK_SIZE,NULL,tskIDLE_PRIORITY+1,NULL); xReturn=pdPASS; }else{ xReturn=errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; } return xReturn; } ``` 这里定义了一个名为`vUARTRxTask()`的任务函数,它不断地尝试从队列中获取字符直到超时为止[^4]。 #### 4. 发送线程设计 同样也需要构建另一个用来向外部写入信息或者回应查询结果的任务实例。 ```c void vUARTTxTask(void *pvParameters){ const TickType_t xDelay = pdMS_TO_TICKS(1000UL); while(true){ char str[]="Hello from STM32!\r\n"; HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),HAL_MAX_DELAY); vTaskDelay(xDelay); } } ``` 该示例中的`vUARTTxTask()`每秒钟都会通过串口打印一次问候语句。 --- ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

章鱼哥嵌入式开发

坚持不易,你们的鼓励是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值