| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- /**********************************
- * 文件名称: uart_communication.c
- * 功能描述: 串口通信模块
- **********************************/
- #include "main.h"
- #include <stdio.h>
- #include <string.h>
- #include "uart_communication.h"
- // 接收缓冲区
- volatile uint16_t com1_rx_len = 0; // 接收帧数据的长度
- volatile uint8_t com1_recv_end_flag = 0; // 帧数据接收完成标志
- uint8_t com1_rx_buffer[UART_BUFFER_SIZE] = {0}; // 接收数据缓存
- uint8_t DMA_USART1_TX_BUF[UART_BUFFER_SIZE] = {0}; // DMA发送缓存
- void uart_comm_Init(u32 bound)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- DMA_InitTypeDef DMA_InitStructure;
-
- // 使能 GPIO 时钟(TX 和 RX)
- RCC_AHB1PeriphClockCmd(UART_COMM_TX_GPIO_CLK | UART_COMM_RX_GPIO_CLK, ENABLE);
-
- // 使能 USART 时钟
- RCC_APB2PeriphClockCmd(UART_COMM_CLK, ENABLE);
-
- // 使能 DMA 时钟
- RCC_AHB1PeriphClockCmd(UART_DMA_CLK, ENABLE);
-
- // 等待 DMA 流可配置
- while (DMA_GetCmdStatus(UART_DMA_TX_STREAM) != DISABLE);
-
- // 配置 TX 引脚
- GPIO_InitStructure.GPIO_Pin = UART_COMM_TX_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(UART_COMM_TX_GPIO_PORT, &GPIO_InitStructure);
-
- // 配置 RX 引脚
- GPIO_InitStructure.GPIO_Pin = UART_COMM_RX_PIN;
- GPIO_Init(UART_COMM_RX_GPIO_PORT, &GPIO_InitStructure);
-
- // 配置 GPIO 复用功能
- GPIO_PinAFConfig(UART_COMM_TX_GPIO_PORT, UART_COMM_TX_SOURCE, UART_COMM_TX_AF);
- GPIO_PinAFConfig(UART_COMM_RX_GPIO_PORT, UART_COMM_RX_SOURCE, UART_COMM_RX_AF);
-
- // ========== 关键修复:添加 USART 初始化配置 ==========
- USART_InitStructure.USART_BaudRate = bound;
- 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(UART_COMM, &USART_InitStructure);
- // ===================================================
-
- // 配置 NVIC - USART 中断
- NVIC_InitStructure.NVIC_IRQChannel = UART_COMM_IRQ;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
-
- // 配置 NVIC - DMA 接收中断
- NVIC_InitStructure.NVIC_IRQChannel = UART_DMA_RX_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
-
- // 配置 NVIC - DMA 发送中断
- NVIC_InitStructure.NVIC_IRQChannel = UART_DMA_TX_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
-
- // 配置 DMA 接收
- DMA_DeInit(UART_DMA_RX_STREAM);
- DMA_InitStructure.DMA_Channel = UART_DMA_RX_CHANNEL;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART_COMM->DR;
- DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)com1_rx_buffer;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
- DMA_InitStructure.DMA_BufferSize = UART_BUFFER_SIZE;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(UART_DMA_RX_STREAM, &DMA_InitStructure);
-
- // 使能 DMA 接收完成中断(可选,用于处理缓冲区满的情况)
- DMA_ITConfig(UART_DMA_RX_STREAM, DMA_IT_TC, ENABLE);
- DMA_Cmd(UART_DMA_RX_STREAM, ENABLE);
-
- // 配置 DMA 发送
- DMA_DeInit(UART_DMA_TX_STREAM);
- while (DMA_GetCmdStatus(UART_DMA_TX_STREAM) != DISABLE);
- DMA_InitStructure.DMA_Channel = UART_DMA_TX_CHANNEL;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART_COMM->DR;
- DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DMA_USART1_TX_BUF;
- DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
- DMA_InitStructure.DMA_BufferSize = UART_BUFFER_SIZE;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(UART_DMA_TX_STREAM, &DMA_InitStructure);
-
- DMA_ITConfig(UART_DMA_TX_STREAM, DMA_IT_TC, ENABLE);
- DMA_Cmd(UART_DMA_TX_STREAM, DISABLE);
-
- // 使能 USART 中断和 DMA
- USART_ITConfig(UART_COMM, USART_IT_IDLE, ENABLE);
- USART_DMACmd(UART_COMM, USART_DMAReq_Rx, ENABLE);
- USART_DMACmd(UART_COMM, USART_DMAReq_Tx, ENABLE);
-
- // 使能 USART
- USART_Cmd(UART_COMM, ENABLE);
- }
- /**
- * @brief 串口通信初始化函数
- */
- void uart_communication_init(void)
- {
- uart_comm_Init(UART_BAUDRATE);
- }
- /**
- * @brief 发送单个字符
- */
- void uart_send_char(uint8_t ch)
- {
- // 等待发送缓冲区空
- while ((USART1->SR & USART_SR_TXE) == 0);
- USART_SendData(UART_COMM, ch);
- }
- /**
- * @brief 发送数据块
- */
- void uart_send_data(uint8_t *data, uint16_t length)
- {
- for (uint16_t i = 0; i < length; i++) {
- uart_send_char(data[i]);
- }
- }
- /**
- * @brief 发送字符串
- */
- void uart_send_string(char *str)
- {
- while (*str)
- {
- uart_send_char((uint8_t)*str++);
- }
- }
- /**
- * @brief 发送浮点数
- */
- void uart_send_float(float value)
- {
- uint8_t data[4];
- memcpy(data, &value, 4);
- uart_send_data(data, 4);
- }
- /**
- * @brief 发送整数
- */
- void uart_send_int(int32_t value)
- {
- uint8_t data[4];
- memcpy(data, &value, 4);
- uart_send_data(data, 4);
- }
- /**
- * @brief 检查是否有数据接收到
- */
- uint8_t uart_is_data_available(void)
- {
- return (com1_recv_end_flag == 1);
- }
- /**
- * @brief 获取接收到的数据
- */
- uint16_t uart_get_received_data(uint8_t *buffer, uint16_t max_len)
- {
- uint16_t len = 0;
-
- if (com1_recv_end_flag && com1_rx_len > 0) {
- len = (com1_rx_len < max_len) ? com1_rx_len : max_len;
- memcpy(buffer, com1_rx_buffer, len);
-
- // 清空标志
- com1_recv_end_flag = 0;
- com1_rx_len = 0;
- }
-
- return len;
- }
- /**
- * @brief USART1 中断服务函数
- */
- void USART1_IRQHandler(void)
- {
- if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
- {
- // 关键修复:先清空闲中断标志(读SR再读DR)
- volatile uint32_t tmp_sr = USART1->SR;
- volatile uint16_t tmp_dr = USART1->DR;
- (void)tmp_sr;
- (void)tmp_dr;
-
- // 关闭DMA,防止在操作过程中DMA继续写入
- DMA_Cmd(UART_DMA_RX_STREAM, DISABLE);
-
- // 获取接收到的数据长度
- com1_rx_len = UART_BUFFER_SIZE - DMA_GetCurrDataCounter(UART_DMA_RX_STREAM);
-
- if (com1_rx_len > 0) {
- com1_recv_end_flag = 1;
- }
-
- // 清除DMA标志
- DMA_ClearFlag(UART_DMA_RX_STREAM, DMA_FLAG_TCIF5);
-
- // 重新配置DMA
- DMA_SetCurrDataCounter(UART_DMA_RX_STREAM, UART_BUFFER_SIZE);
- DMA_Cmd(UART_DMA_RX_STREAM, ENABLE);
- }
- }
- /**
- * @brief DMA 发送完成中断处理
- */
- void DMA2_Stream7_IRQHandler(void)
- {
- if (DMA_GetFlagStatus(DMA2_Stream7, DMA_FLAG_TCIF7) != RESET)
- {
- DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7);
- DMA_Cmd(DMA2_Stream7, DISABLE);
- // 注意:这里不需要再使能TC中断,因为DMA发送完成后,我们不需要额外的串口发送完成中断
- // 如果需要确认所有数据已从串口发出,可以等待TC标志
- // while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
- }
- }
- /**
- * @brief DMA 接收完成中断处理(缓冲区满时触发)
- */
- void DMA2_Stream5_IRQHandler(void)
- {
- if (DMA_GetFlagStatus(DMA2_Stream5, DMA_FLAG_TCIF5) != RESET)
- {
- DMA_ClearFlag(DMA2_Stream5, DMA_FLAG_TCIF5);
-
- // 缓冲区满,接收完成
- com1_recv_end_flag = 1;
- com1_rx_len = UART_BUFFER_SIZE;
-
- // 重新配置DMA
- DMA_Cmd(DMA2_Stream5, DISABLE);
- DMA_SetCurrDataCounter(DMA2_Stream5, UART_BUFFER_SIZE);
- DMA_Cmd(DMA2_Stream5, ENABLE);
- }
- }
- /**
- * @brief DMA 发送函数
- */
- void DMA_USART_COMM_Send(uint8_t *data, uint16_t size)
- {
- // 等待上一次发送完成
- while (DMA_GetCmdStatus(UART_DMA_TX_STREAM) != DISABLE);
-
- // 复制数据到发送缓冲区
- memcpy(DMA_USART1_TX_BUF, data, size);
-
- // 配置DMA并开始发送
- DMA_SetCurrDataCounter(UART_DMA_TX_STREAM, size);
- DMA_Cmd(UART_DMA_TX_STREAM, ENABLE);
- }
- // printf 重定向(默认禁用,需要时取消注释并删除上面的 #if 0)
- #if 0
- #if (__ARMCC_VERSION >= 6010050)
- __asm(".global __use_no_semihosting\n\t");
- __asm(".global __ARM_use_no_argv \n\t");
- #else
- #pragma import(__use_no_semihosting)
- struct __FILE
- {
- int handle;
- };
- #endif
- int _ttywrch(int ch)
- {
- ch = ch;
- return ch;
- }
- void _sys_exit(int x)
- {
- x = x;
- }
- char *_sys_command_string(char *cmd, int len)
- {
- return NULL;
- }
- FILE __stdout;
- int fputc(int ch, FILE *f)
- {
- uart_send_char((uint8_t)ch);
- return ch;
- }
- #endif
|