You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32G030K8裸机UART收发无响应问题求助

STM32G030K8 UART无回复问题求助
  • 首次尝试实现STM32G030K8的基础UART功能:PC发送一个字符,MCU返回硬编码字符(ASCII 85,即'U'),但发送字符后无任何回复
  • 使用Hercules终端和串口适配器测试,硬件(接线、MCU发送功能)已通过Cube IDE编写的HAL程序验证正常,因此怀疑代码存在问题
  • 无调试经验,暂时无法进行调试
  • 使用环境:Keil IDE、ST-LINK v2编程器、C99标准

附相关代码:

#include "stm32g0xx.h"


void initClocks(void){
    //RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;        // ENABLE GPIO PORT A CLOCK (BIT 0)       ???     (I believe the next line replaces this one)
        RCC->IOPENR |= (1<<0);                                          // Enable GPIOA Clock                                   MCO
    RCC->APBENR2 |= RCC_APBENR2_USART1EN;       // ENABLE UART1 CLOCK (BIT 14)              ok
}


void configPinMode(void){
    // RESET PIN MODES
    GPIOA->MODER &= ~((3u << 18)    // CLEAR PA9                ok
                     |(3u << 20));  // CLEAR PA10               ok

    // SET PIN MODES
    GPIOA->MODER |= ((2u << 18)     // SET PA9 TO AF        ok
                    |(2u << 20));   // SET PA10 TO AF       ok
}


void setAF(void){
    // RESET ALTERNATE FUNCTION. AFR[1] IS THE
    // ALTERNATE FUNCTION HIGH REGISTER
    GPIOA->AFR[1] &= ~((15u << 4)       // CLEAR PA9 AF         ok
                      |(15u << 8));     // CLEAR PA10 AF        ok

    // SET ALTERNATE FUNCTION
    GPIOA->AFR[1] |= ((1u << 4)         // SET PA9 AF               not sure if position (high/low) register is ok (maybe AFR[1] is high and AFR[0] is low)
                     |(1u << 8));       // SET PA10 AF          not sure if position (high/low) register is ok (maybe AFR[1] is high and AFR[0] is low)
}


void configUart1Pins(void){
    // SET PIN MODE TO ALTERNATE FUNCTION
    configPinMode();

    // SET ALTERNATE FUNCTION TO BE UART1
    setAF();
}


void configUart1(void){
    // CONFIGURE USART1 CR1 REGISTER
    // CLEAR BITS
    USART1->CR1 &= ~(USART_CR1_M1       // CLEAR M1 FOR 1 START BIT AND 8 DATA BITS (28)                ok
                    |(0x03 << 26)       // INHIBIT INTERRUPTS AT BITS 26 AND 27     (27/26)         ok
                    |USART_CR1_OVER8    // OVERSAMPLING BY 16                       (15)                ok
                    |USART_CR1_CMIE     // INHIBIT CHARACTER MATCH INTERRUPT        (14)                ok
                    |USART_CR1_MME      // DON'T ENABLE MUTE MODE                   (13)                ok
                    |USART_CR1_M0       // CLEAR M0 FOR 1 START BIT AND 8 DATA BITS (12)                ok
                    |USART_CR1_PCE      // NOT IMPLEMENTING PARITY CONTROL          (10)                ok
                    |(0x1F << 3)        // INHIBIT INTERRUPTS AT BITS 4 TO 8        (4-8)               ok
                    |USART_CR1_TE       // DON'T ENABLE TRANSMITTER JUST YET        (3)                 ok
                    |USART_CR1_RE       // DON'T ENABLE RECEIVER JUST YET           (2)                 ok
                    |USART_CR1_UE);     // DON'T ENABLE UART1 JUST YET              (0)                 ok

    // CONFIGURE USART CR2 REGISTER
    // CLEAR BITS
    USART1->CR2 &= ~(USART_CR2_RTOEN    // DISABLE RECEIVER TIMEOUT             (23)                        ok
                    |USART_CR2_ABREN    // NO AUTOMATIC BAUD RATE DETECTION     (20)                        ok
                    |USART_CR2_MSBFIRST // TRANSMIT/RECEIVE LSB FIRST           (19)                        ok
                    |(0x03 << 16)       // IDLE STATE HIGH FOR RX/TX PINS       (17/16)                 ok
                    |USART_CR2_SWAP     // DON'T SWAP FUNCTION OF RX/TX PINS    (15)                        ok
                    |USART_CR2_LINEN    // NO LIN MODE                          (14)                        ok
                    |(0x03 << 12)       // 1 STOP BIT                           (13/12)                 ok
                    |USART_CR2_CLKEN    // DON'T USE CLOCK WITH UART            (11)                        ok
                    |USART_CR2_LBDIE);  // NO LIN BREAK DETECTION INTERRUPT     (6)                         ok

    // CONFIGURE USART CR3 REGISTER
    // CLEAR BITS
    USART1->CR3 &= ~(USART_CR3_TCBGTIE  // NO TRANSMISSION COMPLETE BEFORE GUARD TIME INTERRUPT (24)                ok
                    |USART_CR3_DEM      // NO DRIVER ENABLE MODE                                (14)                ok
                    |(0x7F << 3)        // DISABLE VARIOUS IRRELEVANT MODES                     (9-3)               ok
                    |USART_CR3_IREN     // NO IrDA MODE                                         (1)                 ok
                    |USART_CR3_EIE);    // INHIBIT ERROR INTERRUPT                              (0)                 ok

    // SET BITS
    USART1->CR3 |= (USART_CR3_OVRDIS    // DISABLE OVERRUN FUNCTIONALITY (12)               ok
                   |USART_CR3_ONEBIT);  // USE ONE SAMPLE BIT METHOD     (11)               ok

    // SET BAUD RATE IN BRR REGISTER
    USART1->BRR |= (138<<4);            // Baudrate: Whole Number Part      16MHz/115200=138.8889       (Baudrate 115200)           MCO
        USART1->BRR |= (14<<0);                         // Baudrate: Fractional Part            0.8889*16=14.2224=14        (Oversampling 16)           MCO

    // ENABLE UART
    USART1->CR1 |= (USART_CR1_TE        // ENABLE TRANSMITTER (3)           ok
                   |USART_CR1_RE        // ENABLE RECEIVER    (2)           ok
                   |USART_CR1_UE);      // ENABLE UART1       (0)           ok

}


