STM32F0使用LL库实现Modbus通讯

在本次项目中,限于空间要求我们选用了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使能)等位是需要我们注意的。该寄存器的结构如下:

在控制寄存器1(USART_CR1)中,RXNEIE(RXNE中断使能)被置位后,只要USART_ISRORE=1或者RXNE=1就会产生该中断。接下来我们看一看波特率寄存器(USART_BRR),其结构如下:

对于波特率寄存器(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_TXPA3   ------> 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报文。结合前一张图,很明显收发都是正确的。

欢迎关注:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499414.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32基于SPI和AD7192的数据采集

在开发臭氧发生器的时,我们需要一个高分辨率的AD采集,于是选择了AD7192,选择这款ADC的原因比较简单。首先它是24位的符合我们的精度要求;其次它自带时钟,便于节省空间;第三它有4路单端或2路差分输入&#x…

Modbus协议栈实现Modbus RTU多主站支持

前面我们已经详细讲解过Modbus协议栈的开发过程,并且利用协议栈封装了Modbus RTU主站和从站,Modbus TCP服务器与客户端,Modbus ASCII主站与从站应用。但在使用过程中,我们发现一些使用不便和受限的地方,所以我们就想要…

STM32基于AD5663的UV灯电压控制

在开发臭氧发生器的时,我们使用UV灯来实现臭氧的产生。而UV灯的强度决定了臭氧产生的浓度,UV灯的光强则与其控制电压密切相关。所以我们要控制产生的臭氧的浓度就需要调节其控制电压。我们选择了AD5663这一模拟量输出模块来实现这一点。 1、AD5663简介 …

实现Modbus ASCII多主站应用

前面我们已经分析了Modbus RTU的更新设计和具体实现(如果不清楚可查看前一篇文章)。其实Modbus ASCII与Modbus RTU都是基于串行链路实现的,所以有很多的共同点,基于此,这篇文章我们只讨论与Modbus RTU所不同的部分。 …

STM32一种基于NTC的控温电路及软件实现

NTC(Negative Temperature Coefficient)是一种随温度上升时,电阻值呈指数关系减小的热敏电阻。应用广泛,最近我们就采用了NTC来控制加热并测温,并达到了预期的效果。 1、硬件设计 我们使用三极管作为加热元件&#x…

STM32利用光敏二极管实现光度测量

最近我们在开发臭氧发生器时,需要监测生成的臭氧的浓度,于是想到使用光度计来测量。因为不同浓度的臭氧对管的吸收作用是不相同的,于是检测光照强度的变化就可以得到相应的浓度数据。 1、硬件设计 此次光照度检测我们选用了S1336-5BQ光电点二…

STM32的ADC通道间干扰的问题

最近我们在开发一个项目时,用到了MCU自带的ADC,在调试过程中发现通道之间村在相互干扰的问题。以前其实也用过好几次,但要求都不高所以没有太关注,此次因为物理量的量程较大,所以看到了变化。 首先来说明一下此次的软…

实现Modbus TCP多网段客户端应用

对于Modbus TCP来说与Modbus RTU和Modbus ASCII有比较大的区别,因为它是运行于以太网链路之上,是运行于TCP/IP协议之上的一种应用层协议。在协议栈的前两个版本中,Modbus TCP作为客户端时也存在一些局限性。我们将对这些不足作一定更新。 1、…

改进初学者的PID-介绍

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

改进初学者的PID-采样时间

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

改进初学者的PID-微分冲击

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

LwIP应用开发笔记之一:LwIP无操作系统基本移植

现在,TCP/IP协议的应用无处不在。随着物联网的火爆,嵌入式领域使用TCP/IP协议进行通讯也越来越广泛。在我们的相关产品中,也都有应用,所以我们结合应用实际对相关应用作相应的总结。 1、技术准备 我们采用的开发平台是STM32F407…

改进初学者的PID-修改整定参数

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

改进初学者的PID-积分饱和

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

改进初学者的PID-手自动切换

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

改进初学者的PID-初始化

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

如何优化代码和RAM大小

如果供应商为我自己的项目提供了一个起点,那就太好了。工作blinky始终是一个伟大的首发。方便总是有代价,而且“blinky”就是夸大“切换GPIO引脚”的代码大小。对于具有少量RAM和FLASH的设备,这可能会引起关注:如果blinky占用那么…

改进初学者的PID-正反作用

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

改进初学者的PID-测量的比例介绍

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…

改进初学者的PID-测量的比例编码

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettb…