A basic UART initialization with interrupts using HAL looks something like the one below. I do not want to descirbe the parameters as they are quite obvious. It is an actual pins configuration and the UART peripheral configuration. HAL_UART_MspInit
is called by HAL_UART_Init
, to use it you only need to call MX_USART1_UART_Init
.
#include "stm32f0xx_hal.h"
UART_HandleTypeDef huart1;
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
HAL_UART_Init(&huart1);
}
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(huart->Instance==USART1)
{
__USART1_CLK_ENABLE();
/**USART1 GPIO Configuration
PA2 ------> USART1_TX
PA3 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn); // Enable Interrupt
}
}
The interrupt handling is the following:
void USART1_IRQHandler()
{
HAL_UART_IRQHandler(&huart1);
}
This is the actual ISR, and HAL_UART_IRQHandler(&huart1)
is a HAL definied handler function. It checks which interrupt source flag has been set, calls a callback or wait for more byte to be received and clears the interrupt flags.
In case of RX interrupts this handler counts the received bytes and when the desired amount is received calls this callback function:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
// Your buffer is full with your data process it here or set a flag
}
}
The callback has a weak declaration, you have to implement it.
Now about usage. To send, the following HAL function can be used, this is the simplest:
HAL_UART_Transmit(&huart1, (uint8_t*)"AT\r", 3, 0xFFFFFF)
To receive with interrupt one must use the following function:
HAL_UART_Receive_IT(&huart1, uint8_t *pData, uint16_t size)
where pData
is a pointer to the receive buffer and size
is the number of bytes you are expecting. The HAL_UART_IRQHandler(&huart1)
will call the callback if the number of received bytes equal to size
.
All of this can be generated by using STM32CubeMX code generator, except the callbacks, those are not generated.
The GSM module probably has echo mode enabled by default, so to AT\r
it will respond with \r\nAT\r\n\r\nOK\r\n
, 12 bytes should be waited.
Echo mode can be disabled by ATE0
command and saved as default with the AT&W
command. From that the answer will be \r\nOK\r\n
to the AT\r
.
Best Answer
In general, how to use DMA will depend on what data you transfer and how much.
At least I don't understand why would you disable interrupts, while on STM32 the DMA itself can implement a ring or ping-pong buffer. As soon as one half of the buffer is full, it triggers you with the interrupt (which calls the callback) and keeps receiving data into the second half of the buffer.
But if you are receiving say single keypresses from a terminal program, you most certainly don't want to wait until half-buffer worth of letters has arrived, you would poll the DMA controller if any bytes and how many bytes have been received so you can act on them.