Konvention AVR, mm

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Konvention AVR, mm

Inlägg av övrigt »

Tjena.

Detta blir mitt första inlägg på detta forum. Dock är jag sedan tidigare flitig användare av sökfunktionen på forumet och jag har hittills haft stor nytta av det. Baserat på frågor andra ställt här bestämde jag mig för att böja lära mig använda mikrokontrollers. Valet föll på ett STK500 tillsammans med en ATtiny2313 och en ATmega16 att prova lite med, också det från rekommendationer givna här.

Nu har jag hunnit använda detta ett par veckor och därför samlat på mig ett par frågor som jag inte hittar svar på. För det första, finns där någon programmeringskonvention för AVR Atmel? Tex att en subrutin endast får ändra vissa register och inte några andra osv? En sådan är ju faktiskt inte bara bra för att hjälpa mellan användare utan hjälper även en användare (läs: mig) att strukturera upp sina program, speciellt då de är lite längre och registren inte räcker till för alla funktioner.

Sedan har jag lite funderingar kring detta med att vissa delar av minnet bara tål att raderas och återskrivas ett visst ändligt antal gånger. När behöver man tänka på detta? Kan registren och portarna skrivas till hur många gånger som helst? Det längst hållande verkar vara EEPROM minnet, som enligt databladet typiskt ska hålla för 100 000 skrivningar. Men så många skrivningar går ju ganska snabbt om CPUn är klockad till 4MHz och man uppdaterar något kanske ”bara” var 100e cykel, kanske gör en push+pop. Nått man behöver tänka på när man skriver sina program?

Slutligen undrar jag hur man får bort IC-kretsen (ATmega8515L) som följde med STK500 ur hållaren om man vill prova programmera en annan? Den verkar sitta stenhårt och kortet krasar och knakar ordentligt när jag försöker så hårt jag vågar, dock utan att rubba den. Finns där speciella pincetter el dyl för det?

Verkligen ett grymt forum detta och hade varit kul ifall någon har svar även på mina frågor!

Mvh
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Inlägg av Micke_s »

Jag programmerar bara i c (99% i alla fall) avr-gcc så den sköter registrerna åt en. Men annars så finns det en c standard hur register används i asm nivå.

Minnets antal skrivningar behöver du bara tänka på om du uppdaterar ofta.
Typ klocka i eeprom:et eller volymen sparas vid varje ändring (phillips).
Detta gäller bara EEPROm och FLASH. Ram har obegränsat antal skrivningar.


För ta loss den brukar en skruvmejsel mellan sockeln och chippet funka.
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Inlägg av Swech »

Ram minnet som dina portar och variabler finns i tål att skrivas till
oändligt massa gånger... (kanske inte i all oändlighet men tillräckligt
mycket för att man inte behöver tänka på detta)

EEprom har man för att lagra t.ex. mätdata eller kalibreringar som skall
finnas kvar även då strömmen försvinner,
Detta minne tål minst 100.000 skrivningar... Loggar man ofta
och mycket måste man ta med detta i beräkning.

Flash - här finns själva programkoden. Oftast så skriver man sitt program,
debuggar och ändrar tills man tillslut får det att funka bra. Därefter
ändrar man oftast inte innehållet. Därav garanteras "endast" ca 10.000
omprogrammeringar. Men har man inte fått sitt program att funka på
10.000 försök så bör man ge upp ändå ;)

Register:
R26,27,28,29,30,31 -> dessa kallas även x,y,z och skall därför endast
användas till x,y,z... (om man inte håller tungan rätt i mun)

r0 används vid vissa processorer vid LPM instruktioner och bör
därför ses som ett temporärregister.
r1-r15 är begränsade för vissa instruktioner så oftast så använder man
inte dessa direkt flitigt.
r16 är ett favoritregister för temporära saker.

Själv skapar jag alltid ett register som alltid innehåller 0 samt
ett som innehåller -1 , t.ex. r2,r3

Vid beräkning av index med Z så brukar man:
ldi zl,low(tabell*2)
ldi zh,high(tabell*2)
add zl,r16
adc zh,r2 ;r2 är = 0

ADC kan alltså bara arbeta med register så har man ett som innehåller
just 0 så blir koden lite kompaktare..


Swech
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Inlägg av jesse »

jag har funderat på samma sak nu när mina programsnuttar ska sättas ihop till en enorm apparat

(timers, 2 st uart, ascii-display, ad-omvandlare, polling av tangenter, multiplikation och division med div. kalibreringsvärden, bläddring i menyer till displayen, loggning av data i eeprom, ljudgenerator till larm samt PWM till displayens LED bakgrundsljus, kalibrering av intern RC-oscillator mot yttre signaler mm... Puh! :x )

