Skocz do zawartości
Komentator

Kurs STM32 - #5 - Komunikacja z komputerem, UART

Pomocna odpowiedź

Witam,
mam problem z moją płytką NUCLEO. Wykonuję kurs i na temacie komunikacja przez UART lub pomiar napięcia ADC, wszystko wykonuję tak jak jest w instrukcjach, łącze sie z Real Term albo Tera Term ale nic nie widze, nic nie jest wysyłane. Całą konfigurację robie dokładnie jak jest opisane, łącznie z konfiguracją w wyżej wymienionych programach. Nie wiem co się dzieje.

Udostępnij ten post


Link to post
Share on other sites

kacpus123, witam na forum 🙂 Czy korzystasz z dokładnie takiej samej płytki jak jest używana w kursie? Pytam, bo nie widzę zarejestrowanego zestawu na Twój adres. Czy port COM jest widoczny w systemie bez problemu?

Udostępnij ten post


Link to post
Share on other sites

Witam panowie, niestety straciłem już siłę do zadania domowego. 🙁 Dlaczego program nie wchodzi w obsługę przerwania? Komunikacja z komputerem jest ok, funkcje przykładowe z main działają. Sprawdziłem debugerem że program w ogóle nie wchodzi w przerwanie. Gdzie popełniam błąd?

#include "stm32f10x.h"



void USART2_IRQHandler(void)
{
if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE)!= RESET)
{
	char c = USART_ReceiveData(USART2);

	switch(c)
	{	case 'a':

			if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_4))
				GPIO_ResetBits(GPIOA, GPIO_Pin_4);
			else
				GPIO_SetBits(GPIOA,GPIO_Pin_4);

		break;

			case 'b':

			if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_5))
				GPIO_ResetBits(GPIOA, GPIO_Pin_5);
			else
				GPIO_SetBits(GPIOA,GPIO_Pin_5);
			break;


		case 'c':

			if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_6))
				GPIO_ResetBits(GPIOA, GPIO_Pin_6);
			else
				GPIO_SetBits(GPIOA,GPIO_Pin_6);

			break;


		case 'd':

			if(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_7))
				GPIO_ResetBits(GPIOA, GPIO_Pin_7);
			else
				GPIO_SetBits(GPIOA,GPIO_Pin_7);
			break;


   }

}
USART_ClearITPendingBit(USART2, USART_FLAG_RXNE);
}




void wyslijznak(char z)
{
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
USART_SendData(USART2, z);

}

void wyslijslowo(const char* s)
{
   while (*s)
	{
		wyslijznak(*s++);
	}
}


int main(void)
{ 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

GPIO_InitTypeDef port;
USART_InitTypeDef uart;
NVIC_InitTypeDef przerwanie;


GPIO_StructInit(&port);
port.GPIO_Pin = GPIO_Pin_2;
port.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &port);

port.GPIO_Pin=GPIO_Pin_3;
port.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &port);

port.GPIO_Pin= GPIO_Pin_4 | GPIO_Pin_5 |GPIO_Pin_6 |GPIO_Pin_7 ;
port.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOA,&port);







USART_StructInit(&uart);
uart.USART_BaudRate = 9600;
uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &uart);

USART_Cmd(USART2, ENABLE);


przerwanie.NVIC_IRQChannel = USART2_IRQn;
przerwanie.NVIC_IRQChannelPreemptionPriority = 0;
przerwanie.NVIC_IRQChannelSubPriority = 0;
przerwanie.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&przerwanie);

wyslijslowo("Hello");
while(1)
{ if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE)) 
    {
		 char c = USART_ReceiveData(USART2);
    switch (c)
    {
        case 'a':
            wyslijslowo("Odebrano komunikat A!\r\n");
            break;
        case 'b':
            wyslijslowo("Odebrano komunikat B!\r\n");
            break;
        default:
            wyslijslowo("Nieznany komunikat:(\r\n");
            break;

	 }


 }
}
}

Co wywołuje to "globalne przerwanie USART2"? Wydaje mi się że pojawienie się bitu startu na Rx kontrolera, a może się mylę?

Udostępnij ten post


Link to post
Share on other sites

dzami97, czy przypadkiem nie brakuje Ci jeszcze czegoś w rodzaju "USART_ITConfig(USART2, USART_IT_RXNE, ENABLE)" przy konfiguracji przerwania?

Udostępnij ten post


Link to post
Share on other sites

