完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
配置串口,完成串口回显
咱们书接上回,在cubemx配置好了串口工程所需要的所有选项之后,就可以正式进入MDK编写你的程序啦! 在开始本次的教程之前,我们首先需要知道stm32的串口都有什么样的工作模式,分别为查询模式,中断模式还有DMA模式,让我们一步步来。 查询模式 顾名思义,就是在程序的while(1)中不断的循环进行发送和接收的语句,这样的工作效率是非常底的,但是却可以让我们入门串口通信。 知道了查询模式的概念之后,我们就需要了解一下HAL库当中和串口发送接收有关的函数,并且熟悉他们的用法了。 和串口有关的底层驱动在stm32f1xx_hal_uart.c这个文件里,如图。 这么多的函数看上去眼花缭乱的,但是在本章内容中,我们只需要了解接收和发送两个函数即可。 (1)串口发送函数 HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) 可以看到函数共有四个参数,分别为你在cubemx中初始化的第几号串口,要发送的数据,发送的数据长度,以及超时时间。具体用法为: char str[12] = "Hello Worldn"; HAL_UART_Transmit(&huart1, (uint8_t*)str, 12, 0xFFFF); 这样两句代码,就可以将Hello World从stm32发送到上位机。 (2)串口接收函数 HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) 此函数的四个参数和发送函数中的参数内容大体相同,只是将发送换为接收,具体的使用方法为: char recv_buf[13] = {0}; while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ //接收13个字节的数据,不超时 if(HAL_OK == HAL_UART_Receive(&huart1, (uint8_t*)recv_buf, 13, 0xFFFF)) { //将接收到的数据发送 HAL_UART_Transmit(&huart1, (uint8_t*)recv_buf, 13, 0xFFFF); } } 效果如图所示: 到这里,我们已经了解了串口的查询模式。 中断模式 故名思意,在中断模式下,我们main函数无需每时每刻都在扫面串口接收的数据,只有当数据发送进来的时候采取进行数据的处理,这样也会极大的提高单片机的运行效率。 在开始中断模式之前,我们需要在cubemx设置中打开串口1的中断开关,如图: 然后我们点击生成工程,此时我们会发现在stm32f1xx_it.c文件里面多出来一个void USART1_IRQHandler(void)函数,没错,当串口中断被触发之后,就会自动进入这个函数中处理,因此我们只需要将逻辑处理函数在这个地方编写即可。 void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ uint8_t ch = 0; if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE) != RESET) { ch = (uint16_t)READ_REG(huart1.Instance -> DR); WRITE_REG(huart1.Instance -> DR,ch); } /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ } 由于种种原因,cubemx生成的初始化串口代码中并不包含使能串口的中断,因此如果直接这样写程序的话会发现程序并没有跑起来,其实不然,我们只需要在串口初始化的函数后面加上这样一句代码即可。 __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); 当串口接收中断被触发后,在中断处理函数中实现了将接收到的信息原封不动的发回给上位机,实现了串口的回显。 DMA模式 了解这个模式之前,我们首先要知道DMA是个什么东西,起到什么作用。 DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。 通俗的将就是DMA可以绕过cpu,将数据从一个寄存器直接搬到另一个寄存器,这样一来也会大大节约资源,加速程序的运行。 DMA模式串口回显 通过上述两种模式我们可以看出,虽然我们完成了串口回显的项目需要,但是我们每次只能传输指定长度的数据,这在以后的生产制造中显然是不现实的,我们每次要传输的数据一定是不定长的,这个时候就需要DMA前来救场。 那么DMA又是如何处理不定长数据的呢? 在DMA中有一个数据传输结束的中断标志,意思就是当cpu发起DMA传输之后,cpu便不再干涉传输的过程,但是身为开发者我们要如何知道数据是否传输完成呢,这时,当DMA传输完成后便会自动的向cpu发送一个中断,标志着数据传输完成,开发者便可以根据这个中断来开发实际的应用。 这里我们以串口接收DMA为例子讲解一下此过程。 首先,我们在配置工程中打开串口接收的DMA,如图: 生成工程之后,同样因为cubemx的bug,在串口初始化的时候,cubemx并不会自动帮我们使能,还需要我们手动添加代码。 首先找到usart.c,找到void MX_USART1_UART_Init(void),在这个函数的末尾处添加代码 HAL_UART_Receive_DMA(&huart1,Usart_Rx_Buf,RX_SIZE);Usart_Rx_Buf和RX_SIZE分别为自己定义的一个串口接收缓冲区的数组和该数组的大小,这部分可以根据需要自行定制,笔者暂时定义为512。 然后在这个c文件的末尾整合一下DMA回显的函数,便于调用。 void Uart_DMA_Rx_Data(UART_HandleTypeDef *huart) { if(__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(huart); HAL_UART_DMAStop(huart); HAL_UART_Receive_DMA(huart,Usart_Rx_Buf,RX_SIZE); printf("收到数据:%sn",Usart_Rx_Buf); } } 将这个函数加入到usart.h这个头文件中,再回到串口中断处理函数,将这个函数放入中断处理函数中,每次上位机向单片机发送数据后触发中断,在中断中DMA就会将Usart_Rx_Buf缓冲区中的数据发回上位机,实现串口回显项目的需求。 void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ //函数传入的参数为你配置的串口号 Uart_DMA_Rx_Data(&huart1); /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 09:13 , Processed in 0.797666 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号