Skocz do zawartości
mw9501

[STM32F4] Problem z Receiverem UART

Pomocna odpowiedź

Witajcie

Realizuję komunikację pomiędzy mikroprocesorem STM32F411RE (NUCLEO) a modułem SIM800L. Wykorzystuję do tego interfejs UART.

Inicjalizuję go poprzez bibliotekę HAL'a. Samą wymianę danych postanowiłem zrobić ręcznie, odwołując się bezpośrednio do rejestrów UART.

Poniżej funkcja inicjalizacyjna:

void uart_init(uint32_t baud)
{
	uart_gpio.Pin = GPIO_PIN_9 | GPIO_PIN_10; //TX RX
	uart_gpio.Mode = GPIO_MODE_AF_PP;
	uart_gpio.Alternate = GPIO_AF7_USART1;
	uart_gpio.Speed = GPIO_SPEED_HIGH;
	uart_gpio.Pull = GPIO_PULLUP;
	HAL_GPIO_Init(GPIOA,&uart_gpio);

	usart.Instance = USART1;
	usart.Init.BaudRate = baud;
	usart.Init.Parity = USART_PARITY_NONE;
	usart.Init.StopBits = USART_STOPBITS_1;
	usart.Init.WordLength = USART_WORDLENGTH_8B;
	usart.Init.Mode = USART_MODE_TX_RX;
	HAL_USART_Init(&usart);
}

 

Sama komunikacja odbywa się w funkcji "sim_reception", w przerwaniu od timera mikroprocesora.

#define SIM_TX_BUF_SIZE		32
#define SIM_RX_BUF_SIZE		32 

volatile unsigned char sim_tx_buf[SIM_TX_BUF_SIZE];
volatile unsigned char sim_rx_buf[SIM_RX_BUF_SIZE];
volatile unsigned char sim_tx_len = 0;
volatile unsigned char sim_rx_len = 0;

enum { handshake, hdsh_resp };
volatile uint8_t sim_states = handshake;

#define SIM_HNDSHK			"AT\r\n"

void sim_reception(void)
{
	//RX
	//if Receiver not empty flag is set and we have space in rx buffer, we read byte
	while(USART1 -> SR & USART_SR_RXNE)
	{
		if(sim_rx_len < SIM_RX_BUF_SIZE)
			sim_rx_buf[sim_rx_len++] = USART1 -> DR; //after reading byte we increment buffer length
		else
			break;
	}

	//TX
	//if Transmitter empty flag is set and we have data in tx buffer, we send byte
	while(USART1 -> SR & USART_SR_TXE)
	{
		if(sim_tx_len != 0)
		{
			USART1 -> DR = sim_tx_buf[0];//send one byte
			sim_byte_up(sim_tx_buf);	//shift one byte up
		}
		else
			break;
	}

	switch(sim_states)
	{
		case handshake:
			sim_tx_buf_put(SIM_HNDSHK);

			sim_states = hdsh_resp;
			break;

		case hdsh_resp:

			break;

		default:
			sim_states = handshake;
			break;
	}
}

Na razie chcę wysłać tylko jedno polecenie i odczytać odpowiedź modułu SIM800L. Krótko opiszę nadawanie, które działa bez zarzutu. Wywołuję funkcję "sim_tx_buf_put", która napełnia bufor komendą "SIM_HNDSHK", zdefiniowaną wyżej za pomocą #define. Funkcja bada ile miejsca mamy w buforze i czy wystarczy go jeszcze dla nowego polecenia. Jeśli tak to wstawia je bajt po bajcie i zwiększa odpowiednio zmnienną "sim_tx_len". Nie będe wstawiał kodu tej funkcji, ponieważ działa ona bardzo dobrze, nie mam z nią problemu. Wyżej w kodzie widać, że jest badany stan flagi "Transmitter Empty", gdy się ona pojawi i w buforze Tx są dane przystępuje się do wysyłania danych bajt po bajcie. Po każdym wysłanym bajcie wywoływana jest funkcja "sim_byte_up", która przesuwa bajty bufora "o jeden w górę", czyli sim_tx_buf[0] = sim_tx_buf[1], sim_tx_buf[1] = sim_tx_buf[2] itd. oraz zmniejsza wartość "sim_tx_len" o jeden, następnie wysyłany jest kolejny bajt i tak do opróżnienia bufora.

Nadajnik działa jak należy, co pokazuje screenshot z analizatora stanów logicznych.

1326861970_ramkatxrx.thumb.png.2c7774cb84acdea799488bc72a2a6099.png

Po wysłaniu wiadomości "AT\r\n" moduł SIM800L odsyła odpowiedź. Zatem flaga "Receiver Not Empty" powinna zostać aktywowana, bufor Rx jest pusty, tak więc coś powinno zostać zapisane w buforze. Jednak nic takiego się nie dzieje.

Screenshoty z debugowania.

debug1.thumb.png.a026809a8fec06c4f79e684ac5ce3a1a.pngdebug2.thumb.png.8a4b157892e95e2e0ea0f49b786ad2e3.png

W buforze Rx pojawia się tylko jeden bajt o wartości 127. Dalszych procedur odbioru nawet nie opracowałem, bo skoro w buforze odbiorczym nic nie ma...

Nie bardzo wiem z czym jest związany ten problem, próbowałem wyprowadzić Tx i Rx we wszystkich możliwych konfiguracjach, jednak zawsze jest tak samo, nadajnik wysyła bez żadnego problemu a odbiornik nie może nic odczytać.

Jeśli ktoś ma jakiś pomysł co może być przyczyną problemu i jak to rozwiązać to byłbym bardzo wdzięczny za pomoc 😉

 

Pozdrawiam

mw

Udostępnij ten post


Link to post
Share on other sites

@mw9501 nie udostępniłeś całego kodu, więc próba pomocy to niestety zgadywanie. Zacznę więc od najprostszego pytania - włączyłeś taktowanie portu z pinem RX?

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Elvis Tak, oczywiście. Taktowanie jest wszędzie włączone.

int main(void)
{
	HAL_Init();

	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_USART1_CLK_ENABLE();
    	__HAL_RCC_TIM5_CLK_ENABLE();
  
  	timers_init();
	interrupt_init();
  	uart_init(9600);
  	
   	while(1)
	{

	}
}

 

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...