Witam,
dostałem od kolegi taki zestaw i próbuje odebrać dane z mikro kontrolera przez USB(STMicroelectronics STLink Virtual COM Port), lecz nic nie otrzymuje. Po podłączeniu konwerter na pinach PA2 i PA3 dane przychodzą. Już drugi tydzień kombinuje z tym, bo ciekawi mnie czemu, to nie działa :/. Działam na systemie Win 10 i wykonałem wszystkie aktualizacje dla sterowników mikro kontrolera.

Udostępnij ten post


Link to post
Share on other sites

Witam,

Ktoś może wie dlaczego strcmp nie działa? Czy jest jakaś możliwość że Tera Term wysyła mi jakieś dziwne rzeczy i dlatego compare nie działa?

	int bufferSize = 0;
char commandBuffer[3];

while (1)
{
	if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE)) {
		commandBuffer[bufferSize] = USART_ReceiveData(USART2);
		bufferSize++;
	}
	if (bufferSize >= 3) {
		if (strcmp(commandBuffer, "L1T") == 0)
			GPIO_SetBits(GPIOB, LED_1);
		else if (strcmp(commandBuffer, "L1O") == 0)
			GPIO_ResetBits(GPIOB, LED_2);
		bufferSize = 0;
	}
}

Udostępnij ten post


Link to post
Share on other sites

Problemy początkującego:

Próbuje komunikować się z mikrokontrolerem za pomocą USB. Powinienem widzieć wirtualny port w menedzerze urządzeń po COM&LPT ports. Niestety nic takiego nie mam. Efekt jest taki, że nie mogę połączyć się choćby z Tera Term VT i wymieniać danych między płytką a PCtem. Dodam, że wcześniejsze próby z mryganiem diodą na płytce zakończyły się sukcesem.

Dla testu podłączyłem Arduino Nano i po podłączeniu pokazuje się port COM.

Udostępnij ten post


Link to post
Share on other sites

kleszcz, czy zainstalowałeś sterowniki do płytki Nucleo (pobrane ze strony producenta) przed podłączeniem jej do komputera?

Udostępnij ten post


Link to post
Share on other sites

Witam,

Skopiowałem pierwszy program odnośnie transmisji UART do płytki Nucleo (wysyłanie napisu Hello) a w terminalu otrzymuje komunikat "Cannot open port COM5.NOt found.".

Dodam ,że wszystkie poprzednie programy z tego kursu działają bez problemu.

Prosze o rade co może powodować taki bład . Dodam , ze terminal widzi nucleo.

PS. dlaczego w programie nie dodano takich komend ?

uart.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
uart.USART_Mode=USART_Mode_Tx;
uart.USART_Parity=USART_Parity_No;
uart.USART_WordLength=USART_WordLength_8b;
uart.USART_StopBits=USART_StopBits_1;

[ Dodano: 20-04-2018, 16:30 ]

Już to naprawiłem, musiałem zmienić wersje z 32 na 64 - bitową środowiska.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Cześć ! 

W programie obsługi interfejsu USART dla kursu stm32 zamieszczony jest następujący kod :

#include "stm32f10x.h"
 
void send_char(char c)
{
 while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
 USART_SendData(USART2, c);
}
 
void send_string(const char* s)
{
 while (*s)
 send_char(*s++);
}
 
int main(void)
{
 GPIO_InitTypeDef gpio;
 USART_InitTypeDef uart;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
 
 GPIO_StructInit(&gpio);
 gpio.GPIO_Pin = GPIO_Pin_2;
 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_Init(GPIOA, &gpio);
 
 gpio.GPIO_Pin = GPIO_Pin_3;
 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_Init(GPIOA, &gpio);
 
 USART_StructInit(&uart);
 uart.USART_BaudRate = 115200;
 USART_Init(USART2, &uart);
 
 USART_Cmd(USART2, ENABLE);
 
 char tab[12] = {':', '8', '8', '8', '8', '0', '9', '0', '0', '8','\r', '\n'}; //dziwny znak na poczatku widoczny w TeraTerm
 char tab2[13] = {':', '8', '8', '8', '8', '0', '9', '0', '0', '8','\r', '\n','\0'}; //OK
 char tab3[13] = {':', '8', '8', '8', '8', '0', '9', '0', '0', '8','\r', '\n'}; //OK
  
 while (1) {
 //send_string("Hello world!\r\n");
   send_string(&tab[0]);
 }
}

To co wyświetlane jest w Terminalu TeraTerm jest następujące :

znaki.png

I teraz pytanie dlaczego wyświetla taki dziwny znak na początku ciągu znakowego, jak to wyeliminować ? Nie zawszę będziemy wpisywać do funkcji 

send_string("ciag znakow.....r\n"); 

