Skocz do zawartości

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.

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?

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ę?

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?

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.

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

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?

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
Link to post
Share on other sites

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
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
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
Link to post
Share on other sites
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

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.