STM32F103C6裸机UART代码Proteus仿真失效,求错误排查
STM32F103C6裸机UART仿真故障排查
针对你提供的裸机代码,以下是几个关键错误点及修正方案:
1. 系统时钟配置的PLL就绪等待逻辑错误
在SysClockConfig函数中,等待PLL就绪的判断条件写反了:
// 错误代码: while (RCC->CR & (1U<<25)){} // 等待PLL就绪
PLL就绪位PLLRDY(位25)为1时表示PLL已稳定,上述代码会在PLL未就绪时退出循环,逻辑完全相反。正确写法应为:
// 修正后: while (!(RCC->CR & (1U<<25))){} // 等待PLL就绪
2. GPIO复用功能配置错误
UART2的PA2(TX)和PA3(RX)需要配置为复用推挽输出和浮空输入,但你的代码中对CRL寄存器的配置逻辑混乱,直接操作单个位导致配置错误:
- PA2(TX)应配置为复用推挽输出:
CNF2[1:0] = 10,MODE2[1:0] = 11(50MHz速率) - PA3(RX)应配置为浮空输入:
CNF3[1:0] = 01,MODE3[1:0] = 00(输入模式)
修正后的GPIO配置代码:
void uart2_tx_init(void) { /*** 配置UART2 TX所在的GPIOA ***/ /* 1- 使能GPIOA时钟*/ RCC->APB2ENR |= GPIOAEN; /*配置PA2(TX)和PA3(RX)*/ // 先清零PA2和PA3对应的CRL位 GPIOA->CRL &= ~(GPIO_CRL_CNF2 | GPIO_CRL_MODE2 | GPIO_CRL_CNF3 | GPIO_CRL_MODE3); // PA2: 复用推挽输出,50MHz GPIOA->CRL |= (GPIO_CRL_CNF2_1 | GPIO_CRL_MODE2_0 | GPIO_CRL_MODE2_1); // PA3: 浮空输入 GPIOA->CRL |= GPIO_CRL_CNF3_0; // ... 后续UART配置代码 }
3. UART波特率计算错误
你的代码中直接写死了BRR寄存器的值(5U<<0) | (4U<<4),这与8MHz APB1时钟下115200波特率的正确值不符。正确的BRR计算应基于公式:USARTDIV = APB1_FREQ / BAUDRATE,分整数和小数部分:
- 8MHz / 115200 ≈ 69.444,整数部分69(0x45),小数部分0.444*16≈7(0x7)
因此BRR寄存器应设置为0x457。
修正后的波特率配置代码:
/*配置波特率,时钟8MHz,波特率115200*/ USART2->BRR = 0x457;
4. UART初始化顺序错误
UART的正确初始化顺序应为:先配置波特率、数据位、停止位等参数,最后再使能USART控制器(UE位)。你的代码中先使能了UE,再配置其他参数,可能导致配置不生效。
修正后的UART初始化顺序:
/*** 配置UART外设 ***/ /* 1- 使能UART2外设时钟*/ RCC->APB1ENR |= USART2EN; /*先关闭USART控制器,确保配置生效*/ USART2->CR1 &= ~CR1_UE; /*选择1个起始位,8个数据位,无校验位 */ USART2->CR1 &=~ CR1_M; /*停止位设置为1位*/ USART2->CR2 &=~ (1U<<12); USART2->CR2 &=~ (1U<<13); /*配置波特率,时钟8MHz,波特率115200*/ USART2->BRR = 0x457; /*使能发送(Tx)和接收(Rx)*/ USART2->CR1 |= CR1_TE | CR1_RE; /*最后使能USART控制器*/ USART2->CR1 |= CR1_UE;
额外优化:发送函数等待传输完成
当前发送函数只等待TXE位(数据寄存器空),但此时数据可能还在移位寄存器中未发送完成。如果需要确保数据完全发送后再进行下一次发送,可以等待TC位(传输完成):
void UART2_SendChar(int ch) { while (!(USART2->SR & SR_TXE)){} USART2->DR = (ch & 0xFF); while (!(USART2->SR & SR_TC)){} // 等待传输完成 USART2->SR &= ~SR_TC; // 清除TC标志 }
内容的提问来源于stack exchange,提问作者MICHELE OLIVEIRA DE CAMPOS
相关产品推荐
相关产品推荐

