完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片。这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现。本篇将说明基于LL实现USART通讯。 1、概述 我们想要实现基于RS485的Modbus通讯实际就是基于USART的通讯。USART使用可编程波特率发生器提供非常广泛的波特率范围。根据不同配置可以实现我们不同的串行通讯应用需求。其结构图如下: 我们在USART基础上实现一个Modbus的从站应用,所以我们对于接收采用中断接收,而对于发送则根据接收到的信息做出反馈。所以我们要根据接收状态和发送状态来确定我们的操作。 2、USART配置 在实现之前,我们来了解一下满足前述的需求,我们应该做哪些配置。主要有2个寄存器需要注意:控制寄存器1(USART_CR1)和波特率寄存器(USART_BRR)。 首先我们还是来看一看控制寄存器1(USART_CR1)。其中RXNEIE(RXNE中断使能)、TE(发送使能)、RE(接收使能)、UE(USART使能)等位是需要我们注意的。该寄存器的结构如下: 对于波特率寄存器(USART_BRR),顾名思义就是设置波特率。但波特率的值不是随意设置,有一套计算方法,可以查看STM的手册。 3、软件实现 接下来我们在软件上实现我们的应用。我们先看USART配置,我们将其配置为我们需要的参数,并将其配置为中断接收模式。具体代码如下: /*配置上位通讯串口*/ static void Comm_UART_Configuration(void) { LL_USART_InitTypeDef USART_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* 使能相关外设时钟 */ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_USART1); LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA); /* USART1 GPIO 配置:PA2 ------》 USART1_TX PA3 ------》 USART1_RX */ GPIO_InitStruct.Pin = LL_GPIO_PIN_2; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_1; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_3; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_1; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1中断初始化 */ NVIC_SetPriority(USART1_IRQn, 1); NVIC_EnableIRQ(USART1_IRQn); /* USART1端口配置 */ USART_InitStruct.BaudRate = 115200; USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; USART_InitStruct.StopBits = LL_USART_STOPBITS_1; USART_InitStruct.Parity = LL_USART_PARITY_NONE; USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; LL_USART_Init(USART1, &USART_InitStruct); LL_USART_DisableIT_CTS(USART1); LL_USART_ConfigAsyncMode(USART1); LL_USART_Enable(USART1); LL_USART_EnableIT_RXNE(USART1); } 大部分配置都可通过初始化函数来实现,有一些需同过专门的LL库函数实现。配置完成后寄存器的状态如下图所示。 我们配置的波特率是115200,其在寄存器中的配置为1A1,关于波特率的配置问题可以查看相关资料。另外我们还需要编写一个接收中断的服务函数。 /*数据接收中断处理函数,添加到USART1中断响应函数中*/ void USART1_ReceiveDataHandle(void) { if(rxLength》=RECEIVEDATALENGTH) { rxLength=0; } /*接收寄存器为空,等待字节被对应的串口完全接收*/ if(LL_USART_IsActiveFlag_RXNE(USART1)) { uint8_t rData; /*获取接收到的字节*/ rData=LL_USART_ReceiveData8(USART1); rxBuffer[rxLength++] = rData; } if(LL_USART_IsActiveFlag_ORE(USART1)) { LL_USART_ClearFlag_ORE(USART1); } } 需要注意的是需要添加ORE溢出标志的检测,确保每次的接收中断都是有效的。 4、总结 最后我们来测试一下我们的代码。将相关项目下载到目标板并采用两种监测方式查看结果。首先接到PC机的串口,在上位中使用Modscan来查看,其结果如下: 然后通过J-Link在线调试监控数据通讯,其结果如下: 上图中,上部是我们的物理量数据,而下面是接收到的上位下发的读取保持寄存器的Modbus报文。结合前一张图,很明显收发都是正确的。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
2180 浏览 0 评论
1349 浏览 1 评论
4256 浏览 2 评论
2935 浏览 0 评论
这是汽车360全景控制器上的主板,请问圆圈中的原件是什么,起什么作用?
2678 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 02:11 , Processed in 0.583498 second(s), Total 74, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号