STM32 HAL - vysvetlenie kodu

Všetko čo sa týka mikropočítačov + Sekcia Arduino

Moderátori: psichac, Moderátori

bibibo
Pokročilý člen
Pokročilý člen
Príspevky: 625
Dátum registrácie: 05 Nov 2009, 00:00
Bydlisko: Bratislavský kraj

STM32 HAL - vysvetlenie kodu

Príspevok od používateľa bibibo » 01 Jan 2020, 21:08

Ahojte,

doteraz som programoval len v Mbed (nieco ako arduino) a v Bascome. Skusam teraz HAL s MCU STM32L. Snazim sa naprogramovat komunikaciu UART s prerusenim. Nejaky example som nasiel a v podstate to funguje. Nie je mi vsak absolutne jasny kod.

Toto je asi povolenie prerusenia ?

Kód: Vybrať všetko

HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(USART2_IRQn);
Potom su tu dve funkcie, ktore absolutne netusim co ich vola. Nikde v tych zdrojovych suborov som nenasiel co by tieto funkcie volalo.

Kód: Vybrať všetko

void UART2_IRQHandler(void)
{
	HAL_UART_IRQHandler (&huart2);
	
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART2)
{

HAL_UART_Transmit(&huart2, &byte, 1, 100);

HAL_UART_Receive_IT(&huart2, &byte, 1);
}
}
Vo funkcii main je toto. Naco to tam je, ked je to vo funkcii vyssie ?

Kód: Vybrať všetko

HAL_UART_Receive_IT(&huart2, &byte, 1);
Posledna otazka, preco je pred premennou byte ten znak and ?
0

maskrtnik01
Ultimate člen
Ultimate člen
Príspevky: 2564
Dátum registrácie: 20 Júl 2010, 00:00
Bydlisko: okolie KE
Vek: 27

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa maskrtnik01 » 01 Jan 2020, 21:24

Prvé dve riadky áno, povolenie prerušenia a nastavenie jeho priority.

UART2_IRQHandler, odporúčam naštudovať čo je prerušenie procesora(interrupt) a ako funguje. Potom si odpovedáte sám čo to zavolá.

&huart2 to zase vychádza zo syntaxe C. Niektoré funkcie potrebujú modifikovať ten handle na uart modul(nie som na pc ale tuším je to pod kapotou štruktúra). Preto je nutné poslať funkcii adresu a nie hodnotu. Naštudovať čo sú pointery(smerníky).
0

popopepe
Stály člen
Stály člen
Príspevky: 404
Dátum registrácie: 22 Jún 2009, 00:00

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa popopepe » 01 Jan 2020, 22:24

Jak píše kolega, první dva řádky jsou nastavení a povolení přerušení.

Pokud chceš přijímat pomocí přerušení, tak musíš ale taky říct co se má stát.

Takže ten řádek v main ( a nebude ve smyčce, pustí se jenom jednou) odstartuje příjem UART pomocí přerušení. O vše ostatní se stará železo toho procesoru. Ty se o to starat nemusíš.

To statní znamená:

funkce

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) //sem skočí procesor po tom, co obdržel informaci o tom, že něco přijal na libovolném sériovém portu
{
if (huart->Instance == USART2) //pokud to bylo z UART 2
{
//tak tady musíš napsat, co se má stát, to co jsi poslal, je nějaký příklad)
HAL_UART_Transmit(&huart2, &byte, 1, 100); //odešli nějaká data na portu 2, z pozice, na kterou ukazuje ten ukazatel, 1 byte, 100 milisekund timeout)

HAL_UART_Receive_IT(&huart2, &byte, 1); //a znovu začni přijímat pomocí přerušení(port 2, ukazatel kam prsknout přijatá data, kolik jich bude (1 byte)
}
}

Stáhni si reference k HAL, tam jsou ty jednotlivé funkce popsané. Ale je to na dlouhé večery :-)
0

peterple
Ultimate člen
Ultimate člen
Príspevky: 2328
Dátum registrácie: 25 Jún 2013, 21:06
Bydlisko: Krajné
Vek: 57
Kontaktovať používateľa:

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa peterple » 01 Jan 2020, 22:32

