STM32L431 寄存器配置 USART+DMA发送+中断接收

用的外设是PA9 PA10

DMA选择的是DMA2_Channel6

代码中还用了DMA传输完成中断,用来配置ADM2483的管脚。

直接上代码了:

void UART_Init(u32 pclk2, u32 bound, u8 checkMode)
{
    __GPIOA_CLK_ENABLE();
    __GPIOB_CLK_ENABLE();
    __GPIOC_CLK_ENABLE();
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_DMA2_CLK_ENABLE();
    
    MODIFY_REG(USART1->CR1, USART_CR1_UE_Msk, 0);    // 失能串口
    while (READ_BIT(USART1->CR1, USART_CR1_UE_Msk) != 0);
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_EN_Msk, 0);  //dis: Channel disable
    while(DMA2_Channel6->CCR & DMA_CCR_EN_Msk); //确保 DMA 可以被设置
    
    GPIO_Set(GPIOA, GPIO_PIN_9 | GPIO_PIN_10, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_FREQ_LOW, GPIO_NOPULL);    // PB14设置
    GPIO_AF_Set(GPIOA, 9, GPIO_AF7_USART1); // PA9, AF7
    GPIO_AF_Set(GPIOA, 10, GPIO_AF7_USART1); // PA10, AF7

    u32 USARTDiv = 2 * pclk2 * 1000000 / bound;
    USART1->BRR = (USARTDiv & 0xFFFFFFF0) | ((USARTDiv & 0x0F) >> 1);
    // MeterConfig.s.rsCheckMode
    if (checkMode == checkMode_NONE) {
        MODIFY_REG(USART1->CR1, USART_CR1_PCE_Msk, 0);              //  0: Parity control disabled
        MODIFY_REG(USART1->CR1, USART_CR1_M_Msk, 0);  //  M[1:0] = 00: 1 Start bit, 8 data bits, n stop bits
    } else if (checkMode == checkMode_ODD) {
        MODIFY_REG(USART1->CR1, USART_CR1_PCE_Msk, USART_CR1_PCE);  //  1: Parity control enabled
        MODIFY_REG(USART1->CR1, USART_CR1_PS_Msk, USART_CR1_PS);    //  1: Odd parity
        MODIFY_REG(USART1->CR1, USART_CR1_M_Msk, USART_CR1_M0);  //  M[1:0] = 01: 1 Start bit, 8 data bits, n stop bits
    } else if (checkMode == checkMode_EVEN) {
        MODIFY_REG(USART1->CR1, USART_CR1_PCE_Msk, USART_CR1_PCE);  //  1: Parity control enabled
        MODIFY_REG(USART1->CR1, USART_CR1_PS_Msk, 0);               //  0: Even parity
        MODIFY_REG(USART1->CR1, USART_CR1_M_Msk, USART_CR1_M0);  //  M[1:0] = 01: | SB | 8-bit data | PB | STB |
    }
    MODIFY_REG(USART1->CR1, USART_CR1_OVER8_Msk, USART_CR1_OVER8);  //  0: Oversampling by 16
    MODIFY_REG(USART1->CR1, USART_CR1_TE_Msk, USART_CR1_TE);  //  1: Transmitter is enabled
    MODIFY_REG(USART1->CR1, USART_CR1_RE_Msk, USART_CR1_RE);  //  1: Receiver is enabled and begins searching for a start bit

    MODIFY_REG(USART1->CR3, USART_CR3_DMAT_Msk, USART_CR3_DMAT);  //  1: DMA mode is enabled for transmission
    
