完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32cubeMX版本5.2.1
最近由于工作需要用到LWIP,看到网上有人说用cubeMX可以生成LWIP库,同时还能生成FREERTOS系统。就索性把整个工程的驱动库都换成了cubeMX生成的HAL库,在之前写工程基础上更改驱动配置,踩了一些坑,在这里把串口的配置及部分软件代码分享出来,希望能对大家有所帮助。 1、时钟配置 2、串口配置 3、FREERTOS配置 4、代码处理 ①定义发送和接送的缓冲区 #define UART_BUFFSIZE 200 // 定义缓冲区的大小 typedef struct { u16 Uart_SendLens; //待发送数据长度 u16 Uart_RecvLens; //接收到的数据长度 u16 RecvQue_Head; //新接收数据环形队列头指针 u16 RecvQue_Tail; //新接收数据环形队列尾指针 u8 Uart_SentBuff[UART_BUFFSIZE]; u8 Uart_RecvBuff[UART_BUFFSIZE]; }UART_STR; ②串口初始化配置修改 UART_STR Uart1_Str,Uart2_Str,Uart3_Str,Uart4_Str,Uart5_Str; // 定义串口发送接收缓冲区 static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } //以下为自己添加的中断配置 /* USER CODE BEGIN USART1_Init 2 */ __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 开启空闲中断 // 接收DMA通道关联缓冲区 HAL_UART_Receive_DMA(&huart1, Uart1_Str.Uart_RecvBuff, UART_BUFFSIZE); // 以下这两个中断最好关掉,不然debug的时候会莫名其妙进中断,DMA发送不了 __HAL_UART_DISABLE_IT(&huart1, UART_IT_ERR); __HAL_UART_DISABLE_IT(&huart1, UART_IT_PE); /* USER CODE END USART1_Init 2 */ } ③发送函数 /* 函数功能:串口1DMA数据发送 函数形参:Sendbuff :缓冲数据 Bufflens :数据长度 函数返回值:数据长度 备注:无 */ u16 Uart1_DMA_Sent(u8 * Sendbuff, u16 Bufflens) { u16 l_val = Bufflens > UART_BUFFSIZE ? UART_BUFFSIZE : Bufflens; if(Bufflens <= 0) { return 0; } while(__HAL_DMA_GET_COUNTER(&hdma_usart1_tx));//检测DMA发送通道内还有没有数据 if(Sendbuff) { memcpy(Uart1_Str.Uart_SentBuff, Sendbuff, l_val); } HAL_UART_Transmit_DMA(&huart1, Uart1_Str.Uart_SentBuff, l_val); return l_val; } ④接收中断处理 /* *函数功能:串口1接收中断函数 */ void USART1_IRQHandler(void) { if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET) { u16 l_val; l_val = UART_BUFFSIZE - DMA1_Channel5->CNDTR; // 通过DMA接收指针计算接收的字节数 if(l_val > Uart1_Str.RecvQue_Tail) { Uart1_Str.Uart_RecvLens += l_val - Uart1_Str.RecvQue_Tail; } else { Uart1_Str.Uart_RecvLens += UART_BUFFSIZE - Uart1_Str.RecvQue_Tail + l_val; } Uart1_Str.RecvQue_Tail = l_val; Uart1_Str.Uart_RecvLens %= UART_BUFFSIZE; __HAL_UART_CLEAR_IDLEFLAG(&huart1); } HAL_UART_IRQHandler(&huart1); // 这一条保留就行了 } ⑤接收函数 /* 函数功能:接收数据函数 函数形参:* Uart_Str : 串口数据缓冲结构地址 RcvBuff :接收数据缓冲区 RevLen :接收缓冲区长度 函数返回值:接收数据长度 备注:无 */ static u16 Uart_Receive_Data(UART_STR * Uart_Str, u8 * RcvBuff, u16 RevLen) { u16 l_val = 0; // 局部变量 此次能拷贝的数据个数 if(!RevLen || !Uart_Str->Uart_RecvLens) { return 0; } l_val = Uart_Str->Uart_RecvLens; if(l_val > RevLen) // 缓冲区的数据数量比传进来的缓冲区容量大 { l_val = RevLen; } if(Uart_Str->RecvQue_Tail > Uart_Str->RecvQue_Head) { memcpy(RcvBuff, Uart_Str->Uart_RecvBuff + Uart_Str->RecvQue_Head, l_val); } else { if((UART_BUFFSIZE - Uart_Str->RecvQue_Head) >= l_val) { memcpy(RcvBuff, Uart_Str->Uart_RecvBuff + Uart_Str->RecvQue_Head, l_val); } else { memcpy(RcvBuff, Uart_Str->Uart_RecvBuff + Uart_Str->RecvQue_Head, UART_BUFFSIZE - Uart_Str->RecvQue_Head); memcpy(RcvBuff + (UART_BUFFSIZE - Uart_Str->RecvQue_Head), Uart_Str->Uart_RecvBuff, l_val - (UART_BUFFSIZE - Uart_Str->RecvQue_Head)); } } Uart_Str->Uart_RecvLens -= l_val; Uart_Str->RecvQue_Head += l_val; Uart_Str->RecvQue_Head %= UART_BUFFSIZE; return l_val; } /* 函数功能:从串口获取数据 函数形参:* Uartx :串口地址 RcvBuff :接收缓冲指针 RevLen :接收缓冲区大小 函数返回值:接收数据长度 备注:无 */ u16 Get_Uart_Data(USART_TypeDef* Uartx,u8 * RcvBuff, u16 RevLen) { if(Uartx == USART1) { return(Uart_Receive_Data(&Uart1_Str, RcvBuff, RevLen)); } else if(Uartx == USART2) { return(Uart_Receive_Data(&Uart2_Str, RcvBuff, RevLen)); } else if(Uartx == USART3) { return(Uart_Receive_Data(&Uart3_Str, RcvBuff, RevLen)); } else if(Uartx == UART4) { return(Uart_Receive_Data(&Uart4_Str, RcvBuff, RevLen)); } else if(Uartx == UART5) { return(Uart_Receive_Data(&Uart5_Str, RcvBuff, RevLen)); } return 0; } 总结:发送采用单次的DMA发送,而接收则采用DMA循环接收,只要串口有收到数据DMA会自动帮你搬到内存中,地址会自动增加,当接收的数据个数到达设置的最大值时,DMA的接收指针又会重新指向接收buf的头指针。调用Get_Uart_Data()函数,会将最近接收的数据拷贝返回,拷贝的数据个数取决于接收的buf还有串口接收到的数据。这里只写出一个串口,除了串口5(没有DMA),其他的三个串口都可以参照上面写。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1298 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1310 浏览 1 评论
721 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
531 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1327 浏览 2 评论
1730浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
442浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
393浏览 3评论
381浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
362浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-9-21 07:05 , Processed in 0.920932 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号