AVR Assembler - HELP

Sep 20, 2004 5 Replies

Salve a tutti. Ho un problema con un programma in assembler che sto scriverndo per un AT90S2313. In pratica realizza un controllo PWM il cui valore è settato da tre tastini: prog, più e meno. Per programmare bisogna premere contemporaneamente prog e più o meno a seconda.



Ho settato il Timer1 come PWM a 9 bit e senza prescaler (per arrivare vicino alla frequenza di 4 kHz che mi serve). In teoria vorrei che tutte le volte che riaccendo la scheda, il valore del duty cycle fosse quello impostato. Voi direte: te lo scrivi in EEPROM e sei a posto, basta leggerlo ad ogni start-up. Il problema sta qua! :-( Settando il Timer1 come PWM a 8 bit, leggo, scrivo e faccio quello che voglio col valore del OCR1AL, che è il registro che contiene il valore del duty cicle (più o meno... è il registro di compare-match). Quando però passo ai 9 bit, non riesco a fare "resuscitare" i valori allo start-up. Allego qua sotto il codice. Un grande grazie a chi può darmi una mano! Ciao Pelo


.INCLUDE "2313DEF.INC"



;*******DEF************************************************************ ;.DEF =R1 ;.DEF =R2 ;.DEF =R3 ;.DEF =R4 ;.DEF =R5 ;.DEF =R6 ;.DEF =R7 ;.DEF =R8 ;.DEF =R9 ;.DEF =R10 ;.DEF =R11 ;.DEF =R12 ;.DEF =R13 ;.DEF =R14 ;.DEF =R15 .DEF BUFFER =R16 .DEF TEMP =R17 ;.DEF =R18 .DEF TEMP2 =R19 .DEF FLAG =R20 .DEF KEYA =R21 .DEF KEYB =R22 ;.DEF =R23 .DEF BASSO =R24 ; Inizio registri PAIR .DEF ALTO =R25 ;.XL =R26 ; Da non toccare ;.XH =R27 ; " " ;.YL =R28 ; " " ;.YH =R29 ; " " ;.ZL =R30 ; " " ;.ZH =R31 ; " "


.equ EEPROMADDRESS =0x20 .equ PIU =5 .equ MENO =4 .equ PROG =3 .equ STEP =1 ;**************************INTERRUPT VECTORS *********************



.ORG 0x000



rjmp MAIN ;RESET reti ;EXT_INT0 reti ;EXT_INT1 reti ;TIM1_CAPT reti ;TIM1_COMP reti ;TIM1_OVF reti ;TIM0_OVF reti ;SPI_STC reti ;UART_RXC reti ;UART_DRE reti ;UART_TXC reti ;ADC reti ;EE_READY reti ;ANA_COMP



.org 0x010 ;************************************* STACK POINTER INIT



*****************************************

MAIN: ldi BUFFER,low(RAMEND) out SPL,BUFFER



;*********************************** GENERAL INTERRUPT MASK



**************************************** ldi BUFFER,0b10000000 ; Enable the External interrupt 1 ;ldi BUFFER,0b01000000 ; Enable the External interrupt 0 ;ldi BUFFER,0b10000000 ; Enable the External interrupt 0 and 1 out GIMSK, BUFFER


;***************************************** MCUCR INIT



********************************************

;ldi BUFFER,0b00xxxxxx ; Reserved bits ;ldi BUFFER,0bxx1xxxxx ; Sleep mode enable ;ldi BUFFER,0bxxx1xxxx ; Sleep mode select: 0->Idle mode 1->Power down ;ldi BUFFER,0bxxxx1xxx ; ISC11 |->Set external interrupt mode ;ldi BUFFER,0bxxxxx1xx ; ISC10 | See Manual p.30 for details ;ldi BUFFER,0bxxxxxx1x ; ISC01 | ;ldi BUFFER,0bxxxxxxx1 ; ISC00 | ldi BUFFER,0b00001000 out MCUCR,BUFFER


;*************************************** EEPROM INIT



**********************************************

ldi BUFFER,0b00000000 ;Reset the EEPROM address register out EEAR,BUFFER ;Init the EEPROM control register ;ldi BUFFER,0b0000xxxx ;0 are reserved bits ;ldi BUFFER,0bxxxx1xxx ;Ready interrupt enable ;ldi BUFFER,0bxxxxx1xx ;Master write enable ;ldi BUFFER,0bxxxxxx1x ;Write enable ;ldi BUFFER,0bxxxxxxx1 ;Read enable ldi BUFFER,0b00000000 out EECR,BUFFER


;*********************************** TIMER/COUNTER 1 INIT******************************************



ldi BUFFER,0b10000010 ; out TCCR1A,BUFFER ldi BUFFER,0b00000001 ; out TCCR1B,BUFFER



;**************************************** PORT INIT



*********************************************** ;DDR PORT I/O Pullup Comment ;0 0 In No Tristate ;0 1 In Yes Input with pull-up ;1 0 Out No Push-Pull Zero out ;1 1 Out No Push-Pull One out

;**************************************** INIT PORT B



*********************************************

; As OUTPUT Zero OUTPUT ldi BUFFER,0b11111111 out DDRB,BUFFER ldi BUFFER,0b00000000 out PORTB,BUFFER



;**************************************** INIT PORT D



*********************************************

; As INPUT with PULLUP ldi BUFFER,0b00000000 out DDRD,BUFFER ldi BUFFER,0b11111111 out PORTD,BUFFER



;***************************************************************************



************************ ;******************************************** MAIN
************************************************* ;***************************************************************************
************************


; Reads the PWM from the EEPROM Memory ldi BUFFER,EEPROMADDRESS ; Read the first byte out EEAR,BUFFER sbi EECR,EERE read1: sbic EECR,EERE rjmp read1 in BASSO,EEDR



;ldi BUFFER,EEPROMADDRESS ; Read the second byte inc BUFFER out EEAR,BUFFER sbi EECR,EERE read2: sbic EECR,EERE rjmp read2 in ALTO,EEDR out OCR1AH,ALTO out OCR1AL,BASSO



Lupo: sbrc FLAG,0 rjmp xxx in TEMP,PIND sbrc TEMP,PROG rjmp Lupo sbr FLAG,1


Program:



in KEYB,PIND mov TEMP,KEYB in BASSO,OCR1AL in ALTO, OCR1AH



ldi BUFFER,STEP sbrs TEMP,PIU



adiw ALTO:BASSO,STEP sbrs TEMP,MENO sbiw ALTO:BASSO,STEP



out OCR1AH,ALTO out OCR1AL,BASSO in ALTO,OCR1AH in BASSO,OCR1AL



wait_EEWE2: sbic EECR,EEWE ; Waits for write ready rjmp wait_EEWE2 ldi TEMP,EEPROMADDRESS ; Load the high address of position in memory out EEAR,TEMP out EEDR,ALTO sbi EECR,EEMWE ; Set the EEPROM Master Write Enable bit sbi EECR,EEWE ; Set the EEPROM Write Enable bit



wait_EEWE3: sbic EECR,EEWE ; Waits for write ready rjmp wait_EEWE3 ;ldi TEMP,EEPROMADDRESS ; Load the low address of position in memory inc TEMP out EEAR,TEMP out EEDR,BASSO sbi EECR,EEMWE ; Set the EEPROM Master Write Enable bit sbi EECR,EEWE ; Set the EEPROM Write Enable bit


wait_EEWE4: sbic EECR,EEWE ; Waits for write ready rjmp wait_EEWE4


xxx: in KEYA,PIND cp KEYA,KEYB breq Lupo cbr FLAG,1 rjmp Lupo


Non ho tempo adesso di analizzare il tuo listato, pero' ricordo che il primo indirizzo della EEPROM a volte tende a cancellarsi (ho incontrato il problema proprio con un AT90S2313), per cui prova a cambiare la locazione di E2P.

Un altra precauzione e' mettere sempre a zero,cioe' alla prima locazione (che non viene usata ) i puntatori EEAR dopo un operazione in EEPROM. Pare che durante il reset o il power down a volte possano sporcare la memoria puntata, soprattutto se i fronti di discesa della VCC non sono molto ripidi.

Se dopo queste modifiche hai ancora problemi faccelo sapere,

ciao Stefano

"SB" ha scritto nel messaggio news: snipped-for-privacy@4ax.com...

Grazie mille della risposta! Allora qualcuno usa gli AVR! :-)

Già fatto! parto da 0x20 (riga .equ EEPROMADDRESS =0x20)

Perchè parli di puntatori? L'EEAR non è un registro a 8 bit? Cioè una cosa del genere nel caso di lettura? (metacodice)

ldi BUFFER,EEPROMADDRESS out EEAR,BUFFER sbi EECR,EERE wait: sbic EECR,EERE rjmp wait in BUFFER,EEDR out OCR1AH,BUFFER ldi BUFFER,0 out EEAR,BUFFER

Io spegnevo proprio la scheda... Grazie mille Pelo

Mi ci trovo bene

Benissimo

Proprio questo: ldi BUFFER,0 out EEAR,BUFFER

Beh, resettando con il pin RES\ non dovrebbe farlo...

Hai provato? Funziona adesso? Perchè per il resto ho dato un occhiata veloce al listato e mi sembra che possa andare.

ciao Stefano

"SB" ha scritto nel messaggio news: snipped-for-privacy@4ax.com...

Funziona tutto! Però non capisco perche si debba mettere e zero il registro EEAR... quando lo uso dopo lo ricarico di nuovo!!! Mah...

Grazie dieci mila! Pelo

Sono contento

Basta che il registro EEAR sia a zero al momento dello spegnimento, quindi se fai una routine di Power Fail con un interrupt per quella funzione lo puoi mettere a zero cosi'.

Se invece vuoi eliminare il problema complicando l'hardware puoi mettere un MC34064 che controlli il RES\

formatting link

o usare un chip ATMega con il "Brown Out Detector" che essenzialmente fa la stessa cosa.

Comunque la soluzione software e' sempre quella che costa meno ;-)

ciao Stefano

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required