我的问题是让我的计算机(确切地说是虚拟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,USART / Communcation Using DMA中的示例。 USART 1被简单地重新定义为USART 2(因为它是虚拟COM端口使用的那个),并且DMA通道也根据它重新定义。但是,这里的问题非常简单:它只会打印一次stringtosend(每次按下按钮B1都会这样做),也不会通过RX接收数据 - 好像它完全忽略了DMA中断处理程序 - 我我不确定如何测试(此板上没有可用的跟踪功能)。我所拥有的似乎足够好地反映了参考手册,所有主要内容都是:
int main(){
SystemCoreClockInit();
CONFIGURE_UART_PARAM();
ENABLE_UART_DMA();
pushbutton_def();
CONFIGURE_EXTI();
while(1){
}
......应该只对已定义的中断作出反应,但事实并非如此,对于我的生活,我看不出原因。我很乐意,如果你可以帮助我 - 我也想避免使用HAL或LL API - 这不是一个足够复杂的项目来保证它们的使用(USART / DMA两个板之间有几个输入,输出,通信),而且我会我更愿意学习更接近注册级别的工作。
谢谢!
编辑(响应Berendi的建议): 1. GPIOC在另一个文件中定义,使用pushbutton_def()调用:
RCC->IOPENR |= (1UL << 2); //enable GPIOC
我完全理解你的解释是什么意思(事实上,这两个寄存器的寄存器是“相同的”,0x00000020U),但我不确定如何重新定义它:这是我的尝试之后查看参考手册(SYSCFG部分)和来源(仍然,它不起作用):
SYSCFG-&gt; EXTICR [3] =((SYSCFG-&gt; EXTICR [3]&amp; 0x0000)| SYSCFG_EXTICR4_EXTI13_PC);
正如所建议的那样,我在DMA通道之后立即向EXTIhandler添加了USART2->ICR = USART_ICR_TCCF;
。我把它保存在USART定义中。但是,该消息仍然只被发送一次。
答案 0 :(得分:1)
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处理程序。如果它在完成之前总是被重新触发,那么它将再次被调用,而不是让其他处理程序运行。