Tak tak, naštudovať aspoň obecne ako pracuje prerušenie nejakého procesora.
Kto by funkciu UART2_IRQHandler asi volal? Že by to prerušenie?
No a nájsť volanie tej druhej funkcie s označením callback sa dá v zdrojovom kóde veľmi rýchle. Na dva skoky. Najprv sa nájde
HAL_UART_IRQHandler
http://www.disca.upv.es/aperles/arm_cor ... tml#l01517
a tam sa volá UART_Receive_IT
http://www.disca.upv.es/aperles/arm_cor ... tml#l02364
Na riadku 02414 sa volá HAL_UART_RxCpltCallback, ktorý si musí definovať užívateľ.

Odpoveď na čo je volanie HAL_UART_Receive_IT najprv main a potom v tej funkcii je jasná ak vieš ako to pracuje. Treba vedieť princíp ako to fičí a ako sa programujú neblokujúce volania. Napríklad aj v javascripte je to samá callback funkcia.
Takže po poriadku. Čo robí HAL_UART_Receive_IT
http://www.disca.upv.es/aperles/arm_cor ... tml#l00820
čo teda robí? - Požiada HAL o prijatie zadaného počtu byte do zadaného buffera, cez zadané UART rozhranie. Dôležité si je uvedomiť že ona nečaká na prijatie toho znaku ale len niekde (v tej štruktúre čo je odovzdaná ako prvý parameter) niečo skontroluje a nastaví a skončí s vrátením nejakého statusu. Main potom beží ďalej (asi v tom príklade nekonečnou slučkou).
Až sa prijme ten byte cez sériové rozhranie. Tak sa vďaka povolenému prerušeniu zavolá UART2_IRQHandler
Ten zavolá obecnú obsluhu prijatia znaku ktorá je rovnaká pre všetky UARTy HAL_UART_IRQHandler
Ten zase UART_Receive_IT. Ten prijíma dovtedy dokiaľ neprijme všetky požadované znaky. V tomto prípade teda jeden. Čo sa vlastne aj práve stalo. Takže sa zavolá aj HAL_UART_RxCpltCallback

No a tam si užívateľ napísal že ten prijatý znak chce odoslať naspäť, a v druhom volaní že chce zase prijať jeden byte do premennej byte.

Takže celá táto sranda nerobí nič iného len vráti prijatý znak a zariadi aby sa to isté stalo aj s ďalším. Celé to ale beží na pozadí bez toho aby to nejako unúvalo hlavný program. Ten si môže robiť čo len chce (aj nič).

-- Spojený príspevok 01 Jan 2020, 22:50 --

A ešte k tomu znaku Je to operátor ako trebárs + alebo *. V tomto zmysle vypočíta adresu premennej v pamäti.
Teda

Kód: Vybrať všetko

&byte
Vypočíta adresu kde sa premenná byte v pamäti nachádza. Nadáva sa tomu aj odkaz alebo referencia. Ak sa to uloží do premennej tak tej sa nadáva smerník(pointer) a je s tým kopec srandy ak tomu človek nerozumie a ledva ledva tuší o čo tam ide. Chcem tým naznačiť, že toto je pre C programátora ako malá násobilka. Ak toto nedáva tak má iba dve možností - študovať a pochopiť to, alebo sa na C vykašlať. Cez toto skrátka nejde vlak.

V konkrétnom prípade na tom mieste funkcia očakáva ako parameter adresu buffera pre ukladanie prijatých znakov. A preto tam nemôže byť samotne

Kód: Vybrať všetko

byte
čo by znamenalo daj sem hodnotu premennej byte. Teda nie kde ta premenná je ale čo v nej je.
0
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.

bibibo
Pokročilý člen
Pokročilý člen
Príspevky: 625
Dátum registrácie: 05 Nov 2009, 00:00
Bydlisko: Bratislavský kraj

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa bibibo » 03 Jan 2020, 15:43

no mam v tom dobry zmatok. Bol som zvyknuty v inych programovacich jazykoch alebo nastrojoch, ze ked povolim prerusenie, tak rovno tomu prikazu napisem do zatvorky nazov funkcie, ktora je volana v pripade prerusenia. V tomto HAle je to strasne komplikovane. Same volania. Nerozumiem, ze ked uz prerusenie vola UART2_IRQHandler, tak naco tam je este funcia Callback. Ved mozem kod resp. to co sa ma v preruseni vykonat napisat aj do funkcie UART2_IRQHandler, ci nie ? Dalsia vec, ktory mi nie je jasna je, ze v Callback funkcii je HAL_UART_Transmit a potom HAL_UART_Receive_IT. peterple pise, ze to prijatie znaku je volane v druhom volani. V akom druhom volani ? Bol som v tom, ze ked sa zavola funkcia Callback, tak sa postupne vykonaju vsetky prikazy riadok po riadku.
0

