1.配置系统下载程序方式
2.RCC外部晶振
3.串口声明
4.系统时钟
5.生成文件根据自己需求配置
我这设置了所有库,可以选第二个仅需求的
还加了其他功能,这里可不参考,DMA要放在串口前
6.生成后修改
6.1 usart.h
- /* USER CODE BEGIN Includes */
- #include "stdio.h"
- #include "string.h"
- /* USER CODE END Includes */
复制代码- /* USER CODE BEGIN Private defines */
- #define USART1_DMA_REC_SIE 256
- #define USART1_REC_SIE 512
- #define USART_DMA_SENDING 1//DMA发送
- #define USART_DMA_SENDOVER 0//DMA发送结束
- typedef struct
- {
- uint8_t UsartRecFlag:1;//接收标志
- uint8_t dmaSend_flag;//发送标志
- uint16_t UsartDMAReclen;//DMA接收长度
- uint16_t UsartReclen;//串口数据缓存长度
- uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
- uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据
- }teUsart1type;
- extern teUsart1type Usart1type;//定义数据
- void UsartReceive_IDLE(UART_HandleTypeDef *huart);
- void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);
- void Analysis_Serial_Data(void);
- void EnableUsart_IT(void);
- /* USER CODE END Private defines */
复制代码
6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。
- teUsart1type Usart1type;
- /*****************************************************************************
- * 函 数 名 : EnableUsart_IT
- * 负 责 人 : by
- * 创建日期 : 2020年8月26日
- * 函数功能 : 串口2初始化函数,空闲与DMA中断
- * 输入参数 : 无
- * 输出参数 : 无
- * 返 回 值 :
- * 调用关系 :
- * 其 它 :
- *****************************************************************************/
- void EnableUsart_IT(void)
- {
- __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断
- }
- /*****************************************************************************
- * 函 数 名 : Usart1SendData_DMA
- * 负 责 人 : by
- * 创建日期 : 2020年8月26日
- * 函数功能 : 串口2DMA发送函数
- * 输入参数 : 无
- * 输出参数 : 无
- * 返 回 值 :
- * 调用关系 :
- * 其 它 :
- *****************************************************************************/
- void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)
- {
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
- Usart1type.dmaSend_flag = USART_DMA_SENDING;
- HAL_UART_Transmit_DMA(&huart2, pdata, Length);
- }
- /*****************************************************************************
- * 函 数 名 : HAL_UART_TxCpltCallback
- * 负 责 人 : by
- * 创建日期 : 2020年8月26日
- * 函数功能 : 串口2DMA发送回调函数
- * 输入参数 : 无
- * 输出参数 : 无
- * 返 回 值 :
- * 调用关系 :
- * 其 它 :
- *****************************************************************************/
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
- {
- __HAL_DMA_DISABLE(huart->hdmatx);
- if(huart->Instance == huart2.Instance)
- Usart1type.dmaSend_flag = USART_DMA_SENDOVER;
- }
- /*****************************************************************************
- * 函 数 名 : UsartReceive_IDLE
- * 负 责 人 : by
- * 创建日期 : 2020年8月27日
- * 函数功能 : 串口接受空闲中断处理函数
- * 输入参数 : UART_HandleTypeDef *huart 串口句柄
- * 输出参数 : 无
- * 返 回 值 :
- * 调用关系 :DMA接收的数据缓存在USART接收中,释放DMA继续接收
- * 其 它 :
- *****************************************************************************/
- void UsartReceive_IDLE(UART_HandleTypeDef *huart)
- {
- if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
- {
- if(huart->Instance == huart2.Instance)//判断是否为串口2
- {
- if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) //是否为空闲中断
- {
- __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除空闲中断
- HAL_UART_DMAStop(&huart2); //停止本次DMA传输
- Usart1type.UsartDMAReclen = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR; //计算本次传输数据长度
- if(Usart1type.UsartReclen>0)
- {
- memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);
- Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;
- }
- else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录
- {
- Usart1type.UsartReclen=0;
- }
- else
- {
- memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
- Usart1type.UsartReclen=Usart1type.UsartDMAReclen;
- }
- memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零
- Usart1type.UsartRecFlag=1;//空闲标志位置1
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA
- }
- }
- }
- }
- /*****************************************************************************
- * 函 数 名 : Analysis_Serial_Data
- * 负 责 人 : by
- * 创建日期 : 2020年8月26日
- * 函数功能 : 串口接收数据直接打印
- * 输入参数 : void 无
- * 输出参数 : 无
- * 返 回 值 : void
- * 调用关系 :
- * 其 它 :
- *****************************************************************************/
- void Analysis_Serial_Data(void)
- {
- if(Usart1type.UsartRecFlag)
- {
- Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);
- Usart1type.UsartRecFlag=0;
- Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理
- }
- }
- /*****************************************************************************
- * 函 数 名 : fputc
- * 负 责 人 : by
- * 创建日期 : 2020年8月26日
- * 函数功能 : 串口2 printf重定义
- * 输入参数 : printf(d%/s%/%c,a)
- * 输出参数 : 无
- * 返 回 值 :
- * 调用关系 :
- * 其 它 :
- *****************************************************************************/
- #ifdef __GNUC__
- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
- set to 'Yes') calls __io_putchar() */
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #else
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #endif /* __GNUC__ */
-
- PUTCHAR_PROTOTYPE
- {
- HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);
- return ch;
- }
- /* USER CODE END 1 */
- DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
- Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码
6.3 主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数- /* USER CODE BEGIN 2 */
- HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
- HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/
- HAL_CAN_Start(&hcan1);/*can初始化*/
- HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
- EnableUsart_IT();/*串口初始化*/
- CAN_User_Init(&hcan1);
- /* USER CODE END 2 */
复制代码
循环,对应数据输出
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- Analysis_Serial_Data();
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
- 7
复制代码
、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误
|