天天看點

STM32F0使用LL庫實作Modbus通訊

  在本次項目中,限于空間要求我們選用了STM32F030F4作為控制晶片。這款MCU不但封裝緊湊,而且自帶的Flash空間也非常有限,是以我們選擇了LL庫實作。本篇将說明基于LL實作USART通訊。

1、概述

  我們想要實作基于RS485的Modbus通訊實際就是基于USART的通訊。USART使用可程式設計波特率發生器提供非常廣泛的波特率範圍。根據不同配置可以實作我們不同的串行通訊應用需求。其結構圖如下:

STM32F0使用LL庫實作Modbus通訊

  我們在USART基礎上實作一個Modbus的從站應用,是以我們對于接收采用中斷接收,而對于發送則根據接收到的資訊做出回報。是以我們要根據接收狀态和發送狀态來确定我們的操作。

2、USART配置

  在實作之前,我們來了解一下滿足前述的需求,我們應該做哪些配置。主要有2個寄存器需要注意:控制寄存器1(USART_CR1)和波特率寄存器(USART_BRR)。

  首先我們還是來看一看控制寄存器1(USART_CR1)。其中RXNEIE(RXNE中斷使能)、TE(發送使能)、RE(接收使能)、UE(USART使能)等位是需要我們注意的。該寄存器的結構如下:

STM32F0使用LL庫實作Modbus通訊

  在控制寄存器1(USART_CR1)中,RXNEIE(RXNE中斷使能)被置位後,隻要USART_ISRORE=1或者RXNE=1就會産生該中斷。接下來我們看一看波特率寄存器(USART_BRR),其結構如下:

STM32F0使用LL庫實作Modbus通訊

  對于波特率寄存器(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;

  /* 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庫函數實作。配置完成後寄存器的狀态如下圖所示。

STM32F0使用LL庫實作Modbus通訊

  我們配置的波特率是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來檢視,其結果如下:

STM32F0使用LL庫實作Modbus通訊

  然後通過J-Link線上調試監控資料通訊,其結果如下:

STM32F0使用LL庫實作Modbus通訊

  上圖中,上部是我們的實體量資料,而下面是接收到的上位下發的讀取保持寄存器的Modbus封包。結合前一張圖,很明顯收發都是正确的。

歡迎關注:

STM32F0使用LL庫實作Modbus通訊

如果閱讀這篇文章讓您略有所得,還請點選下方的【好文要頂】按鈕。

當然,如果您想及時了解我的部落格更新,不妨點選下方的【關注我】按鈕。

如果您希望更友善且及時的閱讀相關文章,也可以掃描上方二維碼關注我的微信公衆号【木南創智】

繼續閱讀