maskrtnik01
Ultimate člen
Ultimate člen
Príspevky: 2564
Dátum registrácie: 20 Júl 2010, 00:00
Bydlisko: okolie KE
Vek: 27

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa maskrtnik01 » 03 Jan 2020, 15:54

UART2_IRQHandler je samotné prerušenie. Keby ste sa hrabali v boot kóde, áno tento názov je tam uvedený.

HAL_UART_IRQHandler je funkcia ako každá iná, tá je v knižniciach HAL. Tie mimochodom nemusíte používať, ak by ste zvládli priamy prístup k registrom. GPIO, časovače, UART/SPI/I2C atď je ešte celkom v pohode.

Už keby ste riešili usb, tcp/ip stack a podobne, priamo na registre je masochizmus.
Prílohy
037961CF-473E-4E90-8B82-1A27673578CE.png
0

Používateľov profilový obrázok
Tribec Zacks
Pokročilý člen
Pokročilý člen
Príspevky: 709
Dátum registrácie: 26 Jún 2010, 00:00
Bydlisko: Levice / Cork IRL
Vek: 41
Kontaktovať používateľa:

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa Tribec Zacks » 03 Jan 2020, 16:47

@bibibo,

sa pridam k maskrtnikovi, ak neriesis usb alebo tcp/ip stacky, tak na stm mas mozno aj lahsie naucit sa low level register access configuraciu jednotlivych periferii ako pouzivat HAL kniznicu, ma to samozrejme svoje pre a proti, register accessom musis postudovat datasheet a naucit sa co ako funguje (a tie periferie toho teda vedia podstatne viac ako avr a su teda zlozitejsie), stratis tym portabilitu medzi roznymi mcu, ale na druhu stranu ak to dostanes do hlavy, tak aj konfiguracia veci ako napr timer periodicky spusti adc a dma ti to prenese niekde do pamate bez zasahu mcu su neni take tazke, ziskas tym plnu kontrolu nad mcu, cistejsi a zrozumitelnejsi kod konfiguracii periferii, menej kompilacie a "dependencies" atd... no ako hovorim ma to svoje pre a proti :)

ak mozem este dodat, ak sa chces naucit ako funguje mcu a ako sa da vyuzivat jeho hw, zacni sa ucit register access, ak len chces nieco zbuchat a nech to nieco robi, tak je HAL ok...
0
Kreativita a motivacia je to, co prinasa originalne napady a myslienky, disciplina je to, co ich dokaze zrealizovat.

maskrtnik01
Ultimate člen
Ultimate člen
Príspevky: 2564
Dátum registrácie: 20 Júl 2010, 00:00
Bydlisko: okolie KE
Vek: 27

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa maskrtnik01 » 03 Jan 2020, 17:31

Pridám jeden návod pre začiatky. Je to na kus iné stmko, ale rozdiely nie sú drastické.

http://joudove.8u.cz/index.php?option=c ... Itemid=152

Keď napíšete presný typ mcu, pošlem link na datasheet a reference manual, tam je všetko čo treba ku programovaniu.


A na rozvrhnutie pinov a clock tree používam stm32cubemx. Kód si potom robím sám, ale kým len priradzujem piny je to celkom užitočný nástroj.
https://www.st.com/en/development-tools ... ubemx.html
0

peterple
Ultimate člen
Ultimate člen
Príspevky: 2328
Dátum registrácie: 25 Jún 2013, 21:06
Bydlisko: Krajné
Vek: 57
Kontaktovať používateľa:

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa peterple » 03 Jan 2020, 18:14

Ako už písali, nič ti nebráni napísať si svoju vlastnú obsluhu prerušenia. HAL je na to aby to bolo jednotné pre väčšiu rodinu procesorov. Aj Ardinisti idú tým smerom. Poskytujú knižničné funkcie ktoré pokryjú 95% potrieb (100% začiatočníkom) a fungujú na viacerých typoch AVR a dokonca to prerástlo až AVR rodinu a začalo sa to používať kde kade (napr. ESP)
Ak teda vieš tak si napíš sám čo chceš v obsluhe prerušenia robiť a nemusiš potom riešiť žiadne callback funkcie.

