Strana 8 z 10

Re: začiatočník v assembleri

Napísané: 06 Feb 2014, 20:37
od používateľa jaromir
Lebo 0xFF - 0x00 je 0xFF, alebo 0x00 - 0xFF je 0x01 (neviem co od coho odpocitavas).
Rozdiel dvoch nerovnakych cisel nikdy nemoze byt nula.

Re: začiatočník v assembleri

Napísané: 06 Feb 2014, 22:41
od používateľa bebeno28
Jaromír ano to je pravda čo píše. To chápem, že to tak je, ALE už som to vyriešil.

Na samí začiatok pre to ako čaká na zadávanie hesla, som napísal rutinu ktorá do registrov do ktorých sa ukladájú zadané čísla z kláves, najprv dá číslo 0xFF a až potom ide na zapisovanie toho čo sa stlačilo, a to zanamená, že ak zadá iba 4 miestny kód tak v ostatných bude 0xFF

Neviem čo som robil dovtedy zle, že mi to naprd porovnávalo, ale už to ide. Možno na to niekedy prídem :-)

ďakujem za rady, hlavne MiloPS3 a trpezlivosť.

v prílohe celý ASM ( to čo mám zatial napísané ) ak by to ešte niekoho zaujímalo.

Ešte raz ďakujem

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 12:57
od používateľa DJ_Edo
Zdravim pani, konecne mam trocha volneho casu, a tak sa ucim ASM pre ATmega16-ku.
Mam nasledujuci problem: Pomocou prerusenia z INT0 cez tlacitko chcem cez instrukciu ROL posuvat LEDky na porte C. Upravujem tento kod http://www.kvetakov.net/clanky/File/AVR/Preruseni.pdf
Moj upraveny kod je tu, rozumiem takmer vsetkemu, ale neviem spravit to rolovanie v hlavnej casti CYK.
Od rana sa s tym mordujem... :cry: , diky za rady.

.NOLIST
.INCLUDE "m16def.inc"
.LIST

.DEF REG=R16
// .EQU LED_DIR=DDRC
// .EQU LED_DAT=PORTC


.CSEG
.ORG 0
RJMP START
; sem skoci program pri preruseni INT0
.ORG INT0Addr
RJMP INT_ROUTINE

START:
LDI REG,$FF
OUT DDRC,REG
SER REG
OUT PORTC,REG
LDI REG,LOW(RAMEND)
OUT SPL,REG
LDI REG,HIGH(RAMEND)
OUT SPH,REG
; preruseni od sestupne hrany
LDI REG,1<<ISC01
OUT MCUCR,REG
; povoleni preruseni
LDI REG,1<<INT0
OUT GICR,REG
SEI

CYK:
IN REG,PORTC
ROR REG
BRCC CYK
ROR REG
BRCS CYK

// RJMP PC

INT_ROUTINE:
OUT PORTC,REG
RETI

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 13:19
od používateľa wwlado

Kód: Vybrať všetko


CYK:
IN REG,PORTC
ROR REG
BRCC CYK <-- Preco chces skocit naspat??? ved sa tu zacyklis
ROR REG
BRCS CYK <- Deto

Skus pouzit T (jeden bit pouzity na tie ucely)

Kód: Vybrať všetko

IN  Reg, PORTC
BST Reg, 0 // Reg.0 -> T
ROR Reg // Posunie vsetky bity
BLD Reg, 7 // Reg.7 <- T 
OUT PORTC, Reg
Potom si osetri INT0 nejakym casovacom

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 14:24
od používateľa DJ_Edo
Skusal som to takto, nefunguje mi to, vacsinou ma to hadze na RJMP START a niekedy spravi nejaky posun na porte C, podla toho kedy chyti impulz ked kliknem na INT0 (PD2) v simulatore.

