cancel
Showing results for 
Search instead for 
Did you mean: 

USART TX DMA on STM32G031

Stastny.Petr
Associate III

Hello I need to send a string via USART every 500ms. I tried to use DMA that seems to be easy to configure. USART transfer works but only without DMA (test in while main cycle). I do not see any problem in DMA configuration. Can you tell me it there is something that I do not set?

I start DMA transfer in Systick cycle. 

Thank you 

 

 

#include "main.h"
#include "stm32g0xx.h"
#include <stdint.h>


#define BAUD_RATE 9600
#define SYS_CLK 64000000

const char message[] = "Hello, world!\r\n";

void DMA_Init(void) {
    // Enable DMA clock
    RCC->AHBENR |= RCC_AHBENR_DMA1EN;

    // Configure DMA for USART1 TX (DMA1 Channel 1)
    DMA1_Channel1->CPAR = (uint32_t)&USART1->TDR;
    DMA1_Channel1->CMAR = (uint32_t)message;
    DMA1_Channel1->CNDTR = sizeof(message) - 1;
    DMA1_Channel1->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE;

    // Enable DMA1 interrupt
    NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}

void USART1_Init(void) {

    // Enable clocks
    RCC->IOPENR |= RCC_IOPENR_GPIOBEN;   // Enable GPIOB clock
    RCC->APBENR2 |= RCC_APBENR2_USART1EN; // Enable USART1 clock

    // Configure PB6 as USART1_TX and PB7 as USART1_RX
    GPIOB->MODER &= ~(GPIO_MODER_MODE6_Msk | GPIO_MODER_MODE7_Msk);
    GPIOB->MODER |= (0x2 << GPIO_MODER_MODE6_Pos) | (0x2 << GPIO_MODER_MODE7_Pos); // Set PB6 and PB7 to AF mode
    GPIOB->AFR[0] |= (0x0 << GPIO_AFRL_AFSEL6_Pos) | (0x0 << GPIO_AFRL_AFSEL7_Pos); // Set AF0 (USART1)

    // Configure USART1
    USART1->BRR = SYS_CLK / BAUD_RATE; // Set baud rate
    USART1->CR3 |= USART_CR3_DMAT; // Enable DMA for transmitter - TOTO JE NAVIC
    USART1->CR1 |= USART_CR1_TE;       // Enable transmitter
    USART1->CR1 |= USART_CR1_UE;       // Enable USART

}

void DMA1_Channel1_IRQHandler(void) {

    if (DMA1->ISR & DMA_ISR_TCIF1) {
        // Clear the transfer complete interrupt flag
        DMA1->IFCR |= DMA_IFCR_CTCIF1;

        // Optional: Disable DMA channel if needed, and re-enable if you need to prepare for the next transfer
        DMA1_Channel1->CCR &= ~DMA_CCR_EN; // Disable DMA channel
        DMA1_Channel1->CNDTR = sizeof(message) - 1;//1; // Reset number of data to transfer
        DMA1_Channel1->CCR |= DMA_CCR_EN; // Re-enable DMA channel
    }

}



void SysTick_Handler(void)
{
    SysTickCounter++;
    if (SysTickCounter>500) {
    	DMA1_Channel1->CCR |= DMA_CCR_EN;	
    	SysTickCounter = 0;
    }
}


void USART1_SendString(const char *str) {
    while (*str) {
        while (!(USART1->ISR & USART_ISR_TXE_TXFNF_Msk)); // Wait until TX buffer is empty
        USART1->TDR = *str++;                             // Transmit character
    }
}


int main(void)
{
  CLK_Config();
  GPIO_Init();
  SysTick_Init();

  DMA_Init();
  USART1_Init();


  while (1)
  {
 
      //USART1_SendString(message); - THIS WORKS, BUT NOT WITH DMA
      //for (volatile int i = 0; i < 1000000; i++);

  }

}

 

0 REPLIES 0