Ohľadom fungovania došlo k nedorozumeniu pretože som sa nevyjadril dosť presne. Samozrejme je to tak že ten kód v callback funkcii zbehne príkaz po príkaze a to som práve myslel. Ako volanie prvej funkcie a potom volanie druhej funkcie.
Ale pre teba to vyznelo ako že sa to robí na dve volania tej callbakc funkcie. Tak som to ale nemyslel.

Kód: Vybrať všetko

if (huart->Instance == USART2)
{
HAL_UART_Transmit(&huart2, &byte, 1, 100); //volanie prvej funkcie posle prave prijaty byte nazad
HAL_UART_Receive_IT(&huart2, &byte, 1);  // volanie druhej funkcie zabezpeci prijatie dalsieho byte na pozadi
}
}
Inak ak chceš písať vlastné obsluhy tak si myslím že je dobré práve začať štúdiom HALu ako to robí a snažiť sa pochopiť že prečo to tak ktosi napísal. Písali to maníci čo už pár rokov také potvory jazdia a je teda sa čomu priučiť.
0
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.

maskrtnik01
Ultimate člen
Ultimate člen
Príspevky: 2564
Dátum registrácie: 20 Júl 2010, 00:00
Bydlisko: okolie KE
Vek: 27

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa maskrtnik01 » 03 Jan 2020, 19:11

Mne tá halka príde dosť ťažkopádna. Samé if a #ifdef.
Kým som nerobil minule s usb-cdc, tak som si zatiaľ všetko písal sám podľa datasheetu a ref manuálu. Na začiatku joudove(link v predošlom príspevku).
0

bibibo
Pokročilý člen
Pokročilý člen
Príspevky: 625
Dátum registrácie: 05 Nov 2009, 00:00
Bydlisko: Bratislavský kraj

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa bibibo » 04 Jan 2020, 10:55

Pouzil som aj ja STM32CubeMX. Ak mate na mysli Low Level API, tak to som uz skusal. Zda sa mi, ze kod v LL je rozsiahlejsi ako v HAL. Taktiez mi pride, ze pre HAL je viac materialov a prikladov na nete. Pouzivam STM32L011F4 a povodne som ho chcel programovat v Mbed, ten podporuje NUCLEO-L011K4. Problem je, ze skompilovany kod z Mbed je prilis velky a nevlezie do MCU. Su na to nejake finty, ale tie momentalne nefunguju resp. Mbed ma nejaky problem a nie je mozne stiahnut z netu Mbed-OS 2 a pouzit ho offline.
0

maskrtnik01
Ultimate člen
Ultimate člen
Príspevky: 2564
Dátum registrácie: 20 Júl 2010, 00:00
Bydlisko: okolie KE
Vek: 27

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa maskrtnik01 » 04 Jan 2020, 11:36

Nie, LL API je zase len knižnica okolo registrov.

Kód: Vybrať všetko

#include <stm32f0xx.h>

#define REFDebounce 200

//Button-related variables
volatile uint16_t in1, in1_0, in1_1, button1;
volatile uint16_t in2, in2_0, in2_1, button2;
volatile uint16_t in3, in3_0, in3_1, button3;
volatile uint16_t in4, in4_0, in4_1, button4;
volatile uint8_t lastButton;

