STM32F0使用LL库实现Modbus通信

  在本次项目中,限于空间要求咱们选用了STM32F030F4做为控制芯片。这款MCU不但封装紧凑,并且自带的Flash空间也很是有限,因此咱们选择了LL库实现。本篇将说明基于LL实现USART通信。编程

1、概述函数

  咱们想要实现基于RS485Modbus通信实际就是基于USART的通信。USART使用可编程波特率发生器提供很是普遍的波特率范围。根据不一样配置能够实现咱们不一样的串行通信应用需求。其结构图以下:测试

 

  咱们在USART基础上实现一个Modbus的从站应用,因此咱们对于接收采用中断接收,而对于发送则根据接收到的信息作出反馈。因此咱们要根据接收状态和发送状态来肯定咱们的操做。ui

2USART配置spa

  在实现以前,咱们来了解一下知足前述的需求,咱们应该作哪些配置。主要有2个寄存器须要注意:控制寄存器1USART_CR1和波特率寄存器(USART_BRR)。调试

  首先咱们仍是来看一看控制寄存器1USART_CR1)。其中RXNEIERXNE中断使能)、TE(发送使能)、RE(接收使能)、UEUSART使能)等位是须要咱们注意的。该寄存器的结构以下:blog

 

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

 

  对于波特率寄存器(USART_BRR),顾名思义就是设置波特率。但波特率的值不是随意设置,有一套计算方法,能够查看STM的手册。io

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报文。结合前一张图,很明显收发都是正确的。

欢迎关注:

相关文章
相关标签/搜索