打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

LiSun

打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1、CudeMX中配置串口时,需要增加DMA功能,并使能串口中断!!!
Mode–Asynchronous Hardware Flow Control(RS232)–Disable

2、在stm32f1xx_it.c中,找到void USART1_IRQHandler(void),并在用户代码区加入UsartReceive_IDLE(&huart1);
备注:根据实际串口号,进行修改,变通,当出现多个串口时,在每个串口中断函数里,都要加入该函数。
extern void UsartReceive_IDLE(UART_HandleTypeDef *huart);

3、应用函数:UartExtInit(&huart1, DMA_MODE);//初始化串口1的DMA模式
UartPutStr(&huart1, TxBuffer, strlen((char )TxBuffer));//发给串口1
len = UartGetStr(&huart1, RxBuffer); //从串口1读取一次数据
4、简化发送函数
#define sendmsg(huart,ExTxBuffer,…) sprintf((char
)ExTxBuffer, ##VA_ARGS);
UartPutStr(&huart, ExTxBuffer, strlen((char *)ExTxBuffer))
sendmsg(huart1,TxBuffer,“a=%d”,1);

/*************笔记****************
***********************************/
#include "uartext.h"
#include "cmsis_os.h"
#include "stdlib.h"

#define   FULL_DUPLEX         1
#define   HALF_DUPLEX         0

#define   SET_RS485_CTR_RX(put)      HAL_GPIO_WritePin(put->rs485Port,put->rs485Pin,put->rs485_ctr_invert?GPIO_PIN_SET:GPIO_PIN_RESET)
#define   SET_RS485_CTR_TX(put)      HAL_GPIO_WritePin(put->rs485Port,put->rs485Pin,put->rs485_ctr_invert?GPIO_PIN_RESET:GPIO_PIN_SET)

USART_RECEIVETYPE *UsartType = NULL;//[UART_USED_NUMBER] = {NULL,NULL,NULL,NULL,NULL,NULL};

USART_RECEIVETYPE* AddUtToArray(UART_HandleTypeDef *huart)
{
    USART_RECEIVETYPE *put = NULL;
    uint8_t found;
    uint16_t len;

    put = UsartType;
    found = 0;
    while(put != NULL)
    {
        if (put->huart == huart)
        {
            found = 1;      //链表中已经存在该串口
            break;
        }
        else
        {
            put = put->next;
        }
    }
    len = sizeof(USART_RECEIVETYPE);
    if(found == 0)
    {
        if(UsartType == NULL)
        {
            put = (USART_RECEIVETYPE *)malloc(len);
            put->rxbuf = (uint8_t *)malloc(UART_RX_BUF_LEN);
            //put->txbuf = (uint8_t *)malloc(UART_TX_BUF_LEN);
            UsartType = put;
            put->huart = huart;
            put->next = NULL;
        }
        else
        {
            put = UsartType;
            while(put->next != NULL)
                put = put->next;
            put->next = (USART_RECEIVETYPE *)malloc(len);
            put = put->next;
            put->rxbuf = (uint8_t *)malloc(UART_RX_BUF_LEN);
            //put->txbuf = (uint8_t *)malloc(UART_TX_BUF_LEN);
            put->huart = huart;
            put->next = NULL;
        }
    }
    return put;
}