void InitializeBoard()
{
	SysTick_Config(8000000);
	
	RCC->AHBRSTR |= RCC_AHBRSTR_GPIOARST;
	RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOARST;
	RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
	
	//PA2 UART2_TX AF1
	//PA3 UART2_RX AF1
	//PA4 LED1
	//PA5 BUTTON1
	//PA6 LED2
	//PA7 BUTTON2
	//PA8 LED3
	//PA11 BUTTON3
	//PA12 LED4
	//PA13 SWDIO
	//PA14 SWCLK
	//PA15 BUTTON4
	
	GPIOA->MODER |= GPIO_MODER_MODER2_1;
	GPIOA->MODER |= GPIO_MODER_MODER3_1;
	GPIOA->MODER |= GPIO_MODER_MODER4_0;
	GPIOA->MODER |= GPIO_MODER_MODER6_0;
	GPIOA->MODER |= GPIO_MODER_MODER8_0;
	GPIOA->MODER |= GPIO_MODER_MODER12_0;
	
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR2_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR3_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR4_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR5_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR6_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR7_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR8_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR11_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR12_0;
	GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR15_0;
	
	//Turn off LEDs
	GPIOA->BSRR |= GPIO_BSRR_BR_4;
	GPIOA->BSRR |= GPIO_BSRR_BR_6;
	GPIOA->BSRR |= GPIO_BSRR_BR_8;
	GPIOA->BSRR |= GPIO_BSRR_BR_12;
	
	//Activate pull-ups on buttons
	GPIOA->PUPDR |= GPIO_PUPDR_PUPDR5_0;
	GPIOA->PUPDR |= GPIO_PUPDR_PUPDR7_0;
	GPIOA->PUPDR |= GPIO_PUPDR_PUPDR11_0;
	GPIOA->PUPDR |= GPIO_PUPDR_PUPDR15_0;
	
	//AF1 at PA2 PA3
	GPIOA->AFR[0] = 0x00001100;
	
	RCC->APB1RSTR |= RCC_APB1RSTR_USART2RST;
	RCC->APB1RSTR &= ~RCC_APB1RSTR_USART2RST;
	RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
	
	//USART2 - Enable RX, TX, IRQ on RX
	USART2->BRR = 0x1381;
	USART2->CR1 |= (USART_CR1_RE | USART_CR1_TE | USART_CR1_RXNEIE);
	USART2->CR1 |= USART_CR1_UE;
	NVIC->ISER[USART2_IRQn >> 0x05] |= (0x01 << (USART2_IRQn & 0x1F));
}
int main()
{
	InitializeBoard();
	//Initialize button-related
	in1 = 3;
	in1_0 = 0;
	in1_1 = 0;
	button1 = 0;
	in2 = 3;
	in2_0 = 0;
	in2_1 = 0;
	button2 = 0;
	in3 = 3;
	in3_0 = 0;
	in3_1 = 0;
	button3 = 0;
	in4 = 3;
	in4_0 = 0;
	in4_1 = 0;
	button4 = 0;
	lastButton = 0;
	
	//Main loop
	while(1)
	{
		//Check buttons pressed
		if(button1 & (lastButton == 0))
		{
			lastButton = 1;
			while (!(USART1->ISR & USART_ISR_TXE)) ;
			USART2->TDR = 'a';
		}
		if (button2 & (lastButton == 0))
		{
			lastButton = 2;
			while (!(USART1->ISR & USART_ISR_TXE)) ;
			USART2->TDR = 'b';
		}
		if (button3 & (lastButton == 0))
		{
			lastButton = 3;
			while (!(USART1->ISR & USART_ISR_TXE)) ;
			USART2->TDR = 'c';
		}
		if (button4 & (lastButton == 0))
		{
			lastButton = 4;
			while (!(USART1->ISR & USART_ISR_TXE)) ;
			USART2->TDR = 'd';
		}
		//Check buttons released
		if ((button1 == 0) & (lastButton == 1))
		{
			lastButton = 0;
		}
		if ((button2 == 0) & (lastButton == 2))
		{
			lastButton = 0;
		}
		if ((button3 == 0) & (lastButton == 3))
		{
			lastButton = 0;
		}
		if ((button4 == 0) & (lastButton == 4))
		{
			lastButton = 0;
		}
	}
}

void USART2_IRQHandler()
{
	if (USART2->ISR & USART_ISR_RXNE)
	{
		char c = USART2->RDR;
		
		//Turn on/off LEDs
		switch (c)
		{
		case 'e':
			GPIOA->BSRR |= GPIO_BSRR_BS_4;
			break;
		case 'f':
			GPIOA->BSRR |= GPIO_BSRR_BS_6;
			break;
		case 'g':
			GPIOA->BSRR |= GPIO_BSRR_BS_8;
			break;
		case 'h':
			GPIOA->BSRR |= GPIO_BSRR_BS_12;
			break;
		case 'i':
			GPIOA->BSRR |= GPIO_BSRR_BR_4;
			break;
		case 'j':
			GPIOA->BSRR |= GPIO_BSRR_BR_6;
			break;
		case 'k':
			GPIOA->BSRR |= GPIO_BSRR_BR_8;
			break;
		case 'l':
			GPIOA->BSRR |= GPIO_BSRR_BR_12;
			break;
		}
	}
}

