完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32的串口介绍
STM32 芯片具有多个 USART 外设用于串口通讯,它是 Universal Synchronous Asynchronous Receiver and Transmitter 的缩写,即通用同步异步收发器可以灵活地与外部设备进行全双工数据交换。有别于 USART,它还有具有 UART 外设(Universal Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。 USART 满足外部设备对工业标准 NRZ 异步串行数据格式的要求,并且使用了小数波特率发生器,可以提供多种波特率,使得它的应用更加广泛。USART 支持同步单向通信和半双工单线通信;还支持局域互连网络 LIN、智能卡(SmartCard)协议与IrDA(红外线数据协会) SIR ENDEC 规范。USART 支持使用 DMA,可实现高速数据通信。 STM32F103与STM32F407的串口使用方法基本相同。
串口配置的模板函数 以STM32F103平台为例,开发了三个核心的串口配置函数,在串口初始化和需要修改参数时可直接调用。这些串口配置函数可以满足大多数应用场景的需求,但需要注意的是为了减少函数的参数个数、提高函数的易用性,部分串口参数直接采用了默认配置(例如收发使能、中断使能、流控禁用等),在一些特殊场景下需要重写部分函数的实现才能修改默认配置。 配置GPIO /** * @brief 配置串口的引脚端口 * @param TXD_Port: 'A'~'G' * @param TXD_Pin: 0~15 * @param RXD_Port: 'A'~'G' * @param RXD_Pin: 0~15 */ void USART_ConfigGPIO(char TXD_Port, uint8_t TXD_Pin, char RXD_Port, uint8_t RXD_Pin) { uint16_t txdPin; uint16_t rxdPin; GPIO_TypeDef *txdPort; GPIO_TypeDef *rxdPort; GPIO_InitTypeDef GPIO_InitStructure; switch (TXD_Port) { case 'A': txdPort = GPIOA; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); break; case 'B': txdPort = GPIOB; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); break; case 'C': txdPort = GPIOC; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); break; case 'D': txdPort = GPIOD; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); break; case 'E': txdPort = GPIOE; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); break; case 'F': txdPort = GPIOF; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE); break; case 'G': txdPort = GPIOG; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE); break; default: break; } txdPin = (uint16_t) (0x0001 << TXD_Pin); switch (RXD_Port) { case 'A': rxdPort = GPIOA; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); break; case 'B': rxdPort = GPIOB; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); break; case 'C': rxdPort = GPIOC; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); break; case 'D': rxdPort = GPIOD; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); break; case 'E': rxdPort = GPIOE; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); break; case 'F': rxdPort = GPIOF; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE); break; case 'G': rxdPort = GPIOG; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE); break; default: break; } rxdPin = (uint16_t) (0x0001 << RXD_Pin); GPIO_InitStructure.GPIO_Pin = txdPin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(txdPort, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = rxdPin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(rxdPort, &GPIO_InitStructure); } 配置NVIC /** * @brief 配置串口的中断向量控制器 * 注意,此函数中未设置中断向量控制器的优先级分组。 * 中断向量控制器的优先级分组应当先在程序其他地方被设置后,再调用此函数。 * 在运行FreeRTOS的系统中,一般情况下采用分组4,即四位都被配置为设置抢占优先级。 * @param portNum: 串口序号1~5 * @param preePriority: 主优先级(抢占优先级) * @param subPriority: 从优先级 */ void USART_ConfigNVIC(uint8_t portNum, uint8_t preePriority, uint8_t subPriority) { NVIC_InitTypeDef NVIC_InitStructure; switch(portNum) { case 1: NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; break; case 2: NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; break; case 3: NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; break; #if defined(STM32F10X_HD) || defined(STM32F10X_HD_VL) || defined(STM32F10X_XL) || defined(STM32F10X_CL) case 4: NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; break; case 5: NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; break; #endif default: break; } NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preePriority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = subPriority; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } 配置USART /** * @brief 配置串口外设 * 注意,函数参数列表中没有列出的配置参数采用默认的配置: * 1. 无硬件流控 2. 双向收发 3. 使能接收中断 4. 开启串口 * 如果需要修改默认的配置参数,则不能直接调用此函数完成串口外设的配置。 * @param portNum: 串口序号1~5 * @param baudRate: 波特率 * * @param wordLength: 数据位长度(枚举变量) * @arg WordLength_8b: 数据位8 * @arg WordLength_9b: 数据位9 * * @param stopBits: 停止位(枚举变量) * @arg StopBits_1: 停止位1 * @arg StopBits_0_5: 停止位0.5 * @arg StopBits_2: 停止位2 * @arg StopBits_1_5: 停止位1.5 * * @param parity: 校验类型(枚举变量) * @arg Parity_No: 无校验 * @arg Parity_Even: 偶校验 * @arg Parity_Odd: 奇校验 */ void USART_ConfigPort(uint8_t portNum, uint32_t baudRate, USART_WordLength_Enum wordLength, USART_StopBits_Enum stopBits, USART_Parity_Enum parity) { USART_InitTypeDef USART_InitStructure; USART_TypeDef* USARTx; //开启外设时钟 switch (portNum) { case 1: USARTx = USART1; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); break; case 2: USARTx = USART2; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); break; case 3: USARTx = USART3; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); break; case 4: USARTx = UART4; RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); break; case 5: USARTx = UART5; RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); break; default: return; } //设置波特率 USART_InitStructure.USART_BaudRate = baudRate; //设置数据位长度(一般情况下无校验时,为8位数据;有奇偶校验时,为9位数据) USART_InitStructure.USART_WordLength = wordLength; //设置停止位 USART_InitStructure.USART_StopBits = stopBits; //设置校验位 if (parity == USART_Parity_No) { USART_InitStructure.USART_Parity = USART_Parity_No; // USART_InitStructure.USART_WordLength = USART_WordLength_8b; } else if (parity == USART_Parity_Even) { USART_InitStructure.USART_Parity = USART_Parity_Even; // USART_InitStructure.USART_WordLength = USART_WordLength_9b; } else if (parity == USART_Parity_Odd) { USART_InitStructure.USART_Parity = USART_Parity_Odd; // USART_InitStructure.USART_WordLength = USART_WordLength_9b; } else { return; } //设置硬件流控 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //设置收发模式 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USARTx, &USART_InitStructure); //设置中断模式 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能外设 USART_Cmd(USARTx, ENABLE); } 扩展库的特性 本串口扩展库的核心是构造了多个循环FIFO队列作为接收数据的缓存。通过向接收数据处理函数传递一个具体的处理函数,可以实现本扩展库较好的封装。开发者设置了合适大小的接收缓冲区之后,仅需要在合适的位置调用接收数据处理函数void USARTx_RevBuffer_Handler(void (*USART1_RevBuffer_HdlPoint)(uint8_t* _Data, uint16_t Count))即可获取缓冲区中保存的串口接收数据,而不必考虑这些数据是如何入队、如何出队的。 本串口扩展库函数采用中断的方式接收串口数据,利用系统空闲处理串口接收数据,采用查询等待的方式发送串口数据。如果需要发送的数据较多,可以考虑利用中断或者DMA传输发送数据,否则系统将会等待较长的时间。同时库函数可以与FREEModbus库配合使用,通过FREEMODBUS_ENABLE宏定义的值可条件编译不同的串口中断服务函数。 需要特别注意的是为了使函数名称与功能更加准确的对应起来,本扩展库中的连续数据发送函数名USART_SendData与标准串口外设库函数中的单字节发送函数名重复了。因为需要将标准库函数中的函数名USART_SendData改为USART_SendByte。当然,也可以修改本扩展库的*连续数据发送函数名,使之区别于标准库的函数名即可。 在"stm32f10x_usart.h"与"stm32f10x_usart.c"需要修改的标准库函数如下: /** * @brief Transmits single data through the USARTx peripheral. * @param USARTx: Select the USART or the UART peripheral. * This parameter can be one of the following values: * USART1, USART2, USART3, UART4 or UART5. * @param Data: the data to transmit. * @retval None */ void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DATA(Data)); /* Transmit Data */ USARTx->DR = (Data & (uint16_t)0x01FF); } 源码 头文件 #ifndef __USART_EXT_H__ #define __USART_EXT_H__ #include "stm32f10x_conf.h" #include "stm32f10x.h" #define USART_Count 5 #define USART1_BufferSize 50 #define USART2_BufferSize 50 #define USART3_BufferSize 50 #define UART4_BufferSize 50 #define UART5_BufferSize 50 typedef enum{ WordLength_8b = USART_WordLength_8b, WordLength_9b = USART_WordLength_9b, } USART_WordLength_Enum; typedef enum{ StopBits_1 = USART_StopBits_1, StopBits_0_5 = USART_StopBits_0_5, StopBits_2 = USART_StopBits_2, StopBits_1_5 = USART_StopBits_1_5, } USART_StopBits_Enum; typedef enum{ Parity_No = USART_Parity_No, Parity_Even = USART_Parity_Even, Parity_Odd = USART_Parity_Odd, } USART_Parity_Enum; void USART_ConfigGPIO(char TXD_Port, uint8_t TXD_Pin, char RXD_Port, uint8_t RXD_Pin); void USART_ConfigNVIC(uint8_t portNum, uint8_t preePriority, uint8_t subPriority); void USART_ConfigPort(uint8_t portNum, uint32_t baudRate, USART_WordLength_Enum wordLength, USART_StopBits_Enum stopBits, USART_Parity_Enum parity); void USART_RevInitAll(void); void USART_RevInit(USART_TypeDef* USARTx); void USART_SendByteData(USART_TypeDef* USARTx,const uint8_t byteData); void USART_SendData_Bit16(USART_TypeDef* USARTx,const uint16_t *Data, uint16_t Count); void USART_SendData(USART_TypeDef* USARTx, const uint8_t *Data, uint16_t Count); uint16_t USART_SendString(USART_TypeDef* USARTx, const char *String); void USART1_RevBuffer_Handler(void (*USART1_RevBuffer_HdlPoint)(uint8_t* _Data, uint16_t Count)); void USART2_RevBuffer_Handler(void (*USART2_RevBuffer_HdlPoint)(uint8_t* _Data, uint16_t Count)); void USART3_RevBuffer_Handler(void (*USART3_RevBuffer_HdlPoint)(uint8_t* _Data, uint16_t Count)); void UART4_RevBuffer_Handler(void (*USART4_RevBuffer_HdlPoint)(uint8_t* _Data, uint16_t Count)); void UART5_RevBuffer_Handler(void (*USART5_RevBuffer_HdlPoint)(uint8_t* _Data, uint16_t Count)); #endif 源文件 #include "usart_ext.h" #include "mb_user.h" /** * 本串口扩展库函数采用中断的方式接收串口数据,利用系统空闲处理串口接收数据,采用查询等待的方式发送串口数据。 * 如果需要发送的数据较多,可以考虑利用中断或者DMA传输发送数据,否则系统将会等待较长的时间。 * 同时库函数可以与FREEModbus库配合使用,通过FREEMODBUS_ENABLE宏定义的值可条件编译不同的串口中断服务函数。 */ /** * 定义串口接收的缓冲区大小,根据串口的应用需求,可以为每个串口设置不同大小的缓冲区 */ const static uint16_t USART_BufferSize[USART_Count] = { USART1_BufferSize, USART2_BufferSize, USART3_BufferSize, UART4_BufferSize, UART5_BufferSize, }; /** * 将各串口接收的缓冲区声明为静态数组变量,防止外部修改 */ static uint8_t USART1_RevBuffer[USART1_BufferSize]; static uint8_t USART2_RevBuffer[USART2_BufferSize]; static uint8_t USART3_RevBuffer[USART3_BufferSize]; static uint8_t USART4_RevBuffer[UART4_BufferSize]; static uint8_t USART5_RevBuffer[UART5_BufferSize]; /** * 指针数组,将各串口接收缓冲区的首地址作为数组的成员,以方便程序操作 */ static uint8_t* USART_RevBuffer[USART_Count]; /** * 指针二维数组,用于管理缓冲区的读写指针 */ static uint8_t* USART_RevPointer[USART_Count][2]; /** * 缓冲区接收数据计数 */ static uint16_t USART_RevCount[USART_Count]; /** * @brief 配置串口的引脚端口 * @param TXD_Port: 'A'~'G' * @param TXD_Pin: 0~15 * @param RXD_Port: 'A'~'G' * @param RXD_Pin: 0~15 */ void USART_ConfigGPIO(char TXD_Port, uint8_t TXD_Pin, char RXD_Port, uint8_t RXD_Pin) { uint16_t txdPin; uint16_t rxdPin; GPIO_TypeDef *txdPort; GPIO_TypeDef *rxdPort; GPIO_InitTypeDef GPIO_InitStructure; switch (TXD_Port) { case 'A': txdPort = GPIOA; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); break; case 'B': txdPort = GPIOB; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); break; case 'C': txdPort = GPIOC; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); break; case 'D': txdPort = GPIOD; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); break; case 'E': txdPort = GPIOE; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); break; case 'F': txdPort = GPIOF; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE); break; case 'G': txdPort = GPIOG; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE); break; default: break; } txdPin = (uint16_t) (0x0001 << TXD_Pin); switch (RXD_Port) { case 'A': rxdPort = GPIOA; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); break; case 'B': rxdPort = GPIOB; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); break; case 'C': rxdPort = GPIOC; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); break; case 'D': rxdPort = GPIOD; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); break; case 'E': rxdPort = GPIOE; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); break; case 'F': rxdPort = GPIOF; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE); break; case 'G': rxdPort = GPIOG; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE); break; default: break; } rxdPin = (uint16_t) (0x0001 << RXD_Pin); GPIO_InitStructure.GPIO_Pin = txdPin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(txdPort, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = rxdPin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(rxdPort, &GPIO_InitStructure); } /** * @brief 配置串口的中断向量控制器 * 注意,此函数中未设置中断向量控制器的优先级分组。 * 中断向量控制器的优先级分组应当先在程序其他地方被设置后,再调用此函数。 * 在运行FreeRTOS的系统中,一般情况下采用分组4,即四位都被配置为设置抢占优先级。 * @param portNum: 串口序号1~5 * @param preePriority: 主优先级(抢占优先级) * @param subPriority: 从优先级 */ void USART_ConfigNVIC(uint8_t portNum, uint8_t preePriority, uint8_t subPriority) { NVIC_InitTypeDef NVIC_InitStructure; switch(portNum) { case 1: NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; break; case 2: NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; break; case 3: NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; break; #if defined(STM32F10X_HD) || defined(STM32F10X_HD_VL) || defined(STM32F10X_XL) || defined(STM32F10X_CL) case 4: NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; break; case 5: NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; break; #endif default: break; } NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = preePriority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = subPriority; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /** * @brief 配置串口外设 * 注意,函数参数列表中没有列出的配置参数采用默认的配置: * 1. 无硬件流控 2. 双向收发 3. 使能接收中断 4. 开启串口 * 如果需要修改默认的配置参数,则不能直接调用此函数完成串口外设的配置。 * @param portNum: 串口序号1~5 * @param baudRate: 波特率 * * @param wordLength: 数据位长度(枚举变量) * @arg WordLength_8b: 数据位8 * @arg WordLength_9b: 数据位9 * * @param stopBits: 停止位(枚举变量) * @arg StopBits_1: 停止位1 * @arg StopBits_0_5: 停止位0.5 * @arg StopBits_2: 停止位2 * @arg StopBits_1_5: 停止位1.5 * * @param parity: 校验类型(枚举变量) * @arg Parity_No: 无校验 * @arg Parity_Even: 偶校验 * @arg Parity_Odd: 奇校验 */ void USART_ConfigPort(uint8_t portNum, uint32_t baudRate, USART_WordLength_Enum wordLength, USART_StopBits_Enum stopBits, USART_Parity_Enum parity) { USART_InitTypeDef USART_InitStructure; USART_TypeDef* USARTx; //开启外设时钟 switch (portNum) { case 1: USARTx = USART1; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); break; case 2: USARTx = USART2; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); break; case 3: USARTx = USART3; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); break; case 4: USARTx = UART4; RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); break; case 5: USARTx = UART5; RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); break; default: return; } //设置波特率 USART_InitStructure.USART_BaudRate = baudRate; //设置数据位长度(一般情况下无校验时,为8位数据;有奇偶校验时,为9位数据) USART_InitStructure.USART_WordLength = wordLength; //设置停止位 USART_InitStructure.USART_StopBits = stopBits; //设置校验位 if (parity == USART_Parity_No) { USART_InitStructure.USART_Parity = USART_Parity_No; // USART_InitStructure.USART_WordLength = USART_WordLength_8b; } else if (parity == USART_Parity_Even) { USART_InitStructure.USART_Parity = USART_Parity_Even; // USART_InitStructure.USART_WordLength = USART_WordLength_9b; } else if (parity == USART_Parity_Odd) { USART_InitStructure.USART_Parity = USART_Parity_Odd; // USART_InitStructure.USART_WordLength = USART_WordLength_9b; } else { return; } //设置硬件流控 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //设置收发模式 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USARTx, &USART_InitStructure); //设置中断模式 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能外设 USART_Cmd(USARTx, ENABLE); } /** * @brief 初始化全部串口缓冲区及其管理变量 */ void USART_RevInitAll(void) { uint8_t i; /// USART_RevBuffer[0] = USART1_RevBuffer; USART_RevBuffer[1] = USART2_RevBuffer; USART_RevBuffer[2] = USART3_RevBuffer; USART_RevBuffer[3] = USART4_RevBuffer; USART_RevBuffer[4] = USART5_RevBuffer; /// for (i = 0; i < USART_Count; ++i) { USART_RevCount = 0; USART_RevPointer[0] = USART_RevBuffer; USART_RevPointer[1] = USART_RevBuffer; } for (i = 0; i < USART_BufferSize[0]; ++i) { USART1_RevBuffer = 0; } for (i = 0; i < USART_BufferSize[1]; ++i) { USART2_RevBuffer = 0; } for (i = 0; i < USART_BufferSize[2]; ++i) { USART3_RevBuffer = 0; } } /** * @brief 初始化指定串口缓冲区及其管理变量 * @param USARTx: 需要初始化的串口 */ void USART_RevInit(USART_TypeDef* USARTx) { uint8_t i; if (USARTx == USART1) { USART_RevBuffer[0] = USART1_RevBuffer; USART_RevCount[0] = 0; USART_RevPointer[0][0] = USART_RevBuffer[0]; USART_RevPointer[0][1] = USART_RevBuffer[0]; for (i = 0; i < USART_BufferSize[0]; ++i) USART1_RevBuffer = 0; } else if (USARTx == USART2) { USART_RevBuffer[1] = USART2_RevBuffer; USART_RevCount[1] = 0; USART_RevPointer[1][0] = USART_RevBuffer[1]; USART_RevPointer[1][1] = USART_RevBuffer[1]; for (i = 0; i < USART_BufferSize[1]; ++i) USART2_RevBuffer = 0; } else if (USARTx == USART3) { USART_RevBuffer[2] = USART3_RevBuffer; USART_RevCount[2] = 0; USART_RevPointer[2][0] = USART_RevBuffer[2]; USART_RevPointer[2][1] = USART_RevBuffer[2]; for (i = 0; i < USART_BufferSize[2]; ++i) USART3_RevBuffer = 0; } else if (USARTx == UART4) { USART_RevBuffer[3] = USART4_RevBuffer; USART_RevCount[3] = 0; USART_RevPointer[3][0] = USART_RevBuffer[3]; USART_RevPointer[3][1] = USART_RevBuffer[3]; for (i = 0; i < USART_BufferSize[3]; ++i) USART4_RevBuffer = 0; } else if (USARTx == UART5) { USART_RevBuffer[4] = USART5_RevBuffer; USART_RevCount[4] = 0; USART_RevPointer[4][0] = USART_RevBuffer[4]; USART_RevPointer[4][1] = USART_RevBuffer[4]; for (i = 0; i < USART_BufferSize[4]; ++i) USART5_RevBuffer = 0; } else { ; } } /** * @brief 通过指定串口发送字节数据 * 通过查询的方式确认发送结果,如果发送失败,此函数会阻塞 * @param USARTx: 发送数据的串口 * @param byteData: 发送的字节数据 */ void USART_SendByteData(USART_TypeDef* USARTx, const uint8_t byteData) { USART_SendByte(USARTx, (uint16_t) byteData); while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET) ; } /** * @brief 通过指定的串口发送连续16位数据 * 单个16位数据的传输通过发送两次8位数据,高位先发送,低位后发送 * 通过查询的方式确认发送结果,如果发送失败,此函数会阻塞 * @param USARTx: 发送数据的串口 * @param Data: 发送16位数据的起始地址 * @param Count: 发送数据的数量 */ void USART_SendData_Bit16(USART_TypeDef* USARTx, const uint16_t *Data, uint16_t Count) { for (uint16_t i = 0; i < Count; i++) { USART_SendByte(USARTx, (*Data) >> 8); while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET) ; USART_SendByte(USARTx, *Data); while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET) ; Data++; } } |
|
|
|
/** * @brief 通过指定的串口发送连续8位数据 * 通过查询的方式确认发送结果,如果发送失败,此函数会阻塞 * @param USARTx: 发送数据的串口 * @param Data: 发送8位数据的起始地址 * @param Count: 发送数据的数量 */ void USART_SendData(USART_TypeDef* USARTx, const uint8_t *Data, uint16_t Count) { uint16_t i; for (i = 0; i < Count; i++) { USART_SendByte(USARTx, (uint16_t) *Data); Data++; while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET) ; } } /** * @brief 通过指定的串口发送字符串 * 通过查询的方式确认发送结果,如果发送失败,此函数会阻塞 * @param USARTx: 发送数据的串口 * @param String: 需要发送的字符串(检测到' |