USART_RECEIVETYPE* FindPut(UART_HandleTypeDef *huart)
{
    USART_RECEIVETYPE *put = NULL;

    put = UsartType;
    while(put != NULL)
    {
        if (put->huart == huart)
        {
            break;
        }
        else
        {
            put = put->next;
        }
    }
    return put;
}
/*****************************************************************************/
// 功能描述:串口扩展功能初始化
// 输入参数:*huart 待初始化串口,tr_mode:DMA或中断工作方式,wmode: 全双工/半双工
//           port,pin:半双工时,发送接收切换控制pin脚
/*****************************************************************************/
void UartExtInit(UART_HandleTypeDef *huart, uint32_t WorkMode)
{
    USART_RECEIVETYPE* put;

    put = AddUtToArray(huart);
    if(put != NULL)
    {
        if (WorkMode)
            put->tx_mode = DMA_MODE;
        else
            put->tx_mode = IT_MODE;
        put->duplex_mode = FULL_DUPLEX;
        put->tx_finish_flag = UART_SENDOVER;
        put->rx_finish_flag = 0;
        if(put->tx_mode == DMA_MODE)
        {
            HAL_UART_Receive_DMA(put->huart, put->rxbuf, UART_RX_BUF_LEN);
        }
        else
        {
            HAL_UART_Receive_IT(put->huart, put->rxbuf, UART_RX_BUF_LEN);
        }
        __HAL_UART_ENABLE_IT(put->huart, UART_IT_IDLE);
    }
}
/*****************************************************************************/
// 功能描述:设置成RS485半双工工作模式
// 输入参数:*huart 待初始化串口,
/*****************************************************************************/
int8_t UartExtRS485(UART_HandleTypeDef *huart, GPIO_TypeDef* port, uint16_t pin, uint8_t rs485_ctr_invert)
{
    USART_RECEIVETYPE* put;
    int8_t result = -1;

    put = AddUtToArray(huart);
    if(put != NULL)
    {
        put->duplex_mode = HALF_DUPLEX;
        put->rs485Port = port;
        put->rs485Pin  = pin;
        put->rs485_ctr_invert = rs485_ctr_invert;
        SET_RS485_CTR_RX(put);
        result = 0;
    }
    return result;
}
/*****************************************************************************/
// 功能描述:设置成RS485半双工工作模式
// 输入参数:*huart 待初始化串口,WorkMode: 0:中断模式 非0:DMA模式
/*****************************************************************************/
int8_t UartExtWorkMode(UART_HandleTypeDef *huart, uint8_t WorkMode)
{
    USART_RECEIVETYPE* put;
    int8_t result = -1;;

    put = AddUtToArray(huart);
    if(put != NULL)
    {
        if (WorkMode)
            put->tx_mode = DMA_MODE;
        else
            put->tx_mode = IT_MODE;
        result = 0;
    }
    return result;
}
/*****************************************************************************/
// 功能描述:设置成RS485半双工工作模式
// 输入参数:*huart 待初始化串口,WorkMode: 0:中断模式 非0:DMA模式
// 输出参数:无
// 返 回 值:无
// 编写时间:2016.10.25
// 作    者:Bruno.Hu
// 修改记录:
/*****************************************************************************/
int8_t UartExtStart(UART_HandleTypeDef *huart)
{
    USART_RECEIVETYPE* put;
    int8_t result = -1;;

    put = FindPut(huart);
    if(put != NULL)
    {
        if(put->tx_mode == DMA_MODE)
        {
            HAL_UART_Receive_DMA(put->huart, put->rxbuf, UART_RX_BUF_LEN);
        }
        else
        {
            HAL_UART_Receive_IT(put->huart, put->rxbuf, UART_RX_BUF_LEN);
        }
        __HAL_UART_ENABLE_IT(put->huart, UART_IT_IDLE);
    }
    return result;
}