void SysTick_Handler()
{
	in1 = ((GPIOA->IDR & GPIO_IDR_5) != 0);
	in2 = ((GPIOA->IDR & GPIO_IDR_7) != 0);
	in3 = ((GPIOA->IDR & GPIO_IDR_11) != 0);
	in4 = ((GPIOA->IDR & GPIO_IDR_15) != 0);
	//Debounce buttons
	if(in1 == 0)
	{
		in1_0++;
		in1_1 = 0;
		if (in1_0 >= REFDebounce)
		{
			in1_0 = REFDebounce + 1;
			button1 = 0;
		}
	}
	else
	{
		in1_0 = 0;
		in1_1++;
		if (in1_1 >= REFDebounce)
		{
			in1_1 = REFDebounce + 1;
			button1 = 1;
		}
	}
	
	if (in2 == 0)
	{
		in2_0++;
		in2_1 = 0;
		if (in2_0 >= REFDebounce)
		{
			in2_0 = REFDebounce + 1;
			button2 = 0;
		}
	}
	else
	{
		in2_0 = 0;
		in2_1++;
		if (in2_1 >= REFDebounce)
		{
			in2_1 = REFDebounce + 1;
			button2 = 1;
		}
	}
	
	if (in3 == 0)
	{
		in3_0++;
		in3_1 = 0;
		if (in3_0 >= REFDebounce)
		{
			in3_0 = REFDebounce + 1;
			button3 = 0;
		}
	}
	else
	{
		in3_0 = 0;
		in3_1++;
		if (in3_1 >= REFDebounce)
		{
			in3_1 = REFDebounce + 1;
			button3 = 1;
		}
	}
	
	if (in4 == 0)
	{
		in4_0++;
		in4_1 = 0;
		if (in4_0 >= REFDebounce)
		{
			in4_0 = REFDebounce + 1;
			button4 = 0;
		}
	}
	else
	{
		in4_0 = 0;
		in4_1++;
		if (in4_1 >= REFDebounce)
		{
			in4_1 = REFDebounce + 1;
			button4 = 1;
		}
	}
}
Takto som ja spravil ovládanie LED a čítanie tlačidiel cez UART. Tlačidla sú trošku zložitejšie, lebo je tam potlačenie zákmitov.

Keď si naštudujete perifériu v datasheete a referenčnom manuáli, dá sa to zvládnuť. Jedna zákerná vec je keď má register nenulovú predvolenú hodnotu. Neraz sa mi stalo, že som pomocou |= dospel k neželanému výsledku. Zase priamo priradzovať hodnotu cez = tiež nie je vždy najmúdrejšie, ovplyvníte aj tie bity ktoré nechcete.

Datasheet: https://www.st.com/resource/en/datashee ... l031f4.pdf
Reference manual: https://www.st.com/content/ccc/resource ... 108282.pdf
0

Používateľov profilový obrázok
Tribec Zacks
Pokročilý člen
Pokročilý člen
Príspevky: 709
Dátum registrácie: 26 Jún 2010, 00:00
Bydlisko: Levice / Cork IRL
Vek: 41
Kontaktovať používateľa:

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa Tribec Zacks » 04 Jan 2020, 14:51

@bibibo,
mas pravdu na nete najdes podstatne viac prikladov okolo HAL. STM na to dost tlaci a vela ludi co s tym zacina preto skonci u HAL, HAL je hardware abstraction layer, skryva vsetko pod seba a tak pouzivas rovnake prikazy a konfiguraciu pre vsetky stm mcu, dan za to je vela zavislosti, dlha kompilacia, vacsi skompilovany kod a podla mojho nazoru aj prehladnost a horsia orientacia v tom co to vlastne robi. Ak preluskas par periferii a ich konfiguraciu (ak das priklad co chces dosiahnut, radi ti pomozeme) tak nebudes odkazany na priklady co najdes na nete. takto zoberes datasheet a nakonfigurujes vsetko presne ako ma byt do presne tvojho projektu, vysledok bude kus mensi a cistejsi kod co robi len to co naozaj ma. (ok ok, so zaciatku s trochou frustracie a mozno nevyhnutnou pomocou, pak to pojde same od seba)

