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
相关产品推荐
相关产品推荐