Potom si osetri INT0 nejakym casovacom, toto kvoli zakmitom z tlacitka? Tam este nie som...

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 15:08
od používateľa Hinsi
Protože ti ten kód vyběhne až do ryti lipovej, kde nemáš žádnej kód. Doběhneš na SEI, pak se udělá to cosi za návěštím CYK, pak to vleze do rutiny přerušení, aniž by přerušení vzniklo, provede RETI, podteče zásobník a program je mimo kód a běží po prázdné FLASH. :)

//tolik asi k vysvětlení toho varování o chybném opcode, a zdánlivě záhadném chování programu.

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 15:28
od používateľa wwlado

Kód: Vybrať všetko


Start:
:
:
SEI
Cyklus:
 ; prazny cyklus. Program caka na prerusenie
RJMP Cyklus

; obsluha INT
Int_routine:
 CLI
 IN ...
:
 OUT ...
 SEI
 RETI
Ano proti zkmytom. Ak budes pouzivat este nejake ine instrukcie mimo tej rutiny, je dobre na zaciatku rutiny ulozit SREG a vsetky pouzivane registre do zasobnika.

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 15:29
od používateľa DJ_Edo
Doplnil som to takto, no nefunguje to, na INT0 reaguje ale nic sa neroluje...

CYK:
IN REG,PORTC
BST Reg, 0 // Reg.0 -> T
ROR Reg // Posunie vsetky bity
BLD Reg, 7 // Reg.7 <- T
RJMP CYK

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 15:44
od používateľa wwlado

Kód: Vybrať všetko

.NOLIST
.INCLUDE "m16def.inc"
.LIST

.DEF	REG=R16

.CSEG
.ORG 0
 RJMP	START
; sem skoci program pri preruseni INT0
.ORG	INT0Addr
 RJMP	INT_ROUTINE

START:
 LDI	 REG,$FF
 OUT	 DDRC,REG
 SER	 REG
 OUT	 PORTC,REG
 LDI	 REG,LOW(RAMEND)
 OUT	 SPL,REG
 LDI	 REG,HIGH(RAMEND)
 OUT	 SPH,REG
; preruseni od sestupne hrany
 LDI	 REG,1<<ISC01
 OUT	 MCUCR,REG
; povoleni preruseni
 LDI	 REG,1<<INT0
 OUT	 GICR,REG
 SEI

Cyklus:
 RJMP Cyklus

INT_ROUTINE:

 ; Ulozenie pouzivaneho registra a statoveho registra
 Push Reg
 In   Reg, SREG
 Push Reg
 Cli 

 ; Posuv portu
 IN	 	REG,PORTC
 BST 	Reg, 0 ; Reg.0 -> T
 ROR 	Reg    ; Posunie vsetky bity
 BLD 	Reg, 7 ; Reg.7 <- T
 OUT	PORTC,REG
 
 ; vytiahnutie ulozenych udajov
 Pop  Reg
 Out  SREG, Reg
 Pop Reg 

RETI

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 16:18
od používateľa DJ_Edo
wwlado, nic sa neroluje...
Toto mozno pomoze:

po nacitani PORTC ma R16 hodnotu 0xFF
po ROR R16=0x7F
po BLD opat 0xFF
ak dam ROL, roluje sa to vselijako, len nie tak ako chcem

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 16:54
od používateľa wwlado
To preto, ze rolujes FF. Roluj 01. Alebo 80.

Vysvetlim ti to.
FF je 0b11111111 ak tie jednicky budes rolovat ROR tak vlozi do prvej C a poslednu vlozi do C. Teda ked C = 0 potom po ROR dostanes 0b01111111 co je 7F. Kedze my sme si ulozili prvy bit do T tak ho na konci vratime na 7 bit. Na koniec. Teda mas zasa 0b11111111.

Ak by si roloval 0b00010001 tak by si videl, ze tu prvu jednotku (0.bit) vlozi do T, posunie na 0b00001000 a nakoniec doplni T na posledne miesto. 0b10001000

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 17:55
od používateľa DJ_Edo
OK diky, uz to funguje, upravil pridal som tam $01:

Kód: Vybrať všetko

.NOLIST
.INCLUDE "m16def.inc"
.LIST

.DEF   REG=R16

