如何启用 UART4 STM32F215?

How do I enable UART4 STM32F215?

我是 运行 标准 CMSIS,由 ST 发布,包含 libc 和所有 jazz。这是无效的代码。

void __attribute__ ((constructor)) uart4_init() {
  // Enable the clock for uart4
  RCC->APB1ENR |= 1 << 19;
  // Enable the clock for GPIO_C, which needs to be configured to pass-through UART4
  RCC->AHB1ENR |= 1 << 2;

  // Set up the GPIOC 11 and 10 pins for UART use
  // Set to alternate function mode
  GPIOC->MODER &= ~(0b1111 << 20);
  GPIOC->MODER |= 0b1010 << 20;
  // Finally set Alternate Function to UART4, to pass through the UART
  GPIOC->AFR[1] &= ~(0b11111111 << 8);
  GPIOC->AFR[1] |= 0b10001000 << 8;

  // Set up the UART port for reasonable sending settings
  // Here follows explanations on all bits set to 1:
    // Enable the serial port
    // Set to nine bits, so we have one to spare for parity
    // (Leave default wakeup method, since unused?)
    // Enable parity
    // Enable odd parity (better at detecting speed mismatch)
    // (Do not set parity error interrupt on)
    // (Do not set transfer buffer empty interrupt on)
    // (Do not set transmission complete, since that is DMA specific)
    // (Do not set recieve buffer not empty interrupt on)
    // (Do not set idle interrupt since we don't use it)
    // (Do not enable transmitter until setup is fully done)
    // (Do not enable reciever until setup is fully done)
    // (Do not enable mute-mode, we don't use it)
    // (Do not send a break character)
  UART4->CR1 = 0b11011000000000; // Set everything up
  // The confusing part, setting the baud rate, is in separate function
  uart4_set_baud(b9600);
  // Enable sending and receiving
  UART4->CR1 |= 0b1100;
}

我已经确认 RCC_APB1ENR 位 19 已设置,但 UART4 的控制寄存器似乎没有任何时钟,因此不进行分配。

(gdb) print/x *0x40023840
 = 0x80000

在阅读了工作代码(HAL 代码,实际上已经混淆)和文档后,我仍然无法弄清楚这一点。

编辑:按照 old_timers 建议清理了代码。现在应该是一个可用的例子。

Edit2:删除了中断以使更普遍地用作基本示例。特别是因为这些中断位还使您可以通过 NVIC 启用 UART 中断。

经过一些指导性的反汇编(感谢 old_timer!)我现在得出结论,我在调试时读取了错误的地址,所以我认为不起作用的东西一直在起作用。

当UART4在0x40004c00时我从0x40024c00读取的本质是...

检查更正后,我发现 CR1 确实采用了我用二进制写入的值 0x37a0(启用后变为 0x37ac)并且 BRR 采用预期值 1666(应该是 9600 波特,如果​​我正确理解文档...)。

之后我可以在向卡发送测试字节后检查状态寄存器并得出结论我已经收到数据并验证它以检查我的波特率是否足够接近,所以它现在可以工作(足以继续测试).

  1. 当您使用 CMSIS 时,也使用人类可读的定义。

    RCC->APB1ENR |= 1 << 19; 
    

数字很容易出错,很快您就会忘记这一行的作用。

 RCC->APB1ENR |= RCC_APB1ENR_UART4EN;

显示它的作用。

这里有更好的示例,例如:

 UART4->CR1 = 0b11011110100000;

 UART4->CR1 |= 0b1100;

我认为

 UART4 -> CR1 |= USART_CR1_RE | USART_CR1_TE; 

更容易阅读,也更不容易出错。

  1. 启用时钟后,您需要提供延迟或read-back。

我不使用 HAL - 但我真的很喜欢低级 HAL 宏

 __HAL_RCC_UART4_CLK_ENABLE(); 

哪个正确启用时钟(请记住,许多 STM32 在 RCC 域中存在错误,需要在勘误表页面中描述的特殊程序)

#define __HAL_RCC_UART4_CLK_ENABLE()  do { \
                                      __IO uint32_t tmpreg = 0x00U; \
                                      SET_BIT(RCC->APB1ENR, RCC_APB1ENR_UART4EN);\
                                      /* Delay after an RCC peripheral clock enabling */ \
                                      tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_UART4EN);\
                                      UNUSED(tmpreg); \
                                      } while(0U)

这个宏与简单的寄存器赋值 + 回读一样有效,但它的作用是正确的,它的名字描述了它的作用。