Autor Tema: Timer y ADC  (Leído 4296 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Leral

  • PIC10
  • *
  • Mensajes: 17
Timer y ADC
« 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


Citar
;#########################   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
              
  
« Última modificación: 26 de Mayo de 2009, 18:37:05 por Leral »

Desconectado FuYiVape

  • PIC12
  • **
  • Mensajes: 69
    • Electronica y Sistemas
Re: Timer y ADC
« Respuesta #1 en: 27 de Mayo de 2009, 10:11:18 »
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!