.CSEG
.ORG 0
RJMP   START
; sem skoci program pri preruseni INT0
.ORG   INT0Addr
RJMP   INT_ROUTINE

START:
LDI    REG,$FF
OUT    DDRC,REG
SER    REG
OUT    PORTC,REG
LDI    REG,LOW(RAMEND)
OUT    SPL,REG
LDI    REG,HIGH(RAMEND)
OUT    SPH,REG
; preruseni od sestupne hrany
LDI    REG,1<<ISC01
OUT    MCUCR,REG
; povoleni preruseni
LDI    REG,1<<INT0
OUT    GICR,REG
LDI    REG,$01
OUT    PORTC,REG
SEI

Cyklus:
RJMP Cyklus

INT_ROUTINE:

; Ulozenie pouzivaneho registra a statoveho registra
Push Reg
In   Reg, SREG
Push Reg
Cli

; Posuv portu
IN     REG,PORTC
BST    Reg, 0 ; Reg.0 -> T
ROR    Reg    ; Posunie vsetky bity
BLD    Reg, 7 ; Reg.7 <- T
OUT    PORTC,REG

; vytiahnutie ulozenych udajov
Pop  Reg
Out  SREG, Reg
Pop Reg

RETI
Idem preskumat tu tvoju cast, aby som pochopil ako to funguje.
Ale mal by som este par otazok:
1. Ako to mam upravit, ak chcem aby sa obratil smer posuvania diod, ked to pride na koniec?
2. Ako to mam upravit (dajme tomu tento jednoduchy priklad s jednym smerom posuvania), tak aby v obsluhe prerusenia bolo co najmenej kodu? Niekde som cital, ze najlepsie je vsetko co je potrebne si dopredu vypocitat v hlavnom programe a v preruseni mat len to najnutnejsie.
Je to mozne spravit tak ako som to povodne chcel, ze v preruseni by bolo len OUT PORTC,REG, popripade este nieco co je nutne? Cim je v obsluhe prerusenia menej kodu, tak tym lepsie, nie?
3. Nie je mi presne jasna funkcia posunu << V jednej knihe sa pise ze: << posunie lavy operand o tolko bitov vlavo, kolko je urcene pravym operandom. No a v mojom kode v LDI REG,1<<ISC01 sa nic neposuva ale do REG zapise hodnotu pozicie ISC01 v MCUCR. Odkial simulator vie tu hodnotu vycitat, ked MCUCR som napisal az v dalsom kroku? Mam v tom trocha hokej. Mozes mi to podrobnejsie vysvetlit? Kde vsake a v akych pripadoch sa to pouziva? Ma operator posunu << (alebo>>) aj nejake ine nestandardne alebo malo zname vyuzitie pri asm pre atmely? Chcem vediet co ma este prekvapi :lol: .
4. Nevies nahodou, kde by som nasiel nejake jednoduche priklady na rozne rotacie diod na jednom porte. Nieco ako precvicovanie prerusovani, roznych skokov, casovacom... ale pre jednoduchy vystup na port na 8 diod.
Lepsie by som sa naucil programovat, pretoze ci ti dioda svieti slebo nie zistis hned, proste hned vidim ci mi kod funguje alebo nie :D .

Este ma napadlo:
5. Ako by sa to riesilo pomocou podmienenych skokov (branchs)?
6. Ako by sa to riesilo pomocou preskokov (skips)?
7. Dalo by sa to riesit este rafinovanejsim/elegantnejsim sposobom?
8. Dalsie moznosti?
Chcem si vyskusat to rolovanie co najroznejsimi sposobmi, aby som sa nieco naucil :D

Re: začiatočník v assembleri

