domingo, 5 de junio de 2011

Input Capture Unit


El timer1 incorpora una unidad de captura la cual puede capturar eventos externos y darnos un tiempo referencial en el cual estos ocurrieron.
La señal que indica el evento puede ser aplicado al pin ICP1 o vía la unidad de comparación analógica. El tiempo que es capturado puede ser usado para medir frecuencia, duty-cycle u alguna otra característica de la señal aplicada.

En el siguiente gráfico de muestra el diagrama de bloques de la unidad de captura.

bloques

Se puede ver que las entradas pueden ser el pin ICP1 o el comparador analógico. LA unidad también cuenta con un modulo de cancelación de ruido el cual tomará 4 muestras de la señal y si las 4 son iguales la señal será valida. También ésta el modulo de detección de flanco que nos permite seleccionar entre los flancos de subida(‘1’) o bajada(‘0’).
Cuando el evento ocurre los 16bits del contador TCNT1 son escritos al registro ICR1, también  en éste mismo instante se generará un interrupción( siempre que se activen los flag’s TICIE1 en el registro TIMSK y I en SREG.

En éste post usaré la unidad de captura para medir la frecuencia de una señal cuadrada.
El principio de medición consiste en capturar el valor de cuenta del timer1 (TCNT1) en un periodo de la señal a medir, luego con el valor de la captura , la frecuencia a la que trabaja el uC y conociendo el pre-escaler usado podremos fácilmente encontrar la frecuencia de la señal.

Por ejemplo: Si se trabaja con una F_CPU=16MHz, el valor capturado es ICR1=0x08BB y el pre-escaler usado es 64, entonces la frecuencia de la señal es:

image

Aplicando los datos a la formula:

image

Ahora pasaré a mostrar el código. Hay algunas macros y rutinas que ya he mostrado en post anteriores pero las estoy volviendo a mostrar.

Primero mostrare las macros.






m24

Ahora mostraré la rutinas de conversión de binario a ascii.

binascii1

binascii2

Ahora la rutinas para manejo del LCD.

lcd1

lcd2

lcd3

Las rutina de retardo que es usado junto a las macros delay_ms y delay_us.

retardo

La rutina para efectuar la división.

div1

div2

Y por último el código principal.






main23


main24

El funcionamiento del programa es como sigue.
  • Se configura los periféricos, se habilita la interrupción y se espera a que ésta ocurra.

  • Cuando ocurra la interrupción por captura el programa saltará a la rutina “CAPTURA_EVEN”, aquí tomará el valor capturado y lo pondrá en dos registros(R19:R18=ICR1H:ICR1L).
  • Se verificara si el timer se ha desbordado, en caso de ser así se mostrará un mensaje indicado que aquella es una frecuencia que no se puede medir(“fuera de rango”).

  • Si no se ha desbordado se calculará la frecuencia, con la formula ya antes mostrada, y se guardará en FRECASCII.

  • Luego del calculo de mostrará la frecuencia en el LCD.

  • Se espera 300ms y luego se espera al siguiente flanco de subida para iniciar la siguiente captura de datos (la medida de la frecuencia se toma entre dos francos de subida).
Hay que tener presente que con este método no se puede medir frecuencias muy altas, mientras mayor es la frecuencia mayor es el error en la medición. En un próximo post  mostraré como usar el mismo timer para hacer medidas de frecuencias mas altas.
Espero este pequeño ejemplo le ayude..!!!

Ahora un video del programa en funcionamiento.


15 comentarios:

  1. Hola amigo que bueno q te animaste al hacer un blog solo para los avrs ya que no hay mucha informacion, yo particularmente eh programado el atmega16 y en c con el winavr que es gratis y me eh guiado de un libro q para mi es muy bueno el The AVR microcontroller and embedded systems que lo encuentras en taringa me gustaria ayudarte en este proyecto, bueno saludos mi correo es xodin_02@hotmail.com comuniquemosnos saludos!!

    ResponderEliminar
  2. hola que tal.. interesante tu blog sobre todo porque es muy dificil encontrar informacion de este tipo, oye por favor me pordrias mandar el codigo a mi correo? jalzak@hotmail.com lo necesito espero que no haya inconveniente ok saludos

    ResponderEliminar
  3. Te recomendaria que te tomes la molestia de copiar el codigo que está en las imagenes, asi aprenderas mas que si te paso el codigo.

    ResponderEliminar
  4. Ok lo estaba haciendo pero hay una parte en la que haces un RJMP PC , y no veo donde declaras PC espero me ñuedas ayudar con eso saludos y gracias

    ResponderEliminar
  5. "PC" es el "Contador de Programa", no tienes que declararlo. Cuando uso "rjmp pc" es para que el programa se quede en esa instrucción infinitamente. Como sabes PC contiene la dirección de la proxima instrucción a ser ejecutada.

    ResponderEliminar
  6. Hola de nuevo,oye necesito comunicar el atmega8 con un adc0834 pero no se como hacerle espero que me puedas ayudar o recomendarme algun texto para aprender sobre el tema gracias..

    ResponderEliminar
  7. Hola... Bueno, yo nunca trabajé con el ADC0834 y para ser honestos nunca usé el protocolo "microwire" que usa éste ADC, pero según lo que he podido leer "microwire"(National) es solamente un subconjunto de SPI(Motorola), osea es SPI en uno de sus 4 modos (creo que es el modo 0). Si es así solamente debes configurar el SPI del ATmega8 al modo correcto, seleccionar el canal del ADC y esperar la data.
    Como te dije, no he usado ningun dispositivo con "microwire" si no te ayudaria más.

    http://www.ucpros.com/work%20samples/Microcontroller%20Communication%20Interfaces%202.htm

    Y la pregunta es.. ¿ Para que usar un ADC externo y de 8 bits, si el ATmega8 tiene uno de 10 bits ?

    ResponderEliminar
  8. si tienes razon... oye me podrias ayudar para conecar 2 atmega8 con protocolo spi gracias

    ResponderEliminar
  9. Te puedo ayudar, pero tienes que darme más información sobre lo que intentas hacer.
    En ese tipo de conexión puedes tener uno como maestro y el otro como esclavo, o los dos como maestros. Se conecta directamente MISO<-->MISO, MOSI<-->MOSI, SCK<-->SCK y SS<-->SS.
    Mientras uno transmite el otro deberá estar escuchando o caso contrario también puedes usar la interrupción "SPI Serial Transfer Complete". La lectura y escritura es similar al UART.
    Para obtener el dato que llegó solamente tienes que leer "SPDR".
    Para escribir primero debes poner "SS=0", luego poner el dato en "SPDR" y dependiendo de la aplicación SS debe volver a '1' ó continuar en '0' hasta que se terminen de enviar los datos.
    Aunque dependiendo de la aplicación quizá tampoco se necesite cambiar el estado de SS.

    ResponderEliminar
  10. Si mira, lo que tengo que hacer es comunicar 3 atmega's 8 por spi 1 maestro y dos esclavos, el maestro va a solicitar a cada uno de los esclavos que le envien informacion para que este la despliegue en LCD, y pues me gustaria saber como realizar la comunicacion...

    ResponderEliminar
  11. http://upload.wikimedia.org/wikipedia/commons/f/fc/SPI_three_slaves.svg
    El enlace muestra la conexión exacta entre los dispositivos (tal como tu lo quieres).

    Primero debes configurar el maestro y el esclavo (En la parte de SPI del manual puedes encontrar la forma de configurar un maestro y un esclavo, ademas de como transmitir y recibir datos).
    Aquí hay un ejemplo de eso.

    //**********************************************
    //**********************************************
    .EQU SCK = PB5
    .EQU MISO = PB4
    .EQU MOSI = PB3
    .EQU SS = PB2
    //**********************************************
    //**********************************************
    SPI_MasterInit:
    ; Set MOSI and SCK output, all others input
    ldi r17,(1<<MOSI)|(1<<SCK)|(1<<SS)
    out DDRB,r17
    ; Enable SPI, Master, set clock rate fck/16
    ldi r17,(1<<SPE)|(1<<MSTR)|(1<<SPR0)
    out SPCR,r17
    ret

    SPI_MasterTransmit:
    ; Start transmission of data (r16)
    out SPDR,r16
    Wait_Transmit:
    ; Wait for transmission complete
    sbis SPSR,SPIF
    rjmp Wait_Transmit
    ret

    //**********************************************
    //**********************************************

    SPI_SlaveInit:
    ; Set MISO output, all others input
    ldi r17,(1<<MISO)
    out DDRB,r17
    ; Enable SPI
    ldi r17,(1<<SPE)
    out SPCR,r17
    ret

    SPI_SlaveReceive:
    ; Wait for reception complete
    sbis SPSR,SPIF
    rjmp SPI_SlaveReceive
    ; Read received data and return
    in r16,SPDR
    ret
    //**********************************************
    //**********************************************

    ResponderEliminar
  12. HOLA BUEN DIA, NECESITO AYUDA ESPERO ME PUEDAS ORIENTAR HACERCA DE COMO HACER UNA DECODIFICADOR DE CONTROL REMOTO MEDIANTE ATMEGA8. NECESITO MOSTRAR EN UN LCD EL BOTON DEL CONTROL QUE PRESIONE, ESPERO QUE ME PUEDAS DAR UNA IDEA DE COMO HACERLO GRACIAS.
    SALUDOS.

    ResponderEliminar
  13. Gracias, muchas gracias por tu ayuda me sirvio de mucho si pude comunicar los 3 atmega8 mediante protocolo spi saludos, y mil gracias.

    ResponderEliminar
  14. una consulta sabes donde puedo comprar el atmega 16u4 lo necesito para hacer unas pruebas y donde puedo comprar el programador usbaso y el cp2112
    sergio

    sergio_canchumani@hotmail.com

    ResponderEliminar
  15. Hola Sergio. No creo que aquí en Lima puedas encontrar el ATmega16u4 (tienes que importarlo).
    Los USBasp y el CP2112 que se muestran en la figura de arriba yo mismo los vendo. Si estas interesado escríbeme.

    ResponderEliminar