void initUART(void){
    // INITIALISE REQUIRED CLOCKS. MUST ALWAYS BE DONE FIRST
    // AS WITHOUT ENABLING THE CLOCKS THE PERIPHERALS CANNOT
    // BE CONFIGURED OR USED.
    initClocks();

    // CONFIGURE PINS FOR UART1
    configUart1Pins();

    // CONFIGURE UART1
    configUart1();
}


void transmitUart(uint8_t data){     // BYTE OF DATA TO BE TRANSMITTED
    // WAIT UNTIL TRANSMIT DATA REGISTER IS READY TO TAKE DATA
    // USART_ISR_TXE EXPANDS TO (1 << 7);
    while(!(USART1->ISR & (1<<7)));     // USART_ISR_TXE is not known, therefore bitmask is used instead

    // LOAD DATA TO TRANSMIT REGISTER
    USART1->TDR = data;
}


void transmitStrUart(char* str) // POINTER TO A STRING TO BE TRANSMITTED
{
    // WHILE NOT END OF STRING
    while(*str){
        // TRANSMIT CHARACTER THEN INCREMENT POINTER TO NEXT CHARACTER
        transmitUart(*str++);
    }
}


uint8_t receiveUart(void){
    uint8_t rxData = 0;

    // IF THERE IS DATA IN THE RECEIVE DATA REGISTER
    // USART_ISR_RXNE EXPANDS TO (1 << 5)
    if(USART1->ISR & (1<<5)){                               // USART_ISR_RXNE is not known, therefore bitmask is used instead
        // READ DATA FROM THE REGISTER
        rxData = USART1->RDR;
    }

    return rxData;
}

int main(void){
    
    //SET UP UART
    initUART();

    while(1){
        // IF DATA WAS RECEIVED
        if(receiveUart() > 0){
            //transmitStrUart("Character Received\n\r");

            // TRANSMIT AN ARBITRARY 'U' (ASCII 85) OVER UART
            transmitUart(85);
        }
    }
}

排查建议

  • 波特率寄存器赋值问题:当前代码用USART1->BRR |= ...赋值,若BRR寄存器初始值不为0,会残留无效位导致波特率错误。应改为直接赋值:USART1->BRR = (138 << 4) | 14;。
  • 接收逻辑缺陷:receiveUart()仅单次检查RXNE位,若主循环执行快,可能错过接收事件;同时若收到ASCII 0字符,返回值为0会导致主循环判断>0不成立。建议修改接收函数为轮询等待:
    uint8_t receiveUart(void){
        // 等待接收数据寄存器非空
        while(!(USART1->ISR & (1 << 5)));
        return USART1->RDR;
    }
    
    主循环简化为:
    while(1){
        uint8_t rx = receiveUart();
        transmitUart(85);
    }
    
  • 复用功能寄存器确认:STM32G0中PA9、PA10对应USART1的AF1,你当前的AFR配置是正确的,但建议直接使用库宏GPIO_AF1_USART1避免位计算错误,比如GPIOA->AFR[1] |= (GPIO_AF1_USART1 << ((9-8)*4)) | (GPIO_AF1_USART1 << ((10-8)*4));。
  • 时钟频率验证:确认系统时钟确实为16MHz,若使用内部HSI,默认是16MHz;若时钟配置被修改,波特率计算会失效。

内容的提问来源于stack exchange,提问作者Magnus Olsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:22:09