Napísané: 23 Apr 2014, 19:18
od používateľa wwlado
Vecer ti odpisem na vsetky otazky. Teraz aspon na zopar, kedze sa venujem malemu.
<< je logicky posuv pre kompiler, nieje to instrukcia. Teda ked napises 1<<0 je vlasne jednotka na nultom bite. Teda 0b00000001. 1<<7 je teda 0b10000000
Teda ked teraz dristnem: ze AEN je 2 tak ked napises 1<<AEN je ako keby si napisal 0b00000100. Dalsim znamienkom s tym spetym je |. Jedna sa o logicky sucet OR. Teda ak AF je napriklad 1 tak vlasne
1<<AEN | 1<<AF je 0b00000100 OR 0b00000010 = 0b00000110
Ak napises 0<<AEN tak na to miesto dosadi nulu. Kedze tam nula uz je bez toho, aby si nieco pisal, tak to skor sluzi ako poznamka programatora.


Je lepsie robit veci v hlavnej slucke a menej v preruseni. Ale to sa tvojho programu netyka. Skor, ked ide o stovky instrukcii v preruseni, aby zbytocne nezdrzoval ine prerusenie.
Ten tvoj kod v preruseni je mensi, ako jedna prazdna procedura v Cecku. Pri volani procedury v C sa pusjnu 16 registre a dva krat za sebou vyvola CLI. Takze prazna procedura ma okolo 38 instrukcii. Nevravim, ze vsetky kompilatori to tak robia, no ten co som rozbalil cez Disasembler to tak mali.
Ti tam mas menej.teda sa tym nemusis zaoberat.


SBRC, SBRS, - preskoci instrukciu, ak nieje/je bit v registry nastaveny.
Teda ak v REG bude na nultom bite jednotka, tak nech odskoci obsluzit najaky podprogram.
SBRC REG, 0 ; ak je na nultom bite npreskoc instrukciu pre obsluhu podprogramu
RCALL Podprogram
SBIC, SBIS - to iste len s portami teda ak stlacim tlacitko, skoc na podprogram ( tlacitko oproti GND)
SBIS PINC, 0 ; tlacitko na PCO

Re: začiatočník v assembleri

Napísané: 24 Apr 2014, 11:27
od používateľa wwlado
BRxx podmienene prikazy mozu odkazat zhriba o 60 instrukcii (64 slov, ale niektore instrukcie maju 2 slova)
instrukcia porovnavania CP, CPI ti vykona porovnanie a zapise do stavoveho slova vysledok. niektore instrukcie napr DEC tiez zapisuju konecny status do statoveho registra. napr.
DEC Reg ; odpocita z reg jednu
BREQ Reg_JeNula
Ked po odpocitani bude v Reg nula, zdvihne sa blajka Z v stavovom registru.
Vlajka Z sa dvihne aj vtedy, ked pri CP/CPI nastane zhoda. teda porovnavane cisla maju rovnaku hodnotu.
Stiahni si Instruction Set AVR. yam je to pekne popisane.
Tak by som ho riesilja. Len nesies ukladat SREG, lebo si uklada do vlajky T smer.

Re: začiatočník v assembleri

Napísané: 24 Apr 2014, 18:04
od používateľa wwlado
Nieco na precitanie

Ak by si chcel nieco potreboval, kludne sa ozvy cez SS. Inac tu su nejake kniznice v ASM, ale pre AVRU. Stale ich vylepsujem. ale na tej stranke su este stare. No mozes tam najst, ako na casovac, AD prevodnik....
http://www.wwlado.szm.com/dirlib.html

Re: začiatočník v assembleri

Napísané: 24 Apr 2014, 19:01
od používateľa DJ_Edo
Diky, popozeram vsetko co si sem dal, to ATmega-aplikacie.pdf vyzera dobre. Ja vacsinou nemam problem pochopit program ak pochopim vyznam instrukcii a ked si to mozem odkrokovat v avrstudiu. Len potrebujem dostatocny pocet jednoduchych prikladov na pochopenie ako sa pise podprogram, prerusenia, skoky preskoky... V hlave si viem povedat postup ako by to asi malo fungovat, ale ked mam sam napisat program tak sa stracam, lebo neviem akymi instrukciami a ako ich poskladat aby som dosiahol svoj ciel. Stracam sa aj preto lebo uP je pre mna zatial dost zlozity "stroj" nie len kvoli 130 instrukciam ale hlavne kvoli velkemu mnozstvu sposobov ako dany ciel dosiahnut. Preto potrebujem co najviac jednoduchych prikladov, ktore budu robit uplne to iste, ale vysledok bude pokazdym dosiahnuty inym sposobom. Tak si to viem odkorovat a porovnat to a naucit sa programovat. Z datasheetu sa programovat nenaucim, pretoze nevidim ako sa to robi...

