gpt4 book ai didi

c - 让 DMA USART 在 STM32L053R8T6 上工作

转载 作者:行者123 更新时间:2023-11-30 14:49:25 25 4
gpt4 key购买 nike

我在让我的计算机(准确地说是虚拟 COM 端口)通过 DMA 和 USART 与 STM32L053R8T6 (Nucleo) 板进行通信时遇到问题。这是我的 DMA 和 USART 部分的代码:

#include "Device/Include/stm32l0xx.h"   // Device header
#include "JB.h"
#include <string.h>

#define PCLK 32000000
#define BAUD 19200

uint8_t stringtosend[] = "test\n";
uint8_t stringtoreceive[] = " ";

void ENABLE_UART_DMA(void){
RCC->AHBENR |= RCC_AHBENR_DMA1EN; //enable periph.clk for DMA1

/**Enabling DMA for transmission
* DMA1, Channel 4 mapped for USART2TX
* USART2 TDR for peripheral address
* stringtosend for data address
* Memory increment, memory to peripheral | 8-bit transfer | transfer complete interrupt**/
DMA1_CSELR->CSELR = (DMA1_CSELR->CSELR & ~DMA_CSELR_C4S) | (4 << (3 * 4));
DMA1_Channel4->CPAR = (uint32_t)&(USART2->TDR);
DMA1_Channel4->CMAR = (uint32_t)stringtosend;
DMA1_Channel4->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE;

/**Enabling DMA for reception
* DMA1, Channel 5 mapped for USART2RX
* USART2 RDR for peripheral address
* stringtoreceive for data address
* Data size given
* Memory increment, peripheral to memory | 8-bit transfer | transfer complete interrupt**/
DMA1_CSELR->CSELR = (DMA1_CSELR->CSELR & ~DMA_CSELR_C5S) | (4 << (4 * 4));
DMA1_Channel5->CPAR = (uint32_t)&(USART2->RDR);
DMA1_Channel5->CMAR = (uint32_t)stringtoreceive;
DMA1_Channel5->CNDTR = sizeof(stringtoreceive);
DMA1_Channel5->CCR = DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_EN;

NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 0); //NVIC enabled, max priority, channels 4-7
NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);
}

void CONFIGURE_UART_PARAM(void){
RCC->IOPENR |= ( 1ul << 0); //Enable GPIOA clock
RCC->APB1ENR |= ( 1ul << 17); //Enable USART#2 clock

GPIOA->AFR[0] &= ~((15ul << 4* 3) | (15ul << 4* 2) ); //Clear PA2,PA3
GPIOA->AFR[0] |= (( 4ul << 4* 3) | ( 4ul << 4* 2) ); //Set PA2,PA3
GPIOA->MODER &= ~(( 3ul << 2* 3) | ( 3ul << 2* 2) ); //Same as above
GPIOA->MODER |= (( 2ul << 2* 3) | ( 2ul << 2* 2) );

USART2->BRR = PCLK/BAUD;
USART2->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; //Enable DMA mode in transmit and receive

/*UART enabled for transmission and reception*/
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;

while((USART2->ISR & USART_ISR_TC) != USART_ISR_TC)
{
/* add time out here for a robust application */
}
USART2->ICR = USART_ICR_TCCF;
}

void CONFIGURE_EXTI(void){
SYSCFG->EXTICR[0] = ((SYSCFG->EXTICR[0] & 0x0000) | SYSCFG_EXTICR4_EXTI13_PC); //clear EXTICR and set to PC13(B1)
EXTI->FTSR |= EXTI_FTSR_TR13; //falling edge trigger
EXTI->IMR |= EXTI_IMR_IM13; //unmask
NVIC_SetPriority(EXTI4_15_IRQn, 0); //def interrupt
NVIC_EnableIRQ(EXTI4_15_IRQn);
}

/*************************************************************************************************************************************************************************************************************************/
/*************************************************************************************************************************************************************************************************************************/
/*Interrupt Handlers*/

void DMA1_Channel4_5_6_7IRQHandler(void){
if((DMA1->ISR & DMA_ISR_TCIF4) == DMA_ISR_TCIF4){
DMA1->IFCR = DMA_IFCR_CTCIF4; //Clear Channel 4 Transfer Complete flag
}
else if((DMA1->ISR & DMA_ISR_TCIF5) == DMA_ISR_TCIF5){
DMA1->IFCR = DMA_IFCR_CTCIF5; //Clear Channel 5 Transfer Complete flag

DMA1_Channel5->CCR &= ~DMA_CCR_EN;
DMA1_Channel5->CNDTR = sizeof(stringtoreceive);/* Data size */
DMA1_Channel5->CCR |= DMA_CCR_EN;
}
}

