简体   繁体   English

STM32F407 USART1:清除USART_FLAG_TC要求在实际清除该位之前暂停pgm

[英]STM32F407 USART1 : Clearing USART_FLAG_TC requires pgm to be halted before actually clearing the bit

When initializing USART1 on STM32F407 I have run into a problem when enabling TC interrupt. 在STM32F407上初始化USART1时,启用TC中断时遇到问题。 The TC flag in SR is set ('1') as soon as the USART RCC is enabled and clearing the flag before enabling TC interrupt has become a headache for me because it throws a TC interrupt as soon as UART_IT_TC is enabld. 一旦启用USART RCC,就将SR中的TC标志设置为“ 1”,在启用TC中断之前清除该标志令我感到头疼,因为一旦启用UART_IT_TC,它就会抛出TC中断。 ie this is a startup problem. 即这是一个启动问题。

By writing 0 to the flag in status register (SR) when initializing the USART and before enabling interrupts should clear the flags. 在初始化USART时以及在允许中断之前,通过将0写入状态寄存器(SR)中的标志,应清除标志。 But it does not when I run the program straight trough, but (!!!) if having a breakpoint and stepping trough the code where SR is cleared works fine, TC flag is set to 0. 但是,当我直接运行程序时,不是这样,而是(!!!)如果有断点并步进运行,清除SR的代码可以正常工作,TC标志设置为0。

Therefor i always get a TC interrupt even before transmitting anything if I run the code without a breakpoint. 因此,即使我在没有断点的情况下运行代码,在发送任何内容之前,我总是会收到TC中断。 And then another one after transmitting a character, naturally. 自然而然地,在传输完一个字符后再出现另一个。 But when I was using a breakpoint where TC flag is cleared gives only one TC IRQ and thats when actually transmitting something. 但是,当我使用清除TC标志的断点时,仅给出一个TC IRQ,而实际上是在传输某些内容时。

Inside the IRQ handler I also clear the flags by writing 0 to SR register and this works without any breakpoint. 在IRQ处理程序中,我还通过向SR寄存器写入0来清除标志,并且该方法没有任何断点。 Both transmitting and receiving data works well after this. 此后,发送和接收数据都工作良好。

So, timing issue was in my mind, but adding even an second delay did not change behavior and then it should not work clearing the SR register later either. 因此,计时问题在我心中,但是即使再加上第二个延迟也不会改变行为,因此以后也不应该清除SR寄存器。 Or? 要么? Does USARTs require settling time for RCC before initializing the USART? USART在初始化USART之前是否需要RCC的建立时间?

void Console_init(long baud)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  USART_InitTypeDef USART_InitStruct;
  NVIC_InitTypeDef NVIC_InitStruct;

  /* Init clock domains */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

  /* Set alternate functions */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

  /* Init GPIO pins */
  GPIO_StructInit(&GPIO_InitStruct);
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;
  GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* Configure UART setup */
  USART_StructInit(&USART_InitStruct);
  USART_InitStruct.USART_BaudRate = baud;
  USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
  USART_InitStruct.USART_Parity = USART_Parity_No;
  USART_InitStruct.USART_StopBits = USART_StopBits_1;
  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
  USART_Init(USART1, &USART_InitStruct);

  /* Enable global interrupts for USART */
  NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
  NVIC_Init(&NVIC_InitStruct);

  /* Clear old interrupt flags and enable required IRQs*/
  USART1->SR = 0;

  /* Enable USART */
  USART_Cmd(USART1, ENABLE);    
}


void console_transmit(void)
{  
  USART_ITConfig(USART1, USART_IT_TC, ENABLE);
  USART1->DR = 0x55;
}

void USART1_IRQHandler(void)
{
  if (USART1->SR & USART_FLAG_TC)
  {
    USART_ITConfig(USART1, USART_IT_TC, DISABLE);
  }

  USART1->SR = 0;
}

In this code I will get two interrupts on TC, one as soon I enables TC and one after character is transmitted. 在这段代码中,我将在TC上收到两个中断,一个我启用TC后立即中断,一个在字符传输后。 This code is what I am using now while trying to understand the issue. 这段代码是我现在在尝试理解该问题时所使用的代码。

Note: I have also tried to clear the SR inside console_transmit before enabling TC but to no help. 注意:我也曾尝试在启用TC之前清除console_transmit内部的SR,但没有帮助。 It almost like it requires to be cleared inside the interrupt handler. 几乎就像需要在中断处理程序中清除它一样。

I think this is a conceptual misunderstanding. 我认为这是一个概念上的误解。

A transmit interrupt does not tell you that something has been transmitted. 发送中断不会告诉你的东西已经被发送。 It tells you that there is space in the buffer, and it is OK to push data to the UART. 它告诉您缓冲区中有空间,可以将数据推送到UART。 Of course at the startup the UART buffer is empty, and you are getting an interrupt as soon as you enable it. 当然,在启动时,UART缓冲区为空,启用后您将立即获得中断。 It is not a matter of timing. 这不是时间问题。 It is an expected behavior. 这是预期的行为。

Such design makes the transmit flow very straightforward: 这种设计使传输流程非常简单:

  • the mainline code prepares the buffer, and enables the interrupt 主线代码准备缓冲区,并启用中断
  • the ISR moves data to UART until either UART is full or there is no more data to send, and ISR将数据移至UART,直到UART已满或没有更多数据要发送为止,并且
  • once there is no more data to send, the ISR disables the interrupt 一旦没有更多数据要发送,ISR将禁用中断

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM