TODOPIC
Otros Microcontroladores / Dispositivos programables => Microcontroladores 8 bits => Mensaje iniciado por: Leral en 26 de Mayo de 2009, 18:33:04
-
Hola tengo un problema, estoy intentando hacer un codigo que lea de la entrada de un solo canal del ADC, luego despues hago unas cuentas y convierto el ADCL y ADCH en un registro al que llamo Temp_real donde esta el valor que tengo que comparar y segun la comparacion aunmentare o decrementare una cuenta que pndre en los timer1 y 2 en modo PWM. Mi problema es que quiero cambiar el valor con el cual comparo los valores del ADC cada 40s y 30s (What_count) . Este cambio lo pretendo hacer con un timer0. Pero no se como hacer para que el ADC y el Timer0 trabajen de mandera paralela.
Otra duda que tengo es si hago bien en inicar los timer1 y 2 en medio del LOOP o deberia hacerlo en el RESET.
En fin son muchas dudas juntas no pretengo que me hagais el codigo, pero si alguien puede pegar un codigo parecido con timers y ADC le estaria agradecido luego yo ya intentaria adaptar el codigo.
EStoy usando un ATmega8
Gracias.
Notas:
- Uso el registro r27 para esperar a que termine la conversion en el ADC
;######################### Project ###########################
.include"m8def.inc"
.def tmp2=r16
.def tmp=r17
.def what_count2=r18
.def temperature=r19
.def count= r20
.def count2=r21
.def temp_real=r22
.def PWM_count=r23
.def anodo=r24
.org 0x000 rjmp RESET
.org 0x009 rjmp TIMER0_OVF ;Timer 0 overflow ADC 0 5interrupt
.org 0x013
RESET:
cli
ldi r16, low(ramend)
ldi r17, high(ramend)
out spl, r16
out sph, r17
ldi r16, $FF
out DDRB, r16
ldi r16, $00
out PORTB, r16
;########### Initialize of cases ######
ldi tmp, 0x00
ldi tmp2, 0x00
ldi temp_real, 0x00
ldi temperature,0x28 ;the temperature is initialize to 92,7ºC
ldi PWM_count, 0x00
ldi count, 0x00
ldi count2, 0x00
ldi what_count2,0x00
;############ initialize timers ############
ldi r16, 0x00
out OCR1AH, r16
out OCR1AL, r16
out OCR2, r16
ldi r16, 0xFF
out TCNT0, r16
sei
;############ ADC ###########################################
ldi r16, (0<<REFS0)|(0<<ADLAR)|(0<<REFS1)
out ADMUX, r16
ldi r16, (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS0)|(1<<ADPS1)
out ADCSRA, r16
;################ Timer 0 ###################################
ldi r16,(1<<CS02)|(1<<CS00)
out TCCR0, r16
; ldi r16,(1<<TOIE0)
; out TIMSK, r16
; 92ºC ------ 28
; 66ºC ------ 78
; 45ºC ------ E6
LOOP:
ldi tmp,0xAA
cp tmp,r27 ; I wait to ADC
brne LOOP
clr r27
cp temp_real, temperature
brlo lower ; if temperature < temp_real I have more temperature than 92ºC so I must cool
;higher
inc PWM_count
out OCR2, PWM_count
rjmp timer2
lower:
dec PWM_count
out OCR2,PWM_count
rjmp timer2
AD_C:
in Temp_real, ADCH ;I take the 9 bits more important of the 10bit that ADC is giving me
in tmp, ADCL
rol Temp_real
rol Temp_real
rol Temp_real
rol Temp_real
rol Temp_real
rol Temp_real
rol Temp_real ; I change de bit 0 for the bit 7
ror tmp ;Shift one position to right the register
cbr tmp, 0 ;Kill the bit 7 for security
add Temp_real,tmp ; Now I have a register with 8bit and a resolution of 9bits
start_ADC_again:
ldi r16, (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS0)|(1<<ADPS1)
out ADCSRA, r16
ldi r27,0xAA
reti
TIMER0_OVF:
inc count
cpi count, 0xFF
brne Loop
inc count2
cp count2, what_count2
brne Loop
ldi count2, 0x00
cpi temperature, 0x28 ;when the case 1(92ºC) just finish the micro go the next case --> Case_2(45ºC)
breq case_2
cpi temperature, 0x78 ;when the case 3(66ºC) just finish the micro go the next case --> Case_1(92ºC)
breq case_1
cpi temperature, 0xE6 ;when the case 2(45ºC) just finish the micro go the next case --> Case_3(66ºC)
breq case_3
reti
Case_1:
ldi temperature, 0x28 ; I take this case and I put the new count to correction of temperature
ldi what_count2,0x04
reti
Case_2:
ldi temperature, 0xE6
ldi what_count2,0x05
reti
Case_3:
ldi temperature, 0x78
ldi what_count2,0x04
reti
timer2: ;warm
ldi r16, (0 << CS12)|(0 << CS10)
out TCCR1B, r16 ;fist I have to stop the other timer
;################ Timer2 in mode fast PWM ####################
ldi r16, (1<< WGM20)|(1<< WGM21)|(1<< COM21)|(1<< CS20)|(1<< CS21)|(1<< CS22);|(1<< COM20)
out TCCR2, r16
rjmp start_ADC_again
timer1: ;cool
ldi r16, (0<< CS20)|(0<< CS21)|(0<< CS22)
out TCCR2, r16 ;fist I have to stop the other timer
;################# PWM timer 1 ###############################
ldi r16, (1 << COM1A1)|(0 << COM1A0)|(0 << WGM11)|(1 << WGM10)
out TCCR1A, r16
ldi r16, (0 << WGM13)|(1 << WGM12)|(1 << CS12)|(1 << CS10)
out TCCR1B, r16
rjmp start_ADC_again
-
Lo que te puedo pasar es un codigo escrito en C.
El programa lee el canal 0 del ADC cada vez que se produce un overflow del timer 1 (cada 1/2 segundo +-).
El valor obtenido lo compara con rangos existentes en una tabla y segun el valor asociado, activa determinados bits de tres puertos para activar reles y asi, seleccionar la base de tiempos de un osciloscopio.
Podes iniciar los timer donde quieras siempre y cuando cuides que no se solape con otra rutina.
Para que el ADC y el timer trabajen de forma paralela, tenes que hacer la conversion en la rutina de interrupcion del timer, como lo hace el codigo que te paso.
Lo que podes hacer, es una tabla parecida a la que te muestro en el codigo, y en vez de contener valores para los puertos, que contenga valores para los PWM y asi cambiar el ancho del pulso.
El codigo tambien envia por el serial, un valor que corresponde a una posicion dentro de las 23 del switch de seleccion de base de tiempos.
Saludos!