stm32 interrupt and serial DMA communication under stm32cubemx

Keywords: Single-Chip Microcomputer stm32 ARM

catalogue

1, External interrupt to realize the flashing and extinguishing of LED

1. Create project

2. Compiling and writing programs

3. Burning

4. Experimental results

2, Serial port interrupt to realize serial port communication

1. Create project

2. Redirect printf and scanf

3. Operation results

4.UART receiving interrupt

3, Serial port DMA receiving and sending data

1. Create project

2. Test routine 1

3. Test results

4. Test routine 2

​ 

5. Test procedure

  4, Summary

5, Reference link

 

1, External interrupt to realize the flashing and extinguishing of LED

1. Create project

 

 

 

 

 

 

 

  Then automatically generate the program.

2. Compiling and writing programs

To see the generated interrupt service function   void EXTI1_IRQHandler(void)

 

You can see that the function calls Hal again_ GPIO_ EXTI_ Irqhandler(), then continues to jump to the next function  

 

You can see that HAL_ is called in here. GPIO_ EXTI_ Callback(), the next function can be seen as_ Start with weak, you need to write the function yourself.  

 

At this time, write the callback program in main.c, and the library function used is HAL_GPIO_TogglePin(), this function is used to flip the level, that is, once an interrupt is generated, it will flip the level once.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{  
{HAL_GPIO_TogglePin(led1_GPIO_Port,led1_Pin);
}
}

 

 

Then compile.

3. Burning

 

Set boot0 to 0 when powered on, and then reset again to run

4. Experimental results

Here, because stm32c8t6 there is no key, DuPont line is selected to replace the switch. Each contact with ground will produce an interrupt

 

2, Serial port interrupt to realize serial port communication

1. Create project

RCC, SYS and CLOCK settings are the same as above

Next, set the serial port USART1, select Asynchronous (Asynchronous communication MODE) in MODE, and enable the USART1 interrupt

Then you can directly generate the project

2. Redirect printf and scanf

#include <stdio.h>
extern UART_HandleTypeDef huart1;   //Declaration serial port

 

  • In stm32f1xx_hal.c   Rewrite fget and fput functions in

 

/**
  * Function function: redirect c library function printf to DEBUG_USARTx
  * Input parameters: None
  * Return value: None
  * Description: None
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * Function function: redirect c library functions getchar and scanf to DEBUG_USARTx
  * Input parameters: None
  * Return value: None
  * Description: None
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

 

 

Add in main.c

 

 #define RXBUFFERSIZE  256
char RxBuffer[RXBUFFERSIZE]; 

 

 

	printf("hello world\n");
			HAL_Delay(1000);

 

Check Use MicroLIB in target to call the microlibrary

 

3. Operation results

 

4.UART receiving interrupt

Specific process:

  1. Initialize serial port
  2. Call the receive interrupt function for the first time in main
  3. Enter receive interrupt and finish receiving data   Enter interrupt callback function
  4. Modify HAL_UART_RxCpltCallback interrupt callback function to process the received data,
  5.   Hal will be called once in the callback function_ UART_ Receive_ It function, so that the program can re trigger the receiving

code implementation

And add the following definitions in main.c:

#include <string.h>
 
#Define rxbuffersize 256 / / maximum number of bytes received
char RxBuffer[RXBUFFERSIZE];   //receive data 

 

In the main() main function, the call interrupt function is called once.

/* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1, RxBuffer, 1);
/* USER CODE END 2 */

 

Add interrupt callback function under main.c

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 
{
	if(huart->Instance==USART1)
	{	
		HAL_UART_Transmit(&huart1,RxBuffer,1,0xff);
	}
	HAL_UART_Receive_IT(&huart1, RxBuffer, 1); 
}

 

Experimental results

 

   You can see the serial port echo.

3, Serial port DMA receiving and sending data

1. Create project

Refer to the above serial port settings for other settings

Here are the differences

Enter DMA Settings

Click add and select USART_RX   USART_TX   The transmission rate is set to medium speed  

DMA transmission mode is normal mode

DMA memory address increases by one byte at a time

 

 

Click System Core DMA on the right

Click Add to add menomen  

 

Normal: normal mode
After one DMA data transmission, stop DMA transmission, that is, only one transmission

DMA pointer increment setting

Increment Address: the address pointer is incremented (described above).

Src Memory on the left represents the peripheral address register

Function: set whether the peripheral address remains unchanged or increases when transmitting data. If it is set to increment, add Data Width bytes to the address in the next transmission,

Dst Memory on the right represents the memory address register

Function: set whether the memory address is incremented when transmitting data. If it is set to increment, add Data Width bytes to the address in the next transmission,

This is the same as Src Memory, except for memory.

The project can then be generated.

2. Test routine 1

