Skocz do zawartości

[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

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)
	{

	}
}

 

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...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.