Takze zatial diky, vsetko si precitam, ak sa niekde zaseknem tak sa Ti ozvem.
DJ_Edo.

Re: začiatočník v assembleri

Napísané: 25 Apr 2014, 19:04
od používateľa DJ_Edo
No tak dneska som sa s tym opat trocha hral, aby som sa to pokusil spravit podla svojej predstavy, teda dopredu si vypocitat stav lediek, ktore v preruseni od INT0, budem posielat na vystup.
Ciastocne sa mi to aj podarilo ale vobec to nie je koser, lebo tie instrukcie v preruseni na ulozenie SREG a REG mi premazu Carry bit, ktory v hlavnom cykle kontrolujem. Funguje to len ked odstranim PUSH a POP, co nie je dobre.
Takze ako sa taketo nieco riesi? Chcem to urobit podobne ako teraz testovanim nejakeho bitu v SREG aby to mal vystup uz dopredu pripraveny ked pride prerusenie.
Takze ako to urobit?

Kód: Vybrať všetko

.NOLIST
.INCLUDE "m16def.inc"
.LIST

.DEF   REG=R16

.CSEG
.ORG 0
RJMP   START
; sem skoci program pri preruseni INT0
.ORG   INT0Addr
RJMP   INT_ROUTINE

START:
LDI    REG,$FF
OUT    DDRC,REG
SER    REG
OUT    PORTC,REG
LDI    REG,LOW(RAMEND)
OUT    SPL,REG
LDI    REG,HIGH(RAMEND)
OUT    SPH,REG
; preruseni od sestupne hrany
LDI    REG,1<<ISC01
OUT    MCUCR,REG
; povoleni preruseni
LDI    REG,1<<INT0
OUT    GICR,REG
LDI    REG,	$01  // alebo 0x01 co je jedno a to iste HEXa cislo
OUT    PORTC,REG
LDI	   R17, $01
LDI	   R18, $FF
SEI


Cyklus:
// CLI
BRCS Cyklus
IN REG, PORTC
ROL REG
ADD R18, R17
LDI	   R18, $FF
BRCS Cyklus

// SEI

INT_ROUTINE:

; Ulozenie pouzivaneho registra a statoveho registra
//Push Reg		// pouzivany register R16
//In   Reg, SREG	// Status Register
//Push Reg

; Posuv portu
OUT    PORTC,REG

; vytiahnutie ulozenych udajov
//Pop  Reg
//Out  SREG, Reg
CLC

//Pop  Reg
RETI

Re: začiatočník v assembleri

Napísané: 25 Apr 2014, 19:53
od používateľa peterple
Tvoja predstava vysielania údaja v prerušení na port je úplne chybná. V tom programe je ale opäť ten problém že z hlavného programu vbehneš do prerušovacej rutiny a potom keď urobíš RETI tak sa program vymkne kontrole (skočí na náhodnú adresu). Síce to už nie je tak celkom evidentné ako si to mal v tom prvom kóde čo si tu poslal ale stále je to ten istý problém.
Asi sa snažíš o to čo si písal v nejakom príspevku dávnejšie. Tak ti k tomu niečo napíšem.

Re: začiatočník v assembleri

Napísané: 25 Apr 2014, 20:06
od používateľa DJ_Edo
Zatial sa ASM len ucim, tak mi porad ako to ma byt spravne.
To posielanie udajov na port v preruseni mi poradil wwlado takto:

; obsluha INT
Int_routine:
CLI
IN ...
:
OUT ...
SEI
RETI

Re: začiatočník v assembleri

