• PY32F003F18之DMA串口


    PY32F003F18使用DMA串口,官方程序省FLASH,但不省内存。单片机内存够大,节省没意义,故做了修改,少用HAL库中的发送和接收,从里面抠出有用的部分,修修改改就可以了。

    一、DMA串口初始化流程:

    假定:串口发送引脚USART2_TX使用PA0,串口接收引脚USART2_RX使用PA1
    1、使能USART2外设时钟,__HAL_RCC_USART2_CLK_ENABLE();

    2、使能GPIOA时钟,__HAL_RCC_GPIOA_CLK_ENABLE();

    3、将串口发送引脚USART2_TX映射到PA0

    4、将串口接收引脚USART2_RX映射到PA1

    5、设置串口帧格式和波特率

    6、将DMA通道1映射到USART2_TX,将DMA通道2映射到USART2_RX

      __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
        HAL_SYSCFG_DMA_Req(0x0807);
        //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
        //DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
        //DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX

    7、配置DMA串口发送,传输"从内存到外设"

    8、配置DMA串口接收,传输"从外设到内存"

    9、关闭串口接收中断

    10、不使能"串口发送数据寄存器为空"产生中断

    11、不使能"串口发送完成"产生中断

    二、测试程序

    1. #include "USART2.h"
    2. #include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
    3. #include "string.h" //使能strcpy(),strlen(),memset()
    4. #include "My_DMA.h"
    5. #include "delay.h"
    6. //PA0 ------> USART2_TX
    7. //PA1 ------> USART2_RX
    8. uint8_t USART2_TX_Buffer[USART2_TX_Buffer_Size]; //USART2发送缓冲区数组;
    9. uint8_t USART2_TX_Buffer_Send_Index=0; //USART2_TX_Buffer[]的发送索引值;
    10. uint8_t USART2_TX_Buffer_Load_Index=0; //USART2_TX_Buffer[]的装载索引值
    11. uint8_t USART2_TX_Completed_Flag;
    12. uint8_t USART2_TX_Overtime_Conter;//USART2发送超时计数器
    13. uint8_t USART2_RX_Buffer[USART2_RX_Buffer_Size]; //USART2接收缓冲区数组
    14. uint8_t USART2_RX_Buffer_StartIndex;//USART2_RX_Buffer[]的装载索引值
    15. uint8_t USART2_RX_Buffer_EndIndex;//USART2_RX_Buffer[]的装载索引值
    16. uint8_t USART2_RX1_Buffer[USART2_RX1_Buffer_Size]; //USART2接收缓冲区数组
    17. void USART2_Init(uint32_t baudrate);
    18. void Usart2Send(void);
    19. void Usart2Receive(void);
    20. void Usart2Send_DMA1_CH1_config(void);
    21. void Usart2Receive_DMA1_CH2_config(void);
    22. #if USART2Type == 0
    23. //函数功能:
    24. //PA2是为USART2_TX,PA3是USART2_RX
    25. //中断优先级为0x01
    26. //波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
    27. void USART2_Init(uint32_t baudrate)
    28. {
    29. GPIO_InitTypeDef GPIO_InitStructureure;
    30. UART_HandleTypeDef UART_HandleStructureure;
    31. /HAL_UART_MspInit开始
    32. __HAL_RCC_USART2_CLK_ENABLE();//使能USART2外设时钟
    33. __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
    34. //串口引脚映射开始/
    35. GPIO_InitStructureure.Pin = GPIO_PIN_2; //选择第2脚,PA2是为USART2_TX
    36. GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP; //复用功能推挽模式
    37. GPIO_InitStructureure.Pull = GPIO_PULLUP; //引脚上拉被激活
    38. GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    39. GPIO_InitStructureure.Alternate = GPIO_AF4_USART2; //将引脚复用为USART2
    40. HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
    41. //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
    42. //将PA0初始化为USART2_TX
    43. GPIO_InitStructureure.Pin = GPIO_PIN_3; //选择第3脚,PA3是USART2_RX
    44. GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP; //复用功能推挽模式
    45. GPIO_InitStructureure.Pull = GPIO_PULLUP; //引脚上拉被激活
    46. GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    47. GPIO_InitStructureure.Alternate = GPIO_AF4_USART2; //将引脚复用为USART2
    48. HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
    49. //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
    50. //将PA1初始化为USART2_RX
    51. //串口引脚映射结束/
    52. /HAL_UART_MspInit结束
    53. UART_HandleStructureure.Instance = USART2; //接口为USART2
    54. UART_HandleStructureure.Init.BaudRate = baudrate; //波特率为115200bps
    55. UART_HandleStructureure.Init.WordLength = UART_WORDLENGTH_8B; //串口字长度为8
    56. UART_HandleStructureure.Init.StopBits = UART_STOPBITS_1; //串口停止位为1
    57. UART_HandleStructureure.Init.Parity = UART_PARITY_NONE; //串口无需奇偶校验
    58. UART_HandleStructureure.Init.HwFlowCtl = UART_HWCONTROL_NONE; //串口无硬件流程控制
    59. UART_HandleStructureure.Init.Mode = UART_MODE_TX_RX; //串口工作模式为发送和接收模式
    60. UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_NO_INIT;//不使用自动波特率
    61. // UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_AUTOBAUDRATE_INIT;//使用自动波特率配置
    62. // UART_HandleStructureure.AdvancedInit.AutoBaudRateEnable=UART_ADVFEATURE_AUTOBAUDRATE_ENABLE;//自动波特率使能
    63. // UART_HandleStructureure.AdvancedInit.AutoBaudRateMode=UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT;//自动波特率模式
    64. HAL_UART_Init(&UART_HandleStructureure);
    65. //根据UART_HandleStructureure型结构初始化USART2
    66. __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
    67. HAL_SYSCFG_DMA_Req(0x0807);
    68. //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
    69. //DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
    70. //DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX
    71. Usart2Send_DMA1_CH1_config();
    72. Usart2Receive_DMA1_CH2_config();
    73. // HAL_NVIC_SetPriority(USART2_IRQn, 0x01, 0);
    74. //设置串口2中断优先级为0x01,0无意义.USART2_IRQn表示中断源为串口2
    75. // __HAL_UART_ENABLE_IT(&UART_HandleStructureure, UART_IT_RXNE);
    76. //开启串口接收中断
    77. //串口接收数据时,使能"接收数据寄存器不为空"则产生中断(位RXNE=1)
    78. //Enable the UART Data Register not empty Interrupt
    79. __HAL_UART_DISABLE_IT(&UART_HandleStructureure, UART_IT_RXNE);
    80. //关闭串口接收中断
    81. //串口接收数据时,不使能"接收数据寄存器不为空"则产生中断(位RXNE=0)
    82. __HAL_UART_DISABLE_IT(&UART_HandleStructureure, UART_IT_TXE);
    83. //串口发送数据时,不使能"串口发送数据寄存器为空"产生中断(位TXE=0)
    84. //Disable the UART Transmit Complete Interrupt
    85. __HAL_UART_DISABLE_IT(&UART_HandleStructureure,UART_IT_TC);
    86. //串口发送数据时,不使能"串口发送完成"产生中断(位TC=1)
    87. /在串口中断服务函数中发送数据配置结束//
    88. // HAL_NVIC_EnableIRQ(USART2_IRQn);
    89. //使能串口2中断
    90. //USART2_IRQn表示中断源为串口2
    91. }
    92. #endif
    93. #if USART2Type ==1
    94. //函数功能:
    95. //PA0是为USART2_TX,PA1是USART2_RX
    96. //中断优先级为0x01
    97. //波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
    98. void USART2_Init(uint32_t baudrate)
    99. {
    100. GPIO_InitTypeDef GPIO_InitStructureure;
    101. UART_HandleTypeDef UART_HandleStructureure;
    102. /HAL_UART_MspInit开始
    103. __HAL_RCC_USART2_CLK_ENABLE();//使能USART2外设时钟
    104. __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
    105. //串口引脚映射开始/
    106. GPIO_InitStructureure.Pin = GPIO_PIN_0; //选择第0脚,PA0是为USART2_TX
    107. GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP; //复用功能推挽模式
    108. GPIO_InitStructureure.Pull = GPIO_PULLUP; //引脚上拉被激活
    109. GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    110. GPIO_InitStructureure.Alternate = GPIO_AF9_USART2; //将引脚复用为USART2
    111. HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
    112. //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
    113. //将PA0初始化为USART2_TX
    114. GPIO_InitStructureure.Pin = GPIO_PIN_1; //选择第1脚,PA1是USART2_RX
    115. GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP; //复用功能推挽模式
    116. GPIO_InitStructureure.Pull = GPIO_PULLUP; //引脚上拉被激活
    117. GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    118. GPIO_InitStructureure.Alternate = GPIO_AF9_USART2; //将引脚复用为USART2
    119. HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
    120. //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
    121. //将PA1初始化为USART2_RX
    122. //串口引脚映射结束/
    123. /HAL_UART_MspInit结束
    124. UART_HandleStructureure.Instance = USART2; //接口为USART2
    125. UART_HandleStructureure.Init.BaudRate = baudrate; //波特率为115200bps
    126. UART_HandleStructureure.Init.WordLength = UART_WORDLENGTH_8B; //串口字长度为8
    127. UART_HandleStructureure.Init.StopBits = UART_STOPBITS_1; //串口停止位为1
    128. UART_HandleStructureure.Init.Parity = UART_PARITY_NONE; //串口无需奇偶校验
    129. UART_HandleStructureure.Init.HwFlowCtl = UART_HWCONTROL_NONE; //串口无硬件流程控制
    130. UART_HandleStructureure.Init.Mode = UART_MODE_TX_RX; //串口工作模式为发送和接收模式
    131. UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_NO_INIT;//不使用自动波特率
    132. // UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_AUTOBAUDRATE_INIT;//使用自动波特率配置
    133. // UART_HandleStructureure.AdvancedInit.AutoBaudRateEnable=UART_ADVFEATURE_AUTOBAUDRATE_ENABLE;//自动波特率使能
    134. // UART_HandleStructureure.AdvancedInit.AutoBaudRateMode=UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT;//自动波特率模式
    135. HAL_UART_Init(&UART_HandleStructureure);
    136. //根据UART_HandleStructureure型结构初始化USART2
    137. __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
    138. HAL_SYSCFG_DMA_Req(0x0807);
    139. //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
    140. //DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
    141. //DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX
    142. Usart2Send_DMA1_CH1_config();
    143. Usart2Receive_DMA1_CH2_config();
    144. // HAL_NVIC_SetPriority(USART2_IRQn, 0x01, 0);
    145. //设置串口2中断优先级为0x01,0无意义.USART2_IRQn表示中断源为串口2
    146. // __HAL_UART_ENABLE_IT(&UART_HandleStructureure, UART_IT_RXNE);
    147. 开启串口接收中断
    148. //串口接收数据时,使能"接收数据寄存器不为空"则产生中断(位RXNE=1)
    149. //Enable the UART Data Register not empty Interrupt
    150. __HAL_UART_DISABLE_IT(&UART_HandleStructureure, UART_IT_RXNE);
    151. //关闭串口接收中断
    152. //串口接收数据时,不使能"接收数据寄存器不为空"则产生中断(位RXNE=0)
    153. __HAL_UART_DISABLE_IT(&UART_HandleStructureure, UART_IT_TXE);
    154. //串口发送数据时,不使能"串口发送数据寄存器为空"产生中断(位TXE=0)
    155. //Disable the UART Transmit Complete Interrupt
    156. __HAL_UART_DISABLE_IT(&UART_HandleStructureure,UART_IT_TC);
    157. //串口发送数据时,不使能"串口发送完成"产生中断(位TC=1)
    158. /在串口中断服务函数中发送数据配置结束//
    159. // HAL_NVIC_EnableIRQ(USART2_IRQn);
    160. //使能串口2中断
    161. //USART2_IRQn表示中断源为串口2
    162. }
    163. #endif
    164. //重定义fputc函数
    165. //函数功能:发送ch的值给USART2串口
    166. int fputc(int ch, FILE *f)
    167. {
    168. _HAL_UART_SendByte(USART2, (unsigned char) ch);
    169. while( _HAL_UART_GET_FLAG(USART2,USART_SR_TC)!= SET); //等待发送完成标志位被置1
    170. return ch;
    171. }
    172. //函数功能:串口2发送一个字节
    173. void USART2_SendByte( unsigned char ch )
    174. {
    175. _HAL_UART_SendByte(USART2, (unsigned char) ch);
    176. while( _HAL_UART_GET_FLAG(USART2,USART_SR_TC)!= SET); //等待发送完成标志位被置1
    177. }
    178. void Usart2Send_DMA1_CH1_config(void)
    179. {
    180. DMA_HandleTypeDef hdma_usart2_tx;
    181. __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
    182. __HAL_RCC_DMA_CLK_ENABLE(); //使能DMA时钟
    183. ///配置串口DMA发送开始
    184. hdma_usart2_tx.DmaBaseAddress = DMA1; //选择DMA1传输
    185. hdma_usart2_tx.Instance = DMA1_Channel1; //DMA1通道1
    186. hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;//DMA传输方向:从内存到外设
    187. hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE; //不使能外设地址增量
    188. hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE; //使能内存地址增量
    189. hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//外设数据宽度为8
    190. hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //存储器数据宽度为8
    191. hdma_usart2_tx.Init.Mode = DMA_NORMAL; //DMA普通模式
    192. hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW; //DMA通道1优先级为低
    193. HAL_DMA_DeInit(&hdma_usart2_tx);
    194. HAL_DMA_Init(&hdma_usart2_tx);
    195. ///配置串口DMA发送结束
    196. // HAL_DMA_ChannelMap(&hdma_usart2_tx,DMA_CHANNEL_MAP_USART2_TX);
    197. //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
    198. //DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
    199. }
    200. void Usart2Receive_DMA1_CH2_config(void)
    201. {
    202. DMA_HandleTypeDef hdma_usart2_rx;
    203. __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
    204. __HAL_RCC_DMA_CLK_ENABLE(); //使能DMA时钟
    205. hdma_usart2_rx.DmaBaseAddress = DMA1; //选择DMA1传输
    206. hdma_usart2_rx.Instance = DMA1_Channel2; //DMA1通道2
    207. // HAL_DMA_ChannelMap(&hdma_usart2_rx,DMA_CHANNEL_MAP_USART2_RX);
    208. //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
    209. //DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX
    210. ///配置串口DMA接收开始
    211. hdma_usart2_rx.DmaBaseAddress = DMA1; //选择DMA1传输
    212. hdma_usart2_rx.Instance = DMA1_Channel2; //DMA1通道2
    213. hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;//DMA传输方向:从外设到内存
    214. hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; //不使能外设地址增量
    215. hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; //使能内存地址增量
    216. hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外设数据宽度为8
    217. hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //存储器数据宽度为8
    218. hdma_usart2_rx.Init.Mode = DMA_NORMAL; //DMA普通模式
    219. hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; //DMA通道2优先级为低
    220. HAL_DMA_DeInit(&hdma_usart2_rx);
    221. HAL_DMA_Init(&hdma_usart2_rx);
    222. ///配置串口DMA接收结束
    223. // HAL_DMA_ChannelMap(&hdma_usart2_rx,DMA_CHANNEL_MAP_USART2_RX);
    224. //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
    225. //DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX
    226. __HAL_DMA_DISABLE(&hdma_usart2_rx);
    227. //"DMA通道x配置寄存器DMA_CCRx"中的EN=0,DMA通道x不使能
    228. // My_DMA_SetConfig(&hdma_usart2_rx,(uint32_t)&USART2->DR,(uint32_t)&USART2_RX_Buffer,USART2_RX_Buffer_Size);
    229. My_DMA1_SetConfig(DMA1_Channel2,(uint32_t)&USART2->DR,(uint32_t)&USART2_RX_Buffer,USART2_RX_Buffer_Size,0);
    230. __HAL_DMA_ENABLE(&hdma_usart2_rx);
    231. //"DMA通道x配置寄存器DMA_CCRx"中的EN=1,DMA通道x使能
    232. _HAL_UART_CLEAR_FLAG(USART2,UART_FLAG_RXNE);
    233. SET_BIT(USART2->CR3, USART_CR3_DMAR);
    234. //"串口控制寄存器3(USART_CR3)中的DMAR位"1,接收时使能DMA
    235. USART2_RX_Buffer_StartIndex=USART2_RX_Buffer_Size-_HAL_DMA_Transfer_Number_Get(DMA1_Channel2);//读DMA1通道2剩余空间
    236. USART2_RX_Buffer_EndIndex=USART2_RX_Buffer_StartIndex;
    237. }
    238. //函数功能:将USART2_TX_Buffer[]中的字符串通过"DMA通道1"写入串口发送寄存器
    239. void Usart2Send1(void)
    240. {
    241. DMA_HandleTypeDef hdma_usart2_tx;
    242. ///配置串口DMA发送开始
    243. hdma_usart2_tx.DmaBaseAddress = DMA1; //选择DMA1传输
    244. hdma_usart2_tx.Instance = DMA1_Channel1; //DMA1通道1
    245. hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;//DMA传输方向:从内存到外设
    246. __HAL_DMA_DISABLE(&hdma_usart2_tx);
    247. My_DMA_SetConfig(&hdma_usart2_tx, (uint32_t)&USART2_TX_Buffer,(uint32_t)&USART2->DR,strlen( (char*)USART2_TX_Buffer ));
    248. __HAL_DMA_ENABLE(&hdma_usart2_tx);
    249. //"DMA通道x配置寄存器DMA_CCRx"中的EN=1,通道x使能
    250. _HAL_UART_CLEAR_FLAG(USART2,UART_FLAG_TC);
    251. SET_BIT(USART2->CR3, USART_CR3_DMAT);
    252. //"串口控制寄存器3(USART_CR3)中的DMAT位"1,发送时使能DMA
    253. while( __HAL_DMA_GET_FLAG(&hdma_usart2_tx,DMA_FLAG_TC1) == RESET)
    254. {//等待"DMA通道1"传输完成
    255. }
    256. __HAL_DMA_CLEAR_FLAG(DMA1_Channel1,DMA_FLAG_TC1);
    257. //"DMA中断标志位清除寄存器DMA_IFCR"中的CTCIF1=0,通道1传输完成标志清零
    258. }
    259. //函数功能:将USART2_TX_Buffer[]中的字符串通过"DMA通道1"写入串口发送寄存器
    260. void Usart2Send(void)
    261. {
    262. _HAL_DMA_DISABLE(DMA1_Channel1);
    263. //"DMA通道1配置寄存器DMA_CCR1"中EN=0,DMA通道1不使能
    264. My_DMA1_SetConfig(DMA1_Channel1,(uint32_t)&USART2_TX_Buffer,(uint32_t)&USART2->DR,strlen( (char*)USART2_TX_Buffer),1);
    265. _HAL_DMA_ENABLE(DMA1_Channel1);
    266. //"DMA通道1配置寄存器DMA_CCR1"中的EN=1,通道1使能
    267. _HAL_UART_CLEAR_FLAG(USART2,UART_FLAG_TC);
    268. SET_BIT(USART2->CR3, USART_CR3_DMAT);
    269. //"串口控制寄存器3(USART_CR3)中的DMAT位"1,发送时使能DMA
    270. while( __HAL_DMA_GET_FLAG(DMA1,DMA_FLAG_TC1) == RESET)
    271. {//等待"DMA通道1"传输完成
    272. }
    273. __HAL_DMA_CLEAR_FLAG(DMA1_Channel1,DMA_FLAG_TC1);
    274. //"DMA中断标志位清除寄存器DMA_IFCR"中的CTCIF1=0,通道1传输完成标志清零
    275. }
    276. //函数功能:
    277. //"串口接收寄存器"通过"DMA1通道2"写入USART2_RX_Buffer[]
    278. //接收完成后,将接收到的有效数据拷贝到USART2_RX1_Buffer[]中
    279. void Usart2Receive(void)
    280. {
    281. uint8_t i;
    282. uint8_t len_New;
    283. uint8_t len_Old;
    284. len_New=_HAL_DMA_Transfer_Number_Get(DMA1_Channel2);//"DMA1通道2"剩余空间
    285. len_Old=len_New;
    286. USART2_RX_Buffer_EndIndex=USART2_RX_Buffer_Size-len_Old;
    287. if(USART2_RX_Buffer_StartIndex!=USART2_RX_Buffer_EndIndex)//发现新数据
    288. {
    289. for(i=0;i<10;i++)//查询是否接收完成
    290. {
    291. delay_us(100);
    292. len_New=_HAL_DMA_Transfer_Number_Get(DMA1_Channel2);//读DMA1通道2剩余空间
    293. if(len_New!=len_Old)//接收没有完成
    294. {
    295. len_Old=len_New;
    296. i=0;
    297. }
    298. else//接收超时,表示DMA接收完成
    299. {
    300. USART2_RX_Buffer_EndIndex=USART2_RX_Buffer_Size-len_Old;
    301. //记录尾部
    302. for(i=0;USART2_RX_Buffer_StartIndex!=USART2_RX_Buffer_EndIndex;)
    303. {//将接收到的数据保存到USART2_RX1_Buffer[]中;
    304. USART2_RX1_Buffer[i]=USART2_RX_Buffer[USART2_RX_Buffer_StartIndex];
    305. i++;
    306. USART2_RX_Buffer_StartIndex++;
    307. }
    308. USART2_RX1_Buffer[i]='\0';
    309. i=11;//接收完成
    310. }
    311. }
    312. strcpy((char*)USART2_TX_Buffer,(char*)USART2_RX1_Buffer);
    313. Usart2Send();//将接收到的数据回传
    314. Usart2Receive_DMA1_CH2_config();//重新初始化串口到DMA接收
    315. }
    316. }
    1. #ifndef __USART2_H
    2. #define __USART2_H
    3. #include "py32f0xx_hal.h"
    4. #define USART2Type 1 //
    5. #define _HAL_UART_SendByte(__INSTANCE__, __DATA__) (__INSTANCE__)->DR = ( (__DATA__) & (uint16_t)0x01FF );
    6. //将(__DATA__)写入串口发送缓冲区
    7. #define _HAL_UART_ReceiveByte(__INSTANCE__) ( (uint16_t)( (__INSTANCE__)->DR & (uint16_t)0x01FF) )
    8. //读串口接收缓冲区
    9. #define _HAL_UART_GET_FLAG(__INSTANCE__, __FLAG__) ( ( (__INSTANCE__)->SR & (__FLAG__) ) == (__FLAG__) )
    10. //读串口中断标志位
    11. //(__FLAG__)=UART_IT_RXNE,读"串口接收寄存器为非空时产生的中断标志位"
    12. //(__FLAG__)=UART_IT_PE,读"串口奇偶校验错误产生的中断标志位"
    13. //(__FLAG__)=UART_IT_ERR,读"帧错误、噪音错误和溢出错误时产生的中断标志位"
    14. //(__FLAG__)=UART_IT_TXE时,读"串口发送寄存器为空产生的中断标志位"
    15. //(__FLAG__)=UART_IT_TC时,读"发送完成产生的中断标志位"
    16. #define _HAL_UART_CLEAR_FLAG(__INSTANCE__, __FLAG__) ( (__INSTANCE__)->SR = ~(__FLAG__) )
    17. //清除串口中断标志位
    18. //(__FLAG__)=UART_IT_RXNE,清除"串口接收寄存器为非空时产生的中断标志位"
    19. //(__FLAG__)=UART_IT_PE,清除"串口奇偶校验错误产生的中断标志位"
    20. //(__FLAG__)=UART_IT_ERR,清除"帧错误、噪音错误和溢出错误时产生的中断标志位"
    21. //(__FLAG__)=UART_IT_TXE时,清除"串口发送寄存器为空产生的中断标志位"
    22. //(__FLAG__)=UART_IT_TC时,清除"发送完成产生的中断标志位"
    23. #define _HAL_UART_ENABLE_IT(__INSTANCE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__INSTANCE__)->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
    24. (((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__INSTANCE__)->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
    25. ((__INSTANCE__)->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))
    26. //设置串口中断使能位
    27. //(__INTERRUPT__)=UART_IT_RXNE,设置"串口接收寄存器为非空"时,使其产生中断
    28. //(__INTERRUPT__)=UART_IT_PE,设置"串口奇偶校验错误"时,使其产生中断
    29. //(__INTERRUPT__)=UART_IT_ERR,设置"帧错误、噪音错误和溢出错误"时,使其产生中断
    30. //(__INTERRUPT__)=UART_IT_TXE时,设置"串口发送寄存器为空"时,使其产生中断
    31. //(__INTERRUPT__)=UART_IT_TC时,设置"串口发送寄存器发送完成"时,使其产生中断
    32. #define _HAL_UART_DISABLE_IT(__INSTANCE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__INSTANCE__)->CR1 &= ~((__INTERRUPT__) & UART_IT_MASK)): \
    33. (((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__INSTANCE__)->CR2 &= ~((__INTERRUPT__) & UART_IT_MASK)): \
    34. ((__INSTANCE__)->CR3 &= ~ ((__INTERRUPT__) & UART_IT_MASK)))
    35. //设置串口中断不使能
    36. //(__INTERRUPT__)=UART_IT_RXNE,设置"串口接收寄存器为非空"时,不使其产生中断
    37. //(__INTERRUPT__)=UART_IT_PE,设置"串口奇偶校验错误"时,不使其产生中断
    38. //(__INTERRUPT__)=UART_IT_ERR,设置"帧错误、噪音错误和溢出错误"时,不使其产生中断
    39. //(__INTERRUPT__)=UART_IT_TXE时,设置"串口发送寄存器为空"时,不使其产生中断
    40. //(__INTERRUPT__)=UART_IT_TC时,设置"串口发送寄存器发送完成"时,不使其产生中断
    41. #define USART2_TX_Buffer_Size 15
    42. extern uint8_t USART2_TX_Buffer[USART2_TX_Buffer_Size];
    43. extern uint8_t USART2_TX_Buffer_Send_Index;//USART2_TX_Buffer[]的发送索引值;
    44. extern uint8_t USART2_TX_Buffer_Load_Index;//USART2_TX_Buffer[]的装载索引值
    45. extern uint8_t USART2_TX_Completed_Flag;
    46. extern uint8_t USART2_TX_Overtime_Conter;//USART2发送超时计数器
    47. #define USART2_RX_Buffer_Size 125
    48. extern uint8_t USART2_RX_Buffer[USART2_RX_Buffer_Size]; //USART2接收缓冲区数组
    49. extern uint8_t USART1_RX_Buffer_StartIndex;//USART1_RX_Buffer[]的装载索引值
    50. extern uint8_t USART1_RX_Buffer_EndIndex;//USART1_RX_Buffer[]的装载索引值
    51. #define USART2_RX1_Buffer_Size 125
    52. extern uint8_t USART2_RX1_Buffer[USART2_RX1_Buffer_Size]; //USART2接收缓冲区数组
    53. extern void USART2_Init(uint32_t baudrate);
    54. extern void Usart2Send(void);
    55. extern void Usart2Receive(void);
    56. #endif /* __USART2_H */
    1. #include "My_DMA.h"
    2. void My_DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
    3. void My_DMA1_SetConfig(DMA_Channel_TypeDef *instance, uint32_t srcAddress, uint32_t dstAddress, uint32_t dataLength,uint8_t direction);
    4. #define _HAL_DMA_CLEAR_FLAG(__INSTANCE__, __FLAG__) ( (__INSTANCE__)->IFCR |= (__FLAG__) )
    5. //清除串口中断标志位
    6. //(__FLAG__)=0x01,CGIF1=1,清除"通道1全局中断标志"
    7. //(__FLAG__)=0x10,CGIF2=1,清除"通道2全局中断标志"
    8. //(__FLAG__)=0x100,CGIF3=1,清除"通道3全局中断标志"
    9. //SrcAddress:源数据地址
    10. //DstAddress:目的数据地址
    11. //DataLength:传输数据长度
    12. void My_DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
    13. {
    14. /* Clear all flags */
    15. if(hdma->Instance==DMA1_Channel1) hdma->ChannelIndex=0x01;
    16. if(hdma->Instance==DMA1_Channel2) hdma->ChannelIndex=0x04;
    17. if(hdma->Instance==DMA1_Channel3) hdma->ChannelIndex=0x08;
    18. hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
    19. //"DMA中断标志位清除寄存器DMA_IFCR"中的CGIFx设置为1,将DMA通道x全局中断标志清零
    20. /* Configure DMA Channel data length */
    21. hdma->Instance->CNDTR = DataLength;//传输数据长度
    22. /* Memory to Peripheral */
    23. if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)//从内存向外设传输
    24. {
    25. /* Configure DMA Channel destination address */
    26. hdma->Instance->CPAR = DstAddress;//目的数据地址
    27. /* Configure DMA Channel source address */
    28. hdma->Instance->CMAR = SrcAddress;//源数据地址
    29. }
    30. /* Peripheral to Memory */
    31. else//从外设向内存传输
    32. {
    33. /* Configure DMA Channel source address */
    34. hdma->Instance->CPAR = SrcAddress;//源数据地址
    35. /* Configure DMA Channel destination address */
    36. hdma->Instance->CMAR = DstAddress;//目的数据地址
    37. }
    38. }
    39. //srcAddress:源数据地址
    40. //dstAddress:目的数据地址
    41. //dataLength:传输数据长度
    42. //direction>0,从内存向外设传输;direction=0,从外设向内存传输
    43. void My_DMA1_SetConfig(DMA_Channel_TypeDef *instance, uint32_t srcAddress, uint32_t dstAddress, uint32_t dataLength,uint8_t direction)
    44. {
    45. uint8_t ChannelIndex;
    46. /* Clear all flags */
    47. if(instance==DMA1_Channel1) ChannelIndex=0x01;
    48. if(instance==DMA1_Channel2) ChannelIndex=0x04;
    49. if(instance==DMA1_Channel3) ChannelIndex=0x08;
    50. DMA1->IFCR = (DMA_ISR_GIF1 << ChannelIndex);
    51. //"DMA中断标志位清除寄存器DMA_IFCR"中的CGIFx设置为1,将DMA通道x全局中断标志清零
    52. /* Configure DMA Channel data length */
    53. instance->CNDTR = dataLength;//传输数据长度
    54. /* Memory to Peripheral */
    55. if( direction )//从内存向外设传输
    56. {
    57. /* Configure DMA Channel destination address */
    58. instance->CPAR = dstAddress;//目的数据地址
    59. /* Configure DMA Channel source address */
    60. instance->CMAR = srcAddress;//源数据地址
    61. }
    62. /* Peripheral to Memory */
    63. else//从外设向内存传输
    64. {
    65. /* Configure DMA Channel source address */
    66. instance->CPAR = srcAddress;//源数据地址
    67. /* Configure DMA Channel destination address */
    68. instance->CMAR = dstAddress;//目的数据地址
    69. }
    70. }
    1. #ifndef __My_DMA_H
    2. #define __My_DMA_H
    3. #include "py32f0xx_hal.h"
    4. #define _HAL_DMA_ENABLE(__INSTANCE__) ((__INSTANCE__)->CCR |= DMA_CCR_EN)
    5. //"DMA通道x配置寄存器DMA_CCRx"中EN=1,DMA通道x使能
    6. #define _HAL_DMA_DISABLE(__INSTANCE__) ((__INSTANCE__)->CCR &= ~DMA_CCR_EN)
    7. //"DMA通道x配置寄存器DMA_CCRx"中EN=0,DMA通道x不使能
    8. #define _HAL_DMA_Transfer_Number_Get(__INSTANCE__) ( (__INSTANCE__)->CNDTR )
    9. //读DMA1通道x剩余空间
    10. extern void My_DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
    11. extern void My_DMA1_SetConfig(DMA_Channel_TypeDef *instance, uint32_t srcAddress, uint32_t dstAddress, uint32_t dataLength,uint8_t direction);
    12. #endif /* __My_DMA_H */
    1. #include "py32f0xx_hal.h"
    2. #include "SystemClock.h"
    3. #include "delay.h"
    4. #include "LED.h"
    5. #include "USART2.h"
    6. #include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
    7. #include "string.h" //使能strcpy(),strlen(),memset()
    8. #include "SystemClock.h"
    9. const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
    10. int main(void)
    11. {
    12. HSE_Config();
    13. // HAL_Init();//systick初始化
    14. delay_init();
    15. HAL_Delay(1000);
    16. USART2_Init(115200);
    17. //PA0是为USART2_TX,PA1是USART2_RX
    18. //中断优先级为0x01
    19. //波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
    20. // printf("%s",CPU_Reset_REG);
    21. strcpy((char*)USART2_TX_Buffer,CPU_Reset_REG);
    22. Usart2Send();
    23. TIM1_LED_Init();
    24. TIM3_LED_Init();
    25. TIM_LED_Init();
    26. while (1)
    27. {
    28. delay_ms(100);
    29. Usart2Receive();
    30. // strcpy((char*)USART2_TX_Buffer,"A234567890\r\n");
    31. // Usart2Send();
    32. }
    33. }

    三、测试结果

     四、不用HAL库DMA函数的目的

    因为HAL库的DMA传输函数,需要将UART_HandleTypeDef,DMA_HandleTypeDef结构型数据申请为全局变量,才可以使用,太浪费内存了。
    UART_HandleTypeDef UART_HandleStructureure;
    DMA_HandleTypeDef hdma_usart2_tx;
    DMA_HandleTypeDef hdma_usart2_rx;

    实在太浪费了。
    贴出官方的测试代码,以示如下:

    1. #include "USART2.h"
    2. #include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
    3. #include "string.h" //使能strcpy(),strlen(),memset()
    4. //PA0 ------> USART2_TX
    5. //PA1 ------> USART2_RX
    6. UART_HandleTypeDef UART_HandleStructureure;
    7. DMA_HandleTypeDef hdma_usart2_tx;
    8. DMA_HandleTypeDef hdma_usart2_rx;
    9. uint8_t aTxBuffer[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    10. uint8_t aRxBuffer[12] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    11. void USART2_Init(uint32_t baudrate);
    12. void USART2_Work(void);
    13. void HAL_UART_MspInit(UART_HandleTypeDef *huart)
    14. {
    15. GPIO_InitTypeDef GPIO_InitStructureure;
    16. if(huart->Instance==USART2)
    17. {
    18. __HAL_RCC_USART2_CLK_ENABLE();//使能USART2外设时钟
    19. __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
    20. __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
    21. __HAL_RCC_DMA_CLK_ENABLE(); //使能DMA时钟
    22. //串口引脚映射开始/
    23. GPIO_InitStructureure.Pin = GPIO_PIN_0; //选择第0脚,PA0是为USART2_TX
    24. GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP; //复用功能推挽模式
    25. GPIO_InitStructureure.Pull = GPIO_PULLUP; //引脚上拉被激活
    26. GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    27. GPIO_InitStructureure.Alternate = GPIO_AF9_USART2; //将引脚复用为USART2
    28. HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
    29. //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
    30. //将PA0初始化为USART2_TX
    31. GPIO_InitStructureure.Pin = GPIO_PIN_1; //选择第1脚,PA1是USART2_RX
    32. GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP; //复用功能推挽模式
    33. GPIO_InitStructureure.Pull = GPIO_PULLUP; //引脚上拉被激活
    34. GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    35. GPIO_InitStructureure.Alternate = GPIO_AF9_USART2; //将引脚复用为USART2
    36. HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
    37. //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
    38. //将PA1初始化为USART2_RX
    39. //串口引脚映射结束/
    40. HAL_NVIC_SetPriority(USART2_IRQn, 0, 1);
    41. //设置串口2中断优先级为0x00,1无意义
    42. HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 1);
    43. //设置DMA1通道1中断优先级为0x00,1无意义
    44. HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 1, 0);
    45. //设置DMA1通道2和通道3中断优先级为0x01,0无意义
    46. }
    47. }
    48. //函数功能:
    49. //PA0是为USART2_TX,PA1是USART2_RX
    50. //中断优先级为0x01
    51. //波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
    52. void USART2_Init(uint32_t baudrate)
    53. {
    54. UART_HandleStructureure.Instance = USART2; //接口为USART2
    55. UART_HandleStructureure.Init.BaudRate = baudrate; //波特率为115200bps
    56. UART_HandleStructureure.Init.WordLength = UART_WORDLENGTH_8B; //串口字长度为8
    57. UART_HandleStructureure.Init.StopBits = UART_STOPBITS_1; //串口停止位为1
    58. UART_HandleStructureure.Init.Parity = UART_PARITY_NONE; //串口无需奇偶校验
    59. UART_HandleStructureure.Init.HwFlowCtl = UART_HWCONTROL_NONE; //串口无硬件流程控制
    60. UART_HandleStructureure.Init.Mode = UART_MODE_TX_RX; //串口工作模式为发送和接收模式
    61. UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_NO_INIT;//不使用自动波特率
    62. // UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_AUTOBAUDRATE_INIT;//使用自动波特率配置
    63. // UART_HandleStructureure.AdvancedInit.AutoBaudRateEnable=UART_ADVFEATURE_AUTOBAUDRATE_ENABLE;//自动波特率使能
    64. // UART_HandleStructureure.AdvancedInit.AutoBaudRateMode=UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT;//自动波特率模式
    65. HAL_UART_Init(&UART_HandleStructureure);
    66. //根据UART_HandleStructureure型结构初始化USART2
    67. // HAL_SYSCFG_DMA_Req(0x0807);
    68. //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
    69. //DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
    70. //DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX
    71. hdma_usart2_tx.DmaBaseAddress = DMA1; //选择DMA1传输
    72. hdma_usart2_tx.Instance = DMA1_Channel1; //DMA1通道1
    73. hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;//DMA传输方向:从内存到外设
    74. hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE; //不使能外设地址增量
    75. hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE; //使能内存地址增量
    76. hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//外设数据宽度为8
    77. hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //存储器数据宽度为8
    78. hdma_usart2_tx.Init.Mode = DMA_NORMAL; //DMA普通模式
    79. hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW; //DMA通道1优先级为低
    80. HAL_DMA_Init(&hdma_usart2_tx);
    81. __HAL_LINKDMA(&UART_HandleStructureure, hdmatx, hdma_usart2_tx);
    82. //这里必须要连接DMA句柄
    83. //令UART_HandleStructureure.hdmatx=&hdma_usart2_tx;//记录
    84. //令hdma_usart2_tx.Parent=&UART_HandleStructureure;//记录
    85. hdma_usart2_rx.DmaBaseAddress = DMA1; //选择DMA1传输
    86. hdma_usart2_rx.Instance = DMA1_Channel2; //DMA1通道2
    87. hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;//DMA传输方向:从外设到内存
    88. hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; //不使能外设地址增量
    89. hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; //使能内存地址增量
    90. hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外设数据宽度为8
    91. hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //存储器数据宽度为8
    92. hdma_usart2_rx.Init.Mode = DMA_NORMAL; //DMA普通模式
    93. hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; //DMA通道2优先级为低
    94. HAL_DMA_Init(&hdma_usart2_rx);
    95. __HAL_LINKDMA(&UART_HandleStructureure, hdmarx, hdma_usart2_rx);
    96. //连接DMA句柄
    97. //令UART_HandleStructureure.hdmarx=&hdma_usart2_rx;//记录
    98. //令hdma_usart2_rx.Parent=&UART_HandleStructureure;//记录
    99. HAL_DMA_ChannelMap(&hdma_usart2_tx,DMA_CHANNEL_MAP_USART2_TX);
    100. HAL_DMA_ChannelMap(&hdma_usart2_rx,DMA_CHANNEL_MAP_USART2_RX);
    101. // HAL_SYSCFG_DMA_Req(0x0807);
    102. //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
    103. //DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
    104. //DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX
    105. HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
    106. HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
    107. HAL_NVIC_EnableIRQ(USART2_IRQn);
    108. //使能串口2中断
    109. //USART2_IRQn表示中断源为串口2
    110. }
    111. //重定义fputc函数
    112. //函数功能:发送ch的值给USART2串口
    113. int fputc(int ch, FILE *f)
    114. {
    115. _HAL_UART_SendByte(USART2, (unsigned char) ch);
    116. while( _HAL_UART_GET_FLAG(USART2,USART_SR_TC)!= SET); //等待发送完成标志位被置1
    117. return ch;
    118. }
    119. //函数功能:串口2发送一个字节
    120. void USART2_SendByte( unsigned char ch )
    121. {
    122. _HAL_UART_SendByte(USART2, (unsigned char) ch);
    123. while( _HAL_UART_GET_FLAG(USART2,USART_SR_TC)!= SET); //等待发送完成标志位被置1
    124. }
    125. void USART2_Work(void)
    126. {
    127. /* 通过DMA方式接收数据 */
    128. if (HAL_UART_Receive_DMA(&UART_HandleStructureure, (uint8_t *)aRxBuffer, 12) != HAL_OK)
    129. {
    130. }
    131. /* 等待接收数据完成 */
    132. while(HAL_UART_GetState(&UART_HandleStructureure) != HAL_UART_STATE_READY)
    133. {}
    134. /* 通过DMA方式发送数据 */
    135. if (HAL_UART_Transmit_DMA(&UART_HandleStructureure, (uint8_t *)aRxBuffer, 12) != HAL_OK)
    136. {
    137. }
    138. /* 等待发送数据完成 */
    139. while(HAL_UART_GetState(&UART_HandleStructureure) != HAL_UART_STATE_READY)
    140. {}
    141. }
    142. //DMA通道1负责串口发送
    143. void DMA1_Channel1_IRQHandler(void)
    144. {
    145. HAL_DMA_IRQHandler(&hdma_usart2_tx);
    146. //若为"DMA通道x半传输中断",则清除“DMA通道x半传输中断”标志位
    147. //若为“DMA通道x传输完成中断”,则清除“DMA通道x传输完成中断”标志位
    148. //若为"DMA通道x传输错误中断",则不使能"DMA通道x传输完成中断""DMA通道x半传输中断""通道x传输错误中断",清除通道x全局中断标志
    149. // HAL_DMA_IRQHandler(UART_HandleStructureure.hdmatx);
    150. }
    151. //DMA通道2负责串口接收
    152. void DMA1_Channel2_3_IRQHandler(void)
    153. {
    154. HAL_DMA_IRQHandler(&hdma_usart2_rx);
    155. //若为"DMA通道x半传输中断",则清除“DMA通道x半传输中断”标志位
    156. //若为“DMA通道x传输完成中断”,则清除“DMA通道x传输完成中断”标志位
    157. //若为"DMA通道x传输错误中断",则不使能"DMA通道x传输完成中断""DMA通道x半传输中断""通道x传输错误中断",清除通道x全局中断标志
    158. // HAL_DMA_IRQHandler(UART_HandleStructureure.hdmarx);
    159. }
    160. void USART2_IRQHandler(void)
    161. {
    162. HAL_UART_IRQHandler(&UART_HandleStructureure);
    163. }

    耗内存,占用FLASH较小。FLASH那么大,节省没啥用。思绪再三,还是修改掉。

  • 相关阅读:
    2022年下半年 软件设计师 上午试卷(41题—75题)
    【Java中23种面试常考的设计模式之适配器模式(Adapter)---结构型模式】
    开源情报 (OSINT)
    JavaScript中的map()和forEach()方法有什么区别?
    Zookeeper:分布式过程协同技术
    元宇宙电商-NFG系统,是如何让数字藏品流通的?
    细节决定成败:探究Mybatis中javaType和ofType的区别
    win11和虚拟机上的ubuntu系统共享文件夹
    GNN Tensorflow packages
    工程水文学复习资料
  • 原文地址:https://blog.csdn.net/weixin_42550185/article/details/133079343