STM32F105RCT6 上跑 FreeRTOS 操作系统,串口发送数据分析

1. STM32F105RCT6 单片机上跑FreeRTOS 操作系统,使用USART2 进行通信,TX 发送数据每个字节之间间隔1ms

在这里插入图片描述

2. 串口发送函数

void UsartSend(USART_TypeDef *USARTx, BYTE *pucSendData, WORD wDataLen)
{
    WORD wLoop = 0;
    
    for (wLoop = 0; wLoop < wDataLen; wLoop++)
    {
        USARTx->DR = pucSendData[wLoop];
        while (FALSE == (USARTx->SR & 0x40));
    }
}

3. 在发送数组未发送完之前把所有中断屏蔽掉,发送完之后再重新开中断

void UsartSend(USART_TypeDef *USARTx, BYTE *pucSendData, WORD wDataLen)
{
    WORD wLoop = 0;

    __disable_irq();  // disable system interrupt
    for (wLoop = 0; wLoop < wDataLen; wLoop++)
    {
        USARTx->DR = pucSendData[wLoop];
        while (FALSE == (USARTx->SR & 0x40));
    }
    __enable_irq(); // enable system interrupt
}

4. 屏蔽中断后效果明显改善了

在这里插入图片描述

5. 之前还试过加临界区,但是我串口2 这里一加临界区保护就会导致安卓屏无法开机

6. 串口1 (USART1)也有一样的问题,加临界区保护之后就好了,但是串口2 不能加临界区保护,具体原因就不分析了,没时间

7. 串口1 (USART1)加临界区保护

static void Usart1Send(USART_TypeDef *USARTx, BYTE *pucSendData, WORD wDataLen)
{
    WORD wLoop = 0;

    taskENTER_CRITICAL(); // add critical zone protection
    for (wLoop = 0; wLoop < wDataLen; wLoop++)
    {
        USARTx->DR = pucSendData[wLoop];
        while (FALSE == (USARTx->SR & 0x40));
    }
    taskEXIT_CRITICAL(); // exit critical zone
}

8. 加临界区保护后串口发送间隔变小了

在这里插入图片描述

9. 因为我这个项目同时用到了好几个串口,可能是串口之间相互干扰了吧,串口中断干扰,后期需要优化一下

10. 还有一种办法,串口发送数据的时候用DMA 搬运数据, USART2_TX 开启DMA

STM32F105RCT6 :
USART2_Rx – DMA1_Channel6
USART2_Tx – DMA1_Channel7
在这里插入图片描述

11. 初始化配置DMA

在这里插入图片描述

12. 初始化配置DMA, 发送DMA

// usart2_tx - dma1_ch7
void USART2_Tx_DMA1_Ch7_Init(uint8_t sendBuff[], uint8_t sendBuffLen)
{
    if (NULL == sendBuff)
    {
        return;
    }
    assert_param(sendBuffLen);

    DMA_InitTypeDef DMA_InitStruct;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    DMA_DeInit(DMA1_Channel7); // usart2_tx - dma1_ch7

    g_usartxDMAxSendDataByteCounter = sendBuffLen;

    DMA_InitStruct.DMA_BufferSize = sendBuffLen;
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)sendBuff;
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)(&(USART2->DR));
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;

    DMA_Init(DMA1_Channel7, &DMA_InitStruct); // usart2_tx - dma1_ch7

    USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
}

13. 将要发送的数组拷贝到全局数组 g_usart2Dma1Channel7TxBuff 里面发送给从机

在这里插入图片描述

void UsartSend(USART_TypeDef *USARTx, BYTE *pucSendData, WORD wDataLen)
{
    memcpy(g_usart2Dma1Channel7TxBuff, pucSendData, wDataLen);
    Usart2Dma1Channel7_TxEnable();
    for (;;)
    {
         if (DMA_GetFlagStatus(DMA1_FLAG_TC7) != RESET)
         {
            DMA_ClearFlag(DMA1_FLAG_TC7);
            break;
         }
    }
}

14. 还可以调整FreeRTOS 的系统时钟节拍

我是在STM32F105RCT6 芯片上跑的freeRTOS 实时操作系统

#define configTICK_RATE_HZ    (1000) // system ticks freq, T = 1 / F = 1 / configTICK_RATE_HZ s = 1ms
### 配置STM32F103RCT6以支持FreeRTOS #### 使用STM32CubeMX初始化项目并启用FreeRTOS 为了使STM32F103RCT6能够顺利运行FreeRTOS操作系统,需通过STM32CubeMX软件完成初步设置。启动STM32CubeMX后加载目标芯片型号STM32F103RCT6。 在“Project Manager”页面指定工程名称、保存路径以及编译工具链选项。随后进入“Pinout & Configuration”,这里可以调整微控制器的各种外设资源配置[^3]。 对于希望集成FreeRTOS的应用场景而言,在中间件(Middlewares)部分找到Real-Time Operating System (RTOS),勾选FreeRTOS来激活它。此时会自动引入必要的源码文件至后续生成的工程项目里[^1]。 接着转到“Configuration”标签下的RCC节点设定系统时钟频率等参数;而有关串口通信单元USARTx则依据实际需求决定是否开启及其工作模式——如果计划利用这些接口实现多线程环境里的调试输出或是与其他设备交互,则记得同步加入`#if SYSTEM_SUPPORT_OS #include "FreeRTOS.h"`这样的条件编译语句以便于之后编写应用程序逻辑时可以直接访问FreeRTOS API函数[^2]。 另外值得注意的一点是在此阶段还需关注内存分配情况特别是堆(heap)区域大小,鉴于之前有开发者反馈过因默认值较小而导致某些复杂任务无法正常执行的问题,建议适当增大`configTOTAL_HEAP_SIZE`宏定义处所指派的空间量级,默认情况下可能仅有几千字节数量级,视具体应用场景可上调至数万乃至更多以确保所有预期功能均能得到良好表现[^4]。 ```c #define configTOTAL_HEAP_SIZE ((size_t)20000U) ``` 以上操作完成后即可导出对应IDE平台上的开发框架供进一步编码使用了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值