void EXTI4_15_IRQHandler(void){
if(!(GPIOC->IDR & (1 << 13))){
/* Clear EXTI 13 flag */
EXTI->PR = EXTI_PR_PIF13;

/* start 8-bit transmission with DMA */
DMA1_Channel4->CCR &= ~DMA_CCR_EN; //channel disable
DMA1_Channel4->CNDTR = sizeof(stringtosend);/* Data size */
DMA1_Channel4->CCR |= DMA_CCR_EN; //channel enable
}
}

//void EXTI4_15_IRQHandler(void){
// if((EXTI->PR & EXTI_PR_PIF13) == EXTI_PR_PIF13){
// /* Clear EXTI 13 flag */
// EXTI->PR = EXTI_PR_PIF13;
//
// /* start 8-bit transmission with DMA */
// DMA1_Channel4->CCR &= ~DMA_CCR_EN; //channel disable
// DMA1_Channel4->CNDTR = sizeof(stringtosend);/* Data size */
// DMA1_Channel4->CCR |= DMA_CCR_EN; //channel enable
// }
//}

现在,该特定代码基于 STM32L0 代码片段包 1.20“使用 DMA 的 USART/通信”中的示例。 USART 1 被简单地重新定义为 USART 2(因为这是虚拟 COM 端口使用的端口),并且 DMA channel 也据此重新定义。然而,这里的问题非常简单:它只会打印 stringtosend 一次(希望每次按下按钮 B1 时都执行一次),并且也不会通过 RX 接收数据 - 就好像它完全忽略 DMA 中断处理程序一样 - 我是这样的我不确定如何测试(该板上没有可用的跟踪功能)。我所拥有的似乎很好地反射(reflect)了引用手册,所有主要内容是:

int main(){

SystemCoreClockInit();
CONFIGURE_UART_PARAM();
ENABLE_UART_DMA();
pushbutton_def();
CONFIGURE_EXTI();

while(1){
}

...它应该只对定义的中断使用react,但是它没有,并且对于我的一生,我不明白为什么。如果你能帮助我,我会很高兴 - 我也想避免 HAL 或 LL API - 这不是一个足够复杂的项目,无法保证它们的使用(多个输入、输出、两个板之间通过 USART/DMA 进行通信),另外我会更喜欢学习更接近寄存器级别的工作。

谢谢!

编辑(响应贝伦迪的建议):1. GPIOC在另一个文件中定义,用pushbutton_def()调用:

RCC->IOPENR |= (1UL << 2); //enable GPIOC
  • 我完全理解你的解释的意思(事实上,这两个引用的寄存器是“相同的”,0x00000020U),但我不确定如何重新定义它:这是我之后的尝试查看引用手册(SYSCFG部分)和源代码(仍然不起作用):

    SYSCFG->EXTICR[3] = ((SYSCFG->EXTICR[3] & 0x0000) | SYSCFG_EXTICR4_EXTI13_PC);

  • 按照建议,我已将 USART2->ICR = USART_ICR_TCCF; 添加到 EXTIhandler,位于 DMA channel 之后。我将其保留在 USART 定义中。不过,该消息仍然只发送一次。

  • 最佳答案

    GPIOC 未启用

    这里,

    RCC->IOPENR  |= ( 1ul <<  0); //Enable GPIOA clock

    您也应该启用GPIOC

    EXTI13 映射到 PA13

    这里,

    SYSCFG->EXTICR[0] = ((SYSCFG->EXTICR[0] & 0x0000) | SYSCFG_EXTICR4_EXTI13_PC); //clear EXTICR and set to PC13(B1)

    您正在设置EXTI0-EXTI3的配置寄存器,实际上将EXTI1映射到PC1 EXTI13 仍然映射到 PA13,它实际上是 SWDIO,连接到板载调试器。我猜想 SWDIO 上的流量会触发 EXTI 中断,处理程序会检查 PC13(由于端口被禁用而始终读取 0),并启用 DMA。不过 DMA 传输只能工作一次,因为

    USART_ISR_TC在中断中没有被清除

    但仅在启动时一次。您应该移动此行

    USART2->ICR = USART_ICR_TCCF;

    到 EXTI 中断处理程序。

    我不确定为什么接收不起作用,也许 DMA 处理程序没有机会运行,因为 EXTI 不断被 SWD 流量重新触发。两个中断具有相同的优先级,中断号较小的中断优先,即 EXTI 处理程序。如果它总是在完成之前重新触发,那么它将被再次调用,而不是让其他处理程序运行。

    关于c - 让 DMA USART 在 STM32L053R8T6 上工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49602503/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com