uart_communication.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /**********************************
  2. * 文件名称: uart_communication.c
  3. * 功能描述: 串口通信模块
  4. **********************************/
  5. #include "main.h"
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include "uart_communication.h"
  9. // 接收缓冲区
  10. volatile uint16_t com1_rx_len = 0; // 接收帧数据的长度
  11. volatile uint8_t com1_recv_end_flag = 0; // 帧数据接收完成标志
  12. uint8_t com1_rx_buffer[UART_BUFFER_SIZE] = {0}; // 接收数据缓存
  13. uint8_t DMA_USART1_TX_BUF[UART_BUFFER_SIZE] = {0}; // DMA发送缓存
  14. void uart_comm_Init(u32 bound)
  15. {
  16. GPIO_InitTypeDef GPIO_InitStructure;
  17. USART_InitTypeDef USART_InitStructure;
  18. NVIC_InitTypeDef NVIC_InitStructure;
  19. DMA_InitTypeDef DMA_InitStructure;
  20. // 使能 GPIO 时钟(TX 和 RX)
  21. RCC_AHB1PeriphClockCmd(UART_COMM_TX_GPIO_CLK | UART_COMM_RX_GPIO_CLK, ENABLE);
  22. // 使能 USART 时钟
  23. RCC_APB2PeriphClockCmd(UART_COMM_CLK, ENABLE);
  24. // 使能 DMA 时钟
  25. RCC_AHB1PeriphClockCmd(UART_DMA_CLK, ENABLE);
  26. // 等待 DMA 流可配置
  27. while (DMA_GetCmdStatus(UART_DMA_TX_STREAM) != DISABLE);
  28. // 配置 TX 引脚
  29. GPIO_InitStructure.GPIO_Pin = UART_COMM_TX_PIN;
  30. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  31. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  32. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  33. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  34. GPIO_Init(UART_COMM_TX_GPIO_PORT, &GPIO_InitStructure);
  35. // 配置 RX 引脚
  36. GPIO_InitStructure.GPIO_Pin = UART_COMM_RX_PIN;
  37. GPIO_Init(UART_COMM_RX_GPIO_PORT, &GPIO_InitStructure);
  38. // 配置 GPIO 复用功能
  39. GPIO_PinAFConfig(UART_COMM_TX_GPIO_PORT, UART_COMM_TX_SOURCE, UART_COMM_TX_AF);
  40. GPIO_PinAFConfig(UART_COMM_RX_GPIO_PORT, UART_COMM_RX_SOURCE, UART_COMM_RX_AF);
  41. // ========== 关键修复:添加 USART 初始化配置 ==========
  42. USART_InitStructure.USART_BaudRate = bound;
  43. USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  44. USART_InitStructure.USART_StopBits = USART_StopBits_1;
  45. USART_InitStructure.USART_Parity = USART_Parity_No;
  46. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  47. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  48. USART_Init(UART_COMM, &USART_InitStructure);
  49. // ===================================================
  50. // 配置 NVIC - USART 中断
  51. NVIC_InitStructure.NVIC_IRQChannel = UART_COMM_IRQ;
  52. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  53. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  54. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  55. NVIC_Init(&NVIC_InitStructure);
  56. // 配置 NVIC - DMA 接收中断
  57. NVIC_InitStructure.NVIC_IRQChannel = UART_DMA_RX_IRQn;
  58. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  59. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  60. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  61. NVIC_Init(&NVIC_InitStructure);
  62. // 配置 NVIC - DMA 发送中断
  63. NVIC_InitStructure.NVIC_IRQChannel = UART_DMA_TX_IRQn;
  64. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  65. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
  66. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  67. NVIC_Init(&NVIC_InitStructure);
  68. // 配置 DMA 接收
  69. DMA_DeInit(UART_DMA_RX_STREAM);
  70. DMA_InitStructure.DMA_Channel = UART_DMA_RX_CHANNEL;
  71. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART_COMM->DR;
  72. DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)com1_rx_buffer;
  73. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  74. DMA_InitStructure.DMA_BufferSize = UART_BUFFER_SIZE;
  75. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  76. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  77. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  78. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  79. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  80. DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  81. DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  82. DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  83. DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  84. DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  85. DMA_Init(UART_DMA_RX_STREAM, &DMA_InitStructure);
  86. // 使能 DMA 接收完成中断(可选,用于处理缓冲区满的情况)
  87. DMA_ITConfig(UART_DMA_RX_STREAM, DMA_IT_TC, ENABLE);
  88. DMA_Cmd(UART_DMA_RX_STREAM, ENABLE);
  89. // 配置 DMA 发送
  90. DMA_DeInit(UART_DMA_TX_STREAM);
  91. while (DMA_GetCmdStatus(UART_DMA_TX_STREAM) != DISABLE);
  92. DMA_InitStructure.DMA_Channel = UART_DMA_TX_CHANNEL;
  93. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&UART_COMM->DR;
  94. DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DMA_USART1_TX_BUF;
  95. DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  96. DMA_InitStructure.DMA_BufferSize = UART_BUFFER_SIZE;
  97. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  98. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  99. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  100. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  101. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  102. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
  103. DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  104. DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
  105. DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  106. DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  107. DMA_Init(UART_DMA_TX_STREAM, &DMA_InitStructure);
  108. DMA_ITConfig(UART_DMA_TX_STREAM, DMA_IT_TC, ENABLE);
  109. DMA_Cmd(UART_DMA_TX_STREAM, DISABLE);
  110. // 使能 USART 中断和 DMA
  111. USART_ITConfig(UART_COMM, USART_IT_IDLE, ENABLE);
  112. USART_DMACmd(UART_COMM, USART_DMAReq_Rx, ENABLE);
  113. USART_DMACmd(UART_COMM, USART_DMAReq_Tx, ENABLE);
  114. // 使能 USART
  115. USART_Cmd(UART_COMM, ENABLE);
  116. }
  117. /**
  118. * @brief 串口通信初始化函数
  119. */
  120. void uart_communication_init(void)
  121. {
  122. uart_comm_Init(UART_BAUDRATE);
  123. }
  124. /**
  125. * @brief 发送单个字符
  126. */
  127. void uart_send_char(uint8_t ch)
  128. {
  129. // 等待发送缓冲区空
  130. while ((USART1->SR & USART_SR_TXE) == 0);
  131. USART_SendData(UART_COMM, ch);
  132. }
  133. /**
  134. * @brief 发送数据块
  135. */
  136. void uart_send_data(uint8_t *data, uint16_t length)
  137. {
  138. for (uint16_t i = 0; i < length; i++) {
  139. uart_send_char(data[i]);
  140. }
  141. }
  142. /**
  143. * @brief 发送字符串
  144. */
  145. void uart_send_string(char *str)
  146. {
  147. while (*str)
  148. {
  149. uart_send_char((uint8_t)*str++);
  150. }
  151. }
  152. /**
  153. * @brief 发送浮点数
  154. */
  155. void uart_send_float(float value)
  156. {
  157. uint8_t data[4];
  158. memcpy(data, &value, 4);
  159. uart_send_data(data, 4);
  160. }
  161. /**
  162. * @brief 发送整数
  163. */
  164. void uart_send_int(int32_t value)
  165. {
  166. uint8_t data[4];
  167. memcpy(data, &value, 4);
  168. uart_send_data(data, 4);
  169. }
  170. /**
  171. * @brief 检查是否有数据接收到
  172. */
  173. uint8_t uart_is_data_available(void)
  174. {
  175. return (com1_recv_end_flag == 1);
  176. }
  177. /**
  178. * @brief 获取接收到的数据
  179. */
  180. uint16_t uart_get_received_data(uint8_t *buffer, uint16_t max_len)
  181. {
  182. uint16_t len = 0;
  183. if (com1_recv_end_flag && com1_rx_len > 0) {
  184. len = (com1_rx_len < max_len) ? com1_rx_len : max_len;
  185. memcpy(buffer, com1_rx_buffer, len);
  186. // 清空标志
  187. com1_recv_end_flag = 0;
  188. com1_rx_len = 0;
  189. }
  190. return len;
  191. }
  192. /**
  193. * @brief USART1 中断服务函数
  194. */
  195. void USART1_IRQHandler(void)
  196. {
  197. if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
  198. {
  199. // 关键修复:先清空闲中断标志(读SR再读DR)
  200. volatile uint32_t tmp_sr = USART1->SR;
  201. volatile uint16_t tmp_dr = USART1->DR;
  202. (void)tmp_sr;
  203. (void)tmp_dr;
  204. // 关闭DMA,防止在操作过程中DMA继续写入
  205. DMA_Cmd(UART_DMA_RX_STREAM, DISABLE);
  206. // 获取接收到的数据长度
  207. com1_rx_len = UART_BUFFER_SIZE - DMA_GetCurrDataCounter(UART_DMA_RX_STREAM);
  208. if (com1_rx_len > 0) {
  209. com1_recv_end_flag = 1;
  210. }
  211. // 清除DMA标志
  212. DMA_ClearFlag(UART_DMA_RX_STREAM, DMA_FLAG_TCIF5);
  213. // 重新配置DMA
  214. DMA_SetCurrDataCounter(UART_DMA_RX_STREAM, UART_BUFFER_SIZE);
  215. DMA_Cmd(UART_DMA_RX_STREAM, ENABLE);
  216. }
  217. }
  218. /**
  219. * @brief DMA 发送完成中断处理
  220. */
  221. void DMA2_Stream7_IRQHandler(void)
  222. {
  223. if (DMA_GetFlagStatus(DMA2_Stream7, DMA_FLAG_TCIF7) != RESET)
  224. {
  225. DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7);
  226. DMA_Cmd(DMA2_Stream7, DISABLE);
  227. // 注意:这里不需要再使能TC中断,因为DMA发送完成后,我们不需要额外的串口发送完成中断
  228. // 如果需要确认所有数据已从串口发出,可以等待TC标志
  229. // while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  230. }
  231. }
  232. /**
  233. * @brief DMA 接收完成中断处理(缓冲区满时触发)
  234. */
  235. void DMA2_Stream5_IRQHandler(void)
  236. {
  237. if (DMA_GetFlagStatus(DMA2_Stream5, DMA_FLAG_TCIF5) != RESET)
  238. {
  239. DMA_ClearFlag(DMA2_Stream5, DMA_FLAG_TCIF5);
  240. // 缓冲区满,接收完成
  241. com1_recv_end_flag = 1;
  242. com1_rx_len = UART_BUFFER_SIZE;
  243. // 重新配置DMA
  244. DMA_Cmd(DMA2_Stream5, DISABLE);
  245. DMA_SetCurrDataCounter(DMA2_Stream5, UART_BUFFER_SIZE);
  246. DMA_Cmd(DMA2_Stream5, ENABLE);
  247. }
  248. }
  249. /**
  250. * @brief DMA 发送函数
  251. */
  252. void DMA_USART_COMM_Send(uint8_t *data, uint16_t size)
  253. {
  254. // 等待上一次发送完成
  255. while (DMA_GetCmdStatus(UART_DMA_TX_STREAM) != DISABLE);
  256. // 复制数据到发送缓冲区
  257. memcpy(DMA_USART1_TX_BUF, data, size);
  258. // 配置DMA并开始发送
  259. DMA_SetCurrDataCounter(UART_DMA_TX_STREAM, size);
  260. DMA_Cmd(UART_DMA_TX_STREAM, ENABLE);
  261. }
  262. // printf 重定向(默认禁用,需要时取消注释并删除上面的 #if 0)
  263. #if 0
  264. #if (__ARMCC_VERSION >= 6010050)
  265. __asm(".global __use_no_semihosting\n\t");
  266. __asm(".global __ARM_use_no_argv \n\t");
  267. #else
  268. #pragma import(__use_no_semihosting)
  269. struct __FILE
  270. {
  271. int handle;
  272. };
  273. #endif
  274. int _ttywrch(int ch)
  275. {
  276. ch = ch;
  277. return ch;
  278. }
  279. void _sys_exit(int x)
  280. {
  281. x = x;
  282. }
  283. char *_sys_command_string(char *cmd, int len)
  284. {
  285. return NULL;
  286. }
  287. FILE __stdout;
  288. int fputc(int ch, FILE *f)
  289. {
  290. uart_send_char((uint8_t)ch);
  291. return ch;
  292. }
  293. #endif