catalogue
2.2.3 serial port initialization function
2.4.2 improve callback function and initialization function
2.6.2 program download and debugging
1.STM32CubeMX operation
This section was in the previous article, and the link is as follows:
2. Program perfection
2.1 perfect usart.h
In order to ensure that the programs we added will not be deleted when updating STM32CubeMX. When we improve the procedure, we need to add the procedure to the formulated position. For example, in usart.h, we will add programs to:
/* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */
First, define a UART_BUF structure, which contains the received buffer data and size, as well as the size of the transmitted data set.
Then define a serial port initialization function E_USART_INIT to define UART_BUF is initialized. Define a serial port interrupt callback function HAL_UART_RxCpltCallback.
/* USER CODE BEGIN Private defines */ typedef struct { uint8_t *rx_buf; //Receive buffer array uint16_t rx_buf_cnt; //Receive buffer count value uint16_t rx_size; //Received data size uint8_t rx_flag; //Receive completion flag bit uint8_t *tx_buf; //Send buffer array uint16_t tx_buf_cnt; //Send buffer count value uint16_t tx_size; //Actual sent data size }UART_BUF; //Serial port structure extern UART_BUF uart4; //Serial port structure entity /* USER CODE END Private defines */ void MX_UART4_Init(void); /* USER CODE BEGIN Prototypes */ void E_USART_INIT(UART_HandleTypeDef *huart); void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); /* USER CODE END Prototypes */
2.2 improve usart.c
2.2.1 header file improvement
Add a perfect program between / * USER CODE BEGIN 0 * / and / * USER CODE END 0 * /
/* USER CODE BEGIN 0 */ #include "string.h" #include "tim.h" #define UART4_RXSIZE one thousand and twenty-four // Maximum value of received data in one frame #define UART4_TXSIZE one thousand and twenty-four // Maximum value of transmitted data in one frame uint8_t uart4_rx_buf[UART4_RXSIZE]; //Send data buffer array uint8_t uart4_tx_buf[UART4_TXSIZE]; //Receive data buffer data UART_BUF uart4; //Serial port structure entity uint8_t RxBuffer; //Receive data intermediate variable /* USER CODE END 0 */
2.2.2 add callback function
Add callback function Hal in / * USER CODE BEGIN 1 * / and / * USER CODE END 1 * /_ UART_ RxCpltCallback.
The basic principle is to call the callback function (RxBuffer) after receiving a data, and then assign the data to rx_buf this array, then clear the count of the timer and restart the count to prevent the timer from interrupting.
/*****************************Rewrite the callback function to receive serial data**********************/ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == UART4) { if(uart4.rx_buf_cnt >= UART4_RXSIZE-1) //Received data volume exceeds the limit, error { uart4.rx_buf_cnt = 0; memset(uart4.rx_buf, 0x00, sizeof(uart4.rx_buf)); HAL_UART_Transmit(huart, (uint8_t *)"data overflow ", 10, 0xFFFF); } else //Normal reception { uart4.rx_buf[uart4.rx_buf_cnt++] = RxBuffer; //Store received data in rx_buf HAL_TIM_Base_Stop_IT(&htim7); __HAL_TIM_SET_COUNTER(&htim7, 0); HAL_TIM_Base_Start_IT(&htim7); //Reset the count value of timer 7 and count again } HAL_UART_Receive_IT(huart, (uint8_t *)&RxBuffer, 1); } }
2.2.3 serial port initialization function
Add serial port parameter initialization function E under the callback function_ USART_ INIT
/*****************************For UART_ Entity uart4 assignment of buf structure**********************/ void E_USART_INIT(UART_HandleTypeDef *huart) { if(huart->Instance == UART4) { uart4.rx_buf = uart4_rx_buf; //Receive data variable initialization uart4.rx_buf_cnt = 0; uart4.rx_size = 0; uart4.rx_flag = 0; uart4.tx_buf = uart4_rx_buf; //Send data variable initialization uart4.tx_buf_cnt = UART4_TXSIZE; uart4.tx_size = 0; HAL_UART_Receive_IT(huart, uart4.rx_buf, 1); //Enable receive interrupt } }
The last sentence in the initialization process is to start the interrupt and let each received data enter the callback function.
2.3 perfect tim.h
Add the function declaration in tim.c, and add between / * USER CODE BEGIN Prototypes * / and / * USER CODE END Prototypes * /:
/* USER CODE BEGIN Prototypes */ void E_TIM_INIT(TIM_HandleTypeDef *htim); void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim); /* USER CODE END Prototypes */
2.4 improve tim.c
2.4.1 improve header file
Add a function reference to the header file
/* USER CODE BEGIN 0 */ #include "usart.h" /* USER CODE END 0 */
2.4.2 improve callback function and initialization function
Add time callback function and time initialization function inside / * USER CODE BEGIN 1 * / and / * USER CODE END 1 * /. The specific meaning has been explained in the notes and will not be repeated here.
/* USER CODE BEGIN 1 */ /*****************************Override time callback function**********************/ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim == &htim7) { __HAL_TIM_CLEAR_FLAG(&htim7, TIM_FLAG_UPDATE); //The generated interrupt proves that no data has been received for more than 4ms, and the reception of one frame is completed HAL_TIM_Base_Stop_IT(&htim7); //After the interrupt, stop the timer and start the next time the data is received uart4.rx_size = uart4.rx_buf_cnt; //Assign the number of received data uart4.rx_buf_cnt = 0; //Clear uart4.rx_flag = 1; //After receiving, set 1 } } void E_TIM_INIT(TIM_HandleTypeDef *htim) { if(htim == &htim7) { __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_UPDATE); //Add manually HAL_TIM_Base_Start_IT(htim); } } /* USER CODE END 1 */
2.5 improve main.c
The above functions are perfect to process the functions of data sending and receiving. Through the above processing, the data sending and receiving can be completed. Before transplanting MODBUS function, you can test whether data sending and receiving are normal. main.c here is to complete the data forwarding function, that is, forward what data is received.
First in /* USER CODE BEGIN 2 * / and /* USER CODE END 2 * / the initialization function of timer and serial port is added internally
/* USER CODE BEGIN 2 */ E_USART_INIT(&huart4); E_TIM_INIT(&htim7); /* USER CODE END 2 */
Then add a program in the while loop of the main function:
while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ // This is used to test what you receive and send. if(uart4.rx_flag == 1) //If a frame of data is received, it is set in the callback function of tim7 { HAL_UART_Transmit(&huart4, (uint8_t *)(uart4.rx_buf), uart4.rx_size, 500);//Forward received data outward while(__HAL_UART_GET_FLAG(&huart4,UART_FLAG_TC)!=SET); //Dead cycle waiting uart4.rx_buf_cnt = 0; //Count value reset uart4.rx_flag=0; //The reception completion flag bit is cleared } HAL_Delay(5); //Cycle every 5ms } /* USER CODE END 3 */ }
2.6 commissioning
2.6.1 setting of Keil
In order to ensure the automatic reset operation after each program download, you need to set the debug of KEIL. The setting steps are as follows: Click √ in front of Reset and Run.
2.6.2 program download and debugging
After compiling correctly, download the program to the circuit board, and then connect the UART4 serial port of the circuit board to the computer port. Open the serial port debugging assistant and configure it in the serial port debugging assistant according to the program.
After the configuration is completed, open the serial port to send and receive data.