//  1: A USART interrupt is generated whenever ORE=1 or RXNE=1 in the USART_ISR register    
    MODIFY_REG(USART1->CR1, USART_CR1_RXNEIE_Msk, USART_CR1_RXNEIE);  

    NVIC_Init(USART1_IRQn, 3, 0);  // 抢占 3,子优先级 1

    // 发送DMA配置
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_MEM2MEM_Msk, (0x0UL << DMA_CCR_MEM2MEM_Pos));  // 00: Low
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_PL_Msk, (0x0UL << DMA_CCR_PL_Pos));  // 00: Low
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_MSIZE_Msk, (0x0UL << DMA_CCR_MSIZE_Pos));  // 00: 8-bits 01: 16-bits 10: 32-bits 11: Reserved
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_PSIZE_Msk, (0x0UL << DMA_CCR_PSIZE_Pos));  // 00: 8-bits 01: 16-bits 10: 32-bits 11: Reserved
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_MINC_Msk, (0x1UL << DMA_CCR_MINC_Pos));  // Memory increment mode
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_PINC_Msk, (0x0UL << DMA_CCR_PINC_Pos));  // Peripheral increment mode
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_CIRC_Msk, (0x0UL << DMA_CCR_CIRC_Pos));  // Circular mode
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_DIR_Msk, (0x1UL << DMA_CCR_DIR_Pos));  // DIR: Data transfer direction 1: Read from memory
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_TCIE_Msk, DMA_CCR_TCIE);  //Transfer complete interrupt enable

    NVIC_Init(DMA2_Channel6_IRQn, 3, 1);  // 抢占 3,子优先级 1
    
    MODIFY_REG(DMA2_CSELR->CSELR, DMA_CSELR_C6S_Msk, ((0x2UL) << DMA_CSELR_C6S_Pos));  // the remaining bytes to be transmitted

    DMA2_Channel6->CPAR = (uint32_t)&(USART1->TDR);      // 外设地址
    DMA2_Channel6->CMAR = (uint32_t)(rsData.sendData);      // 内存地址


    MODIFY_REG(USART1->CR1, USART_CR1_UE_Msk, USART_CR1_UE);    // 使能串口
//    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_EN_Msk, (0x1UL << DMA_CCR_EN_Pos));  //EN: Channel enable
    
}

void UART_DeInit(void)
{
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_EN_Msk, 0);  //dis: Channel enable
    MODIFY_REG(USART1->CR1, USART_CR1_UE_Msk, 0);    // 失能串口
    
    GPIO_Set(GPIOA, GPIO_PIN_9 | GPIO_PIN_10, GPIO_MODE_AIN, GPIO_OTYPE_PP, GPIO_SPEED_FREQ_LOW, GPIO_NOPULL);    // PB14设置
    GPIO_Set(GPIOC, GPIO_PIN_6, GPIO_MODE_AIN, GPIO_OTYPE_PP, GPIO_SPEED_FREQ_LOW, GPIO_NOPULL);    // PC6 -- RE 设置
    __HAL_RCC_DMA2_CLK_DISABLE();
    __HAL_RCC_USART1_CLK_DISABLE();
}

//开启一次 DMA 传输
//DMA_Streamx:DMA 数据流,DMA1_Stream0~7/DMA2_Stream0~7
//ndtr:数据传输量
void UART_DMA_Enable(u16 ndtr)
{
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_EN_Msk, 0);  //dis: Channel disable
    while(DMA2_Channel6->CCR & DMA_CCR_EN_Msk); //确保 DMA 可以被设置
//    memset(rsData.sendData, 0x37, ndtr);
    DMA2_Channel6->CNDTR = ndtr; //DMA 存储器 0 地址
    MODIFY_REG(DMA2_Channel6->CCR, DMA_CCR_EN_Msk, DMA_CCR_EN);  //EN: Channel enable
}

发送任务:

void uartTask(void)
{
    if (rsData.enableFlag == 0 && lcdCtrl.settingFlag != IS_SETTING) {
        UART_Init(4, atoi(RS_BaudRate[MeterConfig.s.rsBaudRate].str), MeterConfig.s.rsCheckMode);
        rsData.enableFlag = 1;
    }

    if (rsData.rcvCompleteFlag == METER_TRUE) {

        memcpy(rsData.sendData, rsData.rcvData, rsData.rcvDataLen);
        UART_DMA_Enable(rsData.rcvDataLen);
        rsData.rcvCompleteFlag = 0;
        rsData.rcvDataLen = 0;
    }
}

接收中断:

void USART1_IRQHandler(void)
{
    //1: A USART interrupt is generated whenever ORE=1 or RXNE=1 in the USART_ISR register
    if ((USART1->ISR & (USART_ISR_ORE_Msk | USART_ISR_RXNE_Msk)) != 0) {
        u8 rcvData = USART1->RDR;
        if (MeterConfig.s.rsMode == RTU_MODE) {
            rtuRcvByte(&rsData, rcvData);

        } else if (MeterConfig.s.rsMode == ASCII_FST) {
            asciiRcvByte(&rsData, rcvData);
        }
        // 清中断
        USART1->ICR = USART_ICR_ORECF;

    }
}

测试OK:

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页