[AVR GCC] USART Zpracovaní řetězce

Začal jsem se zabývat USARTem, protože potřebuju přijímat příkazy z PC (ne data) a rád bych byl nasměrován, jak se řeší tenhle problém.
Příkazy jsou na způsob jednoho písmene nebo řetězce obsahující číselnou hodnotu, kterou je třeba extrahovat. Takže např. něco na způsob “A” a mcu udělá něco nebo “XXX 123” a mcu udělá něco v závislosti na číselné hodnotě “123”.
Zprovoznil jsem si jednoduchou aplikaci na echo přes přerušení USART a když jsem začal googlit po informacích a tutoriálech, tak většinou právě končili tím, co mám už zprovozněný a funkční.
Našel jsem pěknou knihovnu homepage.hispeed.ch/peterfleury/avr-software.html od Petra Fleuryho, která práci s příjmem znaku nebo odeslání znaku či řetězce automatizuje…využívá také přerušení.
Napadá mě tedy si udělat nějaký buffer, do kterého bych načítal přijaté znaky a jakmile by vzniklý řetězec souhlasili s nějakým příkazem, tak se vykoná příslušná rutina a buffer se vyprázdní. Dá se to řešit takhle nebo je něco efektivnějšího/jednoduššího?

Implementuj si nejaky zmysluplny protokol.
T.j.
vytvor si v mcu pole bajtov, naprikla 256 alebo 64 alebo aj 1024 to je ganz egal.
Sprav si protokol, ktory vie do tohto pola vlozit X bajtov od Y-tej adresy (subadresy), alebo ich z tej subadresy vycitat. Protokol si sprav tak, aby hned na zaciatku bola adresa stanice (bud hned - MODBUS, alebo po nejakom uvodnom znaku). Sprava sa zvatsi len o jeden bajt, ale v buducnosti to ocenis.

Priklad pre ASCII protokol “mAAPPSSSSKK<DD…DD>CSCS0x0d”
alebo pre binarny protokol “APSSK<D…D>CS”

kde A je adresa zaraidenia, AA je ASCII interpretacia bajtu adresy zaraidenia

P je prikaz, typicky RD alebo WR, ine prakticky nepotrebujes, takze si mozes protokol zjednodusit tak, ze prikaz RD alebo WR moze byt sucastou SS

SS - subadresa 0-65535, alebo 0-32767 ak bude najvyssi bit prikaz RD alebo WR

K - kolko bajtov chces prenasat z/do zariadenia

“m” a “0x0d” je uvodny a koncovy bajt. “m” je napriklad ako ze vysiela Master, v odpovedi moze byt prve pismenko napriklad : “s” ako Slave. Ale to je na lubovoli.

CS je kontrolna suma. Iba bláhoví ľudia si namýšľajp že práve ich správa dorazí bez chyby.

Ty sa rozhodni, na aku pamatovu bunku v ramci tohto pola budes zapisovat nieco, co bude mcu interpretovat ako prikaz.

Z tohto poľa si možeš načítavať rôzne stavy.

Komunikovať s mcu systémom “XXX 123” nie je moc praktocké a po čase Ťa to aj tak prejde. :slight_smile:

Držím palce.

P.S. Skrátka nejakému protokolu sa tak či tak časom nevyhneš, tak prečo sa trápiť a nenasadiť ho hneď. Môže to byť napríklad rozšírený MODBUS, aj keď tie príkazy typu coil by som vynechal. Stačí naimplementovať iba rd a wr s vnútornými registrami.

:open_mouth:
ale já jsem psal, že neřeším “data” ale jednoduché příkazy. To co si mi popsal sice využiju, ale ne pro problém, co řeším teď. Nemluvě o velikosti programu pro implementaci tohoto protokolu, když mi pomalu dochází programová paměť a řeším fakt jenom pár pevných příkazů. :smiley:
Abych byl konkrétnější…
Pomocí mcu pozicuju servomotor a když přijde na USART “L” nebo “R” tak se servo točí daným směrem, přijde “S” servo se zastaví, když přijde “Pxxx” (kde xxx je třiciferný číslo), tak se servo nastaví do dané pozice. Příslušné rutiny už mám napsané, takže řeším jenom jak zpracovat příjem USARTu a podle přijatého řetězce zavolat příslušnou rutinu.

nevím jestli ti to teda pomůže ale ve škole sme dělali v asembleru na usart tohle: je to jednoduchej RS klopnej obvod je to v assembleru ale v céčku to je skoro stejný, každopádně princip na porovnávání, to by ti stačilo pro ty základní příkazy jako L,P,S, a na tu přesnou pozici už to bude muset bejt tak jak říkáš, zachytávat číselný znaky do zásobníku a pak jak příjde třetí znak podle toho to nastavit na tu pozici…

[code]start:
sbis PINA,0 ; testuje stisk tlacitka PA0
rcall stisk0

	sbic	UCSRA,7					; testuje prijmuty bajt pres UART
	rcall	prijem1
		
	rjmp	start					; zpet na start

stisk0: ldi R16,‘f’
out UDR,R16 ; odesle data
st0x: sbis UCSRA,6 ; testuje odeslany bajt
rjmp st0x

	rcall	DEL1s
	ret

prijem1:in R16,UDR ; prijem znaku
cpi R16,‘s’ ; pokud prijme s -> nastavi LED PA0
brne pr1
cbi PORTC,0
ret
pr1: cpi R16,‘r’ ; pokud prijme r -> nastavi LED PA1
brne pr2
sbi PORTC,0
pr2: ret
[/code]

Zdravím,

no ak mas tak malo pamate, tak potom aj prikazy R, L , S a XXX su na dekodovanie dost komplikovane.

Co Ti brani poslat do MCU jeden bajt a ak ma hodnotu 0 potom servo bude stat, 1 bude sa stale tocit do lava, 2 bude sa stale tocit do prava a od 3 do 255 bude na presne definovanej polohe od 0 - 252. Ak Ti je 253 poloh na urcenie polohy malo, tak si mozes do mcu poslat bajty dva. :slight_smile:

protože ten protokol je pevně definovaný pro aplikaci…
konkrétně se jedná o polysat.calpoly.edu/download/earthstation/documents/gs-232a.pdf, z kterýho chci realizovat jenom některé.

Jinak ten postup bude asi tak, jak jsem psal v prvním příspěvku.

:arrow_right: administrator: přiloženy externí soubory
gs-232a.pdf (292 KB)

Hlavne si ujasni, ako rozlíšiš začiatok a koniec správy. Hlavne koniec je kritický. Začiatok spraávy je už len prvý znak po konci predchádzajúcej.
Možnosti sú:

  1. nejaký špeci koncový znak

  2. timeout od poslaného posledného bajtu. MODBUS to napríklad má ako čas rovnajúci sa dĺžke 3,5 násobku bajtu pri danej prenosovej rýchlosti.

no podle popisu protokolu (polysat.calpoly.edu/download/ear … s-232a.pdf) se jedná o 0x0D, kterým je ukončený každej příkaz (ať směrem k mcu nebo ven)