GPRS 디버깅에서 큰 발견-STM32에서 보낸 문자열의 첫 번째 문자가 손실 됨

지난 며칠 동안 gprs 디버깅 작업을 다시 수행했고 인터넷에서 루틴을 가져 오기 시작하고 마이크로 컨트롤러의 GPRS에 명령을 보냈으며 마이크로 컨트롤러는 모듈에서 반환 된 명령을 수신 할 수 있습니다. 이 경험에 대해 이야기하기 전에 단일 칩 마이크로 컴퓨터가 AT 명령을 GPRS로 보내는 방법을 간략하게 소개하겠습니다. AT 명령이 많이 있습니다. 각 AT 명령이 전송 된 후 단일 칩 마이크로 컴퓨터는 캐리지 리턴 "\ r \"을 보내야합니다. n "을 모듈에 추가합니다. 전송이 완료되었습니다. 다음은 참조를위한 전송 지시 부분입니다.

for (; * b! = '\ 0'; b ++) // *는 전송 된 AT 명령입니다
{
while (USART_GetFlagStatus (USART2, USART_FLAG_TC) == RESET);
USART_SendData (USART2, * b); // UART2_SendData (* b);
}

USART2_Puts ( "\ r \ n"); // 캐리지 리턴 보내기

그런 다음 루틴의 전송 명령 기능을 내 프로젝트에 이식했습니다. 그 결과 수수께끼 같은 현상이 나타났습니다. 프로그램을 마이크로 컨트롤러에 다운로드 한 다음 GPRS에 명령을 보냈지 만 응답을받지 못했습니다. 기준 치수. 이 문제 때문에 하루 종일 디버깅을했는데 왜 내 프로그램에서 같은 보내기 명령 기능을 구현할 수 없나요? 그때 내 마음이 무너질 뻔했다! !

사실 저는 충분히주의하지 않았습니다 (명령 보내기 기능이 괜찮다고 생각하기 전에는 항상 무시했습니다). 후속 디버깅 및 검사에서 프로그램에서 매우 중요한 세부 사항이 발견되었습니다. 캐리지 리턴 문자 UART2_SendLR ();

 루틴의 기능 내용은 다음과 같습니다.

무효 USART2_Puts (char * str)

  while (* str)
  {
while (USART_GetFlagStatus (USART2, USART_FLAG_TC) == RESET); 
USART_SendData (USART2, * str ++); // 현재 문자 보내기

  } 
}

그리고 그 자체 기능은 다음과 같습니다.

무효 USART2_Puts (char * str)

  while (* str)
  {
USART_SendData (USART2, * str ++); // 현재 문자 보내기
while (USART_GetFlagStatus (USART2, USART_FLAG_TXE) == RESET); 
  } 
}

두 문장의 순서와 플래그 비트가 다릅니다. 이전에이 기능을 사용해 왔기 때문에 신경 쓰지 않았지만 이전 AT 명령어 부분과 결합하면 문제가 매우 분명합니다. 내 기능을 사용 하면 , AT 명령어를 보낸 후 즉시 캐리지 리턴 문자가 플래그 비트의 판단없이 전송됩니다.이 경우 허용되지 않으므로 다음 문자가 이전 문자, 즉 마지막 문자를 덮게됩니다. AT 명령이 사라지고 GPRS가 인식하지 못합니다. 데이터를 반환합니다.

그래서 기능을 수정했고 문제가 해결되었습니다.

다음은 문제로 인한 발견입니다. 두 기능은 플래그 비트가 같지 않다고 판단하기 때문에 판단과 전송 순서가 다르기 때문에 호기심에이 기능을 통해 호스트 컴퓨터에 문자열을 보내 디스플레이 효과가 동일한 지 확인하고 싶습니다.

결과적으로 이상한 현상이 발견되었습니다. 루틴 함수에서 보낸 문자열의 첫 번째 문자는 프로그램 재설정이 시작될 때 항상 손실됩니다. 그리고 USART_FLAG_TXE를 사용하여 판단하면 정상일 수 있습니다.

이 두 플래그 비트의 차이점은 인터넷에서 검색되었으며 단일 칩 마이크로 컴퓨터의 직렬 포트 송수신 메커니즘 이 발견되었습니다 .

보내기 : 소프트웨어는 USARTx-> DR에 데이터를 쓰고 하드웨어는 USARTx-> DR의 데이터를 병렬로 "1 비트 레지스터 전송"에 자동으로 전송 한 다음 하드웨어가 자동으로 데이터를 1 비트 레지스터에 직렬로 전송합니다. TX 핀 전송합니다.

수신 : RX에서 오는 데이터가있는 경우 데이터를 비트 단위로 "수신 시프트 레지스터"에 먼저 넣고 전체 바이트를 수신 한 후 하드웨어가 "수신 시프트 레지스터"의 데이터를 병렬로 USARTx로 자동 전송합니다. > 내부 DR.

while (! (USART1-> SR & USART_FLAG_TC));이 문장은 "전송 시프트 레지스터"에서 데이터가 완전히 전송 될 때까지 기다리는 반면 (! (USART1-> SR & USART_FLAG_TXE));이 문장은 USARTx-> DR에서 "Transmit Shift Register"로 데이터 전송을 기다립니다. 후자의 문장을 작성할 때 USARTx-> DR에있는 데이터가 전송 되었기 만하면 데이터가 완전히 전송 될 때까지 기다릴 필요가 없으며 즉시 USARTx-> DR에 다시 쓸 수 있습니다. 많은 시간?

왜곡 된 코드는 분석을 위해 다른 코드를 합성해야합니다. (참고 : while (! (USART1-> SR & USART_FLAG_TC));는 while (USART_GetFlagStatus (USART2, USART_FLAG_TC) == RESET);  while (! (USART1-> SR & USART_FLAG_TXE)); while (USART_GetFlagStatus와 동일) (USART2, USART_FLAG_TXE) == RESET);)

따라서 USART_FLAG_TXE는 USART_FLAG_TC보다 먼저 판단되며, 데이터가 전송되는 한 USART_FLAG_TXE는 0으로 설정되고 USART_FLAG_TC의 판단은 지연되며 데이터가 0이 되려면 시프트 레지스터에 도달해야합니다. 이것은 또한 USART_FLAG_TC를 사용하면 첫 번째 데이터가 판단 및 손실되지 않는 이유를 설명합니다.





추천

출처blog.csdn.net/ludaoyi88/article/details/51219145