men hittills har det funkat bra med olika subrutiner etc. genom att jag noga anger i beskrivningen av varje rutin vilka register som är input och output och vilka register som förstörs under processen...
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Inlägg av Swech »

För att svara på jesses inlägg Spara eller inte spara..

Det finns två vägar vad gäller subrutiner.
1. Subrutinen sparar (push) alla register som den förstör. anropande
rutin behöver inte vara orolig..
2 Anropande rutin sparar vad den kommer att behöva ha kvar då subrutinen är klar.

Nr. 1 kan bli ineffektiv och minsta rutin som avviker från detta kan innebära
svårhittade buggar. så personligen föredrar jag nr 2 men det är
individuellt vad man tycker.

Swech
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Inlägg av jesse »

jMin variant är väl en blandning av 1 och 2 i så fall. Skulle en subrutin förstöra väldigt många register kanske den sparar med push/pop för att städa lite efter sig, men annars måste jag kolla beskrivningen på respektive rutin för att se vad jag måste vara rädd om... Är det en liten rutin som bara använder ett par register och som kanske anropas ofta så känns det lite ineffektivt att hålla på med en massa push och poppande... Om jag vet att det är r16 och r17 som ändrar värde så får jag se till att bevara data i de andra registren i huvudrutinen...

Jag har ännu inte gjort så många subrutiner på flera nivåer... kanske det blir krångligare då?

Däremot vid interrupthantering måste alltid allt sparas (om det påverkas) , inklusive flagg-registret!
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Inlägg av övrigt »

Hallå igen

Ni ska ha tack alla för era svar. Jag fick visst svar på fler frågor jag hade än de jag postade:). Ang flashminnets antal skrivningar så håller jag just nu på och lära mig programmera µC. Har passerat mitt 10e projekt och varje har säkert behövts skrivas om kanske mellan 20 och 50 gånger innan debuggningen varit klar. Därför ville jag byta till en mindre och billigare krets att öva på såhär i början (ATtiny2313), vilket jag gör nu. Gällande subrutiner känns alt 1 mer naturligt för mig, så om man kan pusha och popa obegränsat kör jag helt enkelt på det alternativet, så får en ”egen konvention” som jag använder mig av infinna sig efterhand. Eller en viss blandning blir det nog, tex där vissa beräknings-/avbildningsrutiner får returnera i samma register som argumentet kom i, beroende på sammanhanget.

Där har förresten dykt upp en fråga till sen sist, som det kändes onödigt att starta en ny tråd för.

Jag tänkte prova på att använda SRAM-minnet (till annat än push+pop). För att göra det gjorde jag ett onödigt program som skriver ut de 100 första decimalerna av pi på en liten LED-display. Men jag kom inte på nått smartare sätt att lägga in talen i ram än genom följande (fragment av) rutin

Kod: Markera allt

LOAD_PI: 
push Temp
ldi XL,0x0060

ldi Temp,3
st X+,Temp
ldi Temp,10	;DP
st X+,Temp
ldi Temp,1
st X+,Temp
ldi Temp,4
osv. I main ligger sen en loop som läser in ett värde i taget, mappar över det till hur det ska se ut på displayen och sen skriver ut det på porten. Men hela rutinen ovan tar ju upp en massa plats i flashminnet också. Finns där nått smartare sätt (som använder mindre minne tex) att göra detta, där man på nått sätt direkt lägger in siffrorna i SRAM? Istället alltså för att RESET anropar LOAD_PI ovan. Använder AVR Studio 4.

mvh
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Inlägg av Swech »

Det går att fixa smidigare...

Kod: Markera allt

  	LDI	ZL,LOW(PI_TAB*2)	;ZL:=PTR PI TAB
	LDI	ZH,HIGH(PI_TAB*2)	;ZH:=PTR PI TAB

	LDI	XL,LOW(RAM_PI)	 ;XL:=PTR RAM PI TAB
	LDI	XH,HIGH(RAM_PI)     	;XH:=PTR RAM PI TAB
	LDI	R16,100		;COPY 100 VALUES

LOOP1:
	LPM			;R0:=VALUE FROM PI TAB
	ADIW	ZL,1             	;Z:=PTR NEXT VALUE
	ST	X+,R0		;SAVE VALUE TO RAM
	DEC	R16		;DEC LOOP COUNTER
	BRNE	LOOP1		;LOOP > 0 - AGAIN


PI_TAB:
.DB	3,10,1,4,1,5,9,8 .......  100 VALUES

- ändrat från 25 till 100 värden i tabellen
Swech
Skriv svar