Add in main.C:

 

 /* USER CODE BEGIN Init */
	uint8_t Senbuff[] = "HELLO WORLD";  //Define data sending array
  /* USER CODE END Init */

 

while loop:

  while (1)
  {
    /* USER CODE END WHILE */
			HAL_UART_Transmit_DMA(&huart1, Senbuff, sizeof(Senbuff));
	        HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }

 

3. Test results

 

4. Test routine 2

STM32 IDLE receive idle interrupt

Generation condition of IDLE interrupt of STM32: it will not be generated when there is no data reception on the serial port. After clearing the IDLE flag bit, it must be triggered after the first data is received. Once the received data is cut off and no data is received, the IDLE interrupt is generated

code:

uart.c

 

volatile uint8_t rx_len = 0;  //The length of a frame of data received
volatile uint8_t recv_end_flag = 0; //One frame data receiving completion flag
uint8_t rx_buffer[100]={0};  //Receive data cache array

 

  /* USER CODE BEGIN USART1_Init 2 */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //Enable IDLE interrupt
 
//DMA receiving function, this sentence must be added. If not, the real data transmitted for the first time cannot be received. It is empty, and the data length received at this time is the data length of the buffer
	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);
 
  /* USER CODE END USART1_Init 2 */

 

 uart.h

extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
/* USER CODE BEGIN Private defines */
 
 
#define BUFFER_SIZE  100  
extern  volatile uint8_t rx_len ;  //The length of a frame of data received
extern volatile uint8_t recv_end_flag; //One frame data receiving completion flag
extern uint8_t rx_buffer[100];  //Receive data cache array

 

There is no. h file in the project. You need to find it in the folder  

 

 

 

 

 

main.c

 

 

/*
*********************************************************************************************************
* Function name: DMA_Usart_Send
* Function Description: serial port sending function
* Formal parameters: buf, len
* Return value: None
*********************************************************************************************************
*/
void DMA_Usart_Send(uint8_t *buf,uint8_t len)//Serial transmission package
{
 if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK) //Judge whether the transmission is normal. If there is an exception, enter the exception interrupt function
  {
   Error_Handler();
  }
 
}
 
 
 
/*
*********************************************************************************************************
* Function name: DMA_Usart1_Read
* Function Description: serial port receiving function
* Formal parameters: Data,len
* Return value: None
*********************************************************************************************************
*/
void DMA_Usart1_Read(uint8_t *Data,uint8_t len)//Serial port receiving package
{
	HAL_UART_Receive_DMA(&huart1,Data,len);//Reopen DMA reception
}

Here, it needs to be defined in front of the main function, otherwise an error will be reported when calling in the main function, or you can declare the function before main.

 

while Loop

 

 

 while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
		 if(recv_end_flag == 1)  //Reception completion flag
		{
			
			
			DMA_Usart_Send(rx_buffer, rx_len);
			rx_len = 0;//Clear count
			recv_end_flag = 0;//Clear the end of reception flag bit
//			for(uint8_t i=0;i<rx_len;i++)
//				{
//					rx_buffer[i]=0;// Clear receive cache
//				}
				memset(rx_buffer,0,rx_len);
  }
		HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//Reopen DMA reception
}

stm32f1xx_ In it. C

#include "usart.h"
 
void USART1_IRQHandler(void)
{
	uint32_t tmp_flag = 0;
	uint32_t temp;
	tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //Get the IDLE flag bit
	if((tmp_flag != RESET))//The idle flag is set
	{ 
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);//Clear flag bit
		//temp = huart1.Instance->SR;  // Clear the status register Sr and read the SR register to clear the SR register
		//temp = huart1.Instance->DR; // Read data in data register
		//These two sentences are equivalent to the one above
		HAL_UART_DMAStop(&huart1); //
		temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// Gets the number of untransmitted data in DMA   
		//temp  = hdma_ usart1_ rx.Instance->NDTR;// Read the NDTR register to obtain the number of untransmitted data in DMA,
		//This sentence is equivalent to the one above
		rx_len =  BUFFER_SIZE - temp; //The total count subtracts the number of untransmitted data to obtain the number of received data
		recv_end_flag = 1;	// Accept completion flag position 1	
	 }
  HAL_UART_IRQHandler(&huart1);
 
}

 

5. Test procedure

 

  4, Summary

Through this experiment, it is found that interrupting the communication with serial port DMA can improve the operation efficiency of the program. DMA can directly access the memory without CPU. The burden of CPU is reduced. I am familiar with the basic functions of serial port communication and DMA communication.

5, Reference link

 qq_ Blog of 60678931_ Laul Ken-Yi_CSDN blog

 

Posted by aussieguy on Sat, 06 Nov 2021 16:55:55 -0700