Chciałoby się mieć też możliwość podania adresu wskazującego na pierwszy element tablicy znakowej jak zrealizowano to w 

send_string_BT(&tab[0]);

I teraz najważniejsze pytanie, czy jeśli chcę pozbyć się dziwnego znaku na początku to muszę zwiększyć tablice znakową o miejsce na wartość NULL i czy po stronie odbiorcy liczba bajtów będzie równa : liczba znaków w tablicy + znak \0 (NULL) ????? 

co dla tab[12] daje : 12bajtów + 1bajt(NULL) = 13 bajtów ???

Bardzo proszę o pomoc w wyjaśnieniu tej kwestii 🙂

Edytowano przez simba92

Udostępnij ten post


Link to post
Share on other sites

Znak nie jest wyświetlany na początku, a na końcu poprzedniego komunikatu.

Po prostu języki C/C++ nic nie wiedzą o rozmiarach tablic, w tym przypadku traktują je po prostu jako ciąg bajtów umieszczonych w pamięci, a wszelkiego typu napisy muszą kończyć się znakiem \0.

Tutaj w przypadku tablicy tab funkcja send_string po prostu nie wie gdzie ma skończyć wysyłanie, i lezie poza tablicę wysyłając śmiecie aż napotka przypadkowe zero.

Czyli tak - trzeba przewidzieć miejsce na dodatkowy znak.

Po stronie odbiorcy to już zależy od programu.

Tak przy okazji - znak o kodzie zero to NUL (przez jedno L), NULL to pusty wskaźnik.

  • Lubię! 1
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

ethanak  dziękuje Ci za wyczerpującą odpowiedź i udzieloną pomoc 🙂

Udostępnij ten post


Link to post
Share on other sites

Cześć! 🙂

Dlaczego wyjście sygnału UART ustawiamy w trybie alternatywnym push-pull, a wejście w trybie floating? Czym się kierować podczas samodzielnego konfigurowania?

Z góry dzięki! 🙂

 

Udostępnij ten post


Link to post
Share on other sites

Bo obowiązuje zasada, że każdy kabelek, każdy sygnał musi mieć swojego "drivera" czyli układ sterujący, który zadaje tam jakiś stan logiczny. Za to odbierać może taki sygnał wiele odbiorników / wejść. Tak więc jeśli wysyłasz informacje z procesora (np. linia TXD UARTa) to muszisz sprawić, by ten pin był wyjściem - to on będzie zadawał napięcie w tym drucie i przesyłał je do oddalonego odbiornika, do jego wejścia RXD. W przypadku gdy chcesz wprowadzać inofrmacje do procesora (pin RXD) to ktoś inny musi tym kabelkiem sterować (podłączyć tam swoje TXD) a Ty musisz być wejściem. Stąd kierunki "wyjście " i "wejście".

Powinieneś kierować się przeznaczeniem linii. Z czystymi wejściami i wyjściami jak rozumiem nie będziesz miał już problemów. Wiadomo, że diodka LED czy tranzystor sterujacy przekaźnikiem potrzebuje wyjścia, a przycisk czy jakiś czujnik musi być podłączony do wejścia. Pewnym niuansem są typy szczegółowe, dostępne w niektórych procesorach np. floating, pull-up, pull-down czy schmitt (wejścia) albo open-collector, open-emitter czy hi-z/bidirectional (wyjścia), ale to spróbuj wyszukać. Te konfiguracje umożliwiają pewne ciekawe tryby i są używane w przypadkach gdy np. kilku "konkurentów" ubiega się o sterowanie tą samą linią lub też z powodów konstrukcyjnych nie możesz (lub nie chcesz) zapewnić ciągłego sterowania jednym "driverem". Gdyby ktoś odpiął wtyczkę z odległym, bliźniaczym UARTem od Twojego porcesora, to wyjściu TXD to nie zaszkodzi - zawsze może nadawać "w pustkę", ale wejście RXD przestanie być sterowane i zacznie odbierać zakłócenia z powietrza. Jeśłi Twój program ma odpalać np. rakietę, to pewnie nie chciałbyś żeby wystartowała z powodu poluzowania się głupiego złącza. Wtedy możesz zabezpieczyć się wybraniem typu wejścia "pull-up", który bez sygnału podciąga linię do stanu wysokiego, co dla UARTa oznacza "nic się nie dzieje".

  • Lubię! 1
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

Co za obszerna odpowiedź, dziękuję! 🙂 Jeszcze nie czuję, kiedy używać tych dodatkowych trybów o których wspomniałeś, ale postaram się jakoś sam poszukać. 😉

Udostępnij ten post


Link to post
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »

×