segunda-feira, 16 de junho de 2025

Comunicação serial 232 modo DMA usando o CUBE IDE no STM32F103C6T6

     Olá, veja a demonstração como usar o recurso DMA do microcontrolador da STM32, pois este recurso permite que a CPU do microcontrolador não pare de funcionar  a cada recepção de caracteres que chegam pela serial. Vale lembrar que também é possível configurar este recuso para transmissão, ou seja pode se colocar um vetor(array) para transmissão e então habilitar (ou não) para que ao finalizar gere uma interrupção de envio de todos os dados. aqui será usado a interface gráfica do CUBE IDE.

    Aqui estou usando o microcontrolador STM32F103C6T6 da placa de desenvolvimento blue pill.

configurando o CUBE IDE :

    Basta seguir as imagens para configurar corretamente. Na primeira imagem da aba "PINOUT & CONFIGURATION -> NVIC Setting"  deve estar habilitado as 2 interrupção de DMA e global, pois uma e para coletar os caractere e a outra é acionada quando o DMA atingir o numero de caracteres configurado, observe que na interface gráfica os pinos configurados são destacados.

    Na aba DMA Settings habilita USART_RX, mas se quiser habilitar pra transmissão use o USART_TX

    Na aba Parameter Settings configure a porta serial. 

    Neste exemplo usei o cristal externo na aba RCC, porem se quiser usar o clock interno fique a vontade, pois a propria IDE faz os ajuste automaticamente neste parâmetros, quando se seta na aba "CLOCK CONFIGURATION" .

Pronto ! agora é codificar

O código fonte :


    Pra quem usa o CUBE IDE sabe que ele irá gerar automaticamente o código da estrutura "main.c" quando se salva as configurações portanto é necessário acrescentar apenas algumas variáveis e as chamadas de interrupções, neste caso utilizei a de recepção completa(HAL_UART_RxCpltCallback) mas existe a opção de avaliar quando se chega metade dos dados(HAL_UART_RxHalfCpltCallback), caso precise validar um pacote grande pode ser util. 
    Na rotina principal não precisaria ter nada, porém coloquei uma variável para demonstrar caso seja necessário fazer alguma ação depois que recebe o vetor com os dados recebidos.

#include "main.h"

#include <stdio.h>

UART_HandleTypeDef huart1;

DMA_HandleTypeDef hdma_usart1_rx;


/* USER CODE BEGIN PV */

/* USER CODE END PV */


/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_DMA_Init(void);

static void MX_USART1_UART_Init(void);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */


/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

#define TX_BUFFER_SIZE 128 // Tamanho do buffer de transmissão


uint8_t RxData[20]; //20 bytes de recepção

uint8_t tem_dados = '0';


char txBuffer[TX_BUFFER_SIZE]; // Buffer para enviar mensagens de debug/resposta


void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)

{ //chegou a metade dos dados pode ser util em alguma aplicação

//HAL_UART_Transmit(&huart1,RxData, 10, 50); //imprime a metade coletada

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{ //chegou a quantidade de dados escolhidos

HAL_UART_Receive_DMA(&huart1,RxData,10); // solicita novamente mais 10 bytes

tem_dados = '1';

HAL_UART_Transmit(&huart1,RxData, 10, 50);

int apaga=0;

while(apaga<20)//limpa pacote

{

RxData[apaga] =' ';

apaga++;

}


}


/* USER CODE END 0 */


/**

* @brief The application entry point.

* @retval int

*/

int main(void)

{


/* USER CODE BEGIN 1 */

/* USER CODE END 1 */


/* MCU Configuration--------------------------------------------------------*/


/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();


/* USER CODE BEGIN Init */

/* USER CODE END Init */


/* Configure the system clock */

SystemClock_Config();


/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */


/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_DMA_Init();

MX_USART1_UART_Init();

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

HAL_UART_Receive_DMA(&huart1,RxData,10);

/* Infinite loop */

/* USER CODE BEGIN WHILE */

/* USER CODE END WHILE */

HAL_UART_Transmit(&huart1, (uint8_t*)"Sistema Pronto. Aguardando dados...\n\r", strlen("Sistema Pronto. Aguardando dados...\n\r"), HAL_MAX_DELAY);

for(;;)

{

if(tem_dados == '1')

{

tem_dados = '0';

HAL_UART_Transmit(&huart1, (uint8_t*)"chegou dados!", strlen("chegou dados!"), HAL_MAX_DELAY);

}

}

/* USER CODE BEGIN 3 */

/* USER CODE END 3 */

}


/**

* @brief System Clock Configuration

* @retval None

*/

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};


/** Initializes the RCC Oscillators according to the specified parameters

* in the RCC_OscInitTypeDef structure.

*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}


/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;


if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)

{

Error_Handler();

}

}


/**

* @brief USART1 Initialization Function

* @param None

* @retval None

*/

static void MX_USART1_UART_Init(void)

{


/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */


/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 */

huart1.Instance = USART1;

huart1.Init.BaudRate = 9600;

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;

if (HAL_UART_Init(&huart1) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN USART1_Init 2 */

/* USER CODE END USART1_Init 2 */


}


/**

* Enable DMA controller clock

*/

static void MX_DMA_Init(void)

{


/* DMA controller clock enable */

__HAL_RCC_DMA1_CLK_ENABLE();


/* DMA interrupt init */

/* DMA1_Channel5_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);


}


/**

* @brief GPIO Initialization Function

* @param None

* @retval None

*/

static void MX_GPIO_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct = {0};

/* USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */


/* GPIO Ports Clock Enable */

__HAL_RCC_GPIOC_CLK_ENABLE();

__HAL_RCC_GPIOD_CLK_ENABLE();

__HAL_RCC_GPIOA_CLK_ENABLE();


/*Configure GPIO pin Output Level */

HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);


/*Configure GPIO pin : LED_Pin */

GPIO_InitStruct.Pin = LED_Pin;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);


/* USER CODE BEGIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */

}


/* USER CODE BEGIN 4 */

/* USER CODE END 4 */


/**

* @brief This function is executed in case of error occurrence.

* @retval None

*/

void Error_Handler(void)

{

/* USER CODE BEGIN Error_Handler_Debug */

/* USER CODE END Error_Handler_Debug */

}


#ifdef USE_FULL_ASSERT

/**

* @brief Reports the name of the source file and the source line number

* where the assert_param error has occurred.

* @param file: pointer to the source file name

* @param line: assert_param error line source number

* @retval None

*/

void assert_failed(uint8_t *file, uint32_t line)

{

/* USER CODE BEGIN 6 */

/* USER CODE END 6 */

}

#endif /* USE_FULL_ASSERT */


Obrigado pela atenção! e até a próxima postagem. Data: 16/06/2025         








           


Nenhum comentário :

Postar um comentário

olá,digite aqui seu comentário!