Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Curso Avanzado 8.0 PDF
Curso Avanzado 8.0 PDF
CURSO AVANZADO DE
PROGRAMACIN EN C DE
MICROCONTROLADORES AVR
dinfante29@hotmail.com
dinfante@itmorelia.edu.mx
Revisin 8.0
Septiembre del 2008
Programacin en C de los microcontroladores ATMEL Autor: David Infante Snchez
e-mail: dinfante29@hotmail.com www.comunidadatmel.com
CAPTULO III. TPICOS AVANZADOS
3.1 Manejo de las Interrupciones INT0 e INT1
Existen dos tipos de interrupcin las internas o de software y las externas o de hardware,
por ejemplo la de reset es una externa ya que est asociada a una terminal. Las de software
son generadas por alguna condicin en los perifricos, por ejemplo podemos habilitar una
interrupcin cuando el ADC termine de hacer la conversin, o cuando suceda overflow en
el timer, etc.
Por ejemplo hay interrupciones que son por flanco de bajada en un pin, entonces, suceder
una interrupcin cuando haya un flanco de bajada en el pin. Las subrutinas de interrupcin
son como las funciones que hemos realizado, con la excepcin de que las subrutinas de
interrupcin SON LLAMADAS POR HARDWARE, es decir el microcontrolador llama a
la subrutina de interrupcin cuando el evento sucede y que puede ser en cualquier
momento, en cambio las funciones que define el usuario son llamadas por el software segn
donde haya escrito el programador el llamado de la funcin.
En la figura 3.1 apreciamos las interrupciones externas INT0 e INT1 que estn en los pines
4 y 5 del microcontrolador. Estas interrupciones las podemos configurar para que cuando
exista un 0 (low level) se genere una interrupcin, si cuando salga de la interrupcin sigue
Importante. Vimos que la INT0 e INT1 son los pines 4 y 5, y que a su vez son los puertos
D2 y D3; as que si habilitamos las funciones de interrupcin INT0 y la INT1, debemos
seleccionar esos pines para que sean de entrada; no debemos habilitarlos como salida
porque ahora ya no funcionan como pines de entrada/salida sino como pines de entrada
donde detectarn un evento (flanco de bajada, subido, ambos o nivel 0 lgico) y en ese
momento saltar a la subrutina de interrupcin.
Para probar las interrupciones de INT0 e INT1 se realizarn algunos programas para
entender su funcionamiento.
Project :
Version :
Date : 16/09/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
#include <mega48.h>
var++;
if (var>9)
var=0;
// Place your code here
void main(void)
{
// Declare your local variables here
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=P State1=T State0=T
PORTD=0x04;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
while (1)
{
PORTB=tabla7segmentos [var];
// Place your code here
};
}
Cuando programe el microcontrolador y conecte el microcontrolador notar que cuando se
presiona el interruptor el display se incrementa en varias unidades y es por la razn de los
rebotes que se generan y que se explicaron en los primeros programas del curso.
Programa 12. Disee un programa que cada vez que haya un flanco de subida o bajada en
la INT1 (pin 5) incremente el valor de un display conectado al puerto B, el cual podr
contar de 0 a 9.
Project :
Version :
Date : 16/09/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
#include <mega48.h>
const char tabla7segmentos [10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x6f};
unsigned char var;
void main(void)
{
// Declare your local variables here
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=P State2=T State1=T State0=T
PORTD=0x08;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
while (1)
{
PORTB=tabla7segmentos [var];
// Place your code here
};
}
Programa 14. Disee un programa que cuando haya un flanco de subida en INT0 se
incremente el conteo del display que podra contar de 0 a 9, y que cuando haya un nivel
lgico de 0 en INT1 se decremente el valor del display.
Tomando como ejemplo esta ltima subrutina de interrupcin indica que cualquier
interrupcin generada de PCINT16 a PCINT23 ejecutar esa subrutina, pero no
necesariamente cuanda haya un cambio de nivel de 0 a 1 y de 1 a 0 en esos pines ejecutar
esa subrutina ya que podemos por el codevision habilitar solamente, por dar un ejemplo,
que se habiliten las interrupciones en PCINT16 y PCINT20. En este caso solamente cuando
haya cambio de nivel en esos pines se ejecutar la subrutina de interrupcin, es decir, que
podemos habilitar de manera individual cada pin.
Programa 14. Cuando exista cambio de nivel en PCINT0 o en PCINT7 que se incremente el
valor de un contador de 0 a 9 que se mostrar en un display conectado al puerto B, cuando
exista un cambio de nivel en PCINT8, PCINT9 o PCINT10 se decrementar el valor del
conteo y cuando exista
Por ejemplo, veamos un programa en el cual se desea detectar cada vez que haya un flanco
de bajada en el PIN 18 que es INT1 se incremente un contador BCD que estar conectado
al puerto B.
El pin 18 que es el pin A2 tiene como funcin alterna la de interrupcin externa INT1, lo
vamos a configurar como fuente de interrupcin para detectar flancos de bajada en el pin y
que se contabilice en un display conectado al puerto B.
Project :
Version :
Date : 04/05/2008
#include <tiny461.h>
void main(void)
{
// Declare your local variables here
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: 8bit top=FFh
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0H=0x00;
TCNT0L=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
while (1)
{
// Place your code here
PORTB=tabla7segmentos [conteo];
};
}
while (1)
{
// Place your code here
PORTB=tabla7segmentos [conteo];
};
Otra diferencia que podemos hacer con respecto a los PICs es que los PICs slo tienen un
vector de interrupcin y por tanto saltan a la misma subrutina donde el programador debe
checar cul interrupcin se gener, en cambio los AVR tienen vectores de interrupcin
distintos por lo que el manejo de interrupciones es decenas de veces ms rpido que los
PICs porque estos saltan al mismo vector que los manda a una sola subrutina donde debe
probar cada interrupcin para saber cul fue la que la gener.
Programa 20. Realizar un programa que cuando haya una interrupcin por flanco de subida
en la INT0 se prender un led, y cuando detecte un flanco de subida en INT1 se apagar. El
Led se conectar en el pin B0.
En el siguiente diagrama vemos que la terminal 20 tiene marcado PCINT0 hasta la terminal
10 que tiene PCINT15. Esto significa PIN CHANGE INTERRUPT X, es decir que se
puede generar una interrupcin cuando cambia de nivel lgico esos pines. Si conectaramos
a esos pines un interruptor se generara una interrupcin tanto cunado se presiona el
interruptor como cuando se suelta, ya que se generara un cambio de nivel en ambos casos.
A diferencia de las interrupciones INT0 e INT1 (pines 9 y18) los PCINTX slo funcionan
por cambio de nivel lgico es decir en flanco de subida y bajada; y los INT0 e INT1 si los
Programacin en C de los microcontroladores ATMEL Autor: David Infante Snchez
e-mail: dinfante29@hotmail.com www.comunidadatmel.com
podemos configurar para que funcionen por flanco de subida, bajada, ambos o por nivel
lgico 0.
La otra diferencia es que las INT0 e INT1 tienen una subrutina de interrupcin distinta. En
cambio e la interrupcin PCINT tiene una sla que es la siguiente :
El timer0 est asociado a los pines D5 y D6 (11 y 12), el timer1 est asociado a los pines
B1 y B2 (15 y 16) y el Timer2 est asociado a los pines D3 y B3 (5 y 17).
Indico que determinados pines estn asociados a un timer es por la razn de que cuando
sucede algn evento en el timer se pueden modificar esos pines ponindose a 1 a 0 o
cambiando de valor. Esto es que el Timer puede modificar directamente dos pines
asociados a l.
TCNT0. El corazn del timer0 es el contador TCNT0 (Counter of Timer 0) de 8 bits que
puede contar desde 0 hasta 255, el cual se va incrementando a la frecuencia interna del
microcontrolador dividido entre el preescalamiento de 1, 8, 64, 256 o 1024 seleccionado.
Es importante sealar que el preescalador divide nicamente la frecuencia de operacin del
timer y no la frecuencia del microcontrolador. Vea la siguiente figura, en ella se aprecia que
la frecuencia del oscilador interno es de 8 Mhz, el cual es dividido por 8, por lo que la
frecuencia de trabajo es de 1MHz. Esa frecuencia es para el CPU y los perifricos, pero a
su vez se puede dividir la frecuencia del timer por 1,8 64, 256 o 1024 pero esa divisin slo
afecta al timer y no a la frecuencia de operacin del CPU u otros perifricos del
microcontrolador. Esa frecuencia preescalada es la que determina cada cundo se va a
modificar el timer que es el TCNT0, el valor del TCNT0 se va comparando
automticamente con el OCR0A (Registro de Comparacin del Timer 0 salida A que es el
pin D6) y con el OCR0B (Registro de comparacin del Timer 0 salida B que es el pin D5),
cuando el TCNT0 es igual a uno de esos registros pueden programarse las acciones de: no
OCROB. Este registro de comparacin del Timer0 Salida B es un registro de 8 bits que
puede modificar el programador y que continuamente se compara de manera automtica
con el TCNT0 y cuando son idnticos se puede generar una accin al Pin D5 que es el pin
asociado a la salida B del timer0.
El timer puede ser preescalado por 1, 8, 64, 256 o 1024 esto significa que si la frecuencia
de operacin del microcontrolador es de 1MHz, puede operar el timer a 1MHz, 125KHz,
15.625KHz, 3906.25 Hz y 976.5625Hz. Suponga que el microcontrolador est operando a
1MHz, entonces el timer trabajar a 1MHz (si est preescalado por 1), pero si se preescala
por 1024 entonces trabajar la frecuencia del timer ser 976.5625Hz. Pero recuerde que esa
frecuencia es la velocidad con la que se incrementar en una unidad el timer, y que el timer
cuenta 256 pulsos.
Si configuramos el timer para que se preescale entre 1024 entonces la frecuencia del timer
ser de 976.5625 Hz, y el periodo ser de 1.024 mS as que el timer se incrementar en 1
unidad cada 1.024mS. El tiempo que le llevar al timer ir desde 0 hasta 255 sern 256
cuentas*1.024mS=0.262144 Segundos.
Las siguientes tablas deber tenerlas en mente para los clculos usados para programar el
timer, y tambin tenga en cuenta que estas tablas son vlidas son para una frecuencia
interna de 1MHz, as que si coloca un cristal externo entonces deber recalcular estas tablas
a esa frecuencia usada.
Con los tiempos anteriores podemos calcular el tiempo que le tomar al timer ir de 0 hasta
255 (256 cuentas)
Importante. Recuerde que estas tablas son para una frecuencia de operacin del
microcontrolador de 1 Mhz y que si conecta otro cristal deber calcular los tiempos y
frecuencias.
SEALES PWM. Una seal PWM (Pulse Width Modulation) o modulacin por ancho de
pulso tiene las siguientes caractersticas: El periodo de la seal es fijo, lo que cambia es el
ancho de pulso.
PWM no invertida, en esta figura se aprecia que el periodo de la seal es fijo y lo que se
modifica es el ancho de pulso, en el primer ciclo la modulacin est al 50%, esto es que
durante todo el periodo de la seal estar en 1 el pulso, en el siguiente ciclo se encuentra la
modulacin es del 75%, as que estar en 1 durante partes del periodo de la seal, y en el
ltimo ciclo est al 100% la modulacin, as que est en 1 todo el tiempo que dura el
periodo de la seal.
Las seales PWM son muy utilizadas en control de energa de CA y CD. Si conectramos
un LED con un PWM al 50% veramos que est ligeramente encendido, si subimos el
ancho de pulso el LED prendera con mayor intensidad, y si la modulacin est al 100% el
LED prendera al mximo de intensidad lumnica.
PWM invertida. En una seal PWM invertida la modulacin es cunto tiempo estar en 0 la
seal. Cuando est al 75% significa que partes del periodo de la seal estar en 0. Vea la
siguiente figura de una seal PWM invertida al 50%, 75% y 100%.
En la figura anterior se nota que el pulso va creciendo con respecto al centro, y que si la
modulacin es del 50% entonces durante 50% del tiempo del ciclo estar en 1 pero
centrado con respecto al periodo de la seal.
Estos modos de modulacin del PWM se ilustraron y explicaron debido a que con el
TIMER del ATMEGA es posible generarlos con su timer.
En los siguientes subtemas se pondr el modo de funcionamiento del timer en ingls que es
como lo pone el wizard del codevision y en espaol no ser propiamente su traduccin, sino
ser una traduccin basada en su funcionamiento.
Registros de comparacin OCROA y OCROB, estos dos registros significan que dar una
salida a la comparacin con el timer (Output A Compare Register of Timer 0 y Output B
Compare Register of Timer 0), estos registros son accesibles para que el programador les
escriba un nmero y se comparan continuamente y de manera automtica con el timer
(TCNT0) y cuando se hacen iguales se genera una accin.
OCR0A=100;
OCR0B=200;
Significa que cuando el timer (TCNT0) tenga el valor de 100 se generar una accin, y
cuando el timer (TCNT0) valga 200 se generar otra accin.
Note que el OCR0A est asociado al pin D6 y el OCR0B est asociado al pin D5.
Las acciones que se generarn a la comparacin con el OC0A y OC0B se configuran con el
wizard del codevision.
Programa timer1. Configure el timer0 de tal manera que en la salida B (pin D5) se genere
una seal cuadrada que dur 2.048 mS en bajo y 2.048 mS en alto. En este modo de
Programacin en C de los microcontroladores ATMEL Autor: David Infante Snchez
e-mail: dinfante29@hotmail.com www.comunidadatmel.com
operacin el periodo de la seal no se puede modificar porque el timer siempre cuenta
desde 0 hasta FF, y de los clculos antes vistos tenemos:
Con los tiempos anteriores podemos calcular el tiempo que le tomar al timer ir de 0 hasta
255 (256 cuentas)
Luego debemos configurara para que la accin a generar en la comparacin del TCNT0 con
el OCR0B sea Toggle on Compare Match para que cuando sean iguales el estado del pin
D5 se invierta de valor.
Qu valor debemos poner en OCR0B? No importa el valor que se ponga porque sin
importar el valor que tenga sucedern 256 pulsos ms para que cambie de valor. Vea la
siguiente figura:
Si en OCR0B coloca un 10, transcurrirn 256 cuentas para que suceda otro 10 e invierta el
estado del pin, si coloca un 20 sucedern 256 cuentas para que ocurar otro 20, as que no
importa el valor que le ponga al OCR0B. Para este ejemplo pondremos un 100d.
Tabla de conteo mximo del timer (256 Cuentas) con una frecuencia de 1MHZ
Periodo de una cuenta Tiempo que le llevar contar 256 cuentas
1 S (1MHz) 256 S
8 S (125KHz) 2.048 mS
64 S (15.625KHz) 16.284 mS
256 S (3906.25 Hz) 65.536 mS
1.024 mS (976.565 Hz) 0.262144 S
Si quisiramos generar seales cuadradas con una frecuencia digamos de 2Khz, debemos
hacer lo siguiente:
El periodo de una seal de 2KHz es 0.5mS, con 0.25mS en alto y 0.25mS en bajo, por lo
que debemos escoger un preescalamiento que d ms de 0.5mS para que quepa la seal que
queremos generar, de esa forma vemos que podemos seleccionar cualquier preescalamiento
del segundo en adelante, porque en el primero el tiempo mximo que podemos medir son
256S y ocupamos que sea mayor a 0.5 mS, pero cul de todos es el ms adecuado? Para
ello pondr el siguiente ejemplo: Cuando va a medir 1.5 Volts Cul escala selecciona 2, 20
o 200 Volts? Selecciona el ms cercano es decir 2 Volts para una mayor resolucin; para el
timer razonamos de la misma forma, cul se encuentra ms cercano a 0.5mS la opcin sera
la frecuencia de 125 Khz que est resaltada en verde porque el periodo del timer a las 256
cuentas da 2.048 mS.
Una cuenta con la frecuencia de 125 Khz tarda 8uS, entonces queremos que la seal cambie
cada 0.25mS, as que traducido en cuentas sera 0.25mS/8uS=31.25 cuentas, pero no
podemos 31.25 as que lo redondeamos a 31.
A las 31 cuentas conmutar el pin y se generar una interrupcin donde instrucciones para
actualizar el registro OCR0A a 62, cuando el TCNT0 sea igual a 62 cambiar el pin y se
generar una interrupcin para actualizar el OCR0A a 93 y as sucesivamente.
Ve el vdeo timer2 donde se explica la inicializacin del timer para el siguiente programa.
Programa timer2. Configure el timer para generar una seal cuadrada con una frecuencia
de 2KHz que se generar en el pin D6 (salida A del timer0).
Note que cuando nos genera la subrutina de interrupcin coloca como comentario en la
parte superior: // Timer 0 output compare A interrupt service routine Esto es til para que el
programador sepa de cul subrutina de interrupcin se trata. Ese comentario traducido es:
Subrutina de Interrupcin por Comparacin de la salida B del timer0. Recuerde que las
subrutinas de interrupcin no las llama el programador, sino el evento, que en este caso es
cuando el TCNT0=OCR0A si son iguales salta a esa subrutina de interrupcin.
Entonces cuando el OCR0A con el TCNT0 qu debemos hacer: leer el valor del OCR0A y
sumarle 31 para que se compare 31 cuentas despus que son 0.25mS.Es decir que el cdigo
que colocaremos en esa subrutina de interrupcin es:
OCR0A=CR0A+31;
Recuerde que es importante indicar en la parte de chip que es el ATMEGA48 y que se est
trabajando a 8 MHz y dividido entre 8 como en todos los programas que hemos realizado.
El listado del programa genereado por el wizard es el siguiente, lo que deber agregar a su
programa es lo que est en azul.
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.6 Evaluation
Automatic Program Generator
Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 02/11/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
#include <mega48.h>
void main(void)
{
// Declare your local variables here
// Port C initialization
// Port D initialization
// Func7=In Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=0 State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x40;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=FFh
// OC0A output: Toggle on compare match
// OC0B output: Disconnected
TCCR0A=0x40;
TCCR0B=0x02;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
while (1)
{
// Place your code here
};
}
La traduccin de este modo sera PWM con correccin de fase y quizs no le d una idea
clara, pero en otras palabras y segn su funcionamiento es: PWM centrado con periodo de
510. La razn de este periodo doble es que un ciclo del timer es cuando va de 0 hasta 255 y
de ah regresa a 0, es por ello que el periodo se hace de 510 pulsos (2*255) de reloj.
Aqu tambin se utilizan los registros de 8 bits del timer 0 que son OCR0A y OCR0B, estos
dos registros se comparan de manera automtica con el timer (TCNT0) y cuando se hacen
iguales pueden suceder las siguientes acciones en los pines D6 y D5 que es donde estn
asociados los registros respectivamente:
Ejemplo. Suponga que se configura el timer en el modo de Phase Correct PWM top=FFh
y se selecciona la salida A en Non Inverted PWM y se carga en OCR0A=100; y la salida
B en Inverted PWM y se carga en OCR0B en 200; en la siguiente figura se ilustra la
forma de la seal en el PIND6 que es la asociada a la salida A (OCR0A) y el PIND5 que es
la asociada a la salida B (OCR0B).
En la figura vea que el contador inicia en 0 y llega hasta 255 despus al siguiente pulso el
timer comienza a decrementarse por eso el siguiente conteo es 254 hasta llegar a 0 (el
periodo es 510 cuentas porque va de 0 al mximo y de ah se decrementa). En la salida A se
seleccion Non Inverted PWM, y se carg en el OCR0A un 100, entonces cuando el
TCNT se iguala al OCR0A se pone a 1 el pin D6 y cuando se vuelve hacer el TCNT igual
al OCR0A se pone en 0.
Si ha cursado materias de control y de potencia notar que estas seales ilustradas son
tiles en control de motores.
Con los tiempos anteriores podemos calcular el tiempo que le tomar al timer ir de 0 hasta
255 y regresar a 0 (510 cuentas), esta tabla cambia con respecto a las antes vistas debido a
que el timer cuenta 510 pulsos.
Note que no podemos modificar el periodo de la seal, ya que el nmero de cuentas es fijo
y es de 510 adems de que las frecuencias preescaladas es limitada 5 opciones.
Si queremos un ancho de pulso del 50% tenemos que cargar en el OCR0B un 127, porque
127 es la mitad del 255. Vea el siguiente diagrama para que vea el periodo de 510 pulsos y
que con 127 en el OCR0B se tiene el 50% del ancho de pulso.
Cuando el TCNT0 va incrementndose y se hace igual al 127 del OCR0B se pone a 1 el pin
D5 y se mantiene as hasta que el TCNT0 va decrementndose y se vuelve hacer igual a
127.
En este modo el timer (TCNT0) cuenta desde 0 hasta 255, al siguiente pulso inicia en 0
hasta llegar a 255 cuentas y as sucesivamente. En este caso el periodo de la seal es de 256
cuentas. La salida A del timer0 (TCNT0) se iguala al valor del OCR0A o al OCR0B
pueden suceder las siguientes acciones sobre el pin D6 y D5 respectivamente:
En la siguiente figura vemos que el periodo es de 256 cuentas, ya que el timer0 (TCNT0 va
desde 0 hasta 255), el siguiente conteo a 255 es el 0 para iniciar nuevamente el conteo.
Suponga que la salida A del timer0 asociada al pin D6 se configura como Non-Inverted
PWM y se carga en el OCR0A un 100, entonces al inicio del conteo del timer el pin D6
(lnea roja) el pin est en 0, cuando el TCNT0 se hace igual al OCR0A se pone a 1 el pin, y
se mantiene en 1 hasta que el timer llega a 255, al siguiente pulso el timer regresa a 0
repitindose el ciclo del timer0 e iniciando el pin en 0.
Considere que la salida B del timer0 (asociada al pin D5) se configura como Inverted PWM
y que se carga en el OCR0B un 200, entonces al inciio del conteo del timer el pin D5 (lnea
azul) se pone en 1 y cuando el TCNT0=OCR0B que es 200 el pin se pone en 0 y se
mantiene en ese estado hasta que llega a 255, luego el timer inicia su ciclo en 0 y tambin el
pin se pone en 1 y se coloca en 0 hasta que nuevamente el TCNT0 se hace igual al OCR0B.
Importante. Recuerde que si va a utilizar un pin como entrada analgica del ADC deber
configurarlo como entrada y sin resistencia de pull-up ese pin. En caso de que lo configure
como salida el pin y le aplique un voltaje puede daar el pin.
Ese error es porque la subrutina del ADC est abajo de la subrutina de interrupcin de
sobreflujo, entonces al llamar la funcin de read_adc(0) no la encuentra porque la subrutina
est abajo. Entonces debe invertir esa dos subrutinas: copie el cdigo del ADC en la parte
superior y la del timer en la parte de abajo. (son los bloques de cdigo verde y rosa) y
debern quedar como se muestra en este listado.
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.6 Evaluation
Automatic Program Generator
Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 27/10/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
#include <mega48.h>
#include <delay.h>
void main(void)
{
// Declare your local variables here
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=0 State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x20;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: Fast PWM top=FFh
// OC0A output: Disconnected
// OC0B output: Non-Inverted PWM
TCCR0A=0x23;
TCCR0B=0x03;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
// ADC initialization
// ADC Clock frequency: 500,000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: None
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
// ADC4: On, ADC5: On
while (1)
{
// Place your code here
};
}
Foto a) Modulacin con un ancho de pulso muy pequeo, note que el voltaje medio es de
64.2mV por lo que el led tendr una intensidad muy baja.
En la foto anterior el ancho de pulso es ms grande y por lo tanto el voltaje promedio sube.
Pero existen otros tres modos en los cuales el programador puede configurar el periodo de
la seal, recuerde que el periodo se fija en nmero de cuentas. Estos modos los veremos a
continuacin.
4.5 Modo CTC top =OCR0A (Timer contando desde 0 y con tope el valor de OCR0A)
Este modo Clear Timer on Compare with OCR0A o traducido segn su funcionamiento es:
reinicializacin del timer cuando se haga igual al OCR0A, es decir que si seleccionamos
este modo de operacin el OCR0A es el tope del timer0, entonces si OCR0A=100 entonces
el timer contar de 0 hasta 100 y al siguiente conteo regresar a 0 el timer para continuar su
conteo. Vemos que en este modo el programador fija el periodo de la seal a travs del
registro OCR0A.
Programa Timer5. Disear un programa que cada 10mS cambie de estado el pin B0. Para
ello se utilizar la interrupcin por comparacin con el OCR0A. Aqu notamos que el pin
B0 no est asociado a ningn timer, pero aqu usaremos el timer como un temporizador, no
como un generador de seales, as que cada 10mS se generar una interrupcin en la cual se
cambiar de estado el pin B0.
Para empezar necesitamos seleccionar una frecuencia del timer que multiplicada por 256
cuentas sea la ms cercana y mayor a 10mS. Los 10 mS caben en una frecuencia de conteo
de 15.625KHz.
Cuntas cuentas debe tener el timer para que genere una interrupcin cada 10mS?
10mS/64uS=156.25 pero como deben ser enteros sera un 156. El timer contar desde 0
hasta 156 y luego regresar a 0 hasta llegar a 156 y as continuamente. Cuando el timer
llegue a 156 sucedern dos cosas: el timer regresa a 0 al siguiente conteo y el timer ser
igual al OCR0A. En este programa activaremos la interrupcin por comparacin con el
OCR0A y en esa interrupcin cambiaremos de estado el pin B0. Note que la interrupcin
se generar cada 156 cuentas que corresponden a 10mS.
Quien define el valor mximo al que contar el timer en este modo es el OCR0A. Entonces
hacemos OCR0A=156d que en hexadecimal es 9Ch.
Esta subrutina de interrupcin ser llamada cada vez que el TCNT0 sea igual al OCR0A, y
esto suceder cada 156 cuentas, que en tiempo corresponde a 10mS, y en esa subrutina
deberemos colocar:
PORTB.0=~PORTB.0;
Y eso hace que el pin B0 cambie de valor, y esto suceder cada 10mS,
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.6 Evaluation
Automatic Program Generator
Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 03/11/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
#include <mega48.h>
void main(void)
{
// Declare your local variables here
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x02;
TCCR0B=0x03;
TCNT0=0x00;
OCR0A=0x9C;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
while (1)
{
// Place your code here
};
}
4.6 Modo Fast PWM Top=OCR0A (PWM con ajuste de periodo dado por OCR0A)
En este modo el periodo de la seal PWM se ajusta con el registro OCR0A, por ejemplo si
OCR0A=100 significa que el timer contar desde 0 hasta 100 y despus regresar a 0.
Entonces el registro OCR0B se utiliza para ajustar el ancho de pulso del PWM.
Programa Timer6. Se desea una seal PWM con un periodo de 100S, con un ancho de
pulso del 75%, entonces en este modo si podemos ajustar el periodo del timer, para ello
vemos la siguiente tabla y con un preescalamiento de 1 el timer se incrementa cada 1S y el
timer puede contar hasta 256, por lo que si queremos 100S se escoge ese preescalamiento
y se coloca en OCR0A=100; y el ancho de pulso de 75% corresponde a un 75 que se
cargar en el OCR0B. Entonces la seal PWM se mostrar sobre la salida B. Note que en
este modo el OCR0A fija el periodo en cuentas del PWM y el OCR0B es para establecer el
ancho de pulso del PWM.
El wizard generar el siguiente cdigo y no ser necesario agregar ms cdigo para que el
programa genere la seal deseada.
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.6 Evaluation
Automatic Program Generator
Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 03/11/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
#include <mega48.h>
void main(void)
{
// Declare your local variables here
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=0 State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x20;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: Fast PWM top=OCR0A
// OC0A output: Disconnected
// OC0B output: Non-Inverted PWM
TCCR0A=0x23;
TCCR0B=0x09;
TCNT0=0x00;
OCR0A=0x64;
OCR0B=0x4b;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
while (1)
{
// Place your code here
};
}
Este modo es idntico al modo Phase Correct PWM top=FFh pero la diferencia radica que
el timer no contar hasta FFh sino hasta el valor del OCR0A y cuando se iguala el TCNT0
al valor del OCR0A el timer se reinicializa a 0. Las acciones que pueden generarse en los
pines D5 y D6 son las descritas en el modo Phase Correct PWM top=FFh.
El timer 2 es idntico al timer 0 en el tipo de seales que genera, adems de que el contador
es de 8 bits, pero con las siguiente diferencias:
El timer0 puede preescalar la frecuencia entre 1,8,64,256 y 1024 por lo que para una
frecuencia interna de 1MHz se tienen las siguientes frecuencias del timer0.
Importante. cuando maneje el timer2 deber usar los registros de comparacin asociados a
l que son OCR2A y OCR2B que son los registros de comparacin del timer 2.
Importante. Los valores de frecuencias y periodos que se muestran en la Tabla del timer 2
son calculados considerando una frecuencia de operacin interna de 1MHz, pero si va usar
otro frecuencia de cristal distinta deber calcular esos datos.
El timer1 es de 16 bits (TCNT1) por lo que puede contar desde 0 hasta 65535 (0 hasta
FFFFh), as que los registros asociados a l son de 16 bits.
Puede preescalarse la frecuencia del timer entre 1,8,64,256 y 1024 por lo que para una
frecuencia interna de 1MHz se tienen las siguientes frecuencias de operacin del timer1.
Pero la diferencia del timer0 y timer2 es que el timer1 es de 16 bits por lo que calculamos
la siguiente tabla para cuando el timer cuenta hasta FFFFh pulsos:
4.9.1 Modo Normal top FFFFh (Modo de conteo desde 0 hasta FFFFh)
En este modo el timer va desde 0 hasta FFFF cuando el timer1 llega a FFFF el siguiente
conteo es cero (esto se conoce como sobreflujo y se puede programar una interrupcin cada
vez que llega al valor mximo).
Programa Timer7. Haga un programa que cada segundo cambie de estado el pin B1 donde
se conectar un LED, el led se prender y apagar una vez por segundo.
Primero vemos el preescalamiento que permita medir tiempos de 1 segundo y que est lo
mas cercano a l, as encontramos que se debe preescalar entre 64 la frecuencia del timer
para que opere a 15.625KHz la velocidad de incremento del timer1 y que le llevar
4.194304 Segundos contar desde 0 hasta FFFFh al timer1.
La inicializacin del timer1 se muestra en la siguiente figura, note que en la parte de abajo
donde est COMP. A escribimos 3d09h que corresponde 15625d y que eso en tiempo es
1 segundo. Y tambin se dio click en Interrupcin por Compare Match A que significa
que se va a generar una interrupcin cuando el timer1 sea igual al registro A.
TPICOS SELECTOS DE
PROGRAMACIN DE
MICROCONTROLADORES AVR
dinfante29@hotmail.com
dinfante@itmorelia.edu.mx
Revisin 2.0
Abril del 2008
Instrumentacin Virtual
Programas
1. Osciloscopio digital con despliegue en PC
2. Medidor de temperatura y despliegue en instrumentos virtuales
3. Medidor de nivel a travs de sensores de ultrasonido y despliegue en
instrumentos virtuales
Telemetra
Programas
1. Control de puertos de E/S a travs de radio frecuencia, manipulados a travs
de instrumentos virtuales diseados con LABVIEW
2. Control de la intensidad luminosa de un foco por radio frecuencia y
LABVIEW
Para este curso es necesario contar con el sofware de MATLAB, LABVIEW y CodeVision,
y el curso consta de una introduccin a LABVIEW y teora de procesamiento de seales,
as como su programacin en MATLAB para el diseo de los filtros.