풀링 방식의 STM32 UART 플래그

Sep 28 2020

HAL API를 사용하여 Blue pill stm32f103으로 간단한 전송 속도 변경기를 구축하려고합니다.

내가 달성하고자하는 것 : 9600 보드로 잠긴 오래된 터미널 하나. 최대 300 보드의 오래된 열전 사 프린터.

이 프로젝트는 2 개의 "파란색 알약"으로 구성되며, 하나는 문자 스트림을 9600에 넣는 것뿐입니다. 다른 하나는 9600에서 스트림을 가져 와서 4 바이트마다 UART 3 용 레지스터에 덤프합니다. 하드웨어 흐름 제어를 사용하여 내용은 300 보드 인 UART2로 덤프됩니다.

연속 스트림만큼 잘 작동하지만 기본 송신기를 중지 할 때 전송을 중지하려면 다운 스트림 UART가 필요합니다. RXNE, TXE 및 TC 플래그를 사용해 보았지만 예상대로 작동하지 않습니다. 기본 스트림에서 전송을 중지하면 UART2 (300 baud)가 "TIME OUT"으로 들어가 버퍼에 남아있는 모든 것을 계속 인쇄합니다.

    while (1) {

    if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) == 0) {    // 0 = Empty
        HAL_GPIO_WritePin(BluePill_LED_GPIO_Port, BluePill_LED_Pin,GPIO_PIN_SET);
        HAL_Delay(100);
    }
    HAL_UART_Receive(&huart3, (uint8_t*) uart1_buf, uart_buf_len, 500);

    strcpy(uart2_buf, uart1_buf); // copy the contents of UART1 buffer to UART2 buffer
    if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE) == RESET) {
        HAL_GPIO_WritePin(BluePill_LED_GPIO_Port, BluePill_LED_Pin,GPIO_PIN_SET);
        HAL_Delay(200);
    }

    HAL_UART_Transmit(&huart2, (uint8_t*) uart2_buf, uart_buf_len, 1000);
    if (!(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TXE))) {
        HAL_GPIO_WritePin(BluePill_LED_GPIO_Port, BluePill_LED_Pin,GPIO_PIN_RESET);
        HAL_Delay(200);
    }
}

이 코드는 테스트 목적으로 수정되었습니다. 보시다시피 플래그 조건이 충족되었지만 LED가 켜지지 않을 때 LED가 켜지도록 할 수 있다고 생각했습니다. 또 다른 이상한 점은 LED가 켜지지 않지만 HAL_Delay가 확실히 실행되고 있다는 것입니다.

누군가 내가 뭘 잘못하고 있는지 알려줄 수 있을지도 몰라. 감사

답변

1 Codo Sep 29 2020 at 08:14

속도의 차이로 인해 (주석에서 언급했듯이) 버퍼를 사용해야합니다. 따라서 아래 코드는 이러한 버퍼 (아마도 링 버퍼)에 대한 코드가이 API에 존재한다고 가정합니다.

bool buffer_is_empty();           // returns true if buffer is empty
bool buffer_is_full();            // returns true if buffer is full
uint8_t buffer_remove_byte();     // removes and returns the oldest byte added to the buffer
void buffer_add_byte(uint8_t b);  // adds a byte to the buffer

메인 루프는 바이트 단위로 작동합니다.

  • UART3에서 바이트를 사용할 수있는 경우 수신하여 버퍼에 추가합니다.
  • UART2가 준비되고 버퍼가 비어 있지 않으면 바이트를 제거하고 전송합니다.

다음과 같이 보일 수 있습니다.

uint8_t ch;

while (1) {

    if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) != 0) {  // not empty
        HAL_UART_Receive(&huart3, &ch, 1, 1);
        if (!buffer_is_full()) {
            buffer_add_byte(ch);
        } else {
            // buffer overflow - discard byte
        }
    }

    if (!buffer_is_empty() && __HAL_UART_GET_FLAG(&huart2, UART_FLAG_TXE) != 0) {
        ch = buffer_remove_byte();
        HAL_UART_Transmit(&huart2, &ch, 1, 1);            
    }
}