bsp_uart_fifo.h
/*
*********************************************************************************************************
*
* 模块名称 : 串口中断+FIFO驱动模块
* 文件名称 : bsp_uart_fifo.h
* 说 明 : 头文件
*
*********************************************************************************************************
*/
#ifndef _BSP_USART_FIFO_H_
#define _BSP_USART_FIFO_H_
/*
如果需要更改串口对应的管脚,请自行修改 bsp_uart_fifo.c文件中的 static void InitHardUart(void)函数
*/
/* 定义使能的串口, 0 表示不使能(不增加代码大小), 1表示使能 */
/*
串口分配:
【串口1】
PA9/USART1_TX --- 打印调试口
PA10/USART1_RX
*/
#define UART1_FIFO_EN 1
#define UART2_FIFO_EN 0
#define UART3_FIFO_EN 0
#define UART4_FIFO_EN 0
#define UART5_FIFO_EN 0
#define UART6_FIFO_EN 0
/* 定义端口号 */
typedef enum
{
COM1 = 0, /* USART1 PA9, PA10 或 PB6, PB7*/
COM2 = 1, /* USART2, PD5,PD6 或 PA2, PA3 */
COM3 = 2, /* USART3, PB10, PB11 */
COM4 = 3, /* UART4, PC10, PC11 */
COM5 = 4, /* UART5, PC12, PD2 */
COM6 = 5 /* USART6, PC6, PC7 */
}COM_PORT_E;
/* 定义串口波特率和FIFO缓冲区大小,分为发送缓冲区和接收缓冲区, 支持全双工 */
#if UART1_FIFO_EN == 1
#define UART1_BAUD 115200
#define UART1_TX_BUF_SIZE 1*1024
#define UART1_RX_BUF_SIZE 1*1024
#endif
#if UART2_FIFO_EN == 1
#define UART2_BAUD 9600
#define UART2_TX_BUF_SIZE 1
#define UART2_RX_BUF_SIZE 2*1024
#endif
#if UART3_FIFO_EN == 1
#define UART3_BAUD 9600
#define UART3_TX_BUF_SIZE 1*1024
#define UART3_RX_BUF_SIZE 1*1024
#endif
#if UART4_FIFO_EN == 1
#define UART4_BAUD 115200
#define UART4_TX_BUF_SIZE 1*1024
#define UART4_RX_BUF_SIZE 1*1024
#endif
#if UART5_FIFO_EN == 1
#define UART5_BAUD 115200
#define UART5_TX_BUF_SIZE 1*1024
#define UART5_RX_BUF_SIZE 1*1024
#endif
#if UART6_FIFO_EN == 1
#define UART6_BAUD 115200
#define UART6_TX_BUF_SIZE 1*1024
#define UART6_RX_BUF_SIZE 1*1024
#endif
/* 串口设备结构体 */
typedef struct
{
USART_TypeDef *uart; /* STM32内部串口设备指针 */
uint8_t *pTxBuf; /* 发送缓冲区 */
uint8_t *pRxBuf; /* 接收缓冲区 */
uint16_t usTxBufSize; /* 发送缓冲区大小 */
uint16_t usRxBufSize; /* 接收缓冲区大小 */
__IO uint16_t usTxWrite; /* 发送缓冲区写指针 */
__IO uint16_t usTxRead; /* 发送缓冲区读指针 */
__IO uint16_t usTxCount; /* 等待发送的数据个数 */
__IO uint16_t usRxWrite; /* 接收缓冲区写指针 */
__IO uint16_t usRxRead; /* 接收缓冲区读指针 */
__IO uint16_t usRxCount; /* 还未读取的新数据个数 */
void (*SendBefor)(void); /* 开始发送之前的回调函数指针(主要用于RS485切换到发送模式) */
void (*SendOver)(void); /* 发送完毕的回调函数指针(主要用于RS485将发送模式切换为接收模式) */
void (*ReciveNew)(uint8_t _byte); /* 串口收到数据的回调函数指针 */
}UART_T;
typedef enum
{
UART_OK = 0,
UART_TIMEOUT = 1,
UART_BUSY = 2,
UART_ERROR = 3
}UART_StatusTypeDef;
void bsp_InitUart(void);
void comSendBuf(COM_PORT_E _ucPort, uint8_t *_ucaBuf, uint16_t _usLen);
void comSendChar(COM_PORT_E _ucPort, uint8_t _ucByte);
uint8_t comGetChar(COM_PORT_E _ucPort, uint8_t *_pByte);
uint16_t comGetCharNum(COM_PORT_E _ucPort);
void comClearTxFifo(COM_PORT_E _ucPort);
void comClearRxFifo(COM_PORT_E _ucPort);
void comSetBaud(COM_PORT_E _ucPort, uint32_t _BaudRate);
void USART_SetBaudRate(USART_TypeDef* USARTx, uint32_t BaudRate);
UART_StatusTypeDef uart_receive_byte(uint8_t *byCh, uint32_t dwTimeout);
UART_StatusTypeDef uart_receive_data(uint8_t *byString, uint32_t dwLength, uint32_t dwTimeout);
#endif
bsp_uart_fifo.c
/*
*********************************************************************************************************
*
* 模块名称 : 串口中断+FIFO驱动模块
* 文件名称 : bsp_uart_fifo.c
* 版 本 : V1.0
* 说 明 : 采用串口中断+FIFO模式实现多个串口的同时访问
*
*********************************************************************************************************
*/
#include "bsp.h"
/* 串口1的GPIO */
#define UART1_TX_PORT GPIOA
#define UART1_TX_PIN GPIO_Pin_9
#define UART1_TX_CLK RCC_AHB1Periph_GPIOA
#define UART1_TX_SOURCE GPIO_PinSource9
#define UART1_RX_PORT GPIOA
#define UART1_RX_PIN GPIO_Pin_10
#define UART1_RX_CLK RCC_AHB1Periph_GPIOA
#define UART1_RX_SOURCE GPIO_PinSource10
/* 串口2的GPIO */
#define UART2_TX_PORT GPIOA
#define UART2_TX_PIN GPIO_Pin_2
#define UART2_TX_CLK RCC_AHB1Periph_GPIOA
#define UART2_TX_SOURCE GPIO_PinSource2
#define UART2_RX_PORT GPIOA
#define UART2_RX_PIN GPIO_Pin_3
#define UART2_RX_CLK RCC_AHB1Periph_GPIOA
#define UART2_RX_SOURCE GPIO_PinSource3
/* 串口3的GPIO */
#define UART3_TX_PORT GPIOB
#define UART3_TX_PIN GPIO_Pin_10
#define UART3_TX_CLK RCC_AHB1Periph_GPIOB
#define UART3_TX_SOURCE GPIO_PinSource10
#define UART3_RX_PORT GPIOB
#define UART3_RX_PIN GPIO_Pin_11
#define UART3_RX_CLK RCC_AHB1Periph_GPIOB
#define UART3_RX_SOURCE GPIO_PinSource11
/* 串口4的GPIO */
#define UART4_TX_PORT GPIOC
#define UART4_TX_PIN GPIO_Pin_10
#define UART4_TX_CLK RCC_AHB1Periph_GPIOC
#define UART4_TX_SOURCE GPIO_PinSource10
#define UART4_RX_PORT GPIOC
#define UART4_RX_PIN GPIO_Pin_11
#define UART4_RX_CLK RCC_AHB1Periph_GPIOC
#define UART4_RX_SOURCE GPIO_PinSource11
/* 串口5的GPIO */
#define UART5_TX_PORT GPIOC
#define UART5_TX_PIN GPIO_Pin_12
#define UART5_TX_CLK RCC_AHB1Periph_GPIOC
#define UART5_TX_SOURCE GPIO_PinSource12
#define UART5_RX_PORT GPIOD
#define UART5_RX_PIN GPIO_Pin_2
#define UART5_RX_CLK RCC_AHB1Periph_GPIOD
#define UART5_RX_SOURCE GPIO_PinSource2
/* 串口6的GPIO */
#define UART6_TX_PORT GPIOG
#define UART6_TX_PIN GPIO_Pin_14
#define UART6_TX_CLK RCC_AHB1Periph_GPIOG
#define UART6_TX_SOURCE GPIO_PinSource14
#define UART6_RX_PORT GPIOC
#define UART6_RX_PIN GPIO_Pin_7
#define UART6_RX_CLK RCC_AHB1Periph_GPIOC
#define UART6_RX_SOURCE GPIO_PinSource7
/* 定义每个串口结构体变量 */
#if UART1_FIFO_EN == 1
static UART_T g_tUart1;
static uint8_t g_TxBuf1[UART1_TX_BUF_SIZE]; /* 发送缓冲区 */
static uint8_t g_RxBuf1[UART1_RX_BUF_SIZE]; /* 接收缓冲区 */
#endif
#if UART2_FIFO_EN == 1
static UART_T g_tUart2;
static uint8_t g_TxBuf2[UART2_TX_BUF_SIZE]; /* 发送缓冲区 */
static uint8_t g_RxBuf2[UART2_RX_BUF_SIZE]; /* 接收缓冲区 */
#endif
#if UART3_FIFO_EN == 1
static UART_T g_tUart3;
static uint8_t g_TxBuf3[UART3_TX_BUF_SIZE]; /* 发送缓冲区 */
static uint8_t g_RxBuf3[UART3_RX_BUF_SIZE]; /* 接收缓冲区 */
#endif
#if UART4_FIFO_EN == 1
static UART_T g_tUart4;
static uint8_t g_TxBuf4[UART4_TX_BUF_SIZE]; /* 发送缓冲区 */
static uint8_t g_RxBuf4[UART4_RX_BUF_SIZE]; /* 接收缓冲区 */
#endif
#if UART5_FIFO_EN == 1
static UART_T g_tUart5;
static uint8_t g_TxBuf5[UART5_TX_BUF_SIZE]; /* 发送缓冲区 */
static uint8_t g_RxBuf5[UART5_RX_BUF_SIZE]; /* 接收缓冲区 */
#endif
#if UART6_FIFO_EN == 1
static UART_T g_tUart6;
static uint8_t g_TxBuf6[UART6_TX_BUF_SIZE]; /* 发送缓冲区 */
static uint8_t g_RxBuf6[UART6_RX_BUF_SIZE]; /* 接收缓冲区 */
#endif
static void UartVarInit(void);
static void InitHardUart(void);
static void UartSend(UART_T *_pUart, uint8_t *_ucaBuf, uint16_t _usLen);
static uint8_t UartGetChar(UART_T *_pUart, uint8_t *_pByte);
static void UartIRQ(UART_T *_pUart);
static void ConfigUartNVIC(void);
void RS485_InitTXE(void);
/*
*********************************************************************************************************
* 函 数 名: bsp_InitUart
* 功能说明: 初始化串口硬件,并对全局变量赋初值.
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitUart(void)
{
UartVarInit(); /* 必须先初始化全局变量,再配置硬件 */
InitHardUart(); /* 配置串口的硬件参数(波特率等) */
// RS485_InitTXE(); /* 配置RS485芯片的发送使能硬件,配置为推挽输出 */
ConfigUartNVIC(); /* 配置串口中断 */
}
/*
*********************************************************************************************************
* 函 数 名: ComToUart
* 功能说明: 将COM端口号转换为UART指针
* 形 参: _ucPort: 端口号(COM1 - COM6)
* 返 回 值: uart指针
*********************************************************************************************************
*/
UART_T *ComToUart(COM_PORT_E _ucPort)
{
if (_ucPort == COM1)
{
#if UART1_FIFO_EN == 1
return &g_tUart1;
#else
return 0;
#endif
}
else if (_ucPort == COM2)
{
#if UART2_FIFO_EN == 1
return &g_tUart2;
#else
return 0;
#endif
}
else if (_ucPort == COM3)
{
#if UART3_FIFO_EN == 1
return &g_tUart3;
#else
return 0;
#endif
}
else if (_ucPort == COM4)
{
#if UART4_FIFO_EN == 1
return &g_tUart4;
#else
return 0;
#endif
}
else if (_ucPort == COM5)
{
#if UART5_FIFO_EN == 1
return &g_tUart5;
#else
return 0;
#endif
}
else if (_ucPort == COM6)
{
#if UART6_FIFO_EN == 1
return &g_tUart6;
#else
return 0;
#endif
}
else
{
/* 不做任何处理 */
return 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: ComToUart
* 功能说明: 将COM端口号转换为 USART_TypeDef* USARTx
* 形 参: _ucPort: 端口号(COM1 - COM6)
* 返 回 值: USART_TypeDef*, USART1, USART2, USART3, UART4, UART5
*********************************************************************************************************
*/
USART_TypeDef *ComToUSARTx(COM_PORT_E _ucPort)
{
if (_ucPort == COM1)
{
#if UART1_FIFO_EN == 1
return USART1;
#else
return 0;
#endif
}
else if (_ucPort == COM2)
{
#if UART2_FIFO_EN == 1
return USART2;
#else
return 0;
#endif
}
else if (_ucPort == COM3)
{
#if UART3_FIFO_EN == 1
return USART3;
#else
return 0;
#endif
}
else if (_ucPort == COM4)
{
#if UART4_FIFO_EN == 1
return USART4;
#else
return 0;
#endif
}
else if (_ucPort == COM5)
{
#if UART5_FIFO_EN == 1
return USART5;
#else
return 0;
#endif
}
else
{
/* 不做任何处理 */
return 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: comSendBuf
* 功能说明: 向串口发送一组数据。数据放到发送缓冲区后立即返回,由中断服务程序在后台完成发送
* 形 参: _ucPort: 端口号(COM1 - COM6)
* _ucaBuf: 待发送的数据缓冲区
* _usLen : 数据长度
* 返 回 值: 无
*********************************************************************************************************
*/
void comSendBuf(COM_PORT_E _ucPort, uint8_t *_ucaBuf, uint16_t _usLen)
{
UART_T *pUart;
pUart = ComToUart(_ucPort);
if (pUart == 0)
{
return;
}
if (pUart->SendBefor != 0)
{
pUart->SendBefor(); /* 如果是RS485通信,可以在这个函数中将RS485设置为发送模式 */
}
UartSend(pUart, _ucaBuf, _usLen);
}
/*
*********************************************************************************************************
* 函 数 名: comSendChar
* 功能说明: 向串口发送1个字节。数据放到发送缓冲区后立即返回,由中断服务程序在后台完成发送
* 形 参: _ucPort: 端口号(COM1 - COM6)
* _ucByte: 待发送的数据
* 返 回 值: 无
*********************************************************************************************************
*/
void comSendChar(COM_PORT_E _ucPort, uint8_t _ucByte)
{
comSendBuf(_ucPort, &_ucByte, 1);
}
/*
*********************************************************************************************************
* 函 数 名: comGetChar
* 功能说明: 从接收缓冲区读取1字节,非阻塞。无论有无数据均立即返回。
* 形 参: _ucPort: 端口号(COM1 - COM5)
* _pByte: 接收到的数据存放在这个地址
* 返 回 值: 0 表示无数据, 1 表示读取到有效字节
*********************************************************************************************************
*/
uint8_t comGetChar(COM_PORT_E _ucPort, uint8_t *_pByte)
{
UART_T *pUart;
pUart = ComToUart(_ucPort);
if (pUart == 0)
{
return 0;
}
return UartGetChar(pUart, _pByte);
}
/*
*********************************************************************************************************
* 函 数 名: comGetCharNum
* 功能说明: 获取接收缓冲区内剩余数据量。
* 形 参: _ucPort: 端口号(COM1 - COM5)
* 返 回 值: 获取到的数据量
*********************************************************************************************************
*/
uint16_t comGetCharNum(COM_PORT_E _ucPort)
{
UART_T *pUart;
uint16_t usCount;
pUart = ComToUart(_ucPort);
if (pUart == 0)
{
return 0;
}
/* usRxWrite 变量在中断函数中被改写,主程序读取该变量时,必须进行临界区保护 */
DISABLE_INT();
usCount = pUart->usRxCount;
ENABLE_INT();
return usCount;
}
/*
*********************************************************************************************************
* 函 数 名: comClearTxFifo
* 功能说明: 清零串口发送缓冲区
* 形 参: _ucPort: 端口号(COM1 - COM6)
* 返 回 值: 无
*********************************************************************************************************
*/
void comClearTxFifo(COM_PORT_E _ucPort)
{
UART_T *pUart;
pUart = ComToUart(_ucPort);
if (pUart == 0)
{
return;
}
pUart->usTxWrite = 0;
pUart->usTxRead = 0;
pUart->usTxCount = 0;
}
/*
*********************************************************************************************************
* 函 数 名: comClearRxFifo
* 功能说明: 清零串口接收缓冲区
* 形 参: _ucPort: 端口号(COM1 - COM6)
* 返 回 值: 无
*********************************************************************************************************
*/
void comClearRxFifo(COM_PORT_E _ucPort)
{
UART_T *pUart;
pUart = ComToUart(_ucPort);
if (pUart == 0)
{
return;
}
pUart->usRxWrite = 0;
pUart->usRxRead = 0;
pUart->usRxCount = 0;
}
/*
*********************************************************************************************************
* 函 数 名: comSetBaud
* 功能说明: 设置串口的波特率
* 形 参: _ucPort: 端口号(COM1 - COM5)
* _BaudRate: 波特率,0-4500000, 最大4.5Mbps
* 返 回 值: 无
*********************************************************************************************************
*/
void comSetBaud(COM_PORT_E _ucPort, uint32_t _BaudRate)
{
USART_TypeDef* USARTx;
USARTx = ComToUSARTx(_ucPort);
if (USARTx == 0)
{
return;
}
USART_SetBaudRate(USARTx, _BaudRate);
}
/*
*********************************************************************************************************
* 函 数 名: USART_SetBaudRate
* 功能说明: 修改波特率寄存器,不更改其他设置。如果使用 USART_Init函数, 则会修改硬件流控参数和RX,TX配置
* 根据固件库中 USART_Init函数,将其中配置波特率的部分单独提出来封装为一个函数
* 形 参: USARTx : USART1, USART2, USART3, UART4, UART5
* BaudRate : 波特率,取值 0 - 4500000
* 返 回 值: 无
*********************************************************************************************************
*/
void USART_SetBaudRate(USART_TypeDef* USARTx, uint32_t BaudRate)
{
uint32_t tmpreg = 0x00, apbclock = 0x00;
uint32_t integerdivider = 0x00;
uint32_t fractionaldivider = 0x00;
RCC_ClocksTypeDef RCC_ClocksStatus;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_BAUDRATE(BaudRate));
/*---------------------------- USART BRR Configuration -----------------------*/
/* Configure the USART Baud Rate */
RCC_GetClocksFreq(&RCC_ClocksStatus);
if ((USARTx == USART1) || (USARTx == USART6))
{
apbclock = RCC_ClocksStatus.PCLK2_Frequency;
}
else
{
apbclock = RCC_ClocksStatus.PCLK1_Frequency;
}
/* Determine the integer part */
if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
{
/* Integer part computing in case Oversampling mode is 8 Samples */
integerdivider = ((25 * apbclock) / (2 * (BaudRate)));
}
else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
{
/* Integer part computing in case Oversampling mode is 16 Samples */
integerdivider = ((25 * apbclock) / (4 * (BaudRate)));
}
tmpreg = (integerdivider / 100) << 4;
/* Determine the fractional part */
fractionaldivider = integerdivider - (100 * (tmpreg >> 4));
/* Implement the fractional part in the register */
if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
{
tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
}
else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
{
tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
}
/* Write to USART BRR register */
USARTx->BRR = (uint16_t)tmpreg;
}
/*
*********************************************************************************************************
* 函 数 名: UartVarInit
* 功能说明: 初始化串口相关的变量
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void UartVarInit(void)
{
#if UART1_FIFO_EN == 1
g_tUart1.uart = USART1; /* STM32 串口设备 */
g_tUart1.pTxBuf = g_TxBuf1; /* 发送缓冲区指针 */
g_tUart1.pRxBuf = g_RxBuf1; /* 接收缓冲区指针 */
g_tUart1.usTxBufSize = UART1_TX_BUF_SIZE; /* 发送缓冲区大小 */
g_tUart1.usRxBufSize = UART1_RX_BUF_SIZE; /* 接收缓冲区大小 */
g_tUart1.usTxWrite = 0; /* 发送FIFO写索引 */
g_tUart1.usTxRead = 0; /* 发送FIFO读索引 */
g_tUart1.usRxWrite = 0; /* 接收FIFO写索引 */
g_tUart1.usRxRead = 0; /* 接收FIFO读索引 */
g_tUart1.usRxCount = 0; /* 接收到的新数据个数 */
g_tUart1.usTxCount = 0; /* 待发送的数据个数 */
g_tUart1.SendBefor = 0; /* 发送数据前的回调函数 */
g_tUart1.SendOver = 0; /* 发送完毕后的回调函数 */
g_tUart1.ReciveNew = 0; /* 接收到新数据后的回调函数 */
#endif
#if UART2_FIFO_EN == 1
g_tUart2.uart = USART2; /* STM32 串口设备 */
g_tUart2.pTxBuf = g_TxBuf2; /* 发送缓冲区指针 */
g_tUart2.pRxBuf = g_RxBuf2; /* 接收缓冲区指针 */
g_tUart2.usTxBufSize = UART2_TX_BUF_SIZE; /* 发送缓冲区大小 */
g_tUart2.usRxBufSize = UART2_RX_BUF_SIZE; /* 接收缓冲区大小 */
g_tUart2.usTxWrite = 0; /* 发送FIFO写索引 */
g_tUart2.usTxRead = 0; /* 发送FIFO读索引 */
g_tUart2.usRxWrite = 0; /* 接收FIFO写索引 */
g_tUart2.usRxRead = 0; /* 接收FIFO读索引 */
g_tUart2.usRxCount = 0; /* 接收到的新数据个数 */
g_tUart2.usTxCount = 0; /* 待发送的数据个数 */
g_tUart2.SendBefor = 0; /* 发送数据前的回调函数 */
g_tUart2.SendOver = 0; /* 发送完毕后的回调函数 */
g_tUart2.ReciveNew = 0; /* 接收到新数据后的回调函数 */
#endif
#if UART3_FIFO_EN == 1
g_tUart3.uart = USART3; /* STM32 串口设备 */
g_tUart3.pTxBuf = g_TxBuf3; /* 发送缓冲区指针 */
g_tUart3.pRxBuf = g_RxBuf3; /* 接收缓冲区指针 */
g_tUart3.usTxBufSize = UART3_TX_BUF_SIZE; /* 发送缓冲区大小 */
g_tUart3.usRxBufSize = UART3_RX_BUF_SIZE; /* 接收缓冲区大小 */
g_tUart3.usTxWrite = 0; /* 发送FIFO写索引 */
g_tUart3.usTxRead = 0; /* 发送FIFO读索引 */
g_tUart3.usRxWrite = 0; /* 接收FIFO写索引 */
g_tUart3.usRxRead = 0; /* 接收FIFO读索引 */
g_tUart3.usRxCount = 0; /* 接收到的新数据个数 */
g_tUart3.usTxCount = 0; /* 待发送的数据个数 */
g_tUart3.SendBefor = 0; /* 发送数据前的回调函数 */
g_tUart3.SendOver = 0; /* 发送完毕后的回调函数 */
g_tUart3.ReciveNew = 0; /* 接收到新数据后的回调函数 */
#endif
#if UART4_FIFO_EN == 1
g_tUart4.uart = UART4; /* STM32 串口设备 */
g_tUart4.pTxBuf = g_TxBuf4; /* 发送缓冲区指针 */
g_tUart4.pRxBuf = g_RxBuf4; /* 接收缓冲区指针 */
g_tUart4.usTxBufSize = UART4_TX_BUF_SIZE; /* 发送缓冲区大小 */
g_tUart4.usRxBufSize = UART4_RX_BUF_SIZE; /* 接收缓冲区大小 */
g_tUart4.usTxWrite = 0; /* 发送FIFO写索引 */
g_tUart4.usTxRead = 0; /* 发送FIFO读索引 */
g_tUart4.usRxWrite = 0; /* 接收FIFO写索引 */
g_tUart4.usRxRead = 0; /* 接收FIFO读索引 */
g_tUart4.usRxCount = 0; /* 接收到的新数据个数 */
g_tUart4.usTxCount = 0; /* 待发送的数据个数 */
g_tUart4.SendBefor = 0; /* 发送数据前的回调函数 */
g_tUart4.SendOver = 0; /* 发送完毕后的回调函数 */
g_tUart4.ReciveNew = 0; /* 接收到新数据后的回调函数 */
#endif
#if UART5_FIFO_EN == 1
g_tUart5.uart = UART5; /* STM32 串口设备 */
g_tUart5.pTxBuf = g_TxBuf5; /* 发送缓冲区指针 */
g_tUart5.pRxBuf = g_RxBuf5; /* 接收缓冲区指针 */
g_tUart5.usTxBufSize = UART5_TX_BUF_SIZE; /* 发送缓冲区大小 */
g_tUart5.usRxBufSize = UART5_RX_BUF_SIZE; /* 接收缓冲区大小 */
g_tUart5.usTxWrite = 0; /* 发送FIFO写索引 */
g_tUart5.usTxRead = 0; /* 发送FIFO读索引 */
g_tUart5.usRxWrite = 0; /* 接收FIFO写索引 */
g_tUart5.usRxRead = 0; /* 接收FIFO读索引 */
g_tUart5.usRxCount = 0; /* 接收到的新数据个数 */
g_tUart5.usTxCount = 0; /* 待发送的数据个数 */
g_tUart5.SendBefor = 0; /* 发送数据前的回调函数 */
g_tUart5.SendOver = 0; /* 发送完毕后的回调函数 */
g_tUart5.ReciveNew = 0; /* 接收到新数据后的回调函数 */
#endif
#if UART6_FIFO_EN == 1
g_tUart6.uart = USART6; /* STM32 串口设备 */
g_tUart6.pTxBuf = g_TxBuf6; /* 发送缓冲区指针 */
g_tUart6.pRxBuf = g_RxBuf6; /* 接收缓冲区指针 */
g_tUart6.usTxBufSize = UART6_TX_BUF_SIZE; /* 发送缓冲区大小 */
g_tUart6.usRxBufSize = UART6_RX_BUF_SIZE; /* 接收缓冲区大小 */
g_tUart6.usTxWrite = 0; /* 发送FIFO写索引 */
g_tUart6.usTxRead = 0; /* 发送FIFO读索引 */
g_tUart6.usRxWrite = 0; /* 接收FIFO写索引 */
g_tUart6.usRxRead = 0; /* 接收FIFO读索引 */
g_tUart6.usRxCount = 0; /* 接收到的新数据个数 */
g_tUart6.usTxCount = 0; /* 待发送的数据个数 */
g_tUart6.SendBefor = 0; /* 发送数据前的回调函数 */
g_tUart6.SendOver = 0; /* 发送完毕后的回调函数 */
g_tUart6.ReciveNew = 0; /* 接收到新数据后的回调函数 */
#endif
}
/*
*********************************************************************************************************
* 函 数 名: InitHardUart
* 功能说明: 配置串口的硬件参数(波特率,数据位,停止位,起始位,校验位,中断使能)适合于STM32-F4开发板
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void InitHardUart(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
#if UART1_FIFO_EN == 1 /* 串口1 TX = PA9 RX = PA10 或 TX = PB6 RX = PB7*/
/* 第1步: 配置GPIO */
#if 1 /* TX = PA9 RX = PA10 */
/* 打开 GPIO 时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* 打开 UART 时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* 将 PA9 映射为 USART1_TX */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
/* 将 PA10 映射为 USART1_RX */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
/* 配置 USART Tx 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 配置 USART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#else /* TX = PB6 RX = PB7 */
/* 打开 GPIO 时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* 打开 UART 时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* 将 PB6 映射为 USART1_TX */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
/* 将 PB7 映射为 USART1_RX */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
/* 配置 USART Tx 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 配置 USART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
/* 第2步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = UART1_BAUD; /* 波特率 */
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); /* 使能接收中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(USART1, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(USART1, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */
#endif
#if UART2_FIFO_EN == 1 /* 串口2 TX = PD5 RX = PD6 或 TX = PA2, RX = PA3 */
/* 第1步: 配置GPIO */
#if 0 /* 串口2 TX = PD5 RX = PD6 */
/* 打开 GPIO 时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* 打开 UART 时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* 将 PD5 映射为 USART2_TX */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2);
/* 将 PD6 映射为 USART2_RX */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);
/* 配置 USART Tx 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* 配置 USART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOD, &GPIO_InitStructure);
#else /* 串口2 TX = PA2, RX = PA3 */
/* 打开 GPIO 时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* 打开 UART 时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* 将 PA2 映射为 USART2_TX. 在STM32-V5板中,PA2 管脚用于以太网 */
//GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
/* 将 PA3 映射为 USART2_RX */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
/* 配置 USART Tx 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 配置 USART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#endif
/* 第2步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = UART2_BAUD; /* 波特率 */
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_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); /* 使能接收中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(USART2, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(USART2, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */
#endif
#if UART3_FIFO_EN == 1 /* 串口3 TX = PB10 RX = PB11 */
/* 配置 PB2为推挽输出,用于切换 RS485芯片的收发状态 */
{
RCC_AHB1PeriphClockCmd(RCC_RS485_TXEN, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; /* 设为输出口 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 设为推挽模式 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; /* 上下拉电阻不使能 */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; /* IO口最大速度 */
GPIO_InitStructure.GPIO_Pin = PIN_RS485_TXEN;
GPIO_Init(PORT_RS485_TXEN, &GPIO_InitStructure);
}
/* 打开 GPIO 时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* 打开 UART 时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
/* 将 PB10 映射为 USART3_TX */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
/* 将 PB11 映射为 USART3_RX */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);
/* 配置 USART Tx 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 配置 USART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 第2步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = UART3_BAUD; /* 波特率 */
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(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); /* 使能接收中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(USART3, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(USART3, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */
#endif
#if UART4_FIFO_EN == 1 /* 串口4 TX = PC10 RX = PC11 */
/* 第1步: 配置GPIO */
/* 打开 GPIO 时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
/* 打开 UART 时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
/* 将 PC10 映射为 UART4_TX */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART1);
/* 将 PC11 映射为 UART4_RX */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART1);
/* 配置 USART Tx 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* 配置 USART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* 第2步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = UART1_BAUD; /* 波特率 */
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(UART4, &USART_InitStructure);
USART_ITConfig(UART4, USART_IT_RXNE, ENABLE); /* 使能接收中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(UART4, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(UART4, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */
#endif
#if UART5_FIFO_EN == 1 /* 串口5 TX = PC12 RX = PD2 */
/* 第1步: 配置GPIO */
/* 打开 GPIO 时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC |RCC_AHB1Periph_GPIOD, ENABLE);
/* 打开 UART 时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
/* 将 PC12 映射为 UART5_TX */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5);
/* 将 PD2 映射为 UART5_RX */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5);
/* 配置 UART Tx 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* 配置 UART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* 第2步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = UART5_BAUD; /* 波特率 */
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(UART5, &USART_InitStructure);
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE); /* 使能接收中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(UART5, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(UART5, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */
#endif
#if UART6_FIFO_EN == 1 /* PG14/USART6_TX , PC7/USART6_RX,PG8/USART6_RTS, PG15/USART6_CTS */
/* 第1步: 配置GPIO */
/* 打开 GPIO 时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC |RCC_AHB1Periph_GPIOG, ENABLE);
/* 打开 UART 时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
/* 将 PG14 映射为 USART6_TX */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_USART6);
/* 将 PC7 映射为 USART6_RX */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
/* 将 PG8 映射为 USART6_RTS */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource8, GPIO_AF_USART6);
/* 将 PG15 映射为 USART6_CTS */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource15, GPIO_AF_USART6);
/* 配置 PG14/USART6_TX 为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 输出类型为推挽 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /* 内部上拉电阻使能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /* 复用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/* 配置 PC7/USART6_RX 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* 配置 PG8/USART6_RTS 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/* 配置 PG15/USART6_CTS 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/* 第2步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = UART6_BAUD; /* 波特率 */
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_RTS_CTS; /* 选择硬件流控 */
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; /* 不要硬件流控 */
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART6, &USART_InitStructure);
USART_ITConfig(USART6, USART_IT_RXNE, ENABLE); /* 使能接收中断 */
/*
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
注意: 不要在此处打开发送中断
发送中断使能在SendUart()函数打开
*/
USART_Cmd(USART6, ENABLE); /* 使能串口 */
/* CPU的小缺陷:串口配置好,如果直接Send,则第1个字节发送不出去
如下语句解决第1个字节无法正确发送出去的问题 */
USART_ClearFlag(USART6, USART_FLAG_TC); /* 清发送完成标志,Transmission Complete flag */
#endif
}
/*
*********************************************************************************************************
* 函 数 名: ConfigUartNVIC
* 功能说明: 配置串口硬件中断.
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void ConfigUartNVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
/* NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); --- 在 bsp.c 中 bsp_Init() 中配置中断优先级组 */
#if UART1_FIFO_EN == 1
/* 使能串口1中断 */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
#if UART2_FIFO_EN == 1
/* 使能串口2中断 */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
#if UART3_FIFO_EN == 1
/* 使能串口3中断t */
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
#if UART4_FIFO_EN == 1
/* 使能串口4中断t */
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
#if UART5_FIFO_EN == 1
/* 使能串口5中断t */
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
#if UART6_FIFO_EN == 1
/* 使能串口6中断t */
NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
}
/*
*********************************************************************************************************
* 函 数 名: UartSend
* 功能说明: 填写数据到UART发送缓冲区,并启动发送中断。中断处理函数发送完毕后,自动关闭发送中断
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void UartSend(UART_T *_pUart, uint8_t *_ucaBuf, uint16_t _usLen)
{
uint16_t i;
for (i = 0; i < _usLen; i++)
{
/* 如果发送缓冲区已经满了,则等待缓冲区空 */
#if 0
/*
在调试GPRS例程时,下面的代码出现死机,while 死循环
原因: 发送第1个字节时 _pUart->usTxWrite = 1;_pUart->usTxRead = 0;
将导致while(1) 无法退出
*/
while (1)
{
uint16_t usRead;
DISABLE_INT();
usRead = _pUart->usTxRead;
ENABLE_INT();
if (++usRead >= _pUart->usTxBufSize)
{
usRead = 0;
}
if (usRead != _pUart->usTxWrite)
{
break;
}
}
#else
/* 当 _pUart->usTxBufSize == 1 时, 下面的函数会死掉(待完善) */
while (1)
{
__IO uint16_t usCount;
DISABLE_INT();
usCount = _pUart->usTxCount;
ENABLE_INT();
if (usCount < _pUart->usTxBufSize)
{
break;
}
}
#endif
/* 将新数据填入发送缓冲区 */
_pUart->pTxBuf[_pUart->usTxWrite] = _ucaBuf[i];
DISABLE_INT();
if (++_pUart->usTxWrite >= _pUart->usTxBufSize)
{
_pUart->usTxWrite = 0;
}
_pUart->usTxCount++;
ENABLE_INT();
}
USART_ITConfig(_pUart->uart, USART_IT_TXE, ENABLE);
}
/*
*********************************************************************************************************
* 函 数 名: UartGetChar
* 功能说明: 从串口接收缓冲区读取1字节数据 (用于主程序调用)
* 形 参: _pUart : 串口设备
* _pByte : 存放读取数据的指针
* 返 回 值: 0 表示无数据 1表示读取到数据
*********************************************************************************************************
*/
static uint8_t UartGetChar(UART_T *_pUart, uint8_t *_pByte)
{
uint16_t usCount;
/* usRxWrite 变量在中断函数中被改写,主程序读取该变量时,必须进行临界区保护 */
DISABLE_INT();
usCount = _pUart->usRxCount;
ENABLE_INT();
/* 如果读和写索引相同,则返回0 */
//if (_pUart->usRxRead == usRxWrite)
if (usCount == 0) /* 已经没有数据 */
{
return 0;
}
else
{
*_pByte = _pUart->pRxBuf[_pUart->usRxRead]; /* 从串口接收FIFO取1个数据 */
/* 改写FIFO读索引 */
DISABLE_INT();
if (++_pUart->usRxRead >= _pUart->usRxBufSize)
{
_pUart->usRxRead = 0;
}
_pUart->usRxCount--;
ENABLE_INT();
return 1;
}
}
/*
*********************************************************************************************************
* 函 数 名: UartIRQ
* 功能说明: 供中断服务程序调用,通用串口中断处理函数
* 形 参: _pUart : 串口设备
* 返 回 值: 无
*********************************************************************************************************
*/
static void UartIRQ(UART_T *_pUart)
{
/* 处理接收中断 */
if (USART_GetITStatus(_pUart->uart, USART_IT_RXNE) != RESET)
{
/* 从串口接收数据寄存器读取数据存放到接收FIFO */
uint8_t ch;
ch = USART_ReceiveData(_pUart->uart);
_pUart->pRxBuf[_pUart->usRxWrite] = ch;
if (++_pUart->usRxWrite >= _pUart->usRxBufSize)
{
_pUart->usRxWrite = 0;
}
if (_pUart->usRxCount < _pUart->usRxBufSize)
{
_pUart->usRxCount++;
}
/* 回调函数,通知应用程序收到新数据,一般是发送1个消息或者设置一个标记 */
//if (_pUart->usRxWrite == _pUart->usRxRead)
//if (_pUart->usRxCount == 1)
{
if (_pUart->ReciveNew)
{
_pUart->ReciveNew(ch);
}
}
}
/* 处理发送缓冲区空中断 */
if (USART_GetITStatus(_pUart->uart, USART_IT_TXE) != RESET)
{
//if (_pUart->usTxRead == _pUart->usTxWrite)
if (_pUart->usTxCount == 0)
{
/* 发送缓冲区的数据已取完时, 禁止发送缓冲区空中断 (注意:此时最后1个数据还未真正发送完毕)*/
USART_ITConfig(_pUart->uart, USART_IT_TXE, DISABLE);
/* 使能数据发送完毕中断 */
USART_ITConfig(_pUart->uart, USART_IT_TC, ENABLE);
}
else
{
/* 从发送FIFO取1个字节写入串口发送数据寄存器 */
USART_SendData(_pUart->uart, _pUart->pTxBuf[_pUart->usTxRead]);
if (++_pUart->usTxRead >= _pUart->usTxBufSize)
{
_pUart->usTxRead = 0;
}
_pUart->usTxCount--;
}
}
/* 数据bit位全部发送完毕的中断 */
else if (USART_GetITStatus(_pUart->uart, USART_IT_TC) != RESET)
{
//if (_pUart->usTxRead == _pUart->usTxWrite)
if (_pUart->usTxCount == 0)
{
/* 如果发送FIFO的数据全部发送完毕,禁止数据发送完毕中断 */
USART_ITConfig(_pUart->uart, USART_IT_TC, DISABLE);
/* 回调函数, 一般用来处理RS485通信,将RS485芯片设置为接收模式,避免抢占总线 */
if (_pUart->SendOver)
{
_pUart->SendOver();
}
}
else
{
/* 正常情况下,不会进入此分支 */
/* 如果发送FIFO的数据还未完毕,则从发送FIFO取1个数据写入发送数据寄存器 */
USART_SendData(_pUart->uart, _pUart->pTxBuf[_pUart->usTxRead]);
if (++_pUart->usTxRead >= _pUart->usTxBufSize)
{
_pUart->usTxRead = 0;
}
_pUart->usTxCount--;
}
}
}
/*
*********************************************************************************************************
* 函 数 名: USART1_IRQHandler USART2_IRQHandler USART3_IRQHandler UART4_IRQHandler UART5_IRQHandler
* 功能说明: USART中断服务程序
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
#if UART1_FIFO_EN == 1
void USART1_IRQHandler(void)
{
UartIRQ(&g_tUart1);
}
#endif
#if UART2_FIFO_EN == 1
void USART2_IRQHandler(void)
{
UartIRQ(&g_tUart2);
}
#endif
#if UART3_FIFO_EN == 1
void USART3_IRQHandler(void)
{
UartIRQ(&g_tUart3);
}
#endif
#if UART4_FIFO_EN == 1
void UART4_IRQHandler(void)
{
UartIRQ(&g_tUart4);
}
#endif
#if UART5_FIFO_EN == 1
void UART5_IRQHandler(void)
{
UartIRQ(&g_tUart5);
}
#endif
#if UART6_FIFO_EN == 1
void USART6_IRQHandler(void)
{
UartIRQ(&g_tUart6);
}
#endif
/*
*********************************************************************************************************
* 函 数 名: fputc
* 功能说明: 重定义putc函数,这样可以使用printf函数从串口1打印输出
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
int fputc(int ch, FILE *f)
{
#if 0 /* 将需要printf的字符通过串口中断FIFO发送出去,printf函数会立即返回 */
comSendChar(COM1, ch);
return ch;
#else /* 采用阻塞方式发送每个字符,等待数据发送完毕 */
/* 写一个字节到USART1 */
USART_SendData(USART1, (uint8_t) ch);
/* 等待发送结束 */
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
return ch;
#endif
}
/*
*********************************************************************************************************
* 函 数 名: fgetc
* 功能说明: 重定义getc函数,这样可以使用getchar函数从串口1输入数据
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
int fgetc(FILE *f)
{
#if 1 /* 从串口接收FIFO中取1个数据, 只有取到数据才返回 */
uint8_t ucData;
while(comGetChar(COM1, &ucData) == 0);
return ucData;
#else
/* 等待串口1输入数据 */
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1);
#endif
}
UART_StatusTypeDef uart_receive_byte(uint8_t *byCh, uint32_t dwTimeout)
{
if(NULL == byCh){
return UART_ERROR;
}
if(0 == dwTimeout){
while(1){
if (comGetChar(COM1, byCh))
{
return UART_OK;
}
}
}
else{
while(dwTimeout --){
if (comGetChar(COM1, byCh))
{
return UART_OK;
}
bsp_DelayUS(1);
}
}
return UART_TIMEOUT;
}
UART_StatusTypeDef uart_receive_data(uint8_t *byString, uint32_t dwLength, uint32_t dwTimeout)
{
uint32_t i;
UART_StatusTypeDef enUartStatus = UART_OK;
if(0 == dwLength || NULL == byString)\
{
return UART_ERROR;
}
for(i = 0; i < dwLength; i++)
{
enUartStatus = uart_receive_byte(byString + i, dwTimeout);
if(enUartStatus != UART_OK){
return enUartStatus;
}
}
return enUartStatus;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)