2017-12-15 44 views
0

STM32F407에서 USART1을 초기화 할 때 TC 인터럽트를 활성화 할 때 문제가 발생했습니다. SR의 TC 플래그는 USART RCC가 활성화 되 자마자 '1'로 설정되고 TC 인터럽트를 활성화하기 전에 플래그를 지우는 것은 UART_IT_TC가 enabld되는 즉시 TC 인터럽트를 발생시키기 때문에 나에게 두통이되었습니다. 이것은 시작 문제입니다.STM32F407 USART1 : 지우기 USART_FLAG_TC 비트를 실제로 지우기 전에 pgm을 중지해야합니다.

USART를 초기화 할 때 상태 레지스터 (SR)의 플래그에 0을 쓰고 인터럽트를 활성화하기 전에 플래그를 지워야합니다. 하지만 프로그램 똑 바름을 실행할 때 (!!!) 중단 점이 있고 SR이 지워진 코드가 잘 작동하면 TC 플래그는 0으로 설정됩니다.

그 때문에 나는 항상 중단 점없이 코드를 실행하면 아무 것도 전송하기 전에 TC가 중단됩니다. 그리고 다른 하나는 캐릭터를 전송 한 후, 자연스럽게. 그러나 TC 플래그가 지워진 중단 점을 사용할 때 TC IRQ가 하나만 나오고 실제로 뭔가를 전송할 때 중단 점이 생깁니다.

IRQ 처리기 내부에서 SR 레지스터에 0을 쓰는 방법으로 플래그를 지우고 중단 점 없이도 작동합니다. 데이터 전송 및 수신 모두이 후에 잘 작동합니다.

타이밍 문제가 내 마음에 들었지만 두 번째 지연을 추가해도 동작이 변경되지 않았고 나중에 SR 레지스터를 지우지 않아야합니다. 또는? 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; 
} 

이 코드에서는 TC에서 두 개의 인터럽트를 얻습니다. 곧 TC를 활성화하고 문자를 전송 한 후 하나를 인터럽트합니다. 이 코드는 문제를 이해하는 동안 지금 사용하고 있습니다.

참고 : TC를 활성화하기 전에 console_transmit 내부의 SR을 지우려고했으나 도움이되지 않았습니다. 거의 인터럽트 핸들러 내부에서 지워야 할 것처럼 보입니다.

답변

1

나는 이것이 개념상의 오해라고 생각합니다.

송신 인터럽트가 이 아니고이 전송되었다고 알려줍니다. 그것은 버퍼에 공간이 있다는 것을 알려주며 UART로 데이터를 푸시해도 좋습니다. 물론 시동시 UART 버퍼는 비어 있으며 활성화하면 즉시 인터럽트가 발생합니다. 타이밍의 문제가 아닙니다. 이는 예상되는 동작입니다.

이러한 디자인은 전송이 매우 간단 흐름합니다 :

  • 메인 라인의 코드가 버퍼를 준비하고, 중 UART가 꽉 찼거나 데이터가 더 이상 없을 때까지 UART하는 인터럽트
  • ISR이 데이터를 이동 할 수 있습니다 보내
  • 한 번 더 이상 보낼 데이터가하려면 ISR은 인터럽트
+0

나는 그것이 나에게 말한다 무엇인지를 비활성화합니다. 전송 완료 인터럽트는 전송이 완료되었음을 알립니다. 즉, tx 버퍼에 더 이상 바이트가 없습니다. 전송이 없으면 아무 것도 말해주지 않아야합니다. 데이터 시트에 따르면 플래그 레지스터의 값은 0이므로 usart가 활성화되고 아무 것도 전송되지 않을 때이 플래그가 설정된다는 것은 의미가 없습니다. cpu가 중단 될 때 플래그 지우기가 완료되어야한다는 것은 훨씬 덜 합당합니다. 코드가 끝나면 아이디어는 마지막 바이트가 데이터 레지스터로 보내 졌을 때 TC를 사용하도록 설정하는 것이지만 그 다음에 플래그가 먼저 지워 져야합니다. – zainka

+0

이것은 오해입니다.실제로 거래가 전혀 없을 수도 있지만 단순히 더 많은 데이터를 푸시하는 것이 안전하다는 의미입니다. – user58697

+0

Datasheet tells :이 비트는 데이터를 포함하는 프레임의 전송이 완료되고 TXE가 설정되면 하드웨어에 의해 설정됩니다. TXE가 실제로 설정되었지만 질문하지 않지만 프레임 전송이 없습니다 아직 데이터를 포함하고 있지 않으므로 TC를 설정하기위한 조건이 충족되지 않습니다. 따라서 데이터 시트는 전체 진실을 말하지 않거나 다른 것이 잘못되었습니다. 둘째, 플래그를 지우는 두 가지 방법, SR에 쓰는 방법, SR에서 읽은 다음 DR에 쓰는 방법이 있습니다. DR에 기록 된 데이터가 전송되면 마지막으로 플래그가 다시 설정됩니다. 기껏해야 이름 전송이 잘못되었습니다. – zainka