我正在尝试使用 usart2 直接配置相关寄存器来传输 char 数组:RCC、GPIO、USART2 并且在使用示波器测量时获得了不好的波特率(预期 9600 时约为 8k 波特。)
我正在使用 atollic True Studio 9.0.1 和一个“新嵌入式 C”项目对其进行编码,选择正确的 MCU,stm32F401RE,并将除调试探针之外的所有内容保留为默认值。
我只有一个包括:#include "stm32f4xx.h"
令我惊讶的是,当我使用 stm32CubeMX 创建项目并生成最小代码,然后用我的“裸机”项目代码替换 main.c 内容时,uart 的时基在示波器上看起来几乎完美(9571 波特)。
是不是很有趣?可能会发生什么?
这是我的代码:
包括和主循环:
#include "stm32f4xx.h"
void UART2_Init(void);
void UART2_Test_TX(void);
int main(void)
{
int i = 0;
UART2_Init();
UART2_Test_TX();
while (1)
{
i++;
}
}
一个一直发送“U”的简单测试函数:
void UART2_Test_TX(void)
{
USART_TypeDef * pUSART2;
pUSART2 = USART2;
char data[] = "U";
while(1)
{
while(!(pUSART2->SR && (1<<7)))// TXE transmit data register empty
{
}
pUSART2->DR = (uint16_t)data[0];
}
}
初始化函数:
void UART2_Init(void)
{
RCC_TypeDef * pRCC;
pRCC = RCC;
GPIO_TypeDef * pGPIOA;
pGPIOA = GPIOA;
USART_TypeDef * pUSART2;
pUSART2 = USART2;
//1. Enable the peripheral clock
/*
* The USART2 is connected to the APB1 bus so we have to check here
* the Reset and Clock Configuration Enable register for APB1APB1_ENR
*
* */
pRCC->APB1ENR |= (1 << 17); // Set the USART2EN bit to enable the clock (RCC_APB1ENR_USART2EN)
//2. Configure the GPIO PINS related to UART TX and RX
/*
*
* To do this we need to find the alternate function of the pins in a reference table. That is located in the Section4, table 8 of the Data sheet:
* USART2_RX *PA3, PD6
* USART2_TX *PA2, PD5
* Also in the user manual of the board (UM1724) the RX and TX pins accessible from the PC are located in port A. We have a winner.
*
* That's good but not enough. PINs MAY HAVE UP TO 16 DIFFERENT FUNCTIONALITIES so we need another table and register to select it (in datasheet table 9)
*
* 2.1 So, enable the RCC clock for GPIOA AHB1
* 2.2 Configure the PINs as alternate function
* 2.3 Configure or not Internal Pull-up resistor
* 2.4 select the alternate function Table 9 of datasheet + GPIOA_AFRL, the low pins registers, from 0 to 7
*
* */
pRCC->AHB1ENR |= 1<<0;//RCC_AHB1ENR_GPIOAEN; // 2.1 Enable the source clock for GPIOA
// configuring pin 2 TX
pGPIOA->MODER &= ~(0b11<<4); // 2.2 Clear previous configuration in PIN2
pGPIOA->MODER |= (0b10<<4); // 2.2 Configure PIN2 as alternate function GPIO_Mode_AF
pGPIOA->AFR[0] &= ~(0b1111<<8); // 2.4 clear the bits in the register ;
pGPIOA->AFR[0] |= (0b0111 <<8); // 2.4 AF7 for TX pin
// FOR SPI, I2C, UART the lines must be held high. So we need pull_up resistors
pGPIOA->PUPDR &= ~(0b11<<4);
pGPIOA->PUPDR |= (0b01 <<4);
// configuring pin 3 RX
pGPIOA->MODER &= ~(0b11<<6); // 2.2 Clear previous configuration in PIN3
pGPIOA->MODER |= (0b10<<6); // 2.2 Configure PIN3 as alternate function GPIO_Mode_AF
pGPIOA->AFR[0] &= ~(0b1111<<12); // 2.4 clear the bits in the register;
pGPIOA->AFR[0] |= (0b0111 <<12); // 2.4 AF7 for RX pin
// FOR SPI, I2C, UART the lines must be held high. So we need pull_up resistors
// pGPIOA->PUPDR &= ~(0b11<<6);
// pGPIOA->PUPDR |= (0b01 <<6);
// Note: I would be more efficient to configure all the pins at the same time but we did this way for clarity
//3. Configure the UART parameters: baudrate, data width, parity, number of stop bits etc
/*
* OVERSAMPLE 16
* Baudrate 115200
*
* OVER8 sampling divider
* 19.3.4 BaudRate = Fck/(16 * USARTDIV) .
* USARTDIV = DIV_Mantisa +(DIV_Fraction/ 8 x (2- OVER8))
* Fck = 16Mhz (default HSI)
*
* data width 8
* parity None
* stopbits 1
* */
// Configuring baudrate: 115200, real baudrate 115107.913669065. Error 0.08%
pUSART2->CR1 &= ~(1<<15); // O: Oversample 16 OK1
pUSART2->BRR &= ~(0xFFFF); // Clear the mantisa and fraction
pUSART2->BRR |= (104<<4); // Mantisa
pUSART2->BRR |= (3<<0); // Fraction
uint32_t cBRR = pUSART2->BRR;
//pUSART2->BRR |= (0x9B); // Mantisa and Fraction as Hex OK1
/*
pUSART2->CR1 &= ~(1<<12); // 8 bits OK1
pUSART2->CR1 &= ~(1<<10); // Parity control disable OK1
pUSART2->CR2 &= ~(0b11<<12); // 1 stop bits OK1
*/
//4. Enable the TX engine of UART2 (do we need RX or we can save power?)
/*
* UE bit USART enable
* TE bit Transmit enable
* TDR Register to output the data
* */
pUSART2->CR1 |= (1<<3); // O: Transmit enable
//5. ENABLE THE USART peripheral Always at the end
/*
* Section 19.3.2
* USART_CR1.UE enable the usart
* USART_CR1.M number of bits 8,9
* USART_CR2 number of stops
* DMA enable...
*
* */
pUSART2->CR1 |= (1<<13); // O: USART enable
// Here is ready
}