我正在尝试使用STM32F446RE核-64板的登记液级编程。我想使用DMA通过圆形模式接收数据。每次尝试通过PC COM端口发送到STM32F446RE时,我都会收到DMA传输错误中断。我正在使用TERA定期终端以115200的波特率发送字节上的字节。

问题描述 投票:0回答:1
是正确的序列,可以使用DMA配置UART以进行接收?

到目前为止,我已经实施了:

main.c

#include <stdint.h>
#include <string.h>
#include "stm32f446xx.h"

void HT_Complete_callback(void);
void FT_Complete_callback(void);
void TE_error_callback(void);
void FE_error_callback(void);
void DME_error_callback(void);
void IDLE_IRQ_callback(void);

void DMA_init(void);
void DMA_Config (uint32_t srcAdd, uint32_t destAdd, uint16_t datasize);
void UART2_init (void);
void UART2_config (void);


#define RXSIZE 20
#define pDest (SRAM2_BASE + 0x800)

int main(void)
{
    UART2_init ();
    DMA_init();
    DMA_Config (USART2->DR,(uint32_t) pDest, RXSIZE);
    UART2_config ();

    /* Loop forever */
    while (1)
    {

    }
}

void UART2_init (void)
{
    RCC_TypeDef* pRCC = RCC;
    GPIO_TypeDef* pGPIOA = GPIOA;

    // 1. Enable RCC Clock for UART and GPIOA pins PA2-TX and PA3-RX
    pRCC->AHB1ENR |= (1 << 0);
    pRCC->APB1ENR |= (1 << 17);

    // 2. Configure PA2 and PA3 pins as alternate function pins moder register
    pGPIOA->MODER |= (0x2 << 4);
    pGPIOA->MODER |= (0x2 << 6);

    pGPIOA->AFR[0]  |= (7<<8);
    pGPIOA->AFR[0]  |= (7<<12);

    // Enable internal pull-up for PA2
    pGPIOA->PUPDR |= (0x1 << 4);
    // Enable internal pull-up for PA3
    pGPIOA->PUPDR |= (0x1 << 6);
}

void UART2_config (void)
{
    USART_TypeDef* pUART2 = USART2;
    DMA_Stream_TypeDef* pRXStream = DMA1_Stream5; //RX

    pUART2->CR1 = 0x00;   // Clear ALL

    pUART2->CR1 |= (1 << 4); // Enable IDLE Interrupt
    NVIC_EnableIRQ(USART2_IRQn);

    //Configure baud rate
    pUART2->BRR = 0x8B;

    // 10. Enable RX engine
    pUART2->CR1 |= (1 << 2);

    pUART2->CR3 |= (1 << 6); //DMR bit enable

    // 4. Enable the DMA1 stream 5
    pRXStream->CR &= ~(1<<0);
    while((pRXStream->CR & (1<<0)));

    pRXStream->CR |= 1<<0; // 4. Enable the DMA1 stream 5

    // 11. Enable UART engine
    pUART2->CR1 |= (1 << 13);
}

void HT_Complete_callback(void)
{
    while (1); //TODO: Implement callback
}

void FT_Complete_callback(void)
{
    while (1); //TODO: Implement callback
}

void DMA_init(void)
{
    // 0. Pointers for the registers
    RCC_TypeDef* pRCC = RCC;        //pointer to RCC_Typedef
    DMA_Stream_TypeDef* pRXStream = DMA1_Stream5; //RX

    // 1. Enable DMA1 Clock
    pRCC->AHB1ENR |= (1 << 21);

    pRXStream->CR = 0x0; //clear reg before config

    pRXStream->CR |= (1 << 27); // channel 4 select

    // 2. Enable DMA Interrupts
    DMA1->HIFCR = 0x00; //clear flags first
    pRXStream->CR |= (1<<1);  // TCIE, HTIE, TEIE, DMEIE Enabled
    pRXStream->CR |= (1<<2);
    pRXStream->CR |= (1<<3);
    pRXStream->CR |= (1<<4);

    NVIC_EnableIRQ(DMA1_Stream5_IRQn);

    // 3. Set the Data Direction
    pRXStream->CR |= (1<<6);   // Peripheral to Memory

    // 4. Enable the circular mode (CIRC)
    pRXStream->CR |= 1<<8;

    // 5. Enable the Memory Increment (MINC)
    pRXStream->CR |= 1<<10;

    // 6. Set the Peripheral data size (PSIZE)
    pRXStream->CR &= ~(3<<11);  // 00 : 8 Bit Data

    // 7. Set the Memory data size (MSIZE)
    pRXStream->CR &= ~(3<<13);  // 00 : 8 Bit Data

    // 8. Set the Priority Level
    pRXStream->CR &= ~(3<<16);  // PL = 0
}

void DMA_Config (uint32_t srcAdd, uint32_t destAdd, uint16_t datasize)
{
    DMA_Stream_TypeDef* pRXStream = DMA1_Stream5; //RX

    // 1. Set the data size in CNDTR Register
    pRXStream->NDTR = datasize;

    // 2. Set the  peripheral address in PAR Register
    pRXStream->PAR = srcAdd;

    // 3. Set the  Memory address in M0AR Register
    pRXStream->M0AR = destAdd;

}


void TE_error_callback(void)
{
    while (1); //TODO: Implement callback
}
void FE_error_callback(void)
{
    while (1); //TODO: Implement callback
}
void DME_error_callback(void)
{
    while (1); //TODO: Implement callback
}

void IDLE_IRQ_callback(void)
{
    while (1); //TODO: Implement callback
}

STM32F446_IT.C

#include "stm32f446xx.h" #include <stdint.h> #define is_it_HT() DMA1->HISR & ( 1 << 10) #define is_it_FT() DMA1->HISR & ( 1 << 11) #define is_it_TE() DMA1->HISR & ( 1 << 9) #define is_it_FE() DMA1->HISR & ( 1 << 6) #define is_it_DME() DMA1->HISR & ( 1 << 8) #define is_it_IDLE() USART2->SR & ( 1 << 4) extern void HT_Complete_callback(void); extern void FT_Complete_callback(void); extern void TE_error_callback(void); extern void FE_error_callback(void); extern void DME_error_callback(void); extern void IDLE_IRQ_callback(void); void USART2_IRQHandler(void) { if(is_it_IDLE()) { USART2->SR &= ~( 1 << 4); // clear IDLE bit } else { ; } } void DMA1_Stream5_IRQHandler(void) { if( is_it_HT() ) { DMA1->HIFCR |= ( 1 << 10); HT_Complete_callback(); }else if(is_it_FT() ) { DMA1->HIFCR |= ( 1 << 11); FT_Complete_callback(); }else if ( is_it_TE() ) { DMA1->HIFCR |= ( 1 << 9); TE_error_callback(); }else if (is_it_FE() ) { DMA1->HIFCR |= ( 1 << 6); FE_error_callback(); }else if( is_it_DME() ) { DMA1->HIFCR |= ( 1 << 8); DME_error_callback(); }else{ ; } }

I在通过PC传输字节时尝试调试代码。代码的初始化执行良好,甚至在循环时都可以达到超级。一旦通过PC发送字节。它用于DMA转移中断处理程序。

当DMA试图读取/编写不访问位置时,会发生转移错误。您的功能

void DMA_Config (uint32_t srcAdd, uint32_t destAdd, uint16_t datasize)

认为将其作为第一个参数。更改此

c embedded uart dma stm32f4
1个回答
0
投票

to

DMA_Config ((uint32_t)&(USART2->DR),(uint32_t) pDest, RXSIZE);

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.