Napísané: 25 Apr 2014, 20:12
od používateľa peterple
DJ_Edo napísal: Ale mal by som este par otazok:
1. Ako to mam upravit, ak chcem aby sa obratil smer posuvania diod, ked to pride na koniec?
2. Ako to mam upravit (dajme tomu tento jednoduchy priklad s jednym smerom posuvania), tak aby v obsluhe prerusenia bolo co najmenej kodu? Niekde som cital, ze najlepsie je vsetko co je potrebne si dopredu vypocitat v hlavnom programe a v preruseni mat len to najnutnejsie.
Je to mozne spravit tak ako som to povodne chcel, ze v preruseni by bolo len OUT PORTC,REG, popripade este nieco co je nutne? Cim je v obsluhe prerusenia menej kodu, tak tym lepsie, nie?
3. Nie je mi presne jasna funkcia posunu << V jednej knihe sa pise ze: << posunie lavy operand o tolko bitov vlavo, kolko je urcene pravym operandom. No a v mojom kode v LDI REG,1<<ISC01 sa nic neposuva ale do REG zapise hodnotu pozicie ISC01 v MCUCR. Odkial simulator vie tu hodnotu vycitat, ked MCUCR som napisal az v dalsom kroku? Mam v tom trocha hokej. Mozes mi to podrobnejsie vysvetlit? Kde vsake a v akych pripadoch sa to pouziva? Ma operator posunu << (alebo>>) aj nejake ine nestandardne alebo malo zname vyuzitie pri asm pre atmely? Chcem vediet co ma este prekvapi :lol: .
4. Nevies nahodou, kde by som nasiel nejake jednoduche priklady na rozne rotacie diod na jednom porte. Nieco ako precvicovanie prerusovani, roznych skokov, casovacom... ale pre jednoduchy vystup na port na 8 diod.
Lepsie by som sa naucil programovat, pretoze ci ti dioda svieti slebo nie zistis hned, proste hned vidim ci mi kod funguje alebo nie :D .

Este ma napadlo:
5. Ako by sa to riesilo pomocou podmienenych skokov (branchs)?
6. Ako by sa to riesilo pomocou preskokov (skips)?
7. Dalo by sa to riesit este rafinovanejsim/elegantnejsim sposobom?
8. Dalsie moznosti?
Chcem si vyskusat to rolovanie co najroznejsimi sposobmi, aby som sa nieco naucil :D
1. musiš si nejaký register vybrať za počítadlo. Tam musíš počítať koľko si už urobil rotácií a podľa toho vetviť program tak aby raz rotoval doľava a potom doprava. Tam ale budeš okamžite konfrontovaný s problémom zákmitov tlačidla.
2. To sa rieši trošku inak než si si to vydedukoval. Buď sa všetko stihne urobiť v prerušení, čo je tvoj prípad. Stovky inštrukcií nebýva až tak veľký problém. Inak sa to robí tak že v prerušení sa nastaví nejaký bit napr. do log. 1. V hlavnom programe potom ten bit kontroľuješ a keď je jednotkový vieš že nastal ten zaujímavý jav prerušenia, tak ho oblsúžiš vynuluješ ten bit a je to znova pripravené na nové kolo. Takému bitu sa potom hovorí príznak alebo vlajka (z ang flag).
3. Už ti vysvetľoval vlado takže len stručne: Všetko čo si si o tom naštudoval je pravda. Len ten výraz počíta prekladač pri preklade programu a nie procesor pri behu. Podobne keď napíšeš LDI REG, 1+2, tak sa ti tam nedajú nejaké inštrukcie na spočítanie dvoch čísel ale prekladač ten výraz vypočíta a výsledok sa použije ako druhý operand v LDI inštrukcii.
4. na internete
5.myslíš rotácia? to sa podmienými skokmi nedá.
6. detto.
7. Nie nedalo. Vlado je znalý veci a elegantnejšie (kratšie) sa to už urobiť nedá.
8. Nahradiť rotácie? Neviem o žiadnom spôsobe. Alebo si myslel to blikotanie ledkami?