完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
概述
本文是对UART外设的加深学习(参考正点原子的教学),文章架构如下: 研究串口发送数据配置流程 研究串口接收数据配置流程 研究串口收发数据中断处理流程 阅读完本文,要能回答以下问题: 简述串口发送数据的配置与工作流程。 前文HAL库通过HAL_UART_Init()配置好串口数据格式,简要阐述一下如何实现串口使能、串口发送使能的。 配置好串口后,通过HAL_UART_Transmit()函数进行USART异步发送数据,从该函数接收参数、返回参数的角度简述该函数是如何发送数据的。 从该函数具体实现何种功能的角度简述该函数是如何发送数据的。 该函数实现发送数据功能,需要UART_HandleTypeDef的成员变量*pTxBuffPtr、TxXferSize、 TxXferCount支持,阐述下这三个变量的功能。 简述串口开启接收中断时接收数据的初始化配置与工作流程。 配置好串口相关特性后,接下来就是要开启中断,简述开启接收中断的过程。 开启中断过程中涉及到锁的概念,对关键资源池进行保护,防止抢占,基于进程相关概念分析下锁的作用。 开启接收中断后,中断函数的内部需要进行哪些操作? 为了测试串口是否正确读取到了数据,通常会将读到的数据回调到串口输出,阐述下这一过程。 文章最后,列出了一些值得进一步研究的内容,包括对中断函数内部的优化、进程管理等,后续敬请期待。 串口发送数据的配置流程 1、简述串口发送数据的配置流程。 配置串口数据格式,例如字长、停止位、奇偶校验位和波特率 串口使能、串口发送使能 向发送数据寄存器TDR写入待发送的数据 等待状态寄存器USARTx_SR(ISR)的TC位置1,表征串口发送数据完成 int main(void) { u8 buff[]="test"; HAL_Init(); //³õʼ»¯HAL¿â Stm32_Clock_Init(360,25,2,8); //ÉèÖÃʱÖÓ,180Mhz delay_init(180); uart1_init(); while(1) { HAL_UART_Transmit(&usart1_handler,buff,sizeof(buff),1000); delay_ms(3000); } } 2、前文已经讲解如何通过HAL_UART_Init()配置串口数据格式,但是却没有注意串口使能、串口发送使能是如何实现的,简要阐述一下。 对于串口使能,是通过宏定义的,如下所示 #define __HAL_UART_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE) 1 在配置串口初始化时,宏定义如下使用:首先关闭串口使能,然后使用 UART_SetConfig()配置串口特性,最后打开串口使能。 /* Disable the peripheral */ __HAL_UART_DISABLE(huart); /* Set the UART Communication parameters */ UART_SetConfig(huart); //...... /* Enable the peripheral */ __HAL_UART_ENABLE(huart); 对于串口发送的使能,是通过上文介绍的init成员变量Mode设置好特性,然后通过UART_SetConfig()函数传递Mode取值给配置寄存器相关位。 //通过这里的huart->Init.Mode确定是否使能串口读或写 tmpreg |= (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling; //Mode的取值如下 #define UART_MODE_RX ((uint32_t)USART_CR1_RE) #define UART_MODE_TX ((uint32_t)USART_CR1_TE) #define UART_MODE_TX_RX ((uint32_t)(USART_CR1_TE |USART_CR1_RE)) 3、通过HAL_UART_Transmit()函数进行USART异步发送数据,从该函数接收参数、返回参数的角度简述该函数是如何发送数据的。 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); 1 返回参数HAL_StatusTypeDef标志函数执行的状态结果。 第一个接收参数是UART_HandleTypeDef数据类型,通过上文分析,知道了USART相关的发送数据寄存器的地址信息在这个参数里面。 第二个接收参数是指向char类型的指针,给出了待发送数据的地址 第三个接收参数要给出待发送数据的大小 第四个接收参数是预定发送数据的超时门槛 4、从该函数具体实现何种功能的角度简述该函数是如何发送数据的。 发送数据的主体部分如下所示,只要pdata指向的数据没有发送完,就向数据寄存器里面写pdata指向的数据。 地址每次自加1,指向下一个字节,表明数据寄存器一次只发送一个字节的数据,符合数据寄存器低8(9)位工作的特性。 huart->TxXferSize = Size; huart->TxXferCount = Size; while(huart->TxXferCount > 0) { huart->TxXferCount--; //... huart->Instance->DR = (*pData++ & (uint8_t)0xFF);//8位数据位 5、该函数实现发送数据功能,需要UART_HandleTypeDef的成员变量*pTxBuffPtr、TxXferSize、 TxXferCount支持,阐述下这三个变量的功能。 pTxBuffPtr是串口发送数据的数据缓存指针,只有在开启中断后,将pdata指针传递给pTxBuffPtr(为啥开启中断后才这样做?) TxXferSize设置需要发送的数据量 TxXferCount设置还剩余要发送的数据量 RX对应的三个变量同理解释 串口接收数据的配置与工作流程 上文介绍串口发送数据时,没有涉及中断的概念。本节在开启接收中断的前提下,研究程序流程。 1、简述串口开启接收中断时接收数据的初始化配置与工作流程。 配置串口数据格式,例如字长、停止位、奇偶校验位和波特率 在GPIO复用配置时,需要使能串口x的中断通道,并且设置中断优先级。 串口使能、串口接收使能 开启接收中断 进入主循环,等待响应读中断 int main(void) { HAL_Init(); //初始化HAL库 Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz delay_init(180); uart1_init();//初始化串口参数 HAL_UART_Receive_IT(&usart1_handler, (u8 *)rdata, 1);//该函数会开启接收中断,并且设置接收缓冲以及接收最大数据量 while(1) { } } uart1_init()函数调用HAL_UART_Init(),设置好了串口特性、数据格式,并且对串口以及串口接收数据进行了使能。同时在GPIO复用配置时,使能串口x的中断通道,并且设置中断优先级。中断配置相关概念在中断一文进行说明。 void HAL_UART_MspInit(UART_HandleTypeDef *huart) { GPIO_InitTypeDef GPIO_Initure; if(huart->Instance==USART1)//配置对应串口 { //...... HAL_NVIC_EnableIRQ(USART1_IRQn); //使能串口1中断通道 HAL_NVIC_SetPriority(USART1_IRQn,3,3); //设置串口1的中断优先级 } } 2、配置好串口相关特性后,接下来就是要开启中断,简要阐述开启接收中断的过程。 通过HAL_UART_Receive_IT()开启接收中断,并且设置接收缓冲以及接收最大数据量 HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); 1 研究该函数接收参数,第一个参数包含串口寄存器的实际地址,第二个参数是希望存放接收数据的地址,第三个参数是数据大小 /* Process Locked */ __HAL_LOCK(huart); huart->pRxBuffPtr = pData; huart->RxXferSize = Size; huart->RxXferCount = Size; /* Process Unlocked */ __HAL_UNLOCK(huart); /* Enable the UART Data Register not empty Interrupt */ __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE); 研究该函数实现的功能: 首先指定接收到的数据该存在内存地址哪里,每次接收多少数据。 然后开启数据接收中断,使能RXNE的功能,一旦状态寄存器的RXNE由硬件置1了,表明有数据待读取了,产生中断。只要对数据寄存器执行读操作后,就会自动清零该标志位 进一步可以推断出,进入接收中断,要执行的一步重要操作是:将数据寄存器huart->Instance->DR的值送入到待存放地址huart->pRxBuffPtr中去 3、这里涉及到锁的概念,对资源池进行保护,防止抢占,基于进程相关概念分析下锁的作用。 4、开启接收中断后,中断函数的内部需要进行哪些操作? 调用HAL_UART_IRQHandler()函数执行需要执行的功能 恢复状态标志位并退出中断。 HAL_UART_IRQHandler()内部,又调用UART_Receive_IT()函数,最终实现将数据寄存器huart->Instance->DR的值送入到待存放地址huart->pRxBuffPtr中去 void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&usart1_handler); while (HAL_UART_GetState(&usart1_handler) != HAL_UART_STATE_READY);//µÈ´ý¾ÍÐ÷ while(HAL_UART_Receive_IT(&usart1_handler, (u8 *)rdata, 1) != HAL_OK); } void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) { //...... /* UART in mode Receiver --------------*/ if((tmp1 != RESET) && (tmp2 != RESET)) { UART_Receive_IT(huart); } //...... } static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) { //... *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); //...... } 5、为了测试串口是否正确读取到了数据,通常会将读到的数据回调到串口输出,阐述下这一过程。 通过调用HAL_UART_RxCpltCallback()函数将接收到的数据通过串口1发送,函数如下所示: void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { u8 rec; if(huart->Instance==USART1)//如果串口1 { rec=*(--(huart->pRxBuffPtr)); HAL_UART_Transmit(&usart1_handler,&rec,1,1000); } } 这个函数该在代码哪里被调用呢?在UART_Receive_IT()函数内部被调用,即在接收中断函数里面被调用,再将数据寄存器huart->Instance->DR的值送入到待存放地址huart->pRxBuffPtr中去之后,调用HAL_UART_RxCpltCallback()函数,发送数据。 static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) { //... *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF); //...... HAL_UART_RxCpltCallback(huart); //...... } 在中断函数中使用HAL库执行中断操作并不是一个好的选择,因为在工控领域,中断常常需要高频响应的,这要求中断程序必须足够简洁,如果不够简洁,会造成高优先级中断始终抢占、低优先级中断始终死等。 后续工作包括对中断函数内部的优化、进程管理,有机会再深入研究 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1909 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1678 浏览 1 评论
1172 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
771 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1732 浏览 2 评论
1970浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
807浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
255浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
624浏览 3评论
634浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-24 05:07 , Processed in 0.597652 second(s), Total 42, Slave 37 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号