btw ake IDE pouzivas na programovanie? mozno by sme ti vedeli pomoct so zakladnym projektom na nakonfigurovanie pll atd a dalej uz prides na to ze to nieje nic strasne. btw ked aj veci ako uart tx/rx preluskas a nakodis si vlastne fifo a podobne, tak si prejdes zaciatkami mcu vyvoja a zbytok ti pojde velmi lahko na akom kolvek mcu, ak zostanes pri HAL a netovych prikladoch, tak moze byt ze na ne budes odkazany a nikdy tak naozaj neporozumies co ten mcu naozaj robi, co treba kde povolit a ako ho presne pouzit cisto na to co potrebujes.


@maskrtnik, ja zvycajne riesim gpio (aj ine periferie) input cez nastavenie periodickeho dma transferu z gpio_in registru do sram a spustane timerom, potom v main loope iba citam sram co je podstatne rychlejsie bez zasahu mcu, funguje to tak k plnej spokojnosti bez dalsej sw filtracie, cista robota... (disco ma jednoduchy rc filter na tlacitku)
0
Kreativita a motivacia je to, co prinasa originalne napady a myslienky, disciplina je to, co ich dokaze zrealizovat.

bibibo
Pokročilý člen
Pokročilý člen
Príspevky: 625
Dátum registrácie: 05 Nov 2009, 00:00
Bydlisko: Bratislavský kraj

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa bibibo » 05 Jan 2020, 14:07

Problem bude, ze ja ten datasheet neviem citat. Neviem co mam hladat resp. co je naco. Ja mam zatial spravenu len testovaciu dosku kde mam STM32L011F4, 20 pin a GPS modul. GPS modul mam pripojeny na LPUART1 a USART2 na PC. V prvom kole chcem spravit, ze ked poslem z PC nejaky znak, napr. "L", tak zacne LPUART1 prijimat data z GPS a posle ich na USART2. Ten znak "L" by sa posielal kazdu minutu. Ak znak "L" nepride do minuty, tak sa cela komunikacia LPUART1 s GPS stopne a MCU by presiel do nejakeho Low Power modu. Prebudenie by bolo prerusenim na USART2 resp. prijatim nejakeho znaku.
Pouzivam Keil a pre prvotnu konfiguraciu pouzivam STM32CubeMX.
0

maskrtnik01
Ultimate člen
Ultimate člen
Príspevky: 2564
Dátum registrácie: 20 Júl 2010, 00:00
Bydlisko: okolie KE
Vek: 27

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa maskrtnik01 » 05 Jan 2020, 14:38

Pozrite si najprv ten seriál na joudove čo som napísal link. Je síce pre F4, ale na L0 to bude podobné. Ja som takto úspešne začal s F0.

Taktiež si môžete prezrieť zdroják čo som minule poslal.
0

bibibo
Pokročilý člen
Pokročilý člen
Príspevky: 625
Dátum registrácie: 05 Nov 2009, 00:00
Bydlisko: Bratislavský kraj

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa bibibo » 09 Jan 2020, 20:51

Nejako sa mi nedari. Ten serial na joudove.8u.cz pisu, ze je potrebne vzdy resetnut bus, ktory sa bude pouzivat. Kupil som knihu o STM32 a tam rovno povolia bus bez resetu. To je vsak momentalne jedno, protoze som to skusal akokolvek a proste mi to nefunguje. Dalej som sa docital, ze kazdy STM32 MCU ma uz default nastaveny nejaky zdroj hodin. Moj STM32L011F4 ma default MSI 2.097MHz. Ked som to spravne pochopil, tak ak mi staci ten default, tak nemusim nic nastavovat resp. nakodovat. Lenze v Keil je nejake nastavenie Clock frekvencie. Default som tam mal 12MHz co som zmenil na 2.097MHz. Netusim vsak, ci Keil vôbec nastavuje Sysclock, pretoze nikde nie je mozne nastavit ktory zdroj hodin sa ma pouzit. Tu je moj kod. Zatial trocha mixovany s HAL ale na skusku staci.

Kód: Vybrať všetko

RCC ->IOPRSTR |= RCC_IOPRSTR_GPIOBRST;
 RCC ->IOPRSTR &= ~RCC_IOPRSTR_GPIOBRST;
	
 RCC -> IOPENR |= RCC_IOPENR_GPIOBEN;
 	
 GPIOB -> MODER |= GPIO_MODER_MODE6_0;
 GPIOB ->OSPEEDR |= GPIO_OSPEEDER_OSPEED6_0;

