Nextion Display with STM32 using STM32CubeIDE


This tutorial interfacing Nextion Diplay with STM32F103 board. All STM32 microcontroller works same with Nextion Display. Nextion Display communicate using usart(Rx/Tx) with any microcontroller.

   We are using STM32CubeMX and STM32IDE for stm32f103 programming. There are following components we need....

Components Requirements:

  ✔   1  ×  STM32F103 Board

  ✔   1  ×  Nextion Display

  ✔   1  ×  ST-Link Programmer 

  ✔   1  ×  TTL Serial to USB Adapter

  ✔   1  ×   LED

  ✔   1  ×   220 Ω Register

  ✔   10  ×   Jumper Wires

  

   First we create Nextion Display screen as shown in nextion display tutorial post. For detail tutorial please visit following link. Nextion Display Tutorial

STM32 with Nextion Display

STM32 USART Project


Above screen you can see there are following control we have crated.

 h0 : Slider 

 t0,t1 : textbox ,( t0 fetch value of h0 slider) (t1 for light title)

b0, b1 : Button for controlling Led.

Nextion display send  h0 slider value to stm32 board and will send it back to t0 textbox, using b0 button send "ON" string to stm32 board and same b1 button send "OFF" string to stm32board. as  per "ON" & "OFF" string will make PC13 built-in LED of board ON/OFF. 

all control user code we have write as per our requirement in Nextion Display Project.

STM32 Programming: 

We need to first receive/Transmits data from UART. It can achieve through three methods  polling , Interrupt and DMA UART receiving Transmit.

 First we are create project with STM32CubeMX for basic configuration code generate.

STM3cube



 

Polling Method: 

HAL_UART_Receive(huart, pData,Size,Timeout)
HAL_UART_Transmit(huart, pData, Size,Timeout)      

The polling method is essentially a blocking function being called from the main routine and it does block the CPU so it can’t proceed in the main task execution until a certain amount of UART data bytes are received. After receiving the required amount of data, the function ends and the CPU continues the main code execution. Otherwise, and if the UART peripheral for some reason didn’t receive the expected amount of data, the function will keep blocking the CPU for a certain amount of time “time-out” after which it gets terminated and gives back the control to the CPU to resume the main code. 


   while(1)
  {
	  HAL_UART_Receive(&huart1, (uint8_t*) Rxbuf,3, 1000);

	    if (strcmp( Rxbuf, "ON") == 0)
	    {
	  	     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
	    }
	    else  if (strcmp(Rxbuf, "OFF") == 0)
	    {
	    	 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
	    }
	    else if(atoi(Rxbuf))
	    {
	    	Nextion_Send("t0",(char *)Rxbuf);
	    }

	   memset(Rxbuf, 0, sizeof(Rxbuf));
	   HAL_Delay(100);

  }

We created Nextion_Send method to send data to nextion display.
    
    
 void Nextion_Send(char * Id, char * String)
{
	uint8_t  Cmd_End[3] = {0xFF,0xFF,0xFF};
	char buf[50];
    int len = sprintf(buf, "%s.txt=\"%s\"",Id,String);

	HAL_UART_Transmit(&huart1, (uint8_t*)buf, len, 1000);
	HAL_UART_Transmit(&huart1, Cmd_End, sizeof(Cmd_End), 1000);
}    
 

Interrrupt Method:

Using interrupt signals is a convenient way to achieve serial UART data reception. The CPU initializes the UART receive hardware so that it fires an interrupt signal whenever a new byte of data is received. And in the ISR code, we save the received data in a buffer for further processing.

This way of handling the UART data reception is a non-blocking way. As the CPU initiates the receiving process and it resumes executing the main code. Until an interrupt is received, then it freezes the main context and switches to the ISR handler to save the received byte to a buffer and switches back to the main context and resume the main code.

HAL_UART_Receive_IT(huart, pData,Size)
HAL_UART_Transmit_IT(huart, pData, Size)      

The above function initializes the UART receive process in interrupt mode (non-blocking) and upon completion, a callback function is called to notify the application and the processor knows that the received data buffer is now ready.

   Example 

   For interrupt first need change in cubemax file 
for enable it. As shown in below figure.

STM32 uart interrupt enable


  In Non-Blocking way interrupt call after complete transmit or receive. After it call function 

 HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

 HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)

   

    
#include "main.h"

UART_HandleTypeDef huart1;

char Rxbuf[50];
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_Receive_IT(&huart1,  (uint8_t*) Rxbuf, 3);
	
	 if (strcmp( Rxbuf, "ON") == 0)
		    {
		  	     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
		    }
		    else  if (strcmp(Rxbuf, "OFF") == 0)
		    {
		    	 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
		    }
		    else if(atoi(Rxbuf))
		    {
		    	Nextion_Send("t0",(char *)Rxbuf);
		    }

		   memset(Rxbuf, 0, sizeof(Rxbuf));
		   HAL_Delay(100); 
}

void Nextion_Send(char * Id, char * String)
{
	uint8_t  Cmd_End[3] = {0xFF,0xFF,0xFF};
	char buf[50];
    int len = sprintf(buf, "%s.txt=\"%s\"",Id,String);

	HAL_UART_Transmit(&huart1, (uint8_t*)buf, len, 1000);
	HAL_UART_Transmit(&huart1, Cmd_End, sizeof(Cmd_End), 1000);
}


int main(void)
{

  HAL_Init();
 
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();

  HAL_UART_Receive_IT(&huart1,  (uint8_t*) Rxbuf, 3);

  while (1)
  {


  }

}

DMA Method: 

This method is a non-blocking one, yet very efficient. However, if you’re receiving a continuous stream of serial data, an insane number of interrupts per second will have to be handled by the CPU which is a huge loading and a waste of time for it. In this situation, even the interrupt method will be inefficient and unnecessarily loading the CPU and consuming too much of the CPU time. And in worst scenarios, there might be some data packets lost or dropped in the way. Now, it comes the time to use the DMA method.  

HAL_UART_Receive_DMA(huart, pData, Size)
HAL_UART_Transmit_DMA(huart, pData, Size)

Using the DMA method in order to direct the received serial UART data from the UART peripheral directly to the memory is considered to be the most efficient way to do such a task. It requires no CPU intervention at all, you’ll have only to set it up and go execute the main application code. The DMA will notify back the CPU upon reception completion and that received data buffer will be in the pre-programmed location.