完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
前言
其实之前做RM比赛的时候就要有做转发器的想法,但是当时是因为云台和底盘上下分开,通过滑环相连,为了减少通讯线路,才萌生做转发器的想法,虽然最后方案讨论不够完善,所以就搁置了。现在是因为某模块以及焊死在板子上,没办法直接使用串口进行通讯,所以不得不使用串口转发的方式,来进行模块的连接。 实现串口转发的方式有很多,各有优劣。本文主要利用DMA方式实现串口转发功能。 环境
方案一:使能两个串口的DMA接收和发送通道,使能串口空闲中断判断数据帧结束,初始化缓存数组变量。 优点:低CPU占用率和中断资源占用率,几乎不出现死机情况 缺点:高延时,内存占用率高,且一旦数据量超过缓存大小就会被覆盖。由于启用4条DMA通道,所以总线占用率也变高,进一步增加延时。 方案二:仅使能两个串口的DMA接收通道,使能串口接收中断判断一字节数据到达,初始化缓存数组变量。 优点:超低延时,内存占用率低 缺点:占用大量中断资源,有概率遇到DMA忙导致数据丢失(大约每1160字节丢1字节),多次频繁请求DMA会出现死机情况(连续发送约16k字节数据后,出现死机情况) 实现 以方案二为例,使用CubeMX新建工程 1.编辑串口参数 2.启用串口发送中断 3.勾选启用串口全局中断 4.取消选择生成HAL中断处理函数,这部分需要我们自己写 使用CubeMX生成我们的工程文件,并打开main.c。在main函数中添加如下代码 /* USER CODE BEGIN 2 */ __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); //使能串口1接收中断 __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE); //使能串口2接收中断 /* USER CODE END 2 */ 打开stm32f1xx_it.c,找到USARTx_IRQHandler(x为你使用的串口号,x=1,2…),编写中断处理函数。 /* 初始化缓存数组 */ uint8_t USART1RxBuff[1]; uint8_t USART2RxBuff[1]; void USART1_IRQHandler(void) { /* 判断中断类型为串口接收中断 */ if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)) { /* 清除中断标志位 */ __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE); /* 将串口接收到的数组移入缓存 */ USART1RxBuff[0] = (uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF); /* 启用DMA发送一字节数据 */ HAL_UART_Transmit_DMA(&huart2, USART1RxBuff, USART1RxFIFO, 1); } /* 判断中断类型为串口发送中断 */ if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) != RESET)) { __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_TC); } /* USER CODE END USART1_IRQn 0 */ } 编写DMA中断处理函数 /** * @brief This function handles DMA1 channel4 global interrupt. */ void DMA1_Channel4_IRQHandler(void) { /* USER CODE BEGIN DMA1_Channel4_IRQn 0 */ huart1.gState = HAL_UART_STATE_READY; //重置串口状态为就绪态 hdma_usart1_tx.State = HAL_DMA_STATE_READY; //重置DMA状态为就绪态 __HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_TC4); //清除DMA传输完成标志位 __HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_HT4); //清除DMA半传输完成标志位 __HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_TE4); //清除DMA传输出错标志位 __HAL_UNLOCK(&hdma_usart1_tx); //解锁DMA /* USER CODE END DMA1_Channel4_IRQn 0 */ } 同样的方法编写另一个串口的中断 然后编译+下载即可实现串口转发功能 后记 实际上这一版程序如文中所说并不完善,有很多正在尝试但是还是未解决的问题
|
|
|
|
只有小组成员才能发言,加入小组>>
3316 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9060 浏览 16 评论
4088 浏览 18 评论
1180浏览 3评论
605浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
599浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2335浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1896浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 05:50 , Processed in 1.164317 second(s), Total 79, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号