Kód: Vybrať všetko

 while (1)
  {
    
    GPIOB->ODR |= GPIO_ODR_OD6;
		HAL_Delay (500);
		GPIOB->ODR &= ~GPIO_ODR_OD6;
		HAL_Delay (500);
		
   
  }
0

maskrtnik01
Ultimate člen
Ultimate člen
Príspevky: 2564
Dátum registrácie: 20 Júl 2010, 00:00
Bydlisko: okolie KE
Vek: 27

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa maskrtnik01 » 09 Jan 2020, 21:04

No ten MCU samozrejme musí byť taktovaný, inak by nefungoval. Takže nabootuje z nejakého predvoleného (Fx majú HSI), a potom je možné (nie nutné) zmeniť zdroj systémových hodín. Ako presne generuje súbory Keil vám nepoviem, nepoužívam ho.

Ohľadom toho resetu, teoreticky by periférie mali byť aj tak vyresetované. Hodiny im samozrejme musíte povoliť, inak ani nemá zmysel šahať na registre.

GPIO vyzerá v poriadku. Skúste ten kód krokovať, keď na nejakom riadku ostane vysieť, napíšte na ktorom.

EDIT: Aha, tu je ten pruser. Reset hodnota pre GPIOB_MODER je 0xFFFFFFFF, čiže analóg. Keď spravíte |=, nič už na tom nezmeníte.
To som spomínal, read-modify-write cez |= môže aj takto dopadnúť.

V RCC module na toto pozor, prepíšete aj to čo nechcete. Ale MODER môžete aj priamo zapísať želanú hodnotu:

Kód: Vybrať všetko

GPIOB->MODER = 
0

Používateľov profilový obrázok
Radus
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1497
Dátum registrácie: 27 Okt 2009, 00:00
Bydlisko: Prešov
Vek: 42

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa Radus » 09 Jan 2020, 22:31

Trochu prispejem, aj keď som len menej znalý. Pri std lib bolo nastavenie oscilátora a hodín v súbore system_stm32fxxx.c. Neviem ako je to v HAL, ale asi to bude podobné. V prostredí Keilu by som to nehľadal. Keď si potom volal funkciu System_init(), tak dôjde k nastaveniu hodín.
0

bibibo
Pokročilý člen
Pokročilý člen
Príspevky: 625
Dátum registrácie: 05 Nov 2009, 00:00
Bydlisko: Bratislavský kraj

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa bibibo » 09 Jan 2020, 22:56

No super. Ano, bolo to tou reset hodnotou GPIOB. Studovanie manual bude teda este na dlhe vecery.
Ano, aj to nastavenie hodin je v tom subore ako pise Radus.
Yatial dakujem vsetkym. Cez vikend sa skusim popasovat s USART.
0

bibibo
Pokročilý člen
Pokročilý člen
Príspevky: 625
Dátum registrácie: 05 Nov 2009, 00:00
Bydlisko: Bratislavský kraj

Re: STM32 HAL - vysvetlenie kodu

Príspevok od používateľa bibibo » 22 Jan 2020, 20:46

No skusam to programovanie v CMSI a nejako sa mi nedari. Skusam jednoduchy kod a to poslat string na USART2, ale nejako sa mi nedari. Neviem kde robim chybu.

Kód: Vybrať všetko

int main(void)
{
 char message[] = "Ahoj\r\n";
 int i;


 RCC -> IOPENR = 0x00000003;
 RCC -> APB1ENR = 0x60000;

 GPIOA -> MODER = 0xEBEBFCFF;
 GPIOA -> OSPEEDR = 0x3c0000;
	

 HAL_Init();
	
 UART2_init();

 while (1)
  {
    
		for(i = 0;i< 6;i++)
		{
			
			USART_write(message[i]);
			HAL_Delay(5);
			
			
			
		}
		
		
		
    
  }
  
}


void USART_write(int ch)
	
{
	while (!(USART2-> ISR & 0x0080)){}
		USART2->TDR = ch;
		
	
	
}

void UART2_init(void)
{
  GPIOA ->AFR[1] = 0x440;
	
  USART2 ->BRR = 0xD0;
  USART2 ->CR1 = 0xc;
  USART2 ->CR1 = 0x1;
	
}


0

Napísať odpoveď
  • Podobné témy
    Odpovedí
    Zobrazení
    Posledný príspevok