/*****************************************************************************/
// 功能描述:串口扩展功能初始化
// 输入参数:*huart 待初始化串口,tr_mode:DMA或中断工作方式,wmode: 全双工/半双工
//           port,pin:半双工时,发送接收切换控制pin脚
/*****************************************************************************/
//void UartExtInit(UART_HandleTypeDef *huart, UART_TRANSCEIVER_MODE tr_mode, UART_WORK_MODE wmode, GPIO_TypeDef* port, uint16_t pin, uint8_t rs485_ctr_invert)
//{
//  USART_RECEIVETYPE* put;
//
//  put = AddUtToArray(huart);
//  if(put != NULL) {
//    put->transceiver_mode = tr_mode;
//    put->work_mode = wmode;
//    put->rs485Port = port;
//    put->rs485Pin  = pin;
//    put->rs485_ctr_invert = rs485_ctr_invert;
//    put->tx_finish_flag = UART_SENDOVER;
//    put->rx_finish_flag = 0;
//    if(put->work_mode == UART_HALF_DUPLEX) {
//      if(put->rs485_ctr_invert) {
//        HAL_GPIO_WritePin(put->rs485Port,put->rs485Pin,GPIO_PIN_SET);
//      } else {
//        HAL_GPIO_WritePin(put->rs485Port,put->rs485Pin,GPIO_PIN_RESET);
//      }
//    }
//    if(put->transceiver_mode == UART_DMA_MODE) {
//      HAL_UART_Receive_DMA(put->huart, put->rxbuf, UART_RX_BUF_LEN);
//    } else {
//      HAL_UART_Receive_IT(put->huart,put->rxbuf,UART_RX_BUF_LEN);
//    }
//    __HAL_UART_ENABLE_IT(put->huart, UART_IT_IDLE);
//  }
//}
/*****************************************************************************/
// 功能描述:通过指定串口发送数据
// 输入参数:*huart 待发送数据的串口,pdata:待发送数据,length:数据长度
/*****************************************************************************/
void UartPutStr(UART_HandleTypeDef *huart, const uint8_t *pdata, uint16_t Length)
{
    USART_RECEIVETYPE* put;
    //uint16_t len = 0;
    uint32_t dly;
    put = FindPut(huart);
    if(put != NULL)
    {
//    while(put->tx_finish_flag == UART_SENDING) {
//      osDelay(1);
//    }
//    for(i=0;(i<Length) && (i<UART_TX_BUF_LEN);i++) {
//      put->txbuf[i] = pdata[i];
//      len++;
//    }
        if(put->duplex_mode == HALF_DUPLEX)
        {
            SET_RS485_CTR_TX(put);
        }
        put->tx_finish_flag = UART_SENDING;
        if(put->tx_mode == DMA_MODE)
        {
            //HAL_UART_DMAStop(put->huart);
            HAL_UART_Transmit_DMA(put->huart, (uint8_t *)pdata, Length);
        }
        else
        {
            //HAL_UART_AbortTransmit_IT(put->huart);
            HAL_UART_Transmit_IT(put->huart, (uint8_t *)pdata, Length);
        }
        dly = (Length * 10000) / put->huart->Init.BaudRate + 3;
        while((put->tx_finish_flag != UART_SENDOVER) && dly)
        {
            osDelay(1);
            dly--;
        }
        osDelay(5);
    }
}
/*****************************************************************************/
// 功能描述:通过指定串口接收数据
// 输入参数:*huart 待接收数据的串口,pdata:接收到的数据存储区
// 返 回 值:接收到数据的长度, 0 表示没有接收到
/*****************************************************************************/
uint16_t UartGetStr(UART_HandleTypeDef *huart, uint8_t *pdata)
{
    uint16_t i, rxlen = 0;
    USART_RECEIVETYPE* put;

    put = FindPut(huart);
    if(put != NULL)
    {
        if(put->rx_finish_flag)
        {
            for(i = 0; i < put->rxlen; i++)
                pdata[i] = put->rxbuf[i];
            put->rx_finish_flag = 0;
            rxlen = put->rxlen;
        }
    }
    return rxlen;
}

/*****************************************************************************/
// 功能描述:串口空闲中断处理 (添加到 USARTn_IRQHandler 中断函数中去)
// 输入参数:*huart 待处理的串口
/*****************************************************************************/
void UsartReceive_IDLE(UART_HandleTypeDef *huart)
{
    USART_RECEIVETYPE *put;

    put = FindPut(huart);
    if(put != NULL)
    {
        if((__HAL_UART_GET_FLAG(put->huart, UART_FLAG_IDLE) != RESET))
        {
            __HAL_UART_CLEAR_IDLEFLAG(put->huart);
            if(put->tx_mode == DMA_MODE)
            {
                HAL_UART_DMAStop(put->huart);
                //HAL_DMA_Abort(put->huart->hdmarx);
#ifdef  __STM32F4xx_HAL_H
                put->rxlen =  UART_RX_BUF_LEN - put->huart->hdmarx->Instance->NDTR;
                put->huart->RxState = HAL_UART_STATE_READY;
#endif
#ifdef  __STM32F1xx_HAL_H
                put->rxlen =  UART_RX_BUF_LEN - put->huart->hdmarx->Instance->CNDTR;
                put->huart->gState = HAL_UART_STATE_READY;
#endif
                put->rx_finish_flag = 1;
                HAL_UART_Receive_DMA(put->huart, put->rxbuf, UART_RX_BUF_LEN);
            }
            else
            {
#ifdef  __STM32F4xx_HAL_H
                put->huart->RxState = HAL_UART_STATE_READY;
#endif
#ifdef  __STM32F1xx_HAL_H
                put->huart->gState = HAL_UART_STATE_READY;
#endif
                __HAL_UART_DISABLE_IT(put->huart, UART_IT_RXNE);
                put->rxlen =  put->huart->RxXferSize - put->huart->RxXferCount;
                put->rx_finish_flag = 1;
                HAL_UART_Receive_IT(put->huart, put->rxbuf, UART_RX_BUF_LEN);
            }
        }
    }
}

/*****************************************************************************/
// 功能描述:串口空闲中断处理 (添加到 USARTn_IRQHandler 中断函数中去)
// 输入参数:*huart 待处理的串口
/*****************************************************************************/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    USART_RECEIVETYPE* put;

    put = FindPut(huart);
    if(put != NULL)
    {
        if(put->tx_mode == DMA_MODE)
        {
            __HAL_DMA_DISABLE(put->huart->hdmatx);
        }
        if(put->duplex_mode == HALF_DUPLEX)
        {
            SET_RS485_CTR_RX(put);
        }
        put->tx_finish_flag = UART_SENDOVER;
    }
}
/*****************************************************************************/
// 功能描述:等待串口接收完成
// 输入参数:*huart 待处理的串口
/*****************************************************************************/
void UartTxFinish(UART_HandleTypeDef *huart, uint32_t timeout)
{
    USART_RECEIVETYPE* put;
    uint32_t TimeOut = 0;

    put = FindPut(huart);
    if(put != NULL)
    {
        while((put->tx_finish_flag == UART_SENDING) && (TimeOut < timeout))
        {
            osDelay(1);
            TimeOut++;
        }
    }
}


//例子:
//void StartRS232Task(void const * argument)
//{
//    osDelay(100);
//    UartExtInit(&huart1, DMA_MODE);//用于RS232串口1,测试用
//    uint16_t len;
//    uint8_t RxBuffer[32],TxBuffer[32];
//    for(;;)
//    {
//        len = UartGetStr(&huart1, RxBuffer); //从串口1读取一次数据
//        if(len > 1)
//        {
//            sendmsg(huart1, TxBuffer, "%s", RxBuffer);
//        }
//        osMessagePut(QueWdtHandle, 0x02, 10);
//        osDelay(2);
//    }
//}
#ifndef __UART_EXT_HEADER__
#define __UART_EXT_HEADER__
#include "stm32f1xx_hal.h"
#include "usart.h"
#include "cmsis_os.h"
#define UART_RX_BUF_LEN      128  
//#define UART_TX_BUF_LEN      128
#define UART_SENDING    1             //发送未完成  
#define UART_SENDOVER   0             //发送完成  

#define   DMA_MODE            1
#define   IT_MODE             0

#define sendmsg_Delay(huart,ExTxBuffer,...) sprintf((char*)ExTxBuffer, ##__VA_ARGS__);\
                                            UartPutStr(&huart, ExTxBuffer, strlen((char *)ExTxBuffer));\
                                            osDelay(strlen((char*)ExTxBuffer)+1)
#define sendmsg(huart,ExTxBuffer,...) sprintf((char*)ExTxBuffer, ##__VA_ARGS__);\
                                      UartPutStr(&huart, ExTxBuffer, strlen((char *)ExTxBuffer))

typedef struct  uart_node{  
  UART_HandleTypeDef      *huart;                       //串口
  uint8_t                 rx_finish_flag:1;             //空闲接收标记  
  uint8_t                 tx_finish_flag:1;             //发送完成标记  
  uint8_t                 tx_mode:1;                    //1: 表示用DMA模式,0: 表示用中断模式
  uint8_t                 duplex_mode:1;                //1: 全双工,0: 半双工设置
  uint8_t                 rs485_ctr_invert:1;           // RS485方向控制脚是否反转
  GPIO_TypeDef*           rs485Port;                    //半双工时,方向切换IO所用的端口
  uint16_t                rs485Pin;                     //半双工时,方向切换IO所用的PIN脚
  uint16_t                rxlen;                        //接收长度
  uint8_t                 *rxbuf;                       //接收缓存  
  //uint8_t                 *txbuf;
  struct uart_node        *next;
}USART_RECEIVETYPE;

//void UartExtInit(UART_HandleTypeDef *huart, uint32_t MODE, GPIO_TypeDef* port, uint16_t pin, uint8_t rs485_ctr_invert);
//void RS485ExtInit(UART_HandleTypeDef *huart, uint32_t mode, GPIO_TypeDef* port, uint16_t pin, uint8_t rs485_ctr_invert);
//void UartExtInit(UART_HandleTypeDef *huart, UART_TRANSCEIVER_MODE tr_mode, UART_WORK_MODE wmode, GPIO_TypeDef* port, uint16_t pin, uint8_t rs485_ctr_invert);
void UartExtInit(UART_HandleTypeDef *huart, uint32_t WorkMode);
int8_t UartExtRS485(UART_HandleTypeDef *huart, GPIO_TypeDef* port, uint16_t pin, uint8_t rs485_ctr_invert);
void UartPutStr(UART_HandleTypeDef *huart, const uint8_t *pdata, uint16_t Length);
uint16_t UartGetStr(UART_HandleTypeDef *huart, uint8_t *pdata);
void UartTxFinish(UART_HandleTypeDef *huart, uint32_t timeout);
#endif


posted on 2020-04-12 18:59  xuejianqiang  阅读(15)  评论(0编辑  收藏  举报  来源
打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033