Page 2 of 2
Re: ADC e microcontrollore Atmega8535
Posted:
20 May 2013, 18:30
by fram
Scusi se faccio tante domande , ho trovato una formula che mi dice come calcolare il modulo dieci di un numero:
avendo un numero=X ho che il modulo dieci lo calcolo:
X:10=q dove q=Q,d(Q=parte intera)
X-10*Q=Y dove Y è il modulo10 di X
faccio un esempio:calcolo il modulo 10 di 25
25:10=2,5
25-10*2=5
ho quindi che il modulo 10 di 25 è 5
è giusta questa formula per quello che mi serve???
Re: ADC e microcontrollore Atmega8535
Posted:
21 May 2013, 16:49
by fram
@deluca
Salve, non riesco a capire il pezzo di codice che mi ha postato la volta scorsa. mi può aiutare a capire come faccio a fare il modulo 10 del valore chemi viene fornito dal registro x5 dell'ADC. se so come si fa poi posso svolgere il codice.
grazie per l'aiuto.
Re: ADC e microcontrollore Atmega8535
Posted:
21 May 2013, 19:27
by deluca
@fram,
visto che stai studiando e ti stai impegnando... e visto che non è semplice per un neofita scrivere in asm,
ti regalo il codice completo che ho scritto per rispolverare il sempre insostituibile vecchio assembly.
E' chiaro che dovrai reimpostare, nel caso necessitasse, i pin per la gestione del display LCD.
Fammi sapere i risultati della compilazione.... io vado con la versione 4.19 build 730 di AvrStudio.
- Code: Select all
;******************************************
; Autore: Giovanni De Luca - INFN-LNS
; Lettura temperatura in °C in Assembly
; Sensore utilizzato LM35 sul canale(0)
; Display LCD 16x2
; Data: 16-05-2013
;******************************************
.include "m8535def.inc"
.DSEG
v: .Byte 2
volt: .Byte 2
volt_d: .Byte 1
.CSEG
.ORG 0
_Reset:
ldi yl,Low(RAMEND)
out SPL,yl
ldi yh,high(RAMEND)
out SPL+1,yh
sbiw yl,32
call LcdIni ;inizializza LCD
;----Start Adc
ldi zl,0x86
out ADCSRA,zl
;----Cursor Off
ldi r24,0xC
call _LCtr
L0000:
;----Leggi Adc(0)
ldi zl,Low(0)
in zh,ADMUX
andi zh,0xe0
Or zl,zh
out ADMUX,zl
call _Adc
sts v,zl
sts v+1,zh
;----Volt = V * 5
lds r24,v
lds r25,v+1
ldi zl,Low(5)
ldi zh,high(5)
call Mp16u
sts volt,zl
sts volt+1,zh
;----Volt_d = Volt mod 10
lds zl,volt
push zl
ldi zl,Low(10)
pop r24
call Div8u
mov zl,r22
sts volt_d,zl
;----Volt = Volt / 10
lds r24,volt
lds r25,volt+1
ldi zl,Low(10)
ldi zh,high(10)
call Di16u
sts volt,zl
sts volt+1,zh
;----Posiziona il Cursore a 1 , 1
ldi r24,0x7F
push r24
ldi zl,Low(1)
pop r24
add r24,zl
call _LCtr
;----Mostra su LCD il risultato
ldi zl,Low(S000*2)
ldi zh,high(S000*2)
call _LSc
lds zl,volt
lds zh,volt+1
call _W2Str
call _LBW
ldi zl,Low(S001*2)
ldi zh,high(S001*2)
call _LSc
lds zl,volt_d
call _B2Str
call _LBW
ldi zl,Low(S002*2)
ldi zh,high(S002*2)
call _LSc
;----WaitMs 100 prima della prox conversione
ldi zl,Low(100)
call _Wms
rjmp L0000 ;torna al main e do-looppa
L0001:
;----Fine del programma
L0002:
jmp L0002
; String constants:
S000: .db "Temp:", 0
S001: .db ".", 0
S002: .db " C ", 0
;-------[ Inizializza LCD
LcdIni: in zl,DDRC
ori zl,0xf0
out DDRC,zl
sbi DDRC,3
sbi DDRC,2
cbi PORTC,3
cbi PORTC,2
ldi zl,0x10
rcall _Wms
ldi r24,0x03
rcall _LOut
ldi zl,0x05
rcall _Wms
rcall _LEN
ldi zl,0x06
rcall _Wus
rcall _LEN
cbi PORTC,4
rcall _LEN
ldi r24,0x28
rcall _LCtr
ldi r24,0x06
rcall _LCtr
ldi r24,0x0c
rcall _LCtr
ldi r24,0x01
rcall _LCtr
ldi zl,0x03
rcall _Wms
ret
_Lch: sbi PORTC,3
rjmp _LNib
_LCtr: cbi PORTC,3
_LNib: mov r21,r24
Swap r24
rcall _LOut
mov r24,r21
_LOut: in r23,PORTC
andi r23,0x0f
Swap r24
andi r24,0xf0
Or r24,r23
out PORTC,r24
rcall _LEN
ret
;------[ LcdEN
_LEN: sbi PORTC,2
Nop
Nop
Nop
Nop
cbi PORTC,2
push zl
ldi zl,0x04
rcall _Wus
pop zl
ret
;------[ Lcd Byte & Word
_LBW: ld r24,Z+
tst r24
breq _LBW1
rcall _Lch
rjmp _LBW
_LBW1: ret
;------[ Lcd String constants
_LSc: lpm
tst r0
breq _LSc1
mov r24,r0
rcall _Lch
adiw zl,1
rjmp _LSc
_Lsc1: ret
;------[ Adc
_Adc: sbi ADCSRA,0x06
_Adc1: sbic ADCSRA,0x04
rjmp _Adc1
in zl,ADCL
in zh,ADCH
sbi ADCSRA,0x04
ret
;------[ IntToStr
_B2str: clr zh
clt
rjmp _W2st4
_W2str: clt
rjmp _W2st4
_I2str: clt
sbrs zh,0x07
rjmp _W2st4
Com zl
Com zh
subi zl,-0x01
sbci zh,-0x01
Set
_W2st4: push yl
push yh
push r6
clr r6
st -Y,r6
_N2str: ldi r21,0x10
Sub r22,r22
_N2st1: lsr r6
rol zl
rol zh
rol r22
rol r6
cpi r22,0x0a
brcs _N2st2
sbci r22,0x0a
inc zl
_N2st2: dec r21
brne _N2st1
subi r22,-0x30
st -Y,r22
mov r22,zl
Or r22,zh
brne _N2str
_N2st5: brtc _N2st3
ldi zl,0x2d
st -Y,zl
_N2st3: mov zl,yl
pop r6
mov zh,yh
pop yh
pop yl
ret
;-----[ Waitms
_Wms: ldi r20,0x14
_Wms1: ldi r21,0x85
_Wms2: dec r21
brne _Wms2
dec r20
brne _Wms1
dec zl
brne _Wms
ret
;-----[ Waitus
_wus: ldi r22,25
_wus1: dec r22
brne _wus1
dec zl
brne _wus
ret
;------[ 8/8 unsigned division
Div8u: Sub r22,r22
ldi r23,0x09
rjmp Div81
Div80: rol r22
cp r22,zl
brcs Div81
Sub r22,zl
Div81: rol r24
dec r23
brne Div80
Com r24
mov zl,r24
ret
;------[ 16x16 hardware multiplay
Mp16u: mul zl,r24
movw r22,r0
mul zl,r25
add r23,r0
mul zh,r24
add r23,r0
movw zl,r22
ret
;------[ 16/16 unsigned division
Di16u: mov r22,zl
mov r23,zh
mov zl,r24
mov zh,r25
clr r24
Sub r25,r25
ldi r20,0x11
d16u1: rol zl
rol zh
dec r20
brne d16u2
ret
d16u2: rol r24
rol r25
Sub r24,r22
sbc r25,r23
brcc d16u3
add r24,r22
Adc r25,r23
clc
rjmp d16u1
d16u3: sec
rjmp d16u1
Re: ADC e microcontrollore Atmega8535
Posted:
22 May 2013, 17:48
by fram
@deluca
Salve, grazie per il programma che ha postato, l'ho studiato ed ho visto che stavo procedendo bene con il mio programma. la mia oramai è una curiosità e mi piacerebbe sapere come svolgere il modulo 10 che è l'unico che non riesco a capire, se mi dice cosa fa vedo di scrivere il codice come sto facendo per gli altri punti che servono. è l'unico punto che non capisco, non riesco a capire come mi fa trasformare il risultato dell'ADC in valore da visualizzare.
grazie.
Re: ADC e microcontrollore Atmega8535
Posted:
22 May 2013, 21:33
by js-bascom
il modulo 10 che è l'unico che non riesco a capire
Semplicemente continua a sottrare 10 dal numero, quando il risutalto e' meno di 10 hai la risposta. (almeno io la capisco in questo modo.
)
ie 35 modulo 10 e' 5
Re: ADC e microcontrollore Atmega8535
Posted:
29 May 2013, 16:28
by fram
@deluca
Salve, mi servirebbe avere un chiarimento:
come già detto in precedenza sto utilizzando l'ADC di un atmega8535 per realizzare un termometro, leggendo bene il datasheet ho visto come fare la conversione del risultato che ho dall'adc ora la posto:
ADC Conversion Result After the conversion is complete (ADIF is high), the conversion result can be found in the ADC Result Registers (ADCL, ADCH).
For single ended conversion, the result is:
ADC=Vin*1024/Vref
where VIN is the voltage on the selected input pin and VREF the selected voltage reference
(see Table 84 on page 219 and Table 85 on page 220). 0x000 represents analog
ground, and 0x3FF represents the selected reference voltage minus one LSB
Io ho settato l'ADC Vref=2.56 e Vin mi viene fornita dal sensore LM35 che da 10mV/°C
Ho solo un dubbio facendo un esempio T=25,5°C ho una Vin=250mV
applicando la formula ho che ADC=102 invece di 25,5 devo aggiungere una divisione per 4??
grazie buona giornata
Re: ADC e microcontrollore Atmega8535
Posted:
14 Jun 2013, 09:39
by fram
mi dite se cosi l'ADC è settato in modo corretto:
;###Configuro l'ADC###
ldi temp, (1<<ADEN)|(1<<ADPS2)|(1<<ADPS0) ;Abilito l'ADC,
out ADCSRA, temp ;prescaling=32(f=125KHz),SFIOR=0 (free-running)
ldi temp,192
out ADMUX, temp
Start_ADC:
sbi ADCSRA, ADSC ;Start of conversion (first sample)
in ta, ADCL ;Prendo il risultato in ADCH e lo metto in ta
Re: ADC e microcontrollore Atmega8535
Posted:
14 Jun 2013, 10:06
by js-bascom
Nota che io uso i Macros dell'AVR001 nei prossimi pezzetti di codice (STORE, SETB etc.)
Per iniziare faccio una conversione inutile a non faccio uso del risultato
- Code: Select all
;ADC definitions
#define ADC_0 (0<<MUX2|0<<MUX1|0<<MUX0)
#define ADC_1 (1<<MUX0)
#define ADC_2 (1<<MUX1)
#define ADC_3 (1<<MUX1|1<<MUX0)
#define ADC_4 (1<<MUX2)
#define ADC_5 (1<<MUX2|1<<MUX0)
#define ADC_6 (1<<MUX2|1<<MUX1)
#define ADC_7 (1<<MUX2|1<<MUX1|1<<MUX0)
;Set up ADC
ldi temp,(1<<ADEN|1<<ADPS2) ;Enable ADC at:32 divider, no ints.
STORE ADCSRA,temp
ldi temp,(1<<REFS0|ADC_0) ;Conversion on channel 0, AVCC reference.
STORE admux,temp
SETB ADCSRA,ADSC,temp2 ;Start 1st conversion to init the adc
WAIT_ADC_init:
SKBS ADCSRA,adif,temp2
rjmp WAIT_ADC_init ;Wait for conversion complete
SETB ADCSRA,adif,temp2 ;Clear conversion flag
- Code: Select all
ldi temp,(1<<REFS0|ADC_0) ;Conversion on channel 0, AVCC reference.
STORE admux,temp
SETB ADCSRA,ADSC,temp2 ;Start conversion
WAIT_CH0:
SKBS ADCSRA,adif,temp2
rjmp WAIT_CH0 ;Wait for conversion complete
SETB ADCSRA,adif,temp2 ;Clear conversion flag
LOAD temp,adcl,temp2 ;Get last conversion result
LOAD temp1,adch
negli ultimi tempi uso l'ADSC invece di adif per vedere quando la conversione e finita, un po' piu' semplice, ma no trovo un esempio al momento.
Re: ADC e microcontrollore Atmega8535
Posted:
14 Jun 2013, 12:07
by fram
Credo di avere impostato bene l'adc..ora mi da un problema:fa la prima lettura ed è ok, poi quando fa la seconda lettura azzera il risultato poi la terza lettura lo da giusto e cosi.. come mai??
P.S. per portare il valore digitalizzato dall'adc (atmega8535) nel valore corretto da visualizzare devo applicare la formula Vin=ADC*Vref/1024???
avendo vref=2,56 Vin=ADC/4???
Re: ADC e microcontrollore Atmega8535
Posted:
14 Jun 2013, 19:22
by fram
Ho risolto alcuni problemi....quello che non riesco a fare è trasformare il valore dell'adc ADCH in valore BCD, sapreste aiutarmi???
grazie...
Re: ADC e microcontrollore Atmega8535
Posted:
15 Jun 2013, 04:48
by js-bascom
Vuoi dire convertrie il valore hex proveniente dal' ADC a numeri es. 0x03FF stampabile con quattro numeri 1 0 2 3 ?
Se questo e' il caso forse questo potra esserti di aiuto, lo uso da molti anni pero' e stato convertito da altri tipi di micros forse non e' il migliore esempio ma funziona.
Re: ADC e microcontrollore Atmega8535
Posted:
17 Jun 2013, 09:48
by fram
Grazie per l'informazione ma trasformare il codice BCD in codice ASCII l'ho gia fatto.
quello che volevo capire è come trasformare il valore che ho nel registro ADCH in BCD, cioè:
avendo una temperatura di 25,5 °C il sensore LM35 mi fornisce una tensione 255mV e l'ADC la converte mettendola nel registro ADCH.
Per portare il valore che ho in ADCH in modo da avere 25,5(BCD) non capisco come fare.mi sapete aiutare???
Re: ADC e microcontrollore Atmega8535
Posted:
17 Jun 2013, 16:16
by deluca
@fram
beh!, adesso non ricordo ma....
scusa ma non ti avevo già spiegato come fare?
............come convertire il valore binario letto dall'adc per poi visualizzarlo sul display?
guarda nei post precedenti, hai visto il codice che avevo scritto prima ? è tutto lì
Re: ADC e microcontrollore Atmega8535
Posted:
02 Nov 2016, 20:35
by Dom
Salve, sono nuovo del forum, un saluto a tutti.
Ho letto la discussione e purtroppo non sono riuscito a venire a capo del mio problema.
Sto usando la scheda STK500 con AVRStudio7, premesso questo praticamente nel momento in cui provo il codice sul controllore atmega8535, con collegato al piedino PA0 (ADC0) il sensore LM35, in uscita, su PORTC (che sarà la porta del LCD) e che momentaneamente collegata agli 8 led che si trovano sulla scheda, non ho alcuna variazione dei led (che dovrebbero rappresentare il binario del valore di temperatura approssimato all'unità). A prescindere se la configurazione mi dava un risultato esatto o meno, il punto è che almeno qualcosa sulla porta a mio avviso doveva uscire dalla conversione;
posto il mio codice che simula un main dove aspetto 10 ms, richiamo la macro "rilevatemp"
alla fine di questo processo dovrei avere in "data_lcd" il valore della conversione per poi dopo 2 secondi mandarlo su PORTC;
- Code: Select all
.include "init_lcd.inc"
.include "wait.inc"
.include "wait_1ms.inc"
.include "stampa.inc"
.include "wait_for.inc"
.DEF tmp=r16
.DEF varCont=r17
.DEF data_lcd=r18
.EQU size=16
.EQU E= PORTA7
.EQU RS= PORTA6
.EQU RW= PORTA5
.CSEG
.ORG $0000 rjmp START ; Reset Handler
.ORG INT0addr reti ; jmp EXT_INT0 ; IRQ0 Handler
.ORG INT1addr reti ; jmp EXT_INT1 ; IRQ1 Handler
.ORG OC2addr reti ; jmp TIM2_COMP ; Timer2 Compare Handler
.ORG OVF2addr reti ; jmp TIM2_OVF ; Timer2 Overflow Handler
.ORG ICP1addr reti ; jmp TIM1_CAPT ; Timer1 Capture Handler
.ORG OC1Aaddr reti ; jmp TIM1_COMPA ; Timer1 CompareA Handler
.ORG OC1Baddr reti ; jmp TIM1_COMPB ; Timer1 CompareB Handler
.ORG OVF1addr reti ; jmp TIM1_OVF ; Timer1 Overflow Handler
.ORG OVF0addr reti ; jmp TIM0_OVF ; Timer0 Overflow Handler
.ORG SPIaddr reti ; jmp SPI_STC ; SPI Transfer Complete Handler
.ORG URXCaddr reti ; jmp USART_RXC ; USART RX Complete Handler
.ORG UDREaddr reti ; jmp USART_UDRE ; UDR Empty Handler
.ORG UTXCaddr reti ; jmp USART_TXC ; USART TX Complete Handler
.ORG ADCCaddr rjmp ADC_complete ; ADC Conversion Complete Handler
.ORG ERDYaddr reti ; jmp EE_RDY ; EEPROM Ready Handler
.ORG ACIaddr reti ; jmp ANA_COMP ; Analog Comparator Handler
.ORG TWIaddr reti ; jmp TWSI ; Two-wire Serial Interface Handler
.ORG INT2addr reti ; jmp EXT_INT2 ; IRQ2 Handler
.ORG OC0addr rjmp TIM0_COMP ; Timer0 Compare Handler
.ORG SPMRaddr reti ; jmp SPM_RDY ; Store Program Memory Ready Handler
.org INT_VECTORS_SIZE
msg0: .db "WELCOME",0
msg1: .db "ATMEL-MONITORING SYSTEM",0
start:
INIT_SP:
ldi tmp,low(ramend)
out SPL,TMP
ldi tmp,high(ramend)
out SPH,tmp
INIT_IO:
ldi tmp,0xff
out DDRC,tmp ;imposto portC come output, 0-7 bit data LCD
ldi tmp,0xE0
out DDRA,tmp;imposto i piedini di uscita per E,RS,RW,
INIT_TimerCounter0:
;inizializzo TimerCounter0,CTC_normal_mode_OC0-Disconnected,(inizialmente off_no clock source)
ldi tmp,(1<<WGM01)|(0<<WGM00)|(0<<COM00)|(0<<COM01)|(0<<CS00)|(0<<CS01)|(0<<CS02)
out TCCR0,tmp
ldi tmp,0xFF
out OCR0,tmp;inizialmente il valore di OCR0 sara pari a max
init_ADC:
ldi tmp, (1<<REFS1)|(1<<REFS0)|(1<<ADLAR);internal 2,56 vref, aggiustamento a sinistra;dovrò leggere solo ADCH
out ADMUX,tmp
ldi tmp, (1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(0<<ADIE)|(1<<ADPS1)|(1<<ADPS0);ADIE clred, interrupt disable ADC_complete, 125kHz ADC
out ADCSRA,tmp
sei ;enableglobalinterrupts
;inizializzo LCD
;init_lcd
;stampa,msg0
main:
wait_for,0,10 ;ripetizioni x*y;tempo base 1ms (quando un parametro è 0 conta l'altro)
rcall rilevatemp
wait_for,100,20 ;attendo 2s
out PORTC,data_lcd; valore in uscita
rjmp main
rilevaTemp:
ldi tmp, (1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(1<<ADIE)|(1<<ADPS1)|(1<<ADPS0);avvio conv. con ADSC e abilito ADIE interr.
out ADCSRA,tmp
ret
;INTERRUPTS
ADC_complete:
;in data_lcd,ADCL
in data_lcd,ADCH
ldi tmp,(0<<ADIE);disabilito interrupt
out ADCSRA,tmp
reti
TIM0_COMP:
ldi varcont,0
reti