Sie sind auf Seite 1von 287

Microcontroladores

Instituto Tecnolgico Superior de Teziutln


Academia de Ingeniera Mecatrnica
Cuerpo Acadmico Calidad y Mejora Continua en Servicios Tecnolgicos

Recopilador
M.S.C.MiguelMontielMartnez

PRESENTACIN
En esta recopilacin se presentan las caractersticas, programacin e interfaces generales de los
microcontroladores ATMega32U4, siendo este dispositivo elegido por contar con una razonable
cantidad de memoria FLASH (32KB), RAM (2KB) y EEPROM (1KB), un mdulo USB que le permite
comunicarse con un equipo de cmputo por medio del protocolo USB-CDC y sobre todo, de tener un
bootloader de fbrica el cual permite su programacin desde un entorno propietario, as como desde un
entorno abierto.
Este microcontrolador permite muy bien su interaccin con el compilador libre AVR-GCC y/o WINAVR, esto depender del gusto personal de la persona que interactu y siga las prcticas sugeridas en
este repositorio.
Es importante agregar que este dispositivo fue elegido entre otras cosas por la facilidad e interaccionar
con la Herramienta XFuzzy 3.1 de la Universidad de .... con la cual se puede generar de una manera
muy sencilla las librerias necesarias en AVR-GCC para desarrollar un sistema difuso de pequea a
mediana complejidad, de igual forma, con miras a interactuar con otras materias tales como Control,
Control Digital y Programacin Avanzada de la Retcula de formacin para un Ingeniero en
Mecatrnica, donde se solicita al estudiante como competencia previa el conocimiento de
microcontroladores, sus interfaces de potencia y comunicacin para lograr el diseo de sistemas de
control ya sean monitoreados o controlados digitalmente.
El microcontrolador ATMega32U4 cuenta adems con la capacidad de ser programado como un
dispositivo Teensyduino, de esta forma se acerca al estudiante a material que se encuentra en gran
abundancia en el entorno digital que ahora nos vemos inmersos.
Se deja al lector el irse profundizando en la lectura de los contenidos propuestos y en caso de encontrar
errores en la redaccin y/o en la captura, por favor hacrmelos saber.
Finalmente no me queda mas que agradecer la lectura de estos textos que han sido recopilados o
elaborados por mi persona.
Atentamente
Miguel Montiel Martnez
Recopilador

ndice de contenido
Unidad 1 Conceptos introductorios a los microcontroladores...................................................................6
1.1 Diferencia entre microcontrolador, microcomputadora y microprocesador...................................7
1.2 Caractersticas y aplicaciones de los microcontroladores...............................................................9
1.3 Tipos de arquitecturas computacionales........................................................................................13
1.3.1 La arquitectura de un microcontrolador................................................................................13
1.4 Tipos de Microcontroladores y sus fabricantes.............................................................................16
Unidad 2 Arquitectura interna de un microcontrolador...........................................................................19
2.1 Componentes del Microcontrolador..............................................................................................20
2.2 Registro internos............................................................................................................................20
2.3 Tipos y distribucin de las memorias internas..............................................................................21
2.4 Perifricos......................................................................................................................................22
2.5 Las instrucciones del microcontrolador.........................................................................................23
Unidad 3 Caractersticas Elctricas del Microcontrolador.......................................................................25
3.1 Distribucin de terminales.............................................................................................................26
3.2 Caractersticas del reloj del sistema..............................................................................................33
3.3 El Reset y sus posibles fuentes......................................................................................................40
3.4 Caractersticas de la fuente de alimentacin y consumo de potencia del MCU............................41
3.4.1 Modo Idle..............................................................................................................................41
3.4.2 Modo Reduccin de ruido en ADC.......................................................................................41
3.4.3 Modo Power-down................................................................................................................41
3.4.4 Modo Power-save..................................................................................................................41
3.4.5 Modo Standby........................................................................................................................42
3.4.6 Velocidad mxima vs velocidad............................................................................................42
Unidad 4 Herramientas de desarrollo de los microcontroladores............................................................44
4.1 Ambiente Integrado de desarrollo (IDE) para microcontroladores...............................................45
4.1.1 Ensamblador y Compilador...................................................................................................46
4.1.2 Simulador, debugger y emulador...........................................................................................51
4.1.3 Equipos programadores (downloaders) de microcontroladores............................................53
4.2 Ejemplos de uso de herramientas de desarrollo............................................................................59
Unidad 5 Puertos de entrada y salida.......................................................................................................62
5.1 Arquitectura de los E/S..................................................................................................................63
5.2 Configuracin y caractersticas elctricas de los puertos de E/S..................................................63
5.3 Usos de los puertos con interfaces para dispositivos perifricos como:.......................................64

5.3.1 Teclados Lineales y Matriciales.............................................................................................64


5.3.2 Display de 7 segmentos.........................................................................................................71
5.3.3 Detectores de proximidad......................................................................................................78
5.3.3.2 El sensor Infrarrojo modulado en frecuencia.................................................................78
5.3.3.3 El Sensor ultrasnico SRF-04........................................................................................78
5.4 Uso de los puertos para manejo de potencia con interfaces con:..................................................80
5.4.1 Transistores, Darlingtons, MOSFETS y relevadores.............................................................80
5.4.2 Optotransistores, optoacopladores y optotriacs.....................................................................86
5.4.3 Puentes H discretos e Integrados...........................................................................................90
5.5 Ejemplo del uso de las interfaces para controlar:..........................................................................91
5.5.1 Motores de DC.......................................................................................................................91
5.5.2 Motores a pasos...................................................................................................................100
5.5.3 Servomotores.......................................................................................................................102
Unidad 6 Interrupciones en un microcontrolador..................................................................................107
6.1 El manejo de las interrupciones...................................................................................................108
6.1.1 Tipos de interrupciones........................................................................................................108
6.1.2 Los vectores de interrupcin................................................................................................108
6.1.3 Las acciones del MCU al responder a una interrupcin......................................................110
6.1.4 Caractersticas de la rutina manejadora de interrupcin......................................................111
6.2 Las interrupciones externas.........................................................................................................112
6.2.1 Caractersticas y configuracin............................................................................................112
6.2.2 Programacin y uso.............................................................................................................112
6.3 Fuentes internas de interrupciones..............................................................................................127
6.3.1 De los timer y contadores....................................................................................................127
Clculo de la Temporizacin en Modo Normal............................................................................135
6.3.2 ADC..........................................................................................................................................139
6.3.3 De la comunicacin serial....................................................................................................139
6.3.4 Del comparador analgico...................................................................................................141
6.3.5 De la EEPROM...................................................................................................................142
6.4 Ejemplos de aplicaciones de las interrupciones..........................................................................142
Unidad 7 Programacin del microcontrolador con aplicaciones...........................................................177
7.1 Tcnicas de control de motores usando:......................................................................................178
7.1.1 PWM....................................................................................................................................178
7.1.1.1 Configurando el PWM en el ATMega32U4 con el Timer 0........................................183
7.1.2 Encoders incrementales como sensor de velocidad y sentido de giroscopio.......................187

7.2 Control de sentido de giro, de posicin y de velocidad...............................................................192


7.2.1 Motores de corriente directamente......................................................................................195
7.2.2 Motores de pasos.................................................................................................................201
7.2.2.1 Clculo de la potencia disipada en un controlador MOSFET para un motor a pasos
usando la tcnica de medios pasos...........................................................................................201
7.4.2.2 Clculo de la energa disipada durante el tiempo Tr...............................................202
7.2.2.3 Determinacin de la energa disipada en TLD........................................................204
7.2.2.4 Determinacin de la energa disipada en el tiempo de espera.................................204
7.2.2.5 Determinacin de la energa total disipada y potencia total disipada en el mosfet de
conmutacin........................................................................................................................205
Unidad 8 El convertidor ADC y DAC...................................................................................................208
8.1 Arquitectura Interna.....................................................................................................................209
8.2 Configuracin y programacin....................................................................................................209
Unidad 9 Puertos seriales y memoria EEPROM...................................................................................219
9.1 El USART....................................................................................................................................220
9.1.1 Libreras para el control del puerto serial............................................................................220
9.1.2 Ejemplo de recepcin de datos desde una terminal de comunicacin serial GtkTerm o
CuteCom hacia el microcontrolador ATmega32U4......................................................................225
9.1.3 Acceso como usuario normal al puerto serial e instalacin de RxTx..................................227
9.1.5 Envo de Datos del microcontrolador hacia el PC usando Scilab 5.x.................................232
9.2 TWI (I2C)....................................................................................................................................237
9.3 Leer y escribir sobre EEPROM I2C............................................................................................249
9.3.1 Lectura y escritura simple de sobre una EEPROM I2C......................................................250
9.3.2 Lectura escritura controlada por el puerto de comunicacin serial.....................................254
Referencias........................................................................................................................................283

Unidad 1
Conceptos introductorios a los microcontroladores

Unidad 1 Conceptos introductorios a los microcontroladores


1.1 Diferencia entre microcontrolador, microcomputadora y microprocesador.
1.2 Caractersticas y aplicaciones de los microcontroladores
1.3 Tipos de arquitecturas computacionales.
1.4 Tipos de Microcontroladores y sus fabricantes.
Competencia especfica
catalogar los diferentes tipos y caractersticas de los microcontroladores.
Actividades de aprendizaje

Cuadro Comparativo: Marcar las diferencias mas importantes entre Microcomputadora,


Microcontrolador y Microprocesador.

Investigacin documental: Acuar las principales caractersticas sobre microcontroladores de 8


bits y sus fabricantes.

1.1 Diferencia entre microcontrolador, microcomputadora y


microprocesador

Es comn escuchar que los trminos microcontrolador, microcomputadora y microprocesador se


intercambian, sin embargo, cada uno es diferente del otro, y es importante entender la diferencia en este
punto.
Definiciones:
Microprocesador. Es una unidad central de procesamiento en un nico circuito; en los 60's los diseos
de microprocesadores se hacan mediante arreglos de varios circuitos MSI y LSI.
Intel, coloca todos los componentes de un CPU en un solo circuito (Unidad lgico Aritmtica,
Decodificador de instrucciones circuteria de control de bus, etc.) al cual denomina 4004, es entonces
cuando nace el Microprocesador (MPU).
Microcomputadora. Cuando un microprocesador y circuiteria perifrica de entrada y salida, memoria se
colocan reunidos en una pequea computadora, especficamente para la adquisicin de datos o
aplicaciones de control, se le denomina microcomputadora.
Entonces, s fueramos a disear un circuito con el microprocesador 8088, se requerira de una memoria
EEPROM para almacenar el programa, circuitos de memoria RAM para almacenar las variables y
resultados y finalmente circuitos de interface E/S para interaccionar con el mundo exterior. Todo esto
Reunido es una microcomputadora.
Microcontrolador. En una extensin a la lgica, cuando los componentes que conforman a una
microcomputadora son colocados en un solo chip de silicio, se le denomina a esto un Microcontrolador.
Texas Instruments fue el primer fabricante del microcontrolador, con la serie TMS1000. Esta serie de
microcontroladores tenia la sufiente RAM, ROM y terminales de E/S como para controlar un horno de
microondas, usarse en temporizadores industriales y en calculadoras.
Este texto puede comprenderse un poco mejor a partir del mapa conceptual figura 1: MCU, MPU,
microcomputadora.

figura 1: MCU, MPU, microcomputadora


Actividad de aprendizaje:
Cuadro Comparativo: Marcar las
Microcontrolador y Microprocesador.

diferencias

mas

importantes

entre

Microcomputadora,

Para elaborar esta actividad, se requiere del uso de un equipo de cmputo y presentarlo en sesion.

1.2 Caractersticas y aplicaciones de los microcontroladores


Los microcontroladores son divertidos, son el corazn y alma de muchas aplicaciones de uso diario y lo
mejor de todo, los microcontroladores son fciles de usar y de disear con ellos, todo esto desde el
punto de vista del diseador. En la siguiente figura, se presenta un esquema generalizado de las partes
que constan a un microcontrolador (vese figura 2: Partes e interfaces de un microcontrolador).

figura 2: Partes e interfaces de un microcontrolador


Fuente: (Gadre, 2000)
De esta forma se puede definir que:
LA CPU: Es la Unidad Central de Procesamiento o coloquialmente el corazon del controlador, su
tarea es la de buscar instrucciones almacenadas en la memoria del programa, decodificar esas
instrucciones y ejecutarlas. El CPU en s est compuesto por registros, una o varias ALU, decodificador
de instrucciones y circuiteria de control.
MEMORIA de PROGRAMA: La memomoria de programa almacena las instrucciones que conforman

al programa; en caso de tener un programa muy grande, la memoria puede ser particionada, en una
memoria interna y en una memoria externa. Generalmente esta memoria es de tipo no voltil, es decir,
al perder energa el microcontrolador, la memoria no se borra (EPROM, EEPROM, FLASH, mask
ROM o OTP).
RAM: La RAM es la memoria de datos del controlador, ya que es usada para este propsito. La CPU
usa la RAM para almacenar datos y la PILA (stack). La pila se utiliza para guardar las direcciones de
retorno al que debe regresar el programa cuando se termina de ejecutar una subrutina o interrupcin.
RELOJ: El controlador ejecuta el programa con cierta cadencia. El ritmo de ejecucin est determinado
por la frecuencia del oscilador. El reloj oscilador puede ser interno (oscilador tipo RC) externo con un
elemento de temporizacin tales como un cristal oscilador, un circuito resonante LC o un circuito RC.
Tan pronto se aplica voltaje al microcontrolador, el oscilador comienza a trabajar.
RESET y DETECTOR de BAJO VOLTAJE: El circuito de reset permite asegurar que todos los
componentes y el circuito de control tienen un estado inicial predeterminado y son inicilizados de
forma adecuada. El detector de bajo voltaje es un circuito que monitorea la fuente de alimentacin, en
caso de un descenso de voltaje, se da la indicacin de RESET.
PUERTO SERIAL: El puerto serial es un componente muy til del microcontrolador, ya que se utiliza
para comunicacin con otros dispositivos externos. Existen dos tipos de puertos seriales: Sncronos y
Asncronos. Para la transferencia sncrona es necesaria una seal de reloj con cada bit de datos enviado,
aunque en la comunicacinasncrona, la seal de reloj no es necesaria, pero la temporizacin est
embebida en los dispositivos que se omunicarn, sin embargo es requerida un bit de sincronia,
denominados bit de Inicio y bit de paro.
PUERTOS ANALGICOS: Las entradas analgicas se utilizan con los convertidores analgicos a
digitales. Un controlador puede tener un ADC o comparadores analgico. Los ADC se utilizan para
adquirir datos de dispositivos como sensores de temperatura y sensores de presin. Una salida
analgica se usa para conversin Digital a Analgica. La mayor parte de los microcontroladores vienen
con mdulos PWM los cuales permiten generar una seal analgica a travs de un filtro RC.
PUERTOS DIGITALES:El microcontrolador usa estos puertos para intercambiar datos digitales con el
mundo exterior.
TEMPORIZADOR/TIMER: El timer es un elemento usado por el controlador para temporizar eventos,
por ejemplo, puede ser usado para enviar datos a un display cada determinado tiempo. El timer tamien
puede ser usado para contar eventos, tanto externos como internos. De este modo al timer se le
denomina contador.
TIMER PERRO GUARDIN: Este temporizador especial (WDT) se utiliza para prevenir cuelgues por
software. Trabaja de la siguiente manera: Una vez inicializado el WDT se incrementa con una seal de

reloj, Si el programa del usuario no resetea el WDT, el contador se desborda y causa un RESET. En
consecuencia al activar este timer, el programador debe tener en cuenta causar cada determinado
tiempo una seal de reseteo del WDT. De este modo se presupone que si el programa de usuario no
resetea al WDT entonces ha fallado, lo que significa un posible comportamiento indeseable, y en
consecuencia, es mejor reinicializar.
RTC. Es un Reloj de tiempo real que tiene la tarea de mantener el tiempo de los das y fechas

Desarrollando aplicaciones con microcontroladores


1. Primero y mas importante, define los requerimientos.
2. Crea la suficiente documentacin para dar soporte a los requerimientos en formato de diagrama
de bloques, diagrama de flujo, diagramas de temporizacin.
3. Busca el hardware mas adecuado para otorgar la funcionalidad mas adecuada. Esto auxilia al
diseador a decidir si requiere de un microcontrolador o no.
4. Si es necesario un microcontrolador, identifica el microcontrolador ms adecuado para ser el
cerebro de tu aplicacin.
5. Identificado una vez el controlador a utilizar, vuelve a verificar si el microcontrolador elegido
satisface los requerimientos de velocidad, energa consumida, etc. De otra forma vuelve al paso
4.
6. El paso siguiente, es adquirir las herramientas necesarias para desarrollar el hardware y el
software, estas herramientas pueden ser ensambladores, compilador (en caso de programar en
lenguaje de alto nivel), simulador del controlador, y si es posible, un emulador del hardware,
una tarjeta de evaluacin, el programador, etc.
7. Si estas familiarizado con un controlador en partcular, puedes iniciar tu diseo y ensamblar un
prototipo, sino, comienza a familiarizarte, escribiendo primero algunos programas de muestra y
probando sobre la tarjeta de evaluacin o sobre el simulador.
8. Una vez familiarizado, comienza a particionar el software en bloques que puedan ser escritos
como subrutinas y ser probados de forma independiente. El desarrollo del hardware puede ir en
forma paralela, y as entrar en una fase de prueba y depuracin. Estos ciclos se realizan de
forma iterativa.
9. Finalmente, se integra todo el software y el hardware y nuevamente se prueba, de nuevo se
entra en la fase de prueba depuracin, hasta que todo trabaje.
10. Durante la escritura del software y el desarrollo del hardware, algo que no debes perder de vista
es la documentacin. Documentar el diseo es extremadamente importante, no solo por
mantener una memoria de tu trabajo, tambin para pruebas durante el ciclo de vida del
dispositivo y futuras revisiones.
11. La etapa final, involucra la implementacin del sistema en el ambiente de objetivo.

1.3 Tipos de arquitecturas computacionales.


Qu es arquitectura computacional?

figura 3: Definiciones de arquitectura de computadoras

1.3.1 La arquitectura de un microcontrolador


La arquitectura del microcontrolador puede clasificarse con base diversas caractersticas. Una muy
comn es a travs del nmero de instrucciones:

CISC

RISC

MISC

Otra clasificacin se basa en la forma en que se accede a la memoria de datos y de programa, el modelo
unificado o Arquitectura Von Neumman (14figura 4: Arquitectura Memoria Unificada) y la
Arquitectura Harvard (figura 5: Arquitectura Memoria Separada), donde la cual se encuentran
separadas la memoria de datos y la memoria de programa.

figura 4: Arquitectura Memoria Unificada

figura 5: Arquitectura Memoria Separada

Una clasificacin mas, se basa en la forma en que los datos internos son manipulados y almacenados
dentro del procesador:

Pila

acumulador

registro-memoria

registro-registro

Para esclarecer la diferencia entre estas arquitecturas, tomemos como ejemplo el siguiente clculo:
C AB
donde A, B y C son variables.
Modelo Pila: En una mquina de tipo pila, los clculos se determinan de la siguiente manera:
Push A

Primero la CPU toma los valores de la pila y almacena los operandos de


regreso en la pila. Para cargar una variable en la pila, la instruccin Push
es utilizada. La pila opera siempre colocando los ltimos valores en la
parte superior. La CPU toma los valores superiores de la pila y realiza
una operacin. El resultado se devuelve a la pila.

Push B
Sub
Pop C

Modelo Acumulador:
En una mquina de este tipo, un operando siempre se encuentre en el registro acumulador, de hecho,
todas las operaciones tienen como centro al acumulador.
Load A

;carga el acumulador con la variable A

Sub B
;resta el valor de la variable
resultado se devuelve al acumulador

del

acumulador

el

Store C
;se lee el contenido del acumulador (A-B) y se almacenada
en la variable C.

Modelo Registro-memoria
En esta arquitectura, los operandos se leen desde la memoria hacia un registro definido y el resultado se
escribe directamente a memoria.
Load Rx, A

; Carga el registro Rx con la variable A

Sub Rx,B

; Resta la variable B del contenido del registro Rx

y almacena el resultado en el registro Rx


Store C

;almacena el valor de Rx en la variable C

Modelo Registro-registro
En este modelo, se accede a la memoria para almacenar los operandos a procesar y se realiza la
operacin directamente entre registros. En el caso de microcontroladores, en este tipo de arquitectura
comnmente es posible usar hasta 32 registros diferentes.
Load Rx,A

; Carga el registro Rx con la variable A

Load Ry,B

; Carga el registro Ry con la variable B

Sub Rz,Rx,Ry

; Se realiza la operacion Rx Ry y se almacena en Rz

Store C,Rz

; Rz se almacena en la variable C

1.4 Tipos de Microcontroladores y sus fabricantes.


En el mercado existe una gran diversidad de microcontroladores y microprocesadores, y elegir uno en
particular, puede ser una pesadilla, generalmente se inicia enumerando los requerimientos en trminos
de las caractersticas y los costos. Aunque la eleccin final puede ser dictada por otros elementos, tales
como la marca, popularidad, el expertise del diseador local.
La lista que a continuacin se presenta es tomada de Gadre (2001), quien consider en ese entonces
como los microcontroladores ms populares de 8 bits.

Compaia

Dispositivo

Memoria On-Chip

Otras caractersticas

AB Semicon Ltd AB180-20

Nil

2 timer de 16 bits, UART, unidad


aritmtica de punto fijo de 32 bits,
controlador DMA

Atmel Corp

ATtiny11

1-kbyte Flash

1 timer de 8bits, comparador analgico,


WDT,
Oscilador
integrado,
una
interrupcin externa.

Dallas Semi

DS80C310

256- RAM

4 ciclos de reloj por ciclo mquina,


UART, 3 timers 16 bits, 10 fuentes de
interrupcin externa e interna

Hitachi

H8/3640

8kByte de ROM

3 timer de 8 bits, 1 timer de 16 bits, 1


timer PWM de 14 bits, 1 WDT, 2 puertos
SCI, 8 ADC de 8 bits

512 Byte de RAM


Microchip

PIC16CR54C

768 Byte de ROM


25 Byte de RAM

Motorola

68HC705KJ1

1240 byte OTP


64 byte RAM

STMicro

ST6203CB1

1 kByte de ROM
64- Byte de RAM

12 terminales E/S, timer de 8 bits,


terminales con alta corriente para manejo
directo de LED, oscilador RC
Timer multifuncin de 15 etapas,
Oscilador integrado, Reset por bajo
voltaje, perro guardin, interrupcin de
teclado, puerto E/S de alta corriente.
Comparador analogico, E/S programable,
detector de bajo voltaje, timer de 8 bits,
perro guardin.

Actividad de aprendizaje
Resumen: Acuar las principales caractersticas sobre microcontroladores de 8 bits y sus fabricantes

Unidad 2
Arquitectura interna de un microcontrolador

Unidad 2 Arquitectura interna de un microcontrolador


2.1 Componentes del Microcontrolador.
2.2 Registro internos.
2.3 Tipos y distribucin de las memorias internas.
2.4 Perifricos
2.5 Las instrucciones del microcontrolador.

Competencia especfica
Definir la arquitectura interna del microcontrolador.
Actividades de aprendizaje

Mapa Conceptual: En un mapa conceptual colocar los componentes mas relevantes del
microcontrolador ATmega32U4.

Cuadro Comparativo: Elaborar un cuadro en el que se expongan las caractersticas de los


perifricos internos de los microcontroladores ATmega48 y ATmega32U4 y el tipo de memorias
que utilizan.

2.1 Componentes del Microcontrolador.


El microcontrolador a estudiar es un AVR, explcitamente el ATMega32u4, el cual a modo de resumen
en la siguiente figura se muestran los componentes que contiene este dispositivo, adems sirve como
referencia para comparar los componentes de este microcontrolador con el ATmega48.

figura 6: Cuadro comparativo entre microcontroladores

2.2 Registro internos.


Los registros de esta microcontrolador son accedidos en formato de 8 bits de forma ortogonal, ya sea
por la ALU, un dispositivo de E/S, etc., en la figura figura 7: Arquitectura AVR se muestra la
arquitectura del ncleo AVR.
Notes que son un total de 38 registros de propsito general, donde 6 de estos registros de 8 bits,
pueden ser utilizados como tres registros de 16 bits para direccionamiento indirecto.
Adems de estos registros de propsito general se cuenta con registros de propsito especfico, tales
como.
El registro de estados contiene informacin acerca del resultado ms recientemente ejecutado por una
instruccin aritmtica. Esta informacin puede ser usada para alterar el flujo del programa. Es

importante advertir que el registro de estados no se guarda automticamente cuando entra una
interrupcin, por lo que se hace necesario su debido uso por medio de software.

figura 7: Arquitectura AVR


Apuntador de Pila
La pila es principalmente usada para almacenar datos temporales, para almacenar variables locales y
direcciones de retorno, las cuales sern usadas al terminar una rutina de servicio de interrupcin o una
llamada de subrutina.
El registro apuntador de Pila, siempre apunta hacia la parte ms alta de la pila, considere que la pila
est implementada para crecer de localidades altas de memoria hacia localidades bajas de memoria, lo
cual implica que la instruccin PUSH decrementa el valor del apuntador de Pila.

2.3 Tipos y distribucin de las memorias internas.


En esta seccin se describe las diferentes memorias en el ATMega32u4. La arquitectura AVR tiene dos
principales espacios de memoria, el espacio de memoria de Datos y el espacio de memoria de
Programa, adicionalmente, el ATMega32u4 cuenta con una memoria EEPROM para almacenamiento
de datos. Todos los espacios de memoria son lineales y regulares. (Esto es una ventaja con respecto a
los pic de gama media que cuentan con memoria paginada)

figura 8: Mapeo de memoria del ATMega32U4

2.4 Perifricos
Los perifricos con los que cuenta el ATMega32u4 son los siguientes:

PLL para el control de USB y timer de alta velocidad, de 32 hasta 96MHz

Un temporizador de 8 bits con preescalador separado y modo de comparacin

Dos temporizadores de 16 bits con preescalador separado y modos de comparacin y captura

Un temporizado de alta velocidad con resolucin de 10 bits con PLL (64MHz) y modo de
comparacin

Cuatro canales PWM de 8 bits

Cuatro canales PWM con resolucin programable de 2 a 16 bits

Seis canales PWM para operaciones de alta velocidad, con resolucin programable de 2 a 11
bits.

Modulador de comparacin a la salida

ADC de 12 canales con resolucin de 10 bits

Interface Maestro-Esclavo SPI

Interface I2C (TWI)

Perro guardin programable con oscilador integrado independiente

Comparador analgico Integrado

Interrupcin y salida del modo Sleep en cambio de nivel de Pin

Sensor de temperatura integrado.

2.5 Las instrucciones del microcontrolador.


Las instrucciones del microcontrolador ATMega32u4 se dividen en las siguientes partes

instrucciones aritmticas y lgicas

Instrucciones de ramificado

Instrucciones de bit y prueba de bit

instrucciones para transferencia de datos

Instrucciones de microcontrolador

Estas instrucciones se caracterizan por ejecutarse, la mayora de ellas (solo las de salto no) en un solo
ciclo mquina, mas informacin puede encontrarse en el apartado 32 instruction Set Summary del data
sheet de este microcontrolador

Unidad 3
Caractersticas Elctricas del Microcontrolador

Unidad 3 Caractersticas Elctricas del Microcontrolador


3.1 Distribucin de terminales
3.2 Caractersticas del reloj del sistema
3.3 El Reset y sus posibles fuentes
3.4 Caractersticas de la fuente de alimentacin y consumo de potencia del MCU

Competencia especfica
Analizar las caractersticas elctricas del microcontrolador.
Actividades de aprendizaje:

Investigacin Documental: Realizar la lectura de las caractersticas del reloj del sistema y
elaborar una sntesis de las mismas.

Mapa Cognitivo (Tipo SOL): Definir el RESET y distinguir sus posibles fuentes mediante un
mapa cognitivo tipo Sol.

Mapa Mental: Enlistar las caractersticas de la fuente de alimentacin y consumo de potencia


del microcontrolador.

3.1 Distribucin de terminales


El microcontrolador ATMega32U4 es un dispositivo que contiene mltiples elementos de entrada y
salida, totalmente configurables, tanto como digitales como analgicos, este dispotivo se encuentra en
empaquetados tanto QNF como en TQFP, en la figura siguiente se muestra el PINOUT o distribucin
de las terminales de este microcontrolador en partcular.

figura 9: Pinout del microcontrolador ATMega32U4


A continuacin se presenta la descripcin que el fabricante da de cada uno de los terminales de este
microcontrolador.
Vcc.
Terminal para la alimentacin.

GND.
Tierra
PORTB (PB7..PB0)
Es un puerto de Entradas Salidas (E/S) bidireccional con resistencias de pull-up internas (elegibles
para cada bit en particular). El puerto B tiene propiedades simtricas tanto como para drenar, as
como para alimentar una carga conectada a cada terminal. Como entradas, las terminales del puerto
B, drenarn muy poca corriente del exterior cuando las resistencia de pull-up estn activadas. Las
terminales de este puerto se ponen en alta impedancia cuando una condicin de reset se activa, o s
el reloj no est funcionando.
El puerto B en particular tiene mejores caractersticas de manejo de cargas que otros puertos.
Por otra parte este puerto tiene otras funciones especiales, las cuales son caractersticas del
ATMega32u4 y se enlistan en la Tabla 1: Caractersticas especiales del Puerto B en el ATMega32U4

Terminal del Funcin Alterna


Puerto
PB7

OC0A/OC1C/PCINT7/nRTS
(Salida en comparacin y PWM en mdulo A para el Temporizador 0, Salida en
comparacin y PWM en mdulo C para el Temporizador 1, Pin de interrupcin 7 en
Flanco, seal nRTS para control de flujo en la UART ).

PB6

OC1B/PCINT6/OC4B/ADC13
(Salida en comparacin y PWM en mdulo B del Temporizador 1, Pin de interrupcin
6 en Flanco, Salida en comparacin y PWM en Mdulo B del Temporizador 4,
Terminal del canal 13 de conversin analgico a digital).

PB5

OC1A/PCINT5/nOC4B/ADC12
(Salida en comparacin y PWM en mdulo A para el Temporizador 1, Pin de
interrupcin 5 en Flanco, Salida negada en comparacin y PWM en Mdulo B del
Temporizador 4, Terminal del canal 12 de conversin analgico a digital).

PB4

PCINT4/ADC11
(Pin de interrupcin 4 en Flanco, Terminal del canal 11 de conversin analgico a
digital).

PB3

PDO/MISO/PCINT3
(Salida de Programacin de Datos, Terminal Master Input Slave Output del mdulo
SPI, Pin de interrupcin 3 en Flanco).

PB2

PDI/MOSI/PCINT2
(Entada de Programacin de Datos, Terminal Master Output Slave Input del mdulo
SPI, Pin de interrupcin 2 en Flanco).

PB1

SCK/PCINT1
(Terminal de Reloj Serial para mdulo SPI, Pin de interrupcin 1 en Flanco).

PB0

nSS/PCINT0
(Terminal Select Slave activa en bajo para el mdulo SPI, Pin de interrupcin 0 en
Flanco).

Tabla 1: Caractersticas especiales del Puerto B en el ATMega32U4


Fuente (AVR, 2010)
Puerto C (PC7, PC6)
Es un puerto de Entradas Salidas (E/S) bidireccional con resistencias de pull-up internas (elegibles
para cada bit en particular).El puerto C tiene propiedades simtricas tanto como para drenar, as
como para alimentar una carga conectada a cada terminal. Como entradas, las terminales del puerto
C, drenarn muy poca corriente del exterior cuando las resistencia de pull-up estn activadas. Las
terminales de este puerto se ponen en alta impedancia cuando una condicin de reset se activa,

inclusive s el reloj no est funcionando.


Solo los terminales 7 y 6 se encuentran disponibles
Por otra parte este puerto tiene otras funciones especiales, las cuales son caractersticas del
ATMega32u4 y se enlistan en la Tabla 2: Caractersticas especiales del Puerto C en el ATMega32U4
Terminal del Funcin Alterna
Puerto
PC7

ICP3/CLKO/OC4A
(Terminal de Captura de entrada del Timer 3, Terminal de salida de Reloj (Divido por
el Reloj del sistema con fines de sincronizacin), Salida en Comparacin y PWM en
mdulo A del Temporizador 4).

PC6

OC3A/nOC4A
(Salida en Comparacin y PEM en mdulo A del Temporizador 3 y Salida negada en
comparacin y PWM en Mdulo A del Temporizador 4)

Tabla 2: Caractersticas especiales del Puerto C en el ATMega32U4


Fuente: (AVR, 2010)
Puerto D (PD7..PD0)
Es un puerto de Entradas Salidas (E/S) bidireccional con resistencias de pull-up internas (elegibles
para cada bit en particular).El puerto D tiene propiedades simtricas tanto como para drenar, as
como para alimentar una carga conectada a cada terminal. Como entradas, las terminales del puerto
D, drenarn muy poca corriente del exterior cuando las resistencia de pull-up estn activadas. Las
terminales de este puerto se ponen en alta impedancia cuando una condicin de reset se activa,
inclusive s el reloj no est funcionando.
Por otra parte este puerto tiene otras funciones especiales, las cuales son caractersticas del
ATMega32u4 y se enlistan en la Tabla 1: Caractersticas especiales del Puerto B en el ATMega32U4

Terminal del Funcin Alterna


Puerto
PD7

T0/OC4D/ADC10
(Entrada para el Temporizador 0, Salida en Comparacin y PWM en mdulo D del
Temporizador 4, Terminal del canal 10 de conversin analgico a digital).

PD6

T1/nOC4D/ADC9
(Entrada para el Temporizador 1, Salida negada en Comparacin y PWM en mdulo D
del Temporizador 4, Terminal del canal 9 de conversin analgico a digital).

PD5

XCK1/nCTS
(Entrada/Salida externa de Reloj para la UART1, seal nCTS para control de flujo en
la UART).

PD4

ICP1/ADC8
(Terminal de Captura de entrada del Timer 1, Terminal del canal 8 de conversin
analgico a digital).

PD3

nINT3/TXD1
(Entrada de Interrupcin externa 3, Pin de Transmisin de USART1).

PD2

nINT2/RXD1
(Entrada de Interrupcin externa 2, Pin de Recepcin de USART1).

PD1

nINT1/SDA
(Entrada de Interrupcin externa 1, Terminal de Datos de Protocolo TWI/I2C).

PD0

nINT0/SCL/OC0B
(Entrada de Interrupcin externa 0, Terminal de Reloj de Protocolo TWI/I2C, Salida en
comparacin de mdulo B del Temporizador 0).

Tabla 3: Caractersticas especiales del Puerto D en el ATMega32U4


Fuente: (AVR,2010)
Puerto E (PE6,PE2)
Es un puerto de Entradas Salidas (E/S) bidireccional con resistencias de pull-up internas (elegibles
para cada bit en particular).El puerto E tiene propiedades simtricas tanto como para drenar, as
como para alimentar una carga conectada a cada terminal. Como entradas, las terminales del puerto
E, drenarn muy poca corriente del exterior cuando las resistencia de pull-up estn activadas. Las
terminales de este puerto se ponen en alta impedancia cuando una condicin de reset se activa,
inclusive s el reloj no est funcionando.
nicamente los terminales 6 y 2 estn presentes.
Por otra parte este puerto tiene otras funciones especiales, las cuales son caractersticas del
ATMega32u4 y se enlistan en la

Terminal del Funcin Alterna


Puerto
PE6

INT6/AIN0
( Entrada de Interrupcin externa 6, Entrada positiva del comparador analgico ).

PE2

nHWB
(Activacin del Bootloader)

Tabla 4: Caractersticas especiales del Puerto E en el ATMega32U4


Fuente: (AVR,2010)
Puerto F (PF7..PF4, PF1, PF0)
El puerto F sirve como entradas analgicas para el convertidor Analgico a Digital.
Es un puerto de Entradas Salidas (E/S) bidireccional con resistencias de pull-up internas (elegibles
para cada bit en particular).El puerto F tiene propiedades simtricas tanto como para drenar, as
como para alimentar una carga conectada a cada terminal. Como entradas, las terminales del puerto
F, drenarn muy poca corriente del exterior cuando las resistencia de pull-up estn activadas. Las
terminales de este puerto se ponen en alta impedancia cuando una condicin de reset se activa,
inclusive s el reloj no est funcionando.
Los bits 2 y 3 no se encuentran presentes en el microcontrolador.
El Puerto F sirve tambin como interfaz JTAG. Si la interfaz JTAG se encuentra habilitada,las
resistencias de pull-up en las terminales PF7(TMI), PF5(TMS) y PF4(TCK) se activarn incluso si
pudiese ocurrir un evento de reset.
DPuerto negativo de datos de Full Speed/Low Speed del mdulo USB. Debe conectarse en serie con
una resistencia de 22 ohms.
D+
Puerto positivo de datos de Full Speed/Low Speed del mdulo USB. Debe conectarse en serie con
una resistencia de 22 ohms.
UGND
Terminal de tierra para el USB
UVCC
Terminal para la alimentacin del regulador interno de voltaje para el USB
UCAP
Terminal para la alimentacin del regulador interno de voltaje para el USB, esta terminal deber
conectarse a un capacitor externo de 1uF.
VBUS
Entrada monitor del Voltaje USB

nRESET
Entrada de Reset, un nivel en BAJO, con una duracin mayor a la establecida por la mnima
longitud de pulso, genera un reset. Incluso si el reloj no est trabajando. La duracin del pulso
mnimo depende de la configuracin del microcontrolador, se debe advertir que pulsos que tengan
una menor duracin no garantizan que el evento de reset ocurra.
XTAL1
Entrada del Amplificador Inversor para el oscilador y entrada para el circuito interno operacional del
reloj interno.
XTAL2
Salida del Amplificador Inversor para el oscilador
AVCC
AVCC es la fuente de alimentacin (entrada) para todos los canales de conversin analgica a
digital. Si el ADC no es utilizado, esta terminal deber conectarse externamente a Vcc. Si el ADC es
usado, entonces, deber conectarse a Vcc a travs de un filtro pasa bajos.
AREF
Esta es la terminal de referencia analgica (entrada) para el ADC.

3.2 Caractersticas del reloj del sistema


A lo largo del presente escrito se describirn las caractersticas de los relojes que presenta internamente
el microcontrolador ATMEGA32U4, as como la forma en que se encuentran distribuidos y la manera
en que interactan entre ellos. Se comenzar con un captulo introductorio que nos presenta un
bosquejo general de los temas a tratar as como una seccin de antecedentes que nos empapen de la
historia ms importante acerca del desarrollo de los clocks de un microcontrolador. El en desarrollo se
hablar de las fuentes de reloj, parmetros de rendimiento y la forma en que funcionan conjuntamente
en el AVR.
INTRODUCCIN

El reloj de un sistema computarizado, por ejemplo el de un microcontrolador, se utiliza principalmente


para cumplir dos tareas bsicas que son:
1. Para sincronizar las diversas operaciones que realizan los diferentes subcomponentes del sistema
informtico.
2. Para saber la hora.
El reloj fsicamente es un circuito integrado que emite una cantidad de pulsos por segundo, de manera
constante. Al nmero de pulsos que emite el reloj cada segundo se le llama frecuencia de reloj. Las
frecuencias de reloj se miden en ciclos sobre segundo, tambin llamados hertzios, siendo cada pulso un
ciclo de reloj. Como la frecuencia de reloj es de varios millones de pulsos por segundo se expresa
habitualmente en megaHertzs. El reloj marca la velocidad de proceso del microcontrolador generando
una seal peridica que es utilizada por todos los componentes del sistema informtico para sincronizar
y coordinar las actividades operativas y as evitar que un componente maneje unos datos
incorrectamente o que una velocidad de transmisin de datos entre dos componentes sea distinta
(Beltrn, 2008).
Cuanto mayor sea la frecuencia de reloj mayor ser la velocidad de proceso del microcontrolador y
podr realizar mayor cantidad de instrucciones elementales en un segundo. En la temporizacin
sncrona, la aparicin de un evento est determinada por el reloj. El bus incluye una lnea de reloj que
es comn a todos los dispositivos, y se suelen sincronizar durante el flanco de subida; considerando que
se denomina flanco de subida al instante en que la seal de reloj cambia de estado bajo a alto. La
mayora de los eventos duran un ciclo de reloj. Cabe mencionar que en un microcontrolador se tienen
diversas fuentes de generacin de una seal de reloj y adems cada uno de los componentes del
hardware funciona a una determinada frecuencia de reloj teniendo as una amplia variedad de maneras
para hacer funcionar el sistema embebido; claro todo depender de los parmetros de funcionamiento
establecidos por el fabricante. Particularmente para el AVR ATMEGA32U4 se tiene toda una
distribucin compleja de relojes, es por ello que enseguida se describirn las caractersticas ms
importantes de cada uno de ellos.

ANTECEDENTES

Un oscilador de cristal es un circuito oscilador electrnico que utiliza la resonancia mecnica de un


cristal de vibracin de material piezoelctrico para crear una seal elctrica con una frecuencia muy
precisa. Esta frecuencia se utiliza comnmente para controlar el tiempo, para proporcionar una seal de
reloj estable de circuitos integrados digitales como en los microcontroladores, y para estabilizar las
frecuencias de los transmisores y receptores de radio.
La piezoelectricidad fue descubierta por Jacques y Pierre Curie en 1880. Paul Langevin investig
primero resonadores de cuarzo para uso en sonar durante la Primera Guerra Mundial I. El primer
oscilador controlado por cristal, usando un cristal de sal de Rochelle, fue construido en 1917 y
patentado en 1918 por Alexander M. Nicholson en los Bell Telephone Laboratories, aunque su
prioridad fue discutida por Walter Guyton Cady, quien construy el primer oscilador de cristal de
cuarzo en 1921.
Osciladores de cristal de cuarzo fueron desarrollados para las referencias de frecuencia de alta
estabilidad durante los aos 1920 y 1930. En 1926 se utilizaron cristales de cuarzo para controlar la
frecuencia de las emisoras de radio y eran populares entre los operadores de radio aficionados. En
1928, Warren Marrison desarroll el primer reloj de cuarzo. Con una precisin de hasta 1 segundo en
30 aos, los relojes de cuarzo se convirtieron en relojes ms precisos del mundo hasta que se
desarrollaron los relojes atmicos en los aos 1950. La escasez de cristales durante la guerra
provocada por la demanda de control de la frecuencia exacta de radios y radares militares y navales
estimularon la investigacin de posguerra en el cultivo de cuarzo sinttico, y en 1950 se desarroll un
proceso hidrotrmico para el crecimiento de cristales de cuarzo a escala comercial en los Laboratorios
Bell. Por la dcada de 1970 prcticamente todos los cristales utilizados en la electrnica eran sintticos.
A pesar de que los osciladores de cristal an ms comnmente utilizan cristales de cuarzo, los
dispositivos que utilizan otros materiales son cada vez ms comunes, tales como resonadores
cermicos.
En primer lugar se mostrar la manera en que est distribuido el reloj del sistema en el ATMEGA32U4,
para lo cual se tiene la siguiente imagen:

figura 10: Sistema de reloj del ATMega32U4


Se nota en el diagrama anterior que el reloj del AVR puede tomarse de diversas fuentes entre las que
estn: un cristal oscilador, un reloj externo, el oscilador del perro guardin o del oscilador RC
calibrado. Esto significa que el usuario tiene la posibilidad de usar algunas de estas opciones segn le
convenga y esto depender de la aplicacin que se le d al microcontrolador, adems de algunas
caractersticas de hardware ya establecidas. El multiplexor de reloj tiene la funcin de escoger cul
de las seales de reloj conectadas se usar, una vez seleccionada, la seal es llevada a un prescalador
que se encarga se multiplicarla por un factor menor a 1 de tal manera que la seal saliente sea de menor
frecuencia, es entonces que el tren de pulsos llega a la unidad de control del relojes del AVR y a la
entrada del multiplexor del PLL. Para el caso de la unidad de control esta se encargar de direccionar la
seal de reloj a los diversos mdulos o componentes del ATMEGA32U4 formando as las seales de
reloj siguientes: clkPLL, clkCPU, clkADC, clkFLASH, clkI/O.
En el caso del PLL es importante mencionar que la entrada al mismo debe tener una frecuencia de 8
Mhz, es por ello que primero hay una etapa de prescalamiento; la funcin del PLL ser elevar la
frecuencia de la seal de reloj de entrada con el fin de mandar trenes de pulsos al USB o al timer de alta
velocidad. Una vez dicho lo anterior ahora se describir a cada uno de los constituyentes del reloj del
sistema.
Reloj del CPU (clkCPU)
Este reloj controla las partes del sistema que tiene que ver con el funcionamiento del ncleo del AVR,
de esta forma si se inhabilita este reloj el ncleo del CPU no podr realizar clculos ni operaciones.
Dicho de otra forma en el reloj que da la cadencia a todo el microcontrolador. El funcionamiento de
este reloj es comparable con un metrnomo con su pndulo que oscila de izquierda a derecha. El
intervalo de tiempo que el pndulo tarda en recorrer esa distancia y regresar a su punto inicial se
denomina ciclo.

figura 11: Formas de onda de reloj


Reloj de entradas/salidas (clkI/O)
Es usado por la mayora de los mdulos I/O, como lo son los Timers/Contadores, SPI y USART.
Adems este reloj es usado por el mdulo de interrupcin externo, pero hay que mencionar que algunas
interrupciones externas son asncronas lo que significa que pueden ser detectadas sin necesidad de que
el reloj I/O est activado.
Reloj flash (clkFLASH)
Controla las operaciones de la interfaz flash y usualmente se activa al mismo tiempo que lo hace el
reloj del CPU.
Reloj del convertidor analgico-digital (clkADC)
Permite detener a los relojes clk I/O y clk CPU con la finalidad de reducir el ruido generado por el circuito
digital, ya que segn Andr-Marie Ampre (1831) la circulacin de la intensidad del campo magntico
en un contorno cerrado es igual a la corriente que lo recorre en ese contorno de tal forma que si la
corriente es variable se produce un campo magntico variable y adems segn Faraday (1831) el
voltaje inducido en un circuito cerrado es directamente proporcional a la rapidez con que cambia en el
tiempo el flujo magntico que atraviesa una superficie cualquiera con el circuito como borde, lo que
significa que la seal alterna de los relojes produce una corriente elctrica que afecta al CAD. De esta
forma si se inhabilitan los relojes se realiza una mejor conversin de la seal de entrada.
Reloj del prescalador PLL (clkPLL)
El PLL requiere una entrada de 8 MHz, pero como las fuentes de reloj pueden ser superiores a este
valor surge la necesidad de un prescalador que permite reducir la frecuencia de la seal de entrada hasta
tener los 8 MHz requeridos. Un multiplexor en el PLL se encargar de escoger entre las diversas
seales de reloj que cumplan el requerimiento de frecuencia mencionado, cabe decir que el oscilador
RC calibrado ya viene definido para trabajar a 8 MHz.
Reloj del timer de alta velocidad (clkTMR)
La frecuencia mxima del reloj para este timer depende del voltaje suministrado al AVR, pero en
general se llega a un mximo de 64 MHz a 5 V. Esta seal de reloj proviene del postescalador del PLL
que permite nuevamente reducir el valor de frecuencia de la seal de reloj pero ahora de la que sale del
PLL que en general alcanza un valor mximo de 96 Mhz.
Reloj del USB (clkUSB)

El hardware USB necesita una frecuencia de operacin de 48 MHz, es por ello que se necesita del
postescalador que permita dividir en 2 la frecuencia de salida del PLL que como se mencion
anteriormente tiene un valor comn de 96 Mhz.
Fuentes de Reloj
Como ya se mencion anteriormente este microcontrolador cuanta con diversas fuente de reloj. En la
tabla siguiente se ven dichas opciones con el respectivo valor que debe poseer el conjunto de 4 bits que
conforman al fusible CKSEL.

figura 12: Opciones para configurar el reloj


Es importante hacer notar que los 1 significan no programados mientras que los 0 significan s
programados. El AVR posee un oscilador de cristal de bajo consumo que puede alcanzar frecuencias
entre 8 y 16 MHz, adems cuenta internamente con el oscilador RC calibrado que funciona a 8 MHz.
Adems es notorio que se puede colocar un reloj externo a placa o cambiar el que tiene, aunque esto
ltimo no es recomendable.
Cristal oscilador de bajo consumo
Los pines XTAL1 y XTAL2 son la entrada y salida, respectivamente, de un amplificador inversor el
cual puede ser configurado para usarse como un oscilador. Este cristal brinda un bajo consumo de
potencia, pero no es capaz de mantener ms entradas de reloj. Para conectarlo correctamente es
necesario colocar dos capacitores en ambas entradas.

figura 13: Conexin de cristal de bajo consumo

El valor de los capacitores debe ser igual y depender de algunos factores como son la frecuencia de
operacin y el ruido generado por el mismo circuito. Adems es necesario programar el fusible CKSEL
segn sea necesario; la imagen siguiente indica los valores recomendados por el fabricante.

figura 14: Palabra en FUSES para la conexin de oscilador de bajo consumo


Cristal oscilador de baja frecuencia
El microcontrolador puede usar un cristal de 32.768 kHz como fuente para un oscilador dedicada a
operar en bajas frecuencias. El cristal deber conectarse de la misma forma que se ve en la ilustracin
5.
Oscilador interno RC calibrado
La frecuencia nominal que posee es de 8 MHz a una temperatura de 25C y voltaje de 3V. Este reloj
puede ser seleccionado al programar los fusibles CKSEL como se nota en la siguiente imagen.

figura 15: Palabra para seleccionar el reloj interno


Cuando este oscilador es usado como un chip de reloj, el oscilador del perro guardin seguir siendo
usado por el timer perro guardin y por el reset time-out.
Reloj externo
El AVR puede usar una fuente de reloj externa como se muestra en la siguiente imagen.

figura 16: Conexin de Reloj externo

Como se nota en la imagen anterior se usan los mismos pines que en el reloj de bajo consumo y baja
frecuencia, slo cambia la inclusin de un oscilador totalmente ajeno a la placa del ATMEGA32U4.
Como es de esperarse es necesario programar algunos fusibles CKSEL con la finalidad de habilitar esta
fuente de reloj.
PLL
El PLL es usado para generar frecuencias altas usadas en la interfaz de USB o en el mdulo del timer
de alta velocidad. El PLL interno de este microcontrolador produce frecuencias de reloj entre 32 MHz y
96 MHz con una entrada promedio de 8 MHz. En la ilustracin que se ve a continuacin se muestra el
proceso por medio del cual son alimentados el USB y el timer gracias al PLL, cabe decir que se divide
la frecuencia entre 1.5 para el TMR y entre 2 para el USB.

figura 17: Sistema de reloj de PLL

3.3 El Reset y sus posibles fuentes


La figura que se muestra a continuacin

figura 18: fuentes de reset

3.4 Caractersticas de la fuente de alimentacin y consumo de


potencia del MCU
El ATMEGA32U4 es un microcontrolador de 8 bits de bajo consumo, esto se consigue al entrar en los
modos de bajo consumo, en los cuales los mdulos que no se utilizan se desactivan con el fin ahorrar
energa.
Para habilitar los modos de bajo consumo, el bit SE en el registro SMCR debe estar en estado ALTO y
una instruccin SLEEP debe ser ejecutada. Los bits SM2, SM1 Y SM0 en el registro SMCR permiten
elegir cual ser el modo de bajo consumo que se activar (Idle, Reduccin de ruido en ADC, Powerdown, Power-save o Standby).
Si una interrupcin ocurre mientras el MCU se encuentra en modo SLEEP, se pondr en estado activo,
bajo el siguiente esquema: El MCU se pone en HALT por cuatro ciclos mas el tiempo de arranque y se
ejecuta entonces la rutina de interrupcin.
Si un reset ocurre durante el modo SLEEP, el MCU se despierta e inicia desde el vector de RESET.

3.4.1 Modo Idle


Este modo de bajo consumo detiene al CPU, pero permite que los siguientes perifricos sigan operando
USB, SPI, USART, Comparador analgico, ADC, interface TWI, Contadores/Temporizadores, Perro
Guardin y el sistema de interrupciones. Este modo bsicamente detiene el clkCPU y el clkFLASH.

3.4.2 Modo Reduccin de ruido en ADC


En este modo se detiene al CPU pero permite que el ADC, interrupciones externas, interfaz TWI, y el
Perro Guardin sigan operando; para salir de este modo, adems de la interrupcin por conversin
terminada, tambin es posible por medio interrupciones del TWI, EEPROM, interrupcin externa o
cambio de nivel, as como los reset ocasionados por el perro guardin, reset externo y reset por
deteccin de bajo voltaje.

3.4.3 Modo Power-down


En este modo el oscilador externo es detenido, mientras las interrupciones externas, la interfaz TWI y
el perro guardin permanecen operativos. Este modo particularmente, detiene todos los relojs, solo
permite la operacin de mdulos asncronos.
Para salir de este modo se deber ocasionar un RESET a travs de el Perro guardin, de forma externa
o por deteccin de bajo voltaje, y por interrupciones externas, cambio en nivel de pin, TWI (address
match) y las fuentes asncronas de interrupcin USB (VBUSTI, WAKEUPI).

3.4.4 Modo Power-save


Este modo es idntico al modo Power-down

3.4.5 Modo Standby


Este modo es indntico al modo power-down con la excepcin de que el oscilador permanece
corriendo. De este modo, se requieren de seis ciclos de reloj para despertar al dispositivo.

3.4.6 Velocidad mxima vs velocidad


La frecuencia mxima de operacin depende del valor de Vcc aplicado al microcontrolador, tal y como
se muestra en la figura 19: Relacin entre velocidad y alimentacin, en esta curva se visualiza una
relacin lineal entre 2.7V < Vcc < 5.5V

figura 19: Relacin entre velocidad y alimentacin

Unidad 4
Herramientas de desarrollo de los microcontroladores

Unidad 4 Herramientas de desarrollo de los microcontroladores


4.1 Ambiente Integrado de desarrollo (IDE) para microcontroladores
4.1.1 Ensamblador y Compilador.
4.1.2 Simulador, debugger y emulador.
4.1.3 Equipos programadores (downloaders) de microcontroladores.
4.2 Ejemplos de uso de herramientas de desarrollo.

Competencia especfica
Utilizar las herramientas de desarrollo de los microcontroladores.
Actividades de aprendizaje:

Videotutorial: Desarrollar un videotutorial para mostrar como se compila, programa y se prueba


un programa bsico del ATmega32U4 con una duracin de 7 minutos.

Simulaciones: Comprobar la programacin del MCU mediante ejemplos de uso de las


herramientas de desarrollo.

4.1 Ambiente Integrado


microcontroladores

de

desarrollo

(IDE)

para

Atmel Studio 6 es el Entorno de Desarrollo Integrado (IDE) de Atmel para el desarrollo de proyectos
con sus productos relacionados con sus microcontroladores.
Durante muchos aos los IDEs de Atmel para sus microcontroladores se mantuvieron separados en dos
versiones principalmente. Por un lado estaba el AVR Studio, que soportaba sus microcontroladores
AVR de 8 bits, entre los tinyAVR, los megaAVR y los Xmega. Eventualmente aparecan nuevas
versiones AVR Studio 4.xx pero era esencialmente el mismo y con ese 4 tan inamovible como el
nombre de una estacin radial. En tanto que por otro lado tenamos al AVR32 Studio, que era desde
luego la plataforma anloga pero para trabajar con los microcontroladores AVR de 32 bits.
Recin en 2011 Atmel decide lanzar su totalmente renovado Studio 5, esta vez fusionando el soporte
para sus microcontroladores emblema de 8 bits y de 32 bits, es decir,
AVR Studio 5 = AVR Studio + AVR32 Studio
En 2012 Atmel vuelve a repotenciar su Studio dndoles cabida esta vez a sus microcontroladores con
procesador ARM de la serie Cortex-M, denominados SAM3 y SAM4. Como era de esperarse, el
nombre ya no va precedido por la palabra AVR. Ahora se llama simplemente ATmel Studio 6. Sin
embargo, al igual que las versiones anteriores, los usuarios de los AVR lo suelen llamar simplemente
Studio 6, a secas.
Entre las herramientas que incluye el nuevo Atmel Studio 6 nos deben interesar las siguientes:
Un editor de cdigos, para editar los programas. Como todo gran editor permite mostrar los
cdigos fuente a colores, con nmeros de lnea, etc.
Un administrador de proyectos, que adems de trabajar con programas en ensamblador, le da un
completo soporte a los compiladores ARM GCC, AVR32 GCC y AVR GCC. A diferencia de
versiones anteriores ahora es menos flexible la integracin con los compiladores comerciales
como CodeVision AVR o ImageCraft AVR.
El ensamblador AVRASM, para trabajar con programas en ensamblador.
Los compiladores de software libre AVR32 GCC y AVR GCC en su versin para Windows
(WinAVR), para desarrollar programas en C para los AVR de 8 y 32 bits, como los tinyAVR,
megaAVR, XMEGA y AVR32. En versiones pasadas de Atmel Studio 6, este compilador se
deba instalar por separado.
El compilador ARM GCC, que es otro derivado de la coleccin GCC pero adaptado para los
microcontroladores ARM.
El simulador AVR Simulator, para simular los programas de los AVR tanto si estn escritos en
lenguaje C o ensamblador. Todava no est disponible un simulador para los microcontroladores
con procesador ARM.
El paquete Atmel Software Framework o ASF, que es un conjunto de ms de 1000 proyectos
escritos en lenguaje C para los AVR de 8 bits y para los ARM y AVR de 32 bits. Incluye
libreras y APIs que facilitan la interface con todos los perifricos de los microcontroladores,
desde los puertos hasta los mdulos USB o CAN.
Un completo sistema de ayuda integrado con servidor local. Haba algunos problemas con esta

caracterstica en el Studio 5 pero en Atmel Studio 6 las cosas andan muy bien.
Atmel Studio 6 permite trabajar con ms de 300 microcontroladores, entre AVR y ARM. Atmel
Studio 6 ya no soporta los siguientes dispositivos, que an estn disponibles en el Studio 4,
ATtiny11, ATtiny12, ATtiny15, ATtiny22, AT90S1200, AT90S2313, AT90S2323, AT90S2343,
AT90S4433, AT90S8515, AT90S8535, ATmega323, ATmega161, ATmega163, ATmega103,
ATmega165, ATmega169, ATmega406, ATmega16HVA, ATmega16HVA2, ATmega64HVE,
ATmega32U6, AT90PWM2, AT90PWM3, AT90SCR100, AT86RF401.

4.1.1 Ensamblador y Compilador.


La siguiente es la distribucin por defecto de las ventanas de Atmel Studio 6. En primer plano tenemos
a Start Page o Pgina de Inicio, a la derecha est la ventana Solution Explorer y abajo, la ventana
Output.

Hacer estas reubicaciones es divertido sobre todo si tenemos en cuenta que podemos regresar a la
distribucin inicial yendo al men Window
Reset Window Layout. Y si queremos volver a tener la
pgina Start Page para ver a la mariquita de nuevo vamos al men View
Start Page. Nota que esta
opcin tambin tiene un icono en la barra de herramientas. Es el men View donde tambin puedes
encontrar las otras ventanas y no en el men Window.
Antes que mostrar una tpica descripcin de cada uno de los elementos del entorno de Atmel Studio 6
los ir presentando a medida que hagan su aparicin y sean requeridos.
Proyectos y soluciones en C
A diferencia de los compiladores Basic, donde basta con crear un archivo BAS suelto y luego
compilarlo, los programas en C siempre forman parte de un proyecto.

Actualmente desarrollar proyectos en C con Atmel Studio 6 es ms sencillo que en versiones anteriores
debido en gran parte a que est adaptado para trabajar especialmente con los compiladores libres GCC
AVR32 y AVR GCC (WinAVR).
Una Solucin (Solution) es un conjunto formado por uno o varios proyectos, as que todo proyecto
debe pertenecer a alguna Solucin. Atmel Studio 6 puede trabajar con uno solo o con todos los
proyectos de la Solucin al mismo tiempo, pero solo puede administrar una Solucin a la vez.

Creacin de un proyecto en C
Abierto Atmel Studio 6 vamos al men File
Page.

New Project o hacemos clic en New Project de Start

De cualquier modo llegaremos al mismo asistente, donde empezamos por seguir lo que indica la
siguiente figura. El nombre y la ubicacin del proyecto pueden ser los que desees.
Ten en cuenta que Atmel Studio 6 crear una nueva carpeta (con el nombre del proyecto) dentro de la
ubicacin indicada. Observa que el nombre de la Solucin es el mismo que el del proyecto.
Todo proyecto debe pertenecer a alguna Solucin, y como estamos creando el primer proyecto, Atmel
Studio 6 le asignar una Solucin automticamente. Cuando creemos los siguientes proyectos
tendremos la opcin de elegir si pertenecern a sta o a una Solucin nueva.
Si activas la casilla Create directory for Solution, la Solucin (que es un archivo a fin de cuentas) se
alojar en la carpeta que deba ser para el proyecto, y el proyecto junto con sus archivos generados irn
a parar a una sub carpeta con el mismo nombre. Esto puede ser conveniente cuando se tiene una
Solucin con varios proyectos. Yo s que parece enredado pero con un par de prcticas lo entiendes
mejor y te acostumbras.
Normalmente prefiero tener un proyecto por cada Solucin, de modo que no tengo que marcar la casilla
indicada y puedo tener todos los archivos del proyecto y de la Solucin dentro de la misma carpeta sin
que se confundan.
Le damos clic a OK y tendremos una ventana mucho menos traumtica. Solo seleccionamos el AVR
con el que trabajaremos. En el futuro podremos cambiar este microcontrolador por otro. Tambin
puedes aprovechar esta ventana para reconocer las memorias de cada dispositivo y para ver las
herramientas que tienen disponibles desde Atmel Studio 6.
En seguida tendremos nuestro proyecto con el Editor de Cdigo mostrndonos el archivo de cdigo
fuente principal listo para que lo editemos. Observa que el Explorador de la Solucin o Solution
Explorer muestra los Proyectos de la Solucin as como los archivos de cada Proyecto. Debajo est el
marco Properties que informa las propiedades de cada archivo seleccionado arriba, como su ubicacin.
De todas las ventanas aqu mostradas o las que puedan surgir en adelante la que no deberas perder de
vista es el Explorador de la Solucin. Desde all accedes a todos los archivos del proyecto (los abres
con doble clic) y tambin puedes construir el proyecto as como establecer su configuracin. Si se te
llega a perder esta ventana la puedes visualizar yendo al men View
Solution Explorer.

Compiladores para microcontroladores AVR


Un microcontrolador ejecuta el programa que lleva grabado en su memoria FLASH. Ese programa est
guardado all en formato de cdigo mquina (a base de unos y ceros) y nosotros lo podemos cambiar
por otro programa que queramos (a eso se llama grabar el microcontrolador). Pero antes tenemos que
crear ese programa. Lo podemos hacer de tres formas.
Escribiendo el cdigo mquina directamente con unos y ceros o sus equivalentes en nmeros
hexadecimales. Es un mtodo factible pero que muy pocos se atreveran a intentar. El programa
escrito puede ser un simple archivo de texto (con extensin .hex) que luego ser decodificado
por el software grabador de microcontroladores. Un programa en cdigo mquina luce ms o
menos as.
:020000020000FC
:1000000012E01EBF1FEF1DBF36D0F0E0E8E15BD06D
:10001000F0E0E8E458D0FFCF0D0D0A207777772E77
:10002000637572736F6D6963726F732E636F6D208A
:100030000D0A203D3D3D3D3D3D3D3D3D3D3D3D3D70
:100040003D3D3D3D3D3D20000D0D0A20546573743E
:10005000696E67207468652054574920696E74651D
:100060007266616365200D0A00000D48692074689E
:10007000657265210000B0E0A0EC1C9112601C9339
:100080001127B0E0A5EC1C9318E6B0E0A4EC1C939B
:1000900016E0B0E0A2EC1C9318E1B0E0A1EC1C93D8
:1000A0000895B0E0A0EC1C9115FFFBCFB0E0A6ECEA
:1000B0000C930895B0E0A0EC1C9117FFFBCFB0E0CB
:1000C000A6EC0C9108950591002311F0EADFFBCF17
:1000D0000895FF93EF93F0E0ECE03197F1F7EF91A3
:1000E000FF910895000000000000089508953AEF80
:1000F00011D03AEF0FD008953AEF0CC034E60AC0A1
:100100003EE108C030E106C035E004C032E002C084
:1001100031E000C0FF93EF93F1E0EAE43197F1F7AB
:0A012000EF91FF913A95B1F70895B1
:00000001FF

Tabla 5: Cdigo mquina

Escribiendo el programa en cdigo ensamblador. El ensamblador es el lenguaje ms elemental


de los microcontroladores y muchos an lo usamos como recurso auxiliar. Sin embargo, sigue
siendo muy engorroso como mtodo de desarrollo ya que si queremos, por ejemplo, que el
microcontrolador ejecute una simple divisin de nmeros puede tomar cerca de 100 lneas de
cdigo ensamblador. El programa escrito en este lenguaje sigue siendo un archivo de texto (esta
vez con extensin .asm) que luego ser convertido en cdigo mquina por un software de
computadora llamado tambin ensamblador (AVRasm en el caso de los microcontroladores
AVR). A continuacin se lista un ejemplo de programa en ensamblador.

;//////////////////////////////////////////////////////////////
;/// FileName:
main.asm
;//////////////////////////////////////////////////////////////
.nolist
.include
.list
.def
.def
.def
.def
.def
.def

"m48Pdef.inc"
arg
tmp
status
del
AddressHigh
AddressLow

=
=
=
=
=
=

R16
R17
R18
R19
R27
R26

; argumento para funciones


; para operaciones temporales
;
;
; Apuntador X
;

;//////////////////////////////////////////////////////////////
;
Code program
;//////////////////////////////////////////////////////////////
.cseg
.org
0x0000
; Reset vector address
Start:
; Setup Stack Pointer
ldi
tmp, high(RAMEND)
out
SPH, tmp
ldi
tmp, low(RAMEND)
out
SPL, tmp

Main:

rcall

usart_init

; Inicializa la usart.

ldi
ldi
rcall
ldi
ldi
rcall

ZH, high(2*StrTest)
ZL, low(2*StrTest)
puts
ZH, high(2*StrType)
ZL, low(2*StrType)
puts

rjmp

Main

;//////////////////////////////////////////////////////////////////////
; Strings. Null ended strings
StrTest:
.db
0x0D,0x0D, 0x0A, " algun texto "
.db
0x0D,0x0A, " =================== ", 0x00
StrType:
.db
0x0D,0x0D, 0x0A, " Probando la com TWI ", 0x0D, 0x0A,0x00
StrHi:
.db
0x0D, "Hola!!! :)", 0x00
;//////////////////////////////////////////////////////////////////////
.include
"usart.asm"
.include
"delays.asm"
.exit

Tabla 6: Ejemplo de cdigo fuente en ensamblador

Escribiendo el programa en un lenguaje de alto nivel. Los dos lenguajes ms usados son el C y

el Basic. Con menos frecuencia se aprecia el Pascal. En este caso el cdigo a escribir es ms
comprensible para nosotros, los humanos. Por ejemplo, para una divisin es suficiente con
escribir una sentencia como a = b/c. El programa escrito en este lenguaje tambin es un archivo
de texto (ahora con extension .c, .bas o .pas) que luego ser convertido en cdigo ensamblador
por el compilador y luego convertido de cdigo ensamblador en cdigo maquina por el
ensamblador del compilador. Abajo tenemos un ejemplo de un programa escrito en lenguaje C.
/********************************************************************
* FileName:
main.c
* Purpose:
Comunicacin bsica por USART0
* Processor: ATmel AVR con mdulo TWI
* Compiler:
AVR IAR C y AVR GCC (WinAVR)
*
*******************************************************************/
#include "avr_compiler.h"
#include "usart.h"
int main(void)
{
char name[20];
usart_init();

// Inicializar USART0 @ 9600-8N1

puts("\n\r algun texto ");


puts("\n\r =================== \n\r");
puts("\n\r - Cul es tu nombre?... \n\r - ");
scanf("%s", name);
printf(" - Gusto en conocerte, %s", name);
}

while(1);

Tabla 7: Ejemplo de cdigo fuente en C


Los compiladores son las herramientas de programacin mas potentes que existen. En resumen, el
compilador traduce el programa escrito en su lenguaje (C, Basic, Pascal u otro) en cdigo ensamblador
y luego generar los archivos de depuracin (*.dbg, *.cof, *.d31, etc.) necesarios y de ejecucin
(*.hex).
Al trabajar con un compilador el programador ya no tiene que preocuparse (o lo hace muy poco) por
los vericuetos del hardware ni por el ensamblador nativo de cada microcontrolador. Esto simplifica de
manera asombrosa el desarrrollo de proyectos.
El compilador convierte el cdigo fuente en el cdigo mquina de cada microcontrolador sin inportar
mucho cul sea. Por ejemplo, un cdigo escrito para un ATmega128P podra ser facilmente compilado
para un ATxmega64A3U u otro y viceversa. Incluso es posible adaptar el cdigo para un
microcontrolador de otra marca, por ejemplo, de Freescale o Microchip. Eso se llama portabilidad.
Conocer un lenguaje de programacin como el C es un mundo aparte y es raro que una persona trate de
aprenderlo al mismo tiempo que va conociendo el microcontrolador. En cursomicros se ofrece un
captulo entero sobre el lenguaje C aunque puede no ser suficiente dada su complejidad comparado con
lenguajes como el Basic.

A continuacin se describen brevemente los principales compiladores para los microcontroladores


AVR. Para conocer ms de su uso se presentan posteriormente los tutoriales respectivos.

El Compilador CodeVisionAVR
El Compilador AVR IAR C
El Compilador AVR GCC
El Compilador Bascom AVR
El Compilador ImageCraft C
El Compilador mikroC for AVR

El compilador AVR GCC


Como su nombre lo revela, AVR GCC es un software derivado del compilador libre GCC (Gnu C
Compiler). Tiene por tanto todo el respaldo de la comunidad OpenSource.
En el pasado el principal inconveniente del compilador AVR GCC era que no tena un IDE propio. Los
programadores deban valerse de otros entornos como CodeBlocks o Eclipse. Pero con el paso del
tiempo el AVR Studio de ATmel lo fue incorporando cada vez ms hasta convertirlo en la actualidad en
su compilador casi oficial para sus microcontroladores AVR, todo gracias a su prestigio. Ahora ya no es
necesario buscar el compilador AVR GCC por separado, pues AVR Studio 5 y Atmel Studio 6 lo
incluyen en su paquete de instalacin. De hecho, incluyen una versin del compilador que es mejor (?)
que la disponible yendo a la web de AVR GCC para Windows (WinAVR) http://winavr.sourceforge.net.

4.1.2 Simulador, debugger y emulador.


La simulacin es un proceso donde se busca proponer un sistema fsico en marcha a partir de un
software, a fin de visualizar el posible comportamiento del sistema real, antes de su implementacin, de
esta forma se permite evitar costos por fallas o por pruebas destructivas.
En cuanto al microcontrolador ATmega48 se refiere, podemos encontrar en el sofftware ISIS,
propiedad de Labcenter Electronics, un buen simulador, ya que permite no solo conocer el
comportamiento lgico del dispositivo, sino que se aproxima un poco mas a la realidad al poner a
disposicin del usuario, un conjunto de elementos que simulan dispositivos analgicos y digitales,
permitiendo as, una mayor interaccin y una mejor prediccin en cuanto al posible comportamiento
del sistema implementado.
Por otra parte, el IDE AVR Studio, tambin cuenta con un simulador de acciones lgicas del
microcontrolador, el cual permite verificar el valor de cada registro, accediendo incluso a los valores bit
a bit, de esta forma, aunque con una interfaz un poco osca, permite una gran manipulacin de bits
dentro del programa del microcontrolador en cuestin.
Simulando Atmega48 con ISIS de PROTEUS.
Los pasos a seguir para la simulacin del programa de un micrcontrolador ATmega48 son los
siguientes:
1. De primera instancia, debemos contar ya con un programa compilado en AVR Studio y
generado un cdigo en Hexadecimal o archivo de depuracin.
2. Iniciar el software ISIS
3. Dar clic en el boton Pick From Libraries
4. De la ventana que aparece, escribir en el campo sealado por la etiqueta Keywords : Atmega48

5. Y en la seccin Results de la misma ventana elegir el microcontrolador ATMEGA48 (solamente


o el primero de la lista)

6. Dar clic en el botn OK, si es que ya no se requieren de mas componentes.


7. La accin anterior causar que aparezca el nombre del microcontrolador elegido en la ventana
devices.

8. Con un clic del ratn, sobre el nombre, podrs colocar el microcontrolador simulado sobre el
rea de trabajo de ISIS, con un nuevo clic del ratn., apareciendo ste de color rojo y mediante
movimientos del raton, podrs colocarlo en una posicin de tu eleccin, con un nuevo clic.
Antes de
dar
el
ltimo
clic

Despus de dar el ltimo clic


9. Dar un doble clic sobre el componente para ver sus propiedades.

10. sasasa

4.1.3 Equipos programadores (downloaders) de microcontroladores.


Los downloaders son programadores del cdigo hexadecimal que se genera cuando se ha compilado y
linkeado correctamente un programa para el microcontrolador
El uso de bootloader permite que un microcontrolador no requiera del uso de un downloader, esto a
cambio de un pequeo coste de espacio de memoria de programa, que es donde se almacena el
bootloader. A continuacin se aborda la secuencia de pasos a seguir a fin de hacer funcionar la tarjeta
que contiene al microcontrolador ATMega32u4

figura 20: Tarjeta para prcticas


fuente:(ComunidadAtmel,2010)
Este clon cuenta con la ventaja de ser un micro con modulo USB integrado, ya que tiene el
atmega32u4, el cual de acuerdo al vendedor puede ser programado con sketchs arduino o mediante avrgcc como un micro normal, pero cuenta con la ventaja de tener un bootloader, el cual le permite grabar
al microcontrolador sin necesidad de un programador externo.

Para trabajarlo en modo arduino en Windows, se requiere del software de Arduino, el plug in de
Teensyduino y finalmente de Flip. Pero como tengo unas cajas Linux, entonces vamos a echarlo a
andar aqu. En otro post les comentar mi motivacin.
Se van a requerir que se descarguen software de los links que a continuacin expongo:
http://arduino.cc/en/Main/Software
http://www.pjrc.com/teensy/td_download.html
https://sourceforge.net/projects/dfu-programmer/files/latest/download?source=files
(al final se trabajar con lnea de comandos- problemas de dependencias en Fedora18)
No eran problemas de dependencias solo hay que cambiar un poco el archivo .pro, quedando de la
siguiente manera
#------------------------------------------------#
# Project created by QtCreator 2011-05-31T09:58:34
#
#------------------------------------------------QT

+= core gui

TARGET = easydfu
TEMPLATE = app

SOURCES += main.cpp\
easydfu.cpp

HEADERS += easydfu.h

FORMS += easydfu.ui

RESOURCES += \
icons.qrc

INCLUDEPATH += "/usr/include/QxtCore/"
LIBS += -lQxtCore -lQxtGui

La linea que se cambio fue


INCLUDEPATH+="/usr/include/qxt/QxtCore"
y en el archivo easydfu.h la lnea 31 que dice
#include qxt/QxtGui/QxtGlobalShortcut

se cambia por
#include QxtGui/QxtGlobalShortcut

no pongo los signos de mayor que y menor que por que me edita el blogspot ;P
y finalmente el archivo easydfu.cpp se modifican la lnea 30 para que el cdigo quede as:
ui->setupUi(this);
//modificado para que lo encuentre el root
programPath = "/usr/local/bin/dfu-programmer";

En Ubuntu (12.04) mi otra box, pude instalar el siguiente paquete


https://sourceforge.net/projects/dfu-programmer/?source=dlp
Que es un cargador grfico del .hex generado hacia el micro, mas o menos tipo Flip (ya tambien en
Fedora18)
Se descargan los paquetes de acuerdo al tipo de sistema que tengamos ya sea de 32 o 64 bits.
Se descomprime el archivo arduino-X.X.X-linuxXX.tgz
El archivo teensyduino.64bit se le dan permisos de ejecucin, solo da clic derecho sobre el icono,
selecciona propiedades, da clic en la pestaa Permisos y sobre la casilla "es ejecutable" coloca una
paloma mediante un clic.
Da un doble clic para instalar y saldr la siguiente pantalla

Da clic en Next y elige el lugar donde descomprimiste el software de arduino.

Escoge las librerias que te interesa instalar (yo seleccion todas y di clic en siguiente)

al dar siguiente, ya nos permitir instalar el software de Teensy

Una vez instalado nos aparece la ventana que indica que ya ha terminado la instalacin.

Da clic en el botn Done.


Ahora ejecuta el software de arduino.

Y elige la tarjeta Teensy 2.0 del menu Herramientas -> Board ->Teensyduino 2.0

De esta forma ya podremos generar sketch's para la tarjeta, el siguiente paso consiste en instalar
DFU, que es el software a utilizar en lugar de Flip de atmel (Esto es por que flip aun no es compatible

con Linux)
Se descomprime el archivo dfu-programmer-0.6.0
ingresamos en la carpeta descomprimida
abrimos una terminal ahi y tecleamos el comando $./bootstrap.sh
luego $./configure
$make
$sudo make install

La instalacion la realiza en /usr/local/bin, por lo que hay que tener cuidado ya que su no ve este
directorio as que para invocar como superusuario debera hacer esto
$ sudo /usr/local/bin/dfu-programmer atmega32u4 erase por ejemplo

para programar un sketch realizado


$sudo /usr/local/bin/dfu-programmer atmega32u4 flash /home/miguel/sketchbook/sketch_may15a/sketch_may15a.cpp.hex

y para que funcione


$sudo /usr/local/bin/dfu-programmer atmega32u4 start

Para la instalacin del entorno grfico (si compila pero no carga correctamente al dfu-programmer).
Se descomprime easydfu_1.0_src.tar.gz
Entramos a la carpeta
ejecutamos la orden qmake de la siguiente manera
qmake-qt4 EasyDFU.pro (recuerda las modificaciones indicadas al inicio del post)
y luego make
se debe usar como root o mediante el comando sudo

Esta es una prueba de que est corriendo el software

4.2 Ejemplos de uso de herramientas de desarrollo.


Code Blocks es un IDE multiplataforma para lenguaje C, en esta entrada describir brevemente como
configurar el Code Blocks para que en Manajro se pueda programar un AVR, en este caso tenemos el
ATmega32U4
La primera parte es muy sencilla ya que solo hay que seguir un asistente, el problema es que cuando se
pretende compilar el nuevo codigo, envia un error

/usr/lib/libm.so: file not recognized: File format not recognized


Process terminated with status 1 (0 minutes, 0 seconds)
0 errors, 0 warnings
Esto es a causa de que el IDE no est correctamente configurado para funcionar con el AVR GCC, por
lo tanto solo hay que redireccionarlo, tal y como se indica en esta entrada de AVR Freaks
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=99954&view=next
De acuerdo a lo que ahi se indica debemos ir al menu settings, luego al menu Compiler..
Seleccionar el compilador "GNU AVR GCC Compiler"

Ir a la pestaa "Search directories" y en la sub-pestaa "Linker"


cambia la ruta por
/usr/lib/avr/lib/
que actualmente dice /usr/lib
ahora ir a la sub-pestaa "Compiler" y editar la entrada para que diga lo siguiente:
/usr/lib/avr/include/avr

Entonces, ahora si al compilar tendremos el siguiente resultado :)

Como puntosiguiente se muestran los enlaces a videos desarrollados por estudiantes de la carrera de
Ingeniera Mecatrnica donde se muestra la forma de usar el IDE mediante un ejemplo simple:

Unidad 5
Puertos de entrada y salida

Unidad 5 Puertos de entrada y salida


5.1 Arquitectura de los E/S
5.2 Configuracin y caractersticas elctricas de los puertos de E/S
5.3 Usos de los puertos con interfaces para dispositivos perifricos como:
5.3.1 Teclados (lineales y matriciales)
5.3.2 Display de siete segmentos.
5.3.3 Detectores de proximidad.
5.4 Usos de los puertos para manejo de potencia con interfaces con:
5.4.1 Transistores, Darlington, MOSFETs y Relevadores.
5.4.2 Optotransistores, optoacopladores y optotriacs.
5.4.3 Puentes H discretos (con transistores, con MOSFET) e integrados (L293, L298)
5.5 Ejemplos de uso de las interfaces para controlar:
5.5.1 Motores DC
5.5.2 Motores de pasos
5.5.3 Servomotores.

Competencia especfica
Manejar los puertos de entrada y salida
Actividades de aprendizaje:

Mapa conceptual: Realizar la lectura de la arquitectura de los puertos E/S del uC ATmega32U4
y elaborar un mapa conceptual que contenga los elementos mas relevantes.

5.1 Arquitectura de los E/S


Todos los puertos del AVR tienen la funcionalidad de lectura modificacin escritura cuando se
utilizan como puertos de Entrada Salida. Esto significa que la direccin de un puerto de un pin puede
cambiar sin cambiar accidentalmente la direccin de cualquier otro pin mediante las instrucciones SBI
y CBI. La misma situacin aplica cuando se configura un pin como salida e incluso con las resistencias
de pull up internas.

figura 21: Esquema elctrico de proteccin de


una terminal E/S
Es importante sealar que las terminales del microcontrolador tienen simetra en cuanto al sinking y
sourcing de corriente, la cual es suficiente para controlar de forma directa un LED. Agregando adems
que cada terminal de forma independiente, puede ser habilitada con una resistencia de pull-up, y tiene
diodos de proteccin a su entrada, tal y como se muestra en la figura 21: Esquema elctrico de
proteccin de una terminal E/S.
Son tres las direcciones de memoria de E/S asignadas para cada Puerto:

Registro de Datos PORTx

Registro de direccin de Datos DDRDx

Registro de Entrada de Terminales PINx (Este registro de solo lectura)

5.2 Configuracin y caractersticas elctricas de los puertos de


E/S
La importancia de la lectura y escritura de los puertos de un microcontrolador, as como el saber como
se debe configurar stos, es tal que si este punto no se conoce a detalle, todas las dems secciones no
podrn ser comprendidas.
En el caso de los microcontroladores AVR, los puertos configurados como entrada, el voltaje para que
tenga un valor cero (bajo) es de 0.2Vcc, si el valor de alimentacin oscila entre 2.7V y 5.5V, en el caso
de los voltajes de estado alto, se toma como valor mximo Vcc + 0.5 en el mismo rango de
alimentacin.
Para los puertos configurados como salida, el estado bajo es de 0.7V y el estado alto tendr un voltaje
de 4.2V

5.3 Usos de los puertos con interfaces para dispositivos


perifricos como:
5.3.1 Teclados Lineales y Matriciales
Los teclados matriciales son ensamblados en forma de matriz, tal y como se muestra en XXXX. El
diagrama muestra un teclado como una matriz de 4x4 o 16 teclas organizadas en 4 filas y 4 columnas.
El circuito de la figura anteriormente menciona muestra que, s no se ha presionado ninguna tecla,
todas las conexiones permanecen abiertas, pero cuando una tecla se presiona, se establece una conexin
columna-regln.

figura 22: Teclado matricial 4 x 4


Las tareas bsicas que se debe realizar un microcontrolador para decodificar un teclado matricial se
enlistan a continuacin:

Chechar si una tecla se oprimi

En caso de ser verdadero el punto anterior proseguir, sino salir

Rastrear los renglones para encontrar la columna activaciones

Descifrar o decodificar que tecla se oprimi.

A fin de detallar la secuencia de microcontrolador, se expone el siguiente diagrama de flujo

figura 23: Lectura de un teclado matricial


Como ver en el diagrama de flujo se describe el procedimiento de lectura del teclado matricial, as
como el valor de retorno que se define con la ecuacin
tecla=4R[i]+col ;
donde el valor de la columna va 0 a 3, y en consecuencia la funcin de lectura de teclado matricial
propone devolver valores que oscilan entre 0 y 15, cabe sealar que en este algoritmo no se contempla
el valor devuelto en caso de no presionar tecla alguna. En el cdigo fuente en Tabla 9: Cdigo de
ejemplo de teclado matricial se propone que el valor devuelto sea 16 en caso de que no se presione
tecla alguna.
Adems se introduce en este contexto el uso de macros para configurar las salidas de los reglones y que
stas sean llamadas desde la funcin que lee el teclado matricial, como ejemplo (Tabla 8: Macro para la
activacin de lectura por columna) se coloca el cdigo de una macro de ejemplo;
#define vSetKeyPadR2() {set_bit(PORT_KEY_R1,PIN_KEY_R1); clear_bit(PORT_KEY_R2,PIN_KEY_R2);\
set_bit(PORT_KEY_R3,PIN_KEY_R3); set_bit(PORT_KEY_R4,PIN_KEY_R4);}

Tabla 8: Macro para la activacin de lectura por columna


En esta macro puede visualizarse que solo un reglon se coloca en estado alto, indicando que est ser la
fila activa a escanear, adems observe que la declaracin de la macro se realiza mediante la directiva
#define que en el lenguaje C en cursos iniciales, se utiliza como un elemento de definicin para
constantes.

/**
*
*
*
* @author miguel
* @date 03/03/2013
* @brief Programa que lee un teclado matricial y saca por los pines
*

pines pin_X0, pin_X1, pin_X2, pin_X3 y pin_X4

considere que las entradas son c1 .. c3

y que las salidas son r1 .. r3

*
* @file main.c
*/

#include <avr/io.h>

#define clear_bit(sfr,bit) (_SFR_BYTE(sfr) &=~_BV(bit))


#define set_bit(sfr,bit) (_SFR_BYTE(sfr)|=_BV(bit))
#define F_CPU 20000000UL
#include <util/delay.h>

/************************************************************************/
/* entradas

*/

/************************************************************************/
#define PIN_KEY_C1 PD4 //1
#define PORT_KEY_C1 PIND
#define PIN_KEY_C2 PD5 //2
#define PORT_KEY_C2 PIND
#define PIN_KEY_C3 PD6 //3
#define PORT_KEY_C3 PIND
#define PIN_KEY_C4 PD7 //4
#define PORT_KEY_C4 PIND

/************************************************************************/
/* Configura entradas

*/

/************************************************************************/
#define CPIN_KEY_C1 DDD4
#define CPORT_KEY_C1 DDRD
#define CPIN_KEY_C2 DDD5
#define CPORT_KEY_C2 DDRD

#define CPIN_KEY_C3 DDD6


#define CPORT_KEY_C3 DDRD
#define CPIN_KEY_C4 DDD7
#define CPORT_KEY_C4 DDRD

/************************************************************************/
/* Salidas

*/

/************************************************************************/
#define PIN_KEY_R1 PD0 //A
#define PORT_KEY_R1 PORTD
#define PIN_KEY_R2 PD1 //B
#define PORT_KEY_R2 PORTD
#define PIN_KEY_R3 PD2 //C
#define PORT_KEY_R3 PORTD
#define PIN_KEY_R4 PD3 //D
#define PORT_KEY_R4 PORTD

/************************************************************************/
/* Configura salidas

*/

/************************************************************************/
#define CPIN_KEY_R1

DDD0

#define CPORT_KEY_R1 DDRD


#define CPIN_KEY_R2

DDD1

#define CPORT_KEY_R2 DDRD


#define CPIN_KEY_R3

DDD2

#define CPORT_KEY_R3 DDRD


#define CPIN_KEY_R4

DDD3

#define CPORT_KEY_R4 DDRD

/************************************************************************/
/* @brief Macros para colocar un valor bajo en cada fila y ser detectada
*

en las columnas

* @params vacio
* @returns vacio

*/

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

#define vSetKeyPadR1() {clear_bit(PORT_KEY_R1,PIN_KEY_R1); set_bit(PORT_KEY_R2,PIN_KEY_R2);\


set_bit(PORT_KEY_R3,PIN_KEY_R3); set_bit(PORT_KEY_R4,PIN_KEY_R4);}

#define vSetKeyPadR2() {set_bit(PORT_KEY_R1,PIN_KEY_R1); clear_bit(PORT_KEY_R2,PIN_KEY_R2);\


set_bit(PORT_KEY_R3,PIN_KEY_R3); set_bit(PORT_KEY_R4,PIN_KEY_R4);}

#define vSetKeyPadR3() {set_bit(PORT_KEY_R1,PIN_KEY_R1); set_bit(PORT_KEY_R2,PIN_KEY_R2);\


clear_bit(PORT_KEY_R3,PIN_KEY_R3); set_bit(PORT_KEY_R4,PIN_KEY_R4);}

#define vSetKeyPadR4() {set_bit(PORT_KEY_R1,PIN_KEY_R1); set_bit(PORT_KEY_R2,PIN_KEY_R2);\


set_bit(PORT_KEY_R3,PIN_KEY_R3); clear_bit(PORT_KEY_R4,PIN_KEY_R4);}

//Prototipos de funcion para teclado matricial


void vInitKeyPad(void);
unsigned char ui8_TestKeyPad(void);

/**
* Salidas para leds
*/
#define pin_X0

PB0

#define Ppin_X0 PORTB


#define pin_X1 PB1
#define Ppin_X1

PORTB

#define pin_X2

PB2

#define Ppin_X2 PORTB


#define pin_X3 PB3
#define Ppin_X3 PORTB
#define pin_X4 PB4
#define Ppin_X4 PORTB

/**
* Configuracion para salidas
*/
#define cpin_X0

DDB0

#define cPpin_X0 DDRB


#define cpin_X1 DDB1
#define cPpin_X1 DDRB
#define cpin_X2

DDB2

#define cPpin_X2 DDRB


#define cpin_X3 DDB3
#define cPpin_X3 DDRB
#define cpin_X4 DDB4
#define cPpin_X4 DDRB

/***
* Programa Principal
*/
int main(void)
{

unsigned char tecla=16;


vInitKeyPad();
set_bit(cPpin_X0,cpin_X0);
set_bit(cPpin_X1,cpin_X1);
set_bit(cPpin_X2,cpin_X2);
set_bit(cPpin_X3,cpin_X3);
set_bit(cPpin_X4,cpin_X4);

while(1)
{

tecla= ui8_TestKeyPad();

if(bit_is_set(tecla,0))
set_bit(Ppin_X0, pin_X0);
else
clear_bit(Ppin_X0, pin_X0);

if(bit_is_set(tecla,1))
set_bit(Ppin_X1, pin_X1);
else
clear_bit(Ppin_X1, pin_X1);

if(bit_is_set(tecla,2))
set_bit(Ppin_X2, pin_X2);
else
clear_bit(Ppin_X2, pin_X2);

if(bit_is_set(tecla,3))
set_bit(Ppin_X3,pin_X3);
else
clear_bit(Ppin_X3, pin_X3);

if(bit_is_set(tecla,4))
set_bit(Ppin_X4,pin_X4);
else
clear_bit(Ppin_X4, pin_X4);

}
}

/**
* @brief funcion que inicializa el teclado

*/

void vInitKeyPad(void)
{
//configurando salidas - renglones
set_bit(CPORT_KEY_R1, CPIN_KEY_R1); set_bit(PORT_KEY_R1,PIN_KEY_R1);
set_bit(CPORT_KEY_R2, CPIN_KEY_R2); set_bit(PORT_KEY_R2,PIN_KEY_R2);
set_bit(CPORT_KEY_R3, CPIN_KEY_R3); set_bit(PORT_KEY_R3,PIN_KEY_R3);
set_bit(CPORT_KEY_R4, CPIN_KEY_R4); set_bit(PORT_KEY_R4,PIN_KEY_R4);
//configurando entradas - columnas
clear_bit(CPORT_KEY_C1, CPIN_KEY_C1);
clear_bit(CPORT_KEY_C2, CPIN_KEY_C2);
clear_bit(CPORT_KEY_C3, CPIN_KEY_C3);
clear_bit(CPORT_KEY_C4, CPIN_KEY_C4);
//colocando resistencias de pull up a las columnas
set_bit(PORT_KEY_C1,PIN_KEY_C1);
set_bit(PORT_KEY_C2,PIN_KEY_C2);
set_bit(PORT_KEY_C3,PIN_KEY_C3);
set_bit(PORT_KEY_C4,PIN_KEY_C4);
}

/**
* @brief funcion que permite escanear el teclado y devuelve un valor entre 0 y 16
*

dependiendo si se presiona alguna tecla o no

*
* @returns devuelve un tipo char sin signo entre 0 a 16, si no se presiona ninguna
*

tecla devuelve 16, si se presiona una tecla regresa un valor de 0 a 15

*
*

Ejemplo:

\verbatim

*
*

tecla=ui8_TestKeyPad();
\endverbatim

*/
unsigned char ui8_TestKeyPad(void)
{
unsigned char k;

for(k=0; k< 16; k++)


{
switch(k)
{
case 0:
vSetKeyPadR1();

break;
case 4:
vSetKeyPadR2();
break;
case 8:
vSetKeyPadR3();
break;
case 12:
vSetKeyPadR4();
break;
}
if(bit_is_clear(PORT_KEY_C1,PIN_KEY_C1)){return(k);}
k++;
if(bit_is_clear(PORT_KEY_C2,PIN_KEY_C2)){return(k);}
k++;
if(bit_is_clear(PORT_KEY_C3,PIN_KEY_C3)){return(k);}
k++;
if(bit_is_clear(PORT_KEY_C4,PIN_KEY_C4)){return(k);}

}
return (16);
}

Tabla 9: Cdigo de ejemplo de teclado matricial

5.3.2 Display de 7 segmentos


Una de las aplicaciones ms populares de los LEDs es la de sealizacin. Quizs la ms utilizada sea
la de 7 LEDs colocadas en forma de ocho tal y como se indica en la Ilustracin 1. Aunque
externamente su forma difiere considerablemente de un diodo LED tpico, internamente estn
constituidos por una serie de diodos LED con unas determinadas conexiones internas. En la Ilustracin
1 se indica el esquema elctrico de las conexiones del interior de un indicador luminoso de 7 segmentos
(EPSA, 2001).

figura 24: Conexiones display de 7 segmentos


La figura 24 muestra un indicador de siete segmentos. Contiene siete LED rectangulares (a - g), en el
que cada uno recibe el nombre de segmento porque forma parte del smbolo que est mostrando. Con
un indicador de siete segmentos se pueden formar los dgitos del 0 al 9, tambin las letras a, c, e y f y
las letras minsculas b y d. Los entrenadores de microprocesadores usan a menudo indicadores de siete
segmentos para mostrar todos los dgitos del 0 al 9 ms a, b, c, d, e y f.

figura 25: Pinout display de 7 segmentos


Polarizando los diferentes diodos, se iluminaran los segmentos correspondientes. De esta manera
podemos sealizar todos los nmeros en base 10. Por ejemplo, si queremos representar el nmero de 1
en el display deberemos mandar seal a los diodos b y c, y los otros diodos deben de tener tensin cero.
Esto lo podemos escribir as 0110000(0). El primer dgito representa al diodo a, el segundo al b, el
tercero al c, y as sucesivamente. Un cero representa que no polarizamos el diodo, es decir no le
aplicamos tensin. Un uno representa que el diodo esta polarizado, y por lo tanto, emite luz. Muchas
veces aparece un octavo segmento, entre parntesis en el ejemplo anterior, que funciona como punto
decimal.

/**
* @author miguel montiel mtz
* @date 03/03/2013
* @brief Programa que muestra en un display de 7 segmentos
*

un numero que sale por el puerto con caracteristica

de ser flexible en su conexion

*
*

Al ser flexible, debe declarar pin a pin y puerto

a puerto a ser utilizado

* \verbatim
*

seg_a --> pin

seg_b

seg_c

seg_d

seg_e

seg_f

seg_g

*
*

pseg_a --> Puerto de conexion

pseg_b

pseg_g

*
*

Del mismo modo se deben declarar los puerto para ser configurados

como salidas

*
*

cseg_a --> bit en el registro DDRx

cseg_b

cseg_c

cseg_g

*
*

cpseg_a --> Puerto de conexion

cpseg_b

cpseg_g

*\endverbatim
*

Si desea utilizar una configuracin diferente, solo debe cambiar los

valores de estas macros indicadas

*
* @file display.c
*/

#include <avr/io.h>

#define clear_bit(sfr,bit) (_SFR_BYTE(sfr) &=~_BV(bit))


#define set_bit(sfr,bit) (_SFR_BYTE(sfr)|=_BV(bit))
#define F_CPU 20000000UL
#include <util/delay.h>

/**
* pines de conexion
*/

#define seg_a

PB0

#define seg_b

PB1

#define seg_c

PB2

#define seg_d

PB3

#define seg_e

PD0

#define seg_f

PD1

#define seg_g

PD2

/**
* Puertos de los pines de conexion
*/
#define pseg_a

PORTB

#define pseg_b

PORTB

#define pseg_c

PORTB

#define pseg_d PORTB


#define pseg_e

PORTD

#define pseg_f

PORTD

#define pseg_g

PORTD

/**
* Configuracion de pines y puertos
*/

#define cseg_a

DDB0

#define cseg_b

DDB1

#define cseg_c

DDB2

#define cseg_d

DDB3

#define cseg_e

DDD0

#define cseg_f

DDD1

#define cseg_g

DDD2

#define cpseg_a

DDRB

#define cpseg_b

DDRB

#define cpseg_c

DDRB

#define cpseg_d DDRB


#define cpseg_e

DDRD

#define cpseg_f

DDRD

#define cpseg_g

DDRD

void initDisplay(void);
void Print(unsigned char value);

int main(void)
{
unsigned char contador=0;

while(1)
{
for(contador=0;contador <16; contador++)
{
Print(contador);
_delay_ms(500);
}

}
}

/**
* @brief Funcion que permite inicializar el display
*/
void initDisplay(void)
{
set_bit(cpseg_a, cseg_a);
set_bit(cpseg_b, cseg_b);
set_bit(cpseg_c, cseg_c);
set_bit(cpseg_d, cseg_d);
set_bit(cpseg_e, cseg_e);
set_bit(cpseg_f, cseg_f);
set_bit(cpseg_g, cseg_g);
}
/**

* @brief Funcion que permite imprimir hacia el display


* la configuracion de conexion es
* Xgfedcba
*/

void Print(unsigned char value)


{
unsigned char out=0x00;
switch(value)
{
case 0:
out=0x3f;
break;
case 1:
out=0x79;
break;
case 2:
out=0x24;
break;
case 3:
out=0x4f;
break;
case 4:
out=0x66;
break;
case 5:
out=0x6d;
break;
case 6:
out=0x7d;
break;
case 7:
out=0x07;
break;
case 8:
out=0x7f;
break;
case 9:
out=0x6f;
break;
case 10:
out=0x3f;
break;

case 11:
out=0x7a;
break;
case 12:
out=0x53;
break;
case 13:
out=0x7c;
break;
case 14:
out=0x5b;
break;
case 15:
out=0x1b;
break;

if(bit_is_set(out,6)) set_bit(pseg_g,seg_g);
else clear_bit(pseg_g,seg_g);

if(bit_is_set(out,5)) set_bit(pseg_f,seg_f);
else clear_bit(pseg_f,seg_f);

if(bit_is_set(out,4)) set_bit(pseg_e,seg_e);
else clear_bit(pseg_e,seg_e);

if(bit_is_set(out,3)) set_bit(pseg_d,seg_d);
else clear_bit(pseg_d,seg_d);

if(bit_is_set(out,2)) set_bit(pseg_c,seg_c);
else clear_bit(pseg_c,seg_c);

if(bit_is_set(out,1)) set_bit(pseg_b,seg_b);
else clear_bit(pseg_b,seg_b);

if(bit_is_set(out,0)) set_bit(pseg_a,seg_a);
else clear_bit(pseg_a,seg_a);
}

Tabla 10: Cdigo de ejemplo para display de siete segmentos

5.3.3 Detectores de proximidad


De acuerdo a la definicin que se ofrece en Wikipedia un detector de proximidad es un transductor
que detecta objetos o seales que se encuentran cerca del elemento sensor.
A continuacin se mostrarn dos ejemplos de sensores de proximidad, una basada en ondas infrarrojas
y otra basada en ondas ultranicas.
5.3.3.2 El sensor Infrarrojo modulado en frecuencia

En un detector de rayos infrarrojos, el elemento sensor es un fotodiodo o un foto transistor, a su vez


ste elemento se conecta a un dispositivo que amplifica y adapta la seal de salida. En este caso
particular, la seal infrarroja se modula en frecuencia y es del tipo reflexin sobre objetos.

Ilustracin 1: modulacin en frecuencia para sensor infrarrojo


fuente: (Pablin, 2008)
En el circuito que se muestra, se basa en el decodificador de tonos el cual, a travs de esta
configuracin, genera una frecuencia determinada por los valores de la resistencia de 10k y el capacitor
de 100nF que estn conectados entre las terminales 5 y 6, esta frecuencia se aplica para llevar a
saturacin y corte al transistor 2N2222, el cual a su vez permite generar rfagas de luz infrarroja a la
frecuencia establecida previamente. Por la lnea 3 se recibe la frecuencia reflejada sobre un objeto.
5.3.3.3 El Sensor ultrasnico SRF-04

Este dispositivo, permite la medicin de distancias a travs de rfagas ultrasnicas emitidas por un
microcontrolador, cuando en una de sus terminales denominada Disparo recibe un pulso cuya duracin
en estado en alto es de 10 milisegundos.

El SRF-04 devuelve un pulso positivo por medio de la terminal ECO, cuyo ancho de pulso es
proporcional al tiempo que dura en ir y venir la rfaga ultrasnica emitida. Una grfica de tiempos se
propone a continuacin (figura 26: Diagrama de funcionamiento de sensor ultrasnico):

figura 26: Diagrama de funcionamiento de sensor ultrasnico


Fuente: (Devantech Ltd, 2003)
El dispositivo cuenta con 5 terminales, dos de ellas, las ms importantes ya fueron descritas
anteriormente, la figura muestra como primer terminal a la alimentacin de este dispositivo, seguida de
la terminal de Eco, la cual es una salida, como tercera terminal se tiene al PIN Disparo, el cual se usa
para indicar al sensor una peticin de medicin, la cuarta terminal es de alta impedancia o no coneccin
(en algunos modelos clones esta terminal no est disponible) y finalmente la terminal de tierra. (Vese
la figura 27: Terminales del SRF-04)

figura 27: Terminales del


SRF-04
Fuente: (Devantech Ltd, 2003)

El clculo de la distancia
El SRF-04 proporciona un pulso proporcional a la distancia, esto es, si el ancho del pulso est medido
en microsegundos, entonces la divisin entre 58, entonces el resultado estar en centmetros, o si se
divide entre 148, la distancia estar en pulgadas.
Alcance del SRF-04 y forma de la onda
En el sensor ultrasnico SRF-04 tiene un patron de onda de forma cnica y la amplitud de dicha onda
depende del rea de superficie, la frecuencia y el tipo de transductor que se utiliza, considere que estas

formas son fijas, se pone a consideracin que las unidades del eje vertical de la figura que se presenta a
continuacin est en dB. Y que la apertura del cono es de 55

figura 28: rango de


deteccin
Debe tomarse en cuenta que para un montaje sobre superficies, el fabricante recomienda una altura
mnima de 30cm sobre el nivel de superficie, montajes mas bajos, requieren que el sensor se apunte un
poco hacia arriba, a fin de evitar los reflejos del suelo.

5.4 Uso de los puertos para manejo de potencia con interfaces


con:
5.4.1 Transistores, Darlingtons, MOSFETS y relevadores
Muchas veces se presenta la difcil situacin de manejar corrientes o tensiones ms grandes que las que
entrega un circuito digital, y entonces nos disponemos al uso de transistores, el tema es hacer que estos
trabajen en modo corte y saturacin sin estados intermedios, es decir que cambien su estado de plena
conduccin a un profundo corte, y eso es lo que veremos en este pequeo tutorial.
Los transistores a utilizar en estos casos deben tener la suficiente ganancia para que la onda cuadrada,
aplicada en su entrada (Base), no sufra ninguna deformacin en la salida (Colector o Emisor), o sea que
conserve perfecta simetra y sus flancos ascendente y descendente se mantengan bien verticales.
La corriente mxima que puede circular de colector a emisor est limitada por la tensin de
polarizacin de Base y el Resistor o la carga del colector.
Polarizacin de un transistor NPN como Emisor Comn
En este caso el emisor est conectado a masa, se dice que este terminal es comn a la seal de base y de
colector. El utilizado en este caso un BC547 y estos son algunos de sus datos:
Tensin Base-Colector (VCBO) = 50 V
Corriente de Colector (Ic) = 100mA = 0,1A

figura 29: Transistor inversor


Cuando la base de Q1 se polariza positivamente, ste conduce la mxima corriente, que le permite Rc.
Rc es la resistencia de carga, que bien podra ser un LED, un rel, etc.
Ic = E/R = 12V / 2200 = 0,0054 = 5,4 mA
Ib = E/R = 12V / 10000 = 0,0012 = 1,2 mA
Es decir la corriente total Colector-Emisor es 6,6mA.
Conexin como seguidor emisivo:
En esta situacin se toma la seal de salida desde el Emisor donde se encuentra la Resistencia de carga,
observa que este esquema comparado al anterior tiene la misma fase de salida que la de entrada.

figura 30: seguidor emisivo


Tambin hay casos en que necesitas que el transistor est conduciendo permanentemente (estado de
saturacin) y que pase al corte ante la presencia de un pulso elctrico, esto sera lo inverso de lo visto
anteriormente, para lograr esto, los circuitos anteriores quedan como estn y slo se reemplazan los
transistores por los complementarios, o sea donde hay un NPN se conecta un PNP.
Cuando la seal es negativa
En ocasiones se da el caso en que las seales lgicas recibidas son negativas o de nivel bajo, para
entonces se puede utilizar un transistor PNP, por ejemplo: el BC557, que es complementario del
BC547, para conseguir los mismos resultados. En la siguiente figura se representa esta condicin, es
decir, un acoplamiento con transistor PNP.

figura 31: Acoplamiento con


transistor PNP
Anlisis para la conexin de un RELE
El diodo en paralelo con la bobina del rel cumple la funcin de absorber las tensiones que se generan
en todos los circuitos inductivos.
Si la bobina del rel tiene 50 ohm de resistencia y funciona a 12 V, puedes calcular el consumo de
corriente que tiene el rel, para as saber que transistor utilizar:
Ic = E/R = 12V / 50 = 0,24 = 240 mA

figura 32: Conexin bsica de


relevador
Con este resultado no se puede utilizar el BC547, cuya corriente mxima es de 100mA, pero si lo
puede hacer un BC337, es conveniente no superar el 50% de la corriente que entregan los transistores.
Ahora bien, si la seal que se aplique a la base del transistor tiene la suficiente amplitud (tensin) y
suficiente intensidad (Amper), no habr dificultad y la corriente de base tambin ser suficiente para
saturar el transistor, que conmutar en forma efectiva el rel.
Montajes Darlington:
En esta conexin se utiliza un BC337 (NPN) el cual si soporta los 240mA que se necesitaba
anteriormente, pero adems un transistor de baja potencia como el BC547 (NPN).
En este tipo de montajes, hay que lograr previamente una ganancia en corriente y esta corriente
aplicarla a la base del BC337, esta es la finalidad del montaje en Darlington.

figura 33: Montaje Darlington


En este circuito el Transistor BC337 es el que recibe la carga del rel y el BC547 solamente soporta la
corriente de base del BC337, adems la ganancia se multiplica sin cargar la salida del componente que
entrega la seal, ya que ahora la corriente que drena el 547 es tomada de la misma fuente y aplicada a
la base del 337. De este modo la resistencia de base del 547 puede ser elevada ya que necesitamos una
corriente mucho menor en la misma.
En el siguiente grfico se describe como lograr la conmutacin de un rel con un transistor de salida
NPN. incluso utilizando tensiones diferentes.

figura 34:
activacin

Doble

transistor

de

En esta situacin como vemos es necesario agregar un transistor de baja potencia, ya que la corriene
que debe manejar es la de base. Con la entrada en "1": El BC547 conduce y enva a masa la base del
BC337 de este modo se mantiene el corte.
Con la entrada en "0": El 547 pasa al corte y su colector queda "abierto", ahora s se polariza la base
del 337 y conmutando el rel.
Otro caso de conmutacin con diferentes tensiones.
Suponiendo que el consumo de un rel sea 200mA.
Para los clculos de polarizacin siempre se debe tomar el menor Beta-B-(hfe) que indiquen los
manuales de los transistores, o sea que si dice 100 a 300, tomamos 100. Veamos que corriente de base
se necesita de acuerdo a estos datos:
Ib = Ic / Hfe = 200mA / 100 = 2mA
Donde:

Ib = Intensidad de Base (en mA)


Ic = Intensidad de Colector
Hfe = Ganancia

figura 35: Clculo


conexin a Relevador

de

Ahora veamos que valor de resistencia de base es necesario para lograr 2mA con una fuente de 5V, que
es la salida que entrega el separador del ejemplo
R = E / I = 5V / 0,002A = 2500 ohm (un valor normalizado es 2k2)
MOSFET
Los MOSFET, o transistores de efecto de campo metal-xido (por sus siglas en ingls), tienen
caractersticas que los hacen tiles para alternar los dispositivos electrnicos en apagados o encendidos.
El dispositivo consume muy poca corriente por s mismo, normalmente debajo de 1 microamperio,
mientras que puede controlar decenas de amperios de corriente. Un canal N, un MOSFET en modo de
mejoramiento alternar un dispositivo a encendido cuando tenga un voltaje de ms de unos cuantos
voltios a travs de sus patas de fuente y compuerta. Cuando su voltaje est en ceros, el MOSFET se
apaga. Puedes fcilmente arreglar esto con unos cuantos dlares en piezas.
Polarizacin del transistor MOSFET
En la figura , la corriente de saturacin del drenador en el circuito mostrado es:
I D (sat) =

V DD
RD

Y la tensin de corte de drenador es V DD. La figura muestra la recta de carga para DC entre una
corriente de saturacin de ID(sat) y una tensin de corte VDD.
Cuando VGS = 0, el punto Q est en el extremo inferior de la recta de carga para continua indicando
corte. Cuando VGS = VGS (on) el punto Q est en el extremo superior de la recta de carga, indicando
saturacin.

figura 36: circuito saturacin

figura 37: curva caracterstica

Cuando la corriente de saturacin es menor que la I D(on) el dispositivo est polarizado en una zona
hmica, es decir, un MOSFET de enriquecimiento est polarizado en la zona hmica cuando se
satisface la condicin:
I D (sat) < I D(on) cuando V GS =V GS (on )
Si la condicin anterior se cumple, entonces el MOSFET en saturacin, se comporta como una pequea
resistencia equivalente, la cual se lee en las hojas de datos como RDS(ON).
Considere el siguiente ejemplo: Un transistor MOSFET, que se encuentra conectado como se indica en
la figura , el cual cuenta con las siguientes caractersticas :

figura 38: Saturacin de un MOSFET

Solucin:

VGS(on)

4,5V

ID(on)

75 mA

RDS(on)

La corriente de saturacin para este circuito es:


I D (sat) =

20V
=20mA
1k

De la operacin anterior se puede ver claramente que ID(on) > ID(sat), por lo tanto, en saturacin, el
MOSFET se comportar como una resistencia pequea, siendo as, entonces que los circuitos
equivalentes sern:

figura
39:
Circuito
equivalente en
saturacin

figura
40:
Circuito
equivalente en
corte

5.4.2 Optotransistores, optoacopladores y optotriacs


Los Optoacopladores u Optoaisladores son dispositivos que podemos encontrar en mltiples
aplicaciones dentro de un equipo electrnico, cuando una seal debe ser transmitida desde un circuito
especfico a otro, sin que exista conexin elctrica entre ambos. A pesar de ser un elemento muy
utilizado, encierra muchos misterios en su interior y estas incgnitas se profundizan cuando su
funcionamiento correcto se pone en duda. Se pueden controlar?Cmo sabemos si funcionan
correctamente? Por lo general, la transmisin de la informacin dentro de un Optoacoplador se realiza
desde un LED infrarrojo que no responde, en las mediciones con el multimetro, a lo que conocemos
como un LED tradicional. Qu podemos hacer entonces? Veamos si en este artculo podemos
encontrar las respuestas que necesitamos.
La evolucin de los semiconductores en el mundo electrnico encontr en los optoacopladores al
reemplazo ideal para dejar de lado al rel (o relay) y al transformador, en especial en aplicaciones
digitales, donde la velocidad de transferencia y la conservacin de la forma de onda deba ser tan fiel
como fuera posible en la salida, reflejando en forma idntica al formato que presentaba en la entrada.
En el caso del rel, la transferencia de una seal analgica es imposible, del mismo modo que sucede
con los transformadores a determinadas frecuencias y con formas de onda especiales. El
optoacoplador fue la solucin empleada en mltiples aplicaciones que requeran importantes cambios
de niveles de tensin entre los circuitos enlazados, donde se requera aislacin de determinado tipo de
ruidos en la transmisin de datos; o en espacios industriales, donde se pudiera (o pudiese) controlar
mediante un impulso lgico, de baja tensin, una carga con elevados consumos en corriente alterna.
Bsicamente, si pudiramos resumirlo en una frase, podra ser la solucin de baja potencia a la

activacin aislada galvnicamente de cargas, mediante un sistema de control


A pesar de que un optoacoplador o acoplador de seales elctricas mediante un enlace ptico puede
tomar formatos fsicos muy variados, su arquitectura es siempre reiterada en el concepto fundamental.
Por un lado, se utiliza para transmitir la informacin un diodo LED infrarrojo, construido a base de un
compuesto de Arseniuro de Galio, que se enlaza en forma ptica con un detector encargado de capturar
esa informacin luminosa y transformarla en una seal elctrica idntica, en su composicin de niveles,
a la que el LED emite. Luego, la naturaleza de este detector nos brindar una respuesta acorde al tipo
de seal aplicada al LED y a la funcin especfica para la que fue construido ese detector que trae
consigo el optoacoplador.

figura 41: Ejemplos de optoacopladores


Por ejemplo, si el elemento receptor (o detector) es un fototransistor, podremos utilizar el dispositivo
para transferir seales analgicas como puede ser audio o video. Si en cambio es otro fotodiodo, o un
foto-SCR, nos ser til como rectificador controlado y aislado elctricamente. De este modo, los
detectores se multiplican en formatos y tipo de aplicacin, como puede ser un Triac (para trabajar con
corrientes alternas) y hasta podemos encontrar puertas lgicas, como detectores dentro de un
optoacoplador. Lo que siempre conservar su naturaleza es el elemento transmisor o emisor; siempre
ser un diodo (o un conjunto de ellos) LED infrarrojo.

figura 42: Optoacoplador de


herradura

figura 43: Optoacoplador


de reflexin

Otro tema muy importante es la gran variedad de encapsulados que encontraremos delante de nuestros
ojos y aunque no lo creamos posible, ser un optoacoplador. Por ejemplo, uno muy popular dentro del
mundo de los robots sigue-lneas es el CNY70, que trabaja por reflexin. Otro tipo de acoplador
ptico muy popular es el que trae una forma de U y su activacin se basa, ya no en un reflejo, sino en
una interrupcin de un haz detectado en forma permanente (en el tercer video hacemos un ensayo con
uno). El extremo ms conocido y familiar, es el que viene en el mismo tipo de encapsulado que un
circuito integrado tradicional, pero con menor cantidad de pines por lado. Es decir, notars que traen
dos o tres pines por lado y eso, adems de llamarte la atencin, te estar indicando que ests (99%)
frente a un optoacoplador. De todos modos, estos ltimos ofrecen una presentacin mltiple en un
mismo encapsulado y su aspecto es el de un circuito integrado clsico con presentaciones de hasta 8
pines por lado (4 optoacopladores individuales en un mismo encapsulado).

figura 44: Empaquetados de optoacopladores


Cmo verificar el funcionamiento
No te preocupes, no te sientas como un marciano si te invade la duda de su accionar adecuado y no
sabes por dnde comenzar a medir; ni qu parmetros controlar y mucho menos cmo hacerlo. La
comprobacin de funcionamiento de este tipo de dispositivos no es sencilla. Seamos sinceros y realistas
desde el comienzo: indefectiblemente (no tienes opcin) debes retirarlo del lugar de trabajo donde se
encuentre para realizar algunas pruebas que no son complejas, que en muy corto tiempo la puedes
realizar y los materiales necesarios para llevarlas a cabo son muy bsicos, muy elementales. Todo esto
vale si deseas hacer un trabajo apropiado, claro est. El primero que debemos hacer a un optoacoplador
es, por lgica, inspeccionarlo fsicamente. Observarlo y verificar que su estructura est correcta sin
demostraciones de quemazn o quebraduras en su estructura fsica. En el caso de los que se encuentran
en encapsulado tipo circuito integrado, suelen quebrarse al explotar y eso facilita mucho el
diagnstico. Sin embargo, cuando su aspecto es ptimo debemos comenzar con la medicin esttica
ms elemental que podemos hacer: mediante el uso del multmetro (en posicin para medir diodos si es
digital, en R X 1 si es analgico) buscar entre los pines hasta encontrar el LED. Recuerda: NO es un
LED convencional por lo tanto, el valor obtenido en la medicin podr resultarte algo extrao.
Una vez descubierto y comprobado el LED, podemos pasar a hacer otro tipo de mediciones que puedan
ayudarnos a incrementar la seguridad de un buen funcionamiento; esto es, que la informacin
introducida en el LED se pueda recuperar en el detector. Para esto, necesitaremos dos multmetros y
algunos cables con pinzas caimanes o cocodrilo en sus extremos, para apoyarnos fsicamente en el
trabajo, porque mantener cuatro puntas de medicin con slo dos manos suele ser algo complicado de
hacer. Por lo tanto, un par de cables y algunos pines de resistencias cortados pueden ser de gran ayuda.
Una vez identificado el LED, ya tenemos la posibilidad de activar el emisor, por lo tanto, la bsqueda
con el segundo instrumento estar orientada a comprobar el funcionamiento del elemento receptor o el
detector que recibe el haz infrarrojo.

Desde que conozco a los optoacopladores, el mtodo mostrado hasta aqu es, por lo general, suficiente
como para detectar el buen funcionamiento de este dispositivo sin necesidad de recurrir a buscar en la
web la hoja de datos del elemento que estamos ensayando. Sin embargo, no ha faltado el diablo a la cita
en varias ocasiones y a pesar de encontrar estas mediciones correctas, el optoacoplador no funcionaba
en su lugar de trabajo, en la aplicacin. Afuera las mediciones eran ptimas, mientras que en circuito,
bajo condiciones de trabajo, el dispositivo no funcionaba de manera correcta. Si lo analizamos en
forma detenida, puede existir una fuga de corriente desde el emisor hacia el detector y los resultados
parecen ser los correctos, sin embargo, la aislacin a ambos lados de los elementos que componen el
optoacoplador no se cumple como debera ser. Por lo tanto, a las mediciones efectuadas, deberamos
agregarle un mtodo dinmico de ensayo, con tensin de trabajo que nos permita comprobar los
elementos, a la vez que tambin nos demuestre que la aislacin est presente entre los elementos.
Avancemos hacia el mtodo dinmico
En este punto te preguntars los motivos por los cuales no cambiamos directamente esta piedra en el
zapato que cuesta unas pocas monedas, antes de perder tanto tiempo en ensayos, sin embargo, cuando
descubres que no tienes uno nuevo para reemplazarlo (ni lo conseguirs en varios das), estars de
acuerdo en que sigamos hacia el ensayo dinmico. Para realizar este trabajo, debemos ante todo, saber
con qu elemento estamos trabajando, conocer su nomenclatura y por supuesto (ahora s) tener acceso a
su hoja de datos. Para esto ltimo, existen muchos espacios en la web donde encontrar la informacin
necesaria que nos permitir conocer la arquitectura interna del componente con el que estamos
trabajando, al que intentamos hacerle los controles sanitarios, para saber si goza de buena salud. Si no
tenemos un espacio de preferencia donde encontrar este tipo de informacin, bastar con escribir la
nomenclatura en cualquier buscador web y apuntar nuestra lectura hacia los archivos PDF que siempre
aparecen. Una vez que tenemos ese resultado, podemos saber de qu manera ensayar nuestro
optoacoplador.

figura 45: Caractersticas mecnicas de empaquetados

Durante la primera etapa del ensayo, lo ms importante dentro de la hoja de datos ser descubrir las

caractersticas funcionales del LED y no confundirnos entre los valores mximos y absolutos que puede
soportar el dispositivo, respecto a los ptimos que se pueden utilizar para un funcionamiento adecuado
y seguro, garantizando una larga vida til. Y como por algn lado debemos comenzar, vamos a hacerlo
con uno de los optoacopladores ms populares, econmicos y adoptados por la industria electrnica
(De nada sirve, durante el aprendizaje, hablar de componentes que vers solo una vez en tu vida). Por
lo tanto, veamos algunas particularidades que debemos tener en cuenta al momento de leer la hoja de
datos de un PC817: un optoacoplador analgico clsico, con un fotodiodo infrarrojo (emisor) y un
fototransistor (detector) que nos ofrece en su salida los pines Colector-Emisor, para tomar all en
forma aislada y proporcional, las variaciones de intensidad luminosa que entregue el LED infrarojo.
Como mencionamos antes, los valores mximos absolutos del PC817 hablan de una corriente de LED
en forma directa (Forward Current) de 50mA, sin embargo, trabajando a ese rgimen el optoacoplador
puede durar unos pocos minutos, antes de calcinarse. Insistamos en este concepto: eso es el mximo
absoluto, no el valor seguro de trabajo. Para saber cul es esta corriente segura de trabajo tenemos
dos mtodos: uno es observando las curvas presentes en las hojas de datos que nos muestren los valores
usuales dentro del rea de Operacin Segura (SOA, Security Operation Area). En el grfico
mostrado abajo (derecha), es el rea que se encuentra debajo de la lnea de puntos. Para ejemplo,
podemos observar que con una corriente de LED de 5mA, 10mA (y un poco ms tambin) podemos
trabajar sin problemas en todo el rango de tensiones (entre colector y emisor) que permite aprovechar el
fototransistor del PC817. Observa que si lo haces trabajar con una corriente de LED de 20mA no
podrs llegar a emplear valores de tensin de 6Volts en el fototransistor. Hasta podramos decir que
trabajar con 5Volts sera estar muy cerca de la zona no segura

5.4.3 Puentes H discretos e Integrados.


Debido a la pequea potencia que suministran los microcontroladores, slo podemos hacer funcionar
directamente unos LED y poco ms. Por este motivo es necesario amplificar las salidas en funcin de
las cargas que vayamos a controlar. Un mtodo sencillo y econmico es emplear el integrado
ULN2003A, que es un conjunto de Darlington (darlington array) montados en un chip con el que
podemos controlar cargas de hasta medio amper.. El chip lleva diodos de proteccin contra las
sobretensiones producidas por cargas inductivas. Esto lo hace ideal para gobernar rels (Chavarrea &
Chiluisa, 2013).

figura 46: pinout del ULN2803


El L293D son cudruples de alta corriente conductores de media -H. ElL293 est diseado para
proporcionar corrientes de excitacin bidireccional de hasta 1 A con tensiones desde 4,5 V a 36 V. El
L293D est diseado para proporcionar corrientes de excitacin bidireccional dehasta600 mA a voltajes

de 4,5 V a 36 V. Ambos dispositivos estn diseados para manejar cargas inductivas, como rels,
solenoides, dc y motores bipolares paso a paso, as como otros high-current/highvoltageCargas en
aplicaciones de alimentacin positiva.
Todas las entradas estn TTL compatible. Cada salida es un circuito duro ttem completo, con un
transistor Darlington y una fuente de pseudo- Darlington. Los conductores estn habilitadas en parejas,
con los conductores 1 y 2 habilitadas por 1,2 EN y conductores 3 y 4 habilitadas por 3,4 E-S Cuando
una entrada de habilitacin es alta, los controladores asociados estn habilitados y su salidas estn
activos y en fase con sus entradas. Cuando la entrada habilitada es bajo, los conductores son personas
con discapacidad y sus salidas estn apagados y en el estado de alta impedancia. Con las entradas de
datos adecuadas, cada par de conductores formas a- H completa (o puente) de accionamiento reversible
adecuado para solenoide o motor aplicaciones.

figura 47: Pinout del L293

5.5 Ejemplo del uso de las interfaces para controlar:


5.5.1 Motores de DC
Elaborar un circuito que permita controlar un motor de corriente directa de 12V usando una interface
de potencia L293D, programando un microcontrolador ATmega48 el cual contiene tres entradas y tres
salidas, adems considera el siguiente funcionamiento:

Inicialmente el motor debe estar detenido. start = stop = 1; I_nD = X.

El motor se mueve si se presiona el botn start = 0 y el botn I_nD = 1 a la izquierda.

El motor se mueve si se presiona el botn start = 0 y el botn I_nD = 0 a la derecha.

Para los casos anteriores al dejar de pulsar start el motor se mantiene girando en el sentido
indicado por I_nD.

El motor se detiene si el botn de stop es presionado y se mantiene as an despus de soltarlo.


O si el botn de stop se mantiene presionado, no importan los estados de start o de I_nD, el
motor permanece detenido (Biblioman, 2013).

Los pines se asignarn a las siguientes terminales:


Id

Descripcin

Puerto

Tipo

start

Botn de inicio

PINC1

Entrada

stop

Botn de paro

PINC2

Entrada

I_nD

Botn de sentido

PINB0

Entrada

Salida hacia L293

PD0

Salida

Salida hacia L293

PD1

Salida

En

Salida de hablitacin de L293

PD2

Salida

Resolucin: Primero se debe plantear el diagrama de estados en funcin de la descripcin del


problema. En este caso, utilizaremos el software Qfsm (http://qfsm.sourceforge.net). Sin embargo es
necesario dar formatos de entradas y salidas, ya que en este software las entradas se definirn como
valores binarios.
Formato para entradas

Formato para salidas

start

stop

I_nD

En

010

Derecha
110
101

010
111
100
110

Detenido

rst_n

111

000

101

011

110

010

011
100
101

Izquierda

011
111

011

figura 48: Diagrama de estados propuesto


Los nmeros que estn sobre las flechas indican las seales de entrada que provienen de start,stop e
I_nD, y los nmeros que estn dentro de los estados, corresponden a las salidas a,b,En.
Agregar que el estado final indicado es el estado Detenido, es por esa causa que en el diagrama de
estaos, se encuentra sealado con doble anillo.
El software permite generar entre otros cdigos HDL , el de AHDL, que por su sintxis es muy similar
al lenguaje C. En el cuadro que a continuacin se presenta, se indica el cdigo fuente generado.

% This file was generated by

% Qfsm Version 0.52

% (C) Stefan Duffner, Rainer Strobel

SUBDESIGN Motor
(clock, reset
start,stop,I_nD

:INPUT;
:INPUT;

:OUTPUT;
a,b,En

:OUTPUT;)

VARIABLE
fsm

MACHINE OF BITS(s0, s1)


WITH STATES (
Detenido = B"00",
Derecha = B"01",
Izquierda = B"10");

reset_async : NODE;
_asynca, _asyncb, _asyncEn : NODE;

BEGIN
reset_sync = DFF(reset,clock,VCC,VCC);
fsm.reset = reset_sync;

fsm.clk = clock;
a = DFF(a_async,clock,VCC,VCC);
b = DFF(b_async,clock,VCC,VCC);
En = DFF(En_async,clock,VCC,VCC);

CASE fsm IS
WHEN Detenido =>
IF (start,stop,I_nD) == B"101" THEN
END IF;
IF (start,stop,I_nD) == B"100" THEN
END IF;
IF (start,stop,I_nD) == B"110" THEN
END IF;
IF (start,stop,I_nD) == B"111" THEN
END IF;
IF (start,stop,I_nD) == B"010" THEN
fsm = Derecha;
(_asynca, _asyncb, _asyncEn) = B"101";
END IF;
IF (start,stop,I_nD) == B"011" THEN

fsm = Izquierda;
(_asynca, _asyncb, _asyncEn) = B"011";
END IF;
WHEN Derecha =>
IF (start,stop,I_nD) == B"100" THEN
fsm = Detenido;
(_asynca, _asyncb, _asyncEn) = B"000";
END IF;
IF (start,stop,I_nD) == B"111" THEN
fsm = Izquierda;
(_asynca, _asyncb, _asyncEn) = B"011";
END IF;
IF (start,stop,I_nD) == B"011" THEN
fsm = Izquierda;
(_asynca, _asyncb, _asyncEn) = B"011";
END IF;
IF (start,stop,I_nD) == B"010" THEN
END IF;
IF (start,stop,I_nD) == B"110" THEN
END IF;
WHEN Izquierda =>
IF (start,stop,I_nD) == B"101" THEN
fsm = Detenido;
(_asynca, _asyncb, _asyncEn) = B"000";
END IF;
IF (start,stop,I_nD) == B"110" THEN
fsm = Derecha;
(_asynca, _asyncb, _asyncEn) = B"101";
END IF;
IF (start,stop,I_nD) == B"010" THEN
fsm = Derecha;
(_asynca, _asyncb, _asyncEn) = B"101";
END IF;
IF (start,stop,I_nD) == B"111" THEN
END IF;
IF (start,stop,I_nD) == B"011" THEN
END IF;
END CASE;
END;

Tabla 11: Cdigo de AHDL para control por FSM


Del cdigo, solo se tomarn los if dentro de cada case, en donde exista una indicacin de cambio de

estado para traducirlo al lenguaje C, por ejemplo


IF (start,stop,I_nD) == B"011" THEN
fsm = Izquierda;
(_asynca, _asyncb, _asyncEn) = B"011";

Estas lneas
se traducen a
C

END IF;
IF (start,stop,I_nD) == B"111" THEN
END IF;

Estas lneas
se ignoran

Para pasar al lenguaje C, son declarados como #define los estados y se les asigna un valor, y se agrega
adems una variable denominada ESTADO, la cual almacenar de forma temporal el estado actual.
En el cuadro siguiente, se muestra el cuadro donde se expone el cdigo C traducido a partir del cdigo
AHDL generado por el software Qfsm.

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>

/*Definicin de macros para set y reset de bits*/


#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=(_BV(bit)))
#define clearbit(sfr,bit) (_SFR_BYTE(sfr)&=~(_BV(bit)))

/*Definicion de entradas y salidas*/


#define start

PINC1

#define pstart

PINC

#define rpstart PORTC


#define stop

PINC2

#define pstop

PINC

#define rpstop PORTC


#define I_nD

PINB0

#define pI_nD

PINB

#define rpI_nD PORTB

#define a

PD0

#define Pa
#define b

PORTD
PD1

#define Pb

PORTD

#define En

PD2

#define pEn

PORTD

/*Defincion para configuracin de entradas y salidas*/


#define cstart

DDC1

#define cpstart

DDRC

#define cstop

DDC2

#define cpstop

DDRC

#define cI_nD

DDB0

#define cpI_nD

DDRB

#define ca

DDD0

#define cPa

DDRD

#define cb

DDD1

#define cPb

DDRD

#define cEn

DDD2

#define cpEn

DDRD

/*Definicion de estados*/
#define DETENIDO 0

#define DERECHA

#define IZQUIERDA 2

int main(void)
{
/*Creacin del estado inicial*/
unsigned char ESTADO=DETENIDO;

/*configurar entradas*/
clearbit(cpstart,cstart);
clearbit(cpstop,cstop);
clearbit(cpI_nD,cI_nD);

/*configurar resistencia pull-up*/


setbit(rpstart,start);
setbit(rpstop,stop);
setbit(rpI_nD,I_nD);

/*configurar salidas*/
setbit(cPa,ca);
setbit(cPb,cb);
setbit(cpEn,cEn);

/*Condiciones iniciales*/
clearbit(Pa,a);
clearbit(Pb,b);
clearbit(pEn,En);

while(1)
{
switch(ESTADO)
{
case

DETENIDO:

{
if(bit_is_clear(pstart,start) && bit_is_set(pstop,stop) && bit_is_clear(pI_nD,I_nD))
{
ESTADO = DERECHA;
setbit(Pa,a);
clearbit(Pb,b);
setbit(pEn,En);
}

if(bit_is_clear(pstart,start) && bit_is_set(pstop,stop) && bit_is_set(pI_nD,I_nD))


{
ESTADO = IZQUIERDA;
clearbit(Pa,a);
setbit(Pb,b);
setbit(pEn,En);
}
break;
}
case

DERECHA:

{
if(bit_is_set(pstart,start) && bit_is_clear(pstop,stop) && bit_is_clear(pI_nD,I_nD))
{
ESTADO = DETENIDO;
clearbit(Pa,a);
clearbit(Pb,b);
clearbit(pEn,En);
}

if(bit_is_set(pstart,start) && bit_is_set(pstop,stop) && bit_is_set(pI_nD,I_nD))


{
ESTADO = IZQUIERDA;
clearbit(Pa,a);
setbit(Pb,b);
setbit(pEn,En);
}

if(bit_is_clear(pstart,start) && bit_is_set(pstop,stop) && bit_is_set(pI_nD,I_nD))


{
ESTADO = IZQUIERDA;
clearbit(Pa,a);
setbit(Pb,b);
setbit(pEn,En);
}
break;
}
case

IZQUIERDA:

{
if(bit_is_set(pstart,start) && bit_is_clear(pstop,stop) && bit_is_set(pI_nD,I_nD))
{
ESTADO = DETENIDO;
clearbit(Pa,a);

clearbit(Pb,b);
clearbit(pEn,En);
}

if(bit_is_set(pstart,start) && bit_is_set(pstop,stop) && bit_is_clear(pI_nD,I_nD))


{
ESTADO = DERECHA;
setbit(Pa,a);
clearbit(Pb,b);
setbit(pEn,En);
}

if(bit_is_clear(pstart,start) && bit_is_set(pstop,stop) && bit_is_clear(pI_nD,I_nD))


{
ESTADO = DERECHA;
setbit(Pa,a);
clearbit(Pb,b);
setbit(pEn,En);
}
break;
}
default:

break;

}
}

Tabla 12: Cdigo para control por FSM


Finalmente se presenta el esquema que muestra las conexiones del circuito
a

figura 49: circuito estados lgicos

5.5.2 Motores a pasos


Las notas siguientes salen del documento expuesto por la Facultad de Ingeniera (UNLP, 2010).
Qu es un motor a pasos?
Es un actuador electromagntico rotatorio que convierten mecnicamente entradas de pulsos digitales
a movimiento rotatorio incremental de la flecha .
La rotacin no solo tiene una relacin directa al nmero de pulsos de entrada , sino que la velocidad
est relacionada a la frecuencia de los pulsos.
Existen tres tipos de motores a pasos, los de reluctancia variable, los de imn permanente y los
hbridos.
Los cuales se clasifican como motores bipolares y unipolares, de acuerdo a su tipo de conexin.
Los motores unipolares, suelen tener 5 o 6 cables de salida.

figura 50: motor a pasos unipolar


Un motor bipolar por otra parte cuenta con solo 4 hilos de conexin y requiere de inversin de fase
para su adecuado funcionamiento.

figura 51: Motor a pasos bipolar


Control por medio de los circuito L297 y L298
Desarrollar el accionamiento de un motor a pasos, mediante el circuito de control L297, que realiza las
funciones de generador de fases y troceado de la corriente que circula por los devanados y el driver de
potencia L298. Se recomienda ampliamente la lectura de las siguientes notas de aplicacin:

AN280. Controlling Voltaje transient in full bridge drives applications

AN468. Constant-current chopper driver ups stepper motor performance

AN470. The L297 stepper motor controller

5.5.3 Servomotores
Las notas presentes pueden encontrarse en la pgina web del autor (Carletti, 2007).
En primer lugar quiero aclarar que, si bien hoy se utiliza ampliamente la palabra abreviada "servo", la
verdadera denominacin de lo que voy a describir aqu es "servomotor". Existen otra clase de servos (o
mejor expresado, servomecanismos) que no son precisamente motores. Tambin hay servos no
rotativos.
Por ejemplo, los sistemas que poseen cilindros hidrulicos pueden ser servocontrolados. Estos cilindros
hidrulicos o neumticos, en su versin ms simple, se mueven de extremo a extremo. Pero no siempre
es as. En muchos casos es necesario que posean realimentacin, lo que les permite ubicarse con
precisin en cualquier lugar de su recorrido. Para esto se utilizan sensores de recorrido lineales, como
potencimetros lineales, sistemas pticos o unos dispositivos llamados LDVT.
De modo que, aclaremos, un actuador mecnico controlado no siempre debe ser rotativo, aunque la
mayora de las veces as es.
Definamos, ahora:
Un servomotor es un motor elctrico que consta con la capacidad de ser controlado, tanto en
velocidad como en posicin.
Un servomecanismo es un actuador mecnico generalmente un motor, aunque no exclusivamente,
que posee los suficientes elementos de control como para que se puedan monitorizar los parmetros de
su actuacin mecnica, como su posicin, velocidad, torque, etc.
En realidad se utilizan muchos otros tipos de servos (o servomotores, mejor) en equipos industriales y
comerciales, desde una diskettera en nuestra computadora o en la videocassettera hogarea, a las
unidades de almacenaje y entrada y salida de datos de grandes sistemas de computacin (hoy, ms que
nada, discos magnticos), y hasta en los ascensores en edificios. El motor de un ascensor, junto con su
equipo de control y detectores de posicionamiento, no es ni ms ni menos que un servomotor. El
mecanismo que saca para afuera el porta-CD de la lectora de CD de su computadora es un servomotor.
Qu convierte un motor en servomotor? O mejor dicho por qu se
considera que algunos motores son servomotores y otros no? La
respuesta no es demasiado complicada: un servomotor tiene integrado o
adosado al menos un detector que permita conocer su posicionamiento y/o
velocidad. A los detectores de posicin se les llama "encoders".
Aclarado esto, pasar a esos servos a los que se refieren en los sitios que
dije antes. Hablo de los servos para radiocontrol de modelos, como los de
marca Futaba, Hitec, etc. Se trata de elementos para control de posicin de
alerones, timn, direccin (en autos), alimentacin de combustible, etc,
para modelos a escala, que se han vuelto populares en robtica porque
entre los disponibles en el comercio hay algunos bastante econmicos, lo
figura 52: Servomotor DC que los hace de ms fcil acceso cuando se trata de la construccin de
aeromodelismo
proyectos personales de robtica y automatizacin casera.
De estos servos de modelismo, comencemos con los servos que se conocen como "analgicos".
Servo analgico para modelismo
Estos servomotores se componen, en esencia, de un motor de corriente continua, un juego de

engranajes para la reduccin de velocidad, un potencimetro ubicado sobre el eje de salida (que se usa
para conocer la posicin) y una plaqueta de circuito para el control.
Como una imagen vale ms que mil palabras, veamos un despiece.

figura 53: Desensamble de un servo


Si lo que se desea controlar es la posicin de un servomecanismo, como en este caso, en lugar de un
tacmetro (que es para medir velocidad) necesitamos un encoder de posicin. Si hablamos de un servo
cuyo movimiento es giratorio, ser necesario un encoder (un
detector que codifica la posicin) que nos d un valor diferente
a su salida segn cual sea su posicin en grados.
Los servos que se usan en modelismo son de este tipo. Como
dije antes, por lo general poseen un motor de CC, que gira a
velocidad alta, una serie de engranajes para producir la
reduccin de velocidad de giro y acrecentar su capacidad de
torque, un potencimetro conectado al eje de salida (que es ni
ms ni menos que el encoder) y un circuito de control de la
realimentacin.
Estos servos reciben seal por tres cables: alimentacin para el
motor y la pequea plaqueta de circuito del control (a travs de
dos cables, positivo y negativo/masa), y una seal controladora
que determina la posicin que se requiere. La alimentacin de
estos servos es, normalmente, de entre 4,8 y 6 voltios.
El estndar de esta seal controladora para todos los servos defigura 54: Cables de un servo estndar
este tipo, elegido para facilitar el uso en radiocontrol, es un
pulso de onda cuadrada de 1,5 milisegundos que se repite a un ritmo de entre 10 a 22 ms. Mientras el
pulso se mantenga en ese ancho, el servo se ubicar en la posicin central de su recorrido. Si el ancho
de pulso disminuye, el servo se mueve de manera proporcional hacia un lado. Si el ancho de pulso
aumenta, el servo gira hacia el otro lado. Generalmente el rango de giro de un servo de stos cubre
entre 90 y 180 de la circunferencia total, o un poco ms, segn la marca y modelo.

figura 55: Seales y posiciones


de un servo
Prctica propuesta
Elaborar un contador que se desborde al llegar a 5, mostrando este resultado en un display de 7
segmentos de nodo comn, el cual ser alimentado por una fuente de 12V a travs de una interfaz
basada en el circuito integrado ULN2803 (o ULN2003), la entrada del contador ser realizada por la
deteccin de un objeto a una distancia de 8 cm o menor, de un sensor ultrasnico.

figura 56: Secuencia para leer el sensor ultrasnico


En la siguiente figura se muestra el circuito funcionando

figura 57: Prctica sensor ultrasnico


A continuacin se propone un circuito de conexiones para esta prcticamente

figura 58: circuito medidor de distancia ultrasnico

Unidad 6
Interrupciones en un microcontrolador

Unidad 6 Interrupciones en un microcontrolador


6.1 El manejo de las interrupciones.
6.1.1 Tipos de interrupciones.
6.1.2 Los vectores de interrupcin.
6.1.3 Las acciones del MCU al responder a una interrupcin.
6.1.4 Caractersticas de la rutina manejadora de interrupcin
6.2 Las interrupciones externas
6.2.1 Caractersticas y configuracin
6.2.2 Programacin y uso.
6.3 Fuentes internas de interrupciones
6.3.1 De los timer y contadores
6.3.2 ADC
6.3.3 De la comunicacin serial
6.3.4 Del comparador analgico.
6.3.5 De la EEPROM
6.4 Ejemplos de aplicaciones de las interrupciones.

Competencia especfica
Programar y aplicar las interrupciones en un microcontrolador.
Actividades de aprendizaje:
Mapa Conceptual: Investigar y catalogar mediante un mapa conceptual los tipos de interrupciones, las
acciones del microcontrolador al responder a una interrupcin, caractersticas de la rutina manejadora
de interrupcin del MCU ATmega32U4.

6.1 El manejo de las interrupciones.


Hay una analoga que siempre recuerdo desde que la le en un buen libro de Turbo Pascal cuando
aprenda a programar en dicho lenguaje. Cuando vamos a recibir una visita en nuestra casa podemos ir
a la puerta a cada momento para ver si ya lleg y atenderla apropiadamente, o podemos quedarnos
haciendo nuestras labores cotidianas esperando a que sea la visita quien llame a la puerta para ir a
recibirla.
Ir a la puerta constantemente se compara por ejemplo con testear los puertos del AVR para ver si se
presion algn pulsador o algn teclado y actuar en consecuencia. Eso se conoce como tcnica Polling
o de sondeo e implica el desperdicio de recursos y ciclos de CPU.
En este captulo aprenderemos a atender nuestras visitas justo cuando llamen a la puerta para que el
AVR no se canse en vano y que se ponga a dormir, si fuera posible. sta es solo una pequea muestra
de lo que se puede conseguir con las interrupciones.

6.1.1 Tipos de interrupciones.


Una interrupcin es una llamada inesperada, urgente e inmediata a una funcin especial denominada
Interrupt Service Routine (ISR).
El mecanismo funciona as: sin importar lo que est haciendo en main o cualquier funcin relacionada
con main, cuando ocurra la interrupcin el CPU har una pausa y pasar a ejecutar el cdigo de ISR.
Tras terminarlo, el CPU regresar a la tarea que estaba realizando antes de la interrupcin, justo donde
la haba suspendido.
Aunque es posible provocar interrupciones desde el programa ejecutndolas como si fueran funciones
ordinarias, las interrupciones son disparadas (llamadas) por eventos del hardware del microcontrolador.
El evento puede ser algn cambio en cierto pin de E/S, el desbordamiento de un Timer, la llegada de un
dato serial, etc. Se puede deducir por tanto que las fuentes de interrupcin estn relacionadas con la
cantidad de recursos del microcontrolador.

6.1.2 Los vectores de interrupcin.


Cada interrupcin est identificada por un Vector de Interrupcin, que no es otra cosa que una direccin
particular en la memoria FLASH. Todos los Vectores estn ubicados en posiciones consecutivas de la
memoria FLASH y forman la denominada Tabla de Vectores de Interrupcin. El RESET no es una
interrupcin pero su direccin 0x0000 tambin se conoce como Vector de Reset. Por defecto, la Tabla
de Vectores de Interrupcin est ubicada en las primeras posiciones de la memoria, tal como se ve
abajo. Solo cuando se habilita el uso de la Seccin de Boot Loader toda la tabla se desplazar al inicio
de dicha seccin.
Enseguida se presenta una tabla con las 35 interrupciones posibles en los ATmegaXX4. Debemos
recordar que solo los ATmega1284 tienen el Timer3 y por tanto las 4 interrupciones relacionadas con el
Timer3 no estarn disponibles en los otros megaAVR de esta serie. Aprenderemos de a poco y para
empezar en este captulo nos ocuparemos de las 7 interrupciones externas, desde INT0 hasta PCINT3.
Las restantes sern estudiadas en sus mdulos respectivos.

Num Vector Direccin de Programa

Nombre de
Vector de Interrupcin

Fuente de interrupcin

0x0000

RESET

External Pin, Power-on Reset, Brown-out


Reset,
Watchdog Reset, and JTAG AVR Reset

0x0002

INT0

External Interrupt Request 0

0x0004

INT1

External Interrupt Request 1

0x0006

INT2

External Interrupt Request 2

0x0008

PCINT0

Pin Change Interrupt Request 0

0x000A

PCINT1

Pin Change Interrupt Request 1

0x000C

PCINT2

Pin Change Interrupt Request 2

0x000E

PCINT3

Pin Change Interrupt Request 3

0x0010

WDT

Watchdog Time-out Interrupt

10

0x0012

TIMER2_COMPA

Timer/Counter2 Compare Match A

11

0x0014

TIMER2_COMPB

Timer/Counter2 Compare Match B

12

0x0016

TIMER2_OVF

Timer/Counter2 Overflow

13

0x0018

TIMER1_CAPT

Timer/Counter1 Capture Event

14

0x001A

TIMER1_COMPA

Timer/Counter1 Compare Match A

15

0x001C

TIMER1_COMPB

Timer/Counter1 Compare Match B

16

0x001E

TIMER1_OVF

Timer/Counter1 Overflow

17

0x0020

TIMER0_COMPA

Timer/Counter0 Compare Match A

18

0x0022

TIMER0_COMPB

Timer/Counter0 Compare match B

19

0x0024

TIMER0_OVF

Timer/Counter0 Overflow

20

0x0026

SPI_STC

SPI Serial Transfer Complete

21

0x0028

USART0_RX

USART0 Rx Complete

22

0x002A

USART0_UDRE

USART0 Data Register Empty

23

0x002C

USART0_TX

USART0 Tx Complete

24

0x002E

ANALOG_COMP

Analog Comparator

25

0x0030

ADC

ADC Conversion Complete

26

0x0032

EE_READY

EEPROM Ready

27

0x0034

TWI

2-wire Serial Interface

28

0x0036

SPM_READY

Store Program Memory Ready

Num Vector Direccin de Programa

Nombre de
Vector de Interrupcin

Fuente de interrupcin

29

0x0038

USART1_RX

USART1 Rx Complete

30

0x003A

USART1_UDRE

USART1 Data Register Empty

31

0x003C

USART1_TX

USART1 Tx Complete

32

0x003E

TIMER3_CAPT

Timer/Counter3 Capture Event

33

0x0040

TIMER3_COMPA

Timer/Counter3 Compare Match A

34

0x0042

TIMER3_COMPB

Timer/Counter3 Compare Match B

35

0x0044

TIMER3_OVF

Timer/Counter3 Overflow

Tabla 13: Vectores de Interrupcin

6.1.3 Las acciones del MCU al responder a una interrupcin.


Para entender cmo funciona el mecanismo de las interrupciones en bajo nivel, recordemos que el
Contador de Programa es un registro que dirige cada una de las instrucciones que ejecuta el CPU. Pues
bien, al dispararse la interrupcin el hardware guardar en la Pila el valor actual del Contador de
Programa y lo actualizar con el valor del Vector de Interrupcin respectivo, de modo que el CPU
pasar a ejecutar el cdigo que se encuentre a partir de esa direccin. Al final del cdigo de la
interrupcin debe haber una instruccin de retorno que restaure el Contador de Programa con el valor
que se haba guardado en la Pila. La instruccin es reti y la pone el compilador.
Si se llegara a producir el evento excepcional en que se disparen dos o ms interrupciones al mismo
tiempo, se ejecutarn las interrupciones en orden de prioridad. Tiene mayor prioridad la interrupcin
cuyo Vector se ubique ms abajo, es decir, entre todas, la interrupcin INT0 tiene siempre las de ganar.
La estructura y caractersticas de la Tabla de Vectores de Interrupcin pueden variar entre las diferentes
familias de megaAVR y a veces entre diferentes partes de una misma serie. Por ejemplo, los megaAVR
de la serie ATmegaXX8 no tienen la interrupcin externa INT2 y tampoco las interrupciones PCINT3
(porque les falta el puerto A). Adems, el ATmega48 no dispone de la funcionalidad de Boot Loader,
as que este AVR no puede desplazar su Tabla de Vectores de Interrupcin. La ausencia de algunas
interrupciones hace que los otros Vectores cambien de valor.
En cualquier caso, para nosotros, los programadores en C o Basic, es suficiente tener en cuenta los
nombres de los Vectores de Interrupcin, que en la tabla de arriba se resaltan con enlaces en en azul.
Los nombres de los Vectores de Interrupcin presentados corresponden al datasheet y no
necesariamente son idnticos a los que utilizan los compiladores AVR GCC o AVR IAR C. Estos
nombres se encuentran definidos en los archivos de dispositivo de cada AVR, ubicados en la carpeta
include de cada compilador. La instalacin por defecto de AVR GCC con Atmel Studio 6 en Windows 7
marca
la
ruta
C:\Program
Files
(x86)\Atmel\Atmel
Studio
6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\avr\include\avr. All los puedes ubicar, y de
hecho es recomendable examinarlos de vez en cuando.
Pero si por el momento deseas ahorrarte el trabajo te dir que la nica diferencia es el apndice _vect.

Es decir, en todos los archivos de dispositivo de AVR IAR C y de AVR GCC (en sus versiones actuales)
los nombres de los Vectores de Interrupcin son los mismos que aparecen en el datasheet pero con el
aadido _vect, como se muestra en la siguiente tabla de ejemplo. Est de ms decir que en nuestros
programas debemos usar la forma con _vect.
Nombre de
Nombre de
Vector de Interrupcin Vector de Interrupcin
en datasheet
en archivo de dispositivo
INT0

INT0_vect

INT1

INT1_vect

INT2

INT2_vect

PCINT0

PCINT0_vect

PCINT1

PCINT1_vect

PCINT2

PCINT2_vect

PCINT3

PCINT3_vect

TIMER0_COMPA

TIMER0_COMPA_vect

TIMER0_COMPB

TIMER0_COMPB_vect

TIMER0_OVF

TIMER0_OVF_vect

USART0_RX

USART0_RX_vect

USART0_UDRE

USART0_UDRE_vect

USART0_TX

USART0_TX_vect

Tabla 14: Equivalencias entre vectores del datasheet y AVRGCC

6.1.4 Caractersticas de la rutina manejadora de interrupcin


En el compilador AVR GCC (WinAVR) la funcin de interrupcin se escribe con la palabra reservada
ISR acompaada del Vector_de_Interrupcion. En las versiones anteriores del compilador se sola usar
SIGNAL en vez de ISR pero actualmente ese mtodo est considerado deprecated (censurado).
Recordemos que el Vector_de_Interrupcion debe tener la terminacin _vect, como se indic
anteriormente, y si tienes dudas puedes buscar en la carpeta include del directorio de instalacin de
AVR GCC (WinAVR).
ISR (Vector_de_Interrupcion)
{
// Cdigo de la funcin de interrupcin.
// No requiere limpiar el flag respectivo. El flag se limpia por hardware
}

6.2 Las interrupciones externas


6.2.1 Caractersticas y configuracin
Las interrupciones externas son disparadas por las terminales INT0 e INT1 o cualquiera de las
PCINT23..0, observse que si son habilitadas las interrupciones, estas se dispararn si los pines INT0,
INT1 o PCINT23..0 son configurados como salidas, la anterior caracterstica provee una forma de
generar una interrupcin por software.
Las interrupciones INT0 e INT1 pueden ser disparadas mediante un flanco de subida, de bajada o por
bajo nivel; esta especificacin puede ser realizada para el registro A de control de interrupciones
externas (EICRA).
Los bits para controlar el sensado de la interrupcin son los bits denominados ISC11 e ISC10 para la
INT1 y para la INT0, son los bits ISC01 e ISC00. Estos bits responden a la siguiente tabla:
ISCx1

ISCx0

Descripcin

En nivel bajo, INTx genera una peticin de interrupcin

Cualquier cambio lgico en INTx genera una peticin de Interrupcin

En flanco de bajada, INTx genera una peticin de interrupcin.

En flanco de subida, INTx genera una peticin de interrupcin

Tabla 15: Control de sensado de Interrupcin externa


Para habilitar las interrupciones, es importante recurrir al registro de enmascaramiento de
interrupciones externas (EIMSK), donde los bits 1 y cero sirve para habilitacin de las interrupciones
externas al ser seteados.

6.2.2 Programacin y uso.


En estas prcticas de ejemplo evitaremos programas sofisticados con cdigos grandes que desven la
atencin hacia una breve aplicacin de la teora expuesta. Por eso no nos vendr mal volver a los
socorridos LEDs parpadeantes.
El programa tendr dos tareas: la rutina principal se encargar de parpadear un LED y la funcin de
interrupcin har bascular otro LED cada vez que presionemos un pulsador. Esto ser como fusionar
dos programas que alguna vez hicimos.
De las seales que se generan al presionar el botn escogeremos el flanco de bajada para disparar la
interrupcin INT0.
Cada aplicacin puede tener sus propias especificaciones, pero, en general, un buen hbito de
programacin es poner la sentencia sie(); que setea el bit I del registro SREG cuando ya todo est listo
para atender a la interrupcin.

Al analizar la estructura del programa, notamos que la funcin ISR es totalmente independiente de
main, es decir, no es referenciada desde ningn punto de main.
Una vez habilitada, la interrupcin se disparar cuando alguien presione el botn (en el flanco de
bajada). En ese preciso instante (quiz cuando se est ejecutando PINC = 0x02 o quiz en algn punto
dentro de delay_ms(600)) el CPU pasar a ejecutar la funcin ISR. Al salir de ISR, el CPU regresar a
continuar la tarea que estaba ejecutando antes de la interrupcin.
/******************************************************************************
* FileName: main.c
* Purpose: Uso de la interrupcin INTx
* Processor: megaAVR
* Compiler: AVR IAR C y AVR GCC (WinAVR)
* Author: Shawn Johnson. http://www.cursomicros.com.
*
* Copyright (C) 2008 - 2013 Shawn Johnson. All rights reserved.
*
* License: Se permiten el uso y la redistribucin de este cdigo con
*
modificaciones o sin ellas, siempre que se mantengan esta
*
licencia y las notas de autor y copyright de arriba.
*****************************************************************************/
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
//****************************************************************************
// Interrupt Service Routine, ISR
// Esta funcin se ejecuta cuando se detecta un flanco de bajada en el pin INT0
//****************************************************************************
ISR (INT0_vect)
{
PINC = 0x01;
// Conmutar pin PC0
delay_ms(40);
// Para pasar los rebotes
}
//****************************************************************************
// Funcin principal
//****************************************************************************
int main(void)
{
DDRC = 0x03;
// Pines PC0 y PC1 para salida (LEDs)
PORTD = 0x04;
// Habilitar pull-up de pin PD2/INT0 (pulsador)
/* Habilitar y configurar la interrupcin INT0 para que se dispare con
* cada flanco de bajada detectado en el pin INT0 (PD2)
*/
EIMSK = (1<<INT0); // Habilitar INT0
EICRA = (2<<INT0*2); // Elegir flanco de bajada (modo 2)
sei();

// Habilitacin general de interrupciones

while(1)
// Bucle infinito
{
PINC = 0x02; // Conmutar pin PC1
delay_ms(600); // Pausa de 600ms
}

Tabla 16: Cdigo para configuracin de interrupciones externas - Shawn Johnson

Practica LCD
Escriba un programa para el microcontrolador AVR, donde haciendo uso de una pantalla LCD de dos
lineas por 16 caracteres, se muestre el mensaje hola en la primera lnea y la sptima posicin, y en la
segunda lnea, el mensaje mundo en la segunda lnea y en la sptima posicin.
Seiscientos milisegundos despus, limpiar la pantalla, y ahora presentar en la segunda lnea un contador
de 0 a 98 que se autoincrementa cada 35milisegundos, al terminar, limpiar la pantalla y mantenerla as
200 milisegundos. Vase las imgenes:

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>

#include "lcd.h"

int main(void)
{
unsigned char i;
char buff[7];
lcd_init();
while(1)
{
lcd_gotorc(1,7);
lcd_puts("Hola");
lcd_gotorc(2,7);
lcd_puts("Mundo");

_delay_ms(600);
lcd_clear();
_delay_ms(400);
for(i=0;i<99;i++)
{
sprintf(buff, "hola%d" ,i);
lcd_gotorc(2,5);
lcd_puts(buff);
_delay_ms(35);
}
lcd_clear();
_delay_ms(200);

}
}

Tabla 17: Ejemplo de uso de libreras LCD de Shawn Johnson


Librerias lcd

/******************************************************************************
* FileName: lcd.h
* Purpose:
*

Librera de funciones para controlar un display LCD con chip

Hitachi HD44780 o compatible. La interface es de 4 bits.

* Processor: ATmel AVR


* Compiler: AVR IAR C y AVR GCC (WinAVR)
* Author:

Shawn Johnson. http://www.cursomicros.com.

*
* Copyright (C) 2008 - 2013 Shawn Johnson. All rights reserved.
*
* License:

Se permiten el uso y la redistribucin de este cdigo con

modificaciones o sin ellas, siempre que se mantengan esta

licencia y las notas de autor y copyright de arriba.

*****************************************************************************/
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
//****************************************************************************
//

CONFIGURACIN DE LOS PINES DE INTERFACE

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

/* Define el puerto a donde se conectar el bus de datos del LCD


* Se utilizar el nible alto del puerto escogido (ejem. PB4-DB4,...,PB7-DB7)
*/
#define lcd_DATAout PORTB
#define lcd_DATAin

PINB

// Registro PORT del puerto


// Registro PIN del puerto

#define lcd_DATAddr DDRB

// Registro DDR del puerto

/* Define el puerto a donde se conectarn las lneas de control del LCD


* E, RW y RS. Puede ser el mismo puerto del bus de datos.
*/
#define lcd_CTRLout PORTB
#define lcd_CTRLin

PINB

// Registro PORT del puerto


// Registro PIN del puerto

#define lcd_CTRLddr DDRB

// Registro DDR del puerto

/* Define los nmeros de los pines del puerto anterior que correspondern a
* las lneas E, RW y RS del LCD.
*/
#define lcd_E

// Pin Enable

#define lcd_RW

// Pin Read/Write

#define lcd_RS

// Pin Register Select

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

CDIGOS DE COMANDO USUALES

//****************************************************************************
#define LCD_CLEAR 0x01

// Limpiar Display

#define LCD_RETHOM 0x02

// Cursor a inicio de lnea 1

#define LCD_LINE1 0x80

// Lnea 1 posicin 0

#define LCD_LINE2 0xC0

// Lnea 2 posicin 0

#define LCD_DDRAM 0x80

// Direccin 0x00 de DDRAM

#define LCD_CGRAM 0x40

// Direccin 0x00 de CGRAM

#define LCD_CURSOR 0x0E


#define LCD_BLINK 0x0D

// Mostrar solo Cursor


// Mostrar solo Blink

#define LCD_CURBLK 0x0F

// Mostrar Cursor + Blink

#define LCD_NOCURBLK 0x0C

// No mostrar ni Cursor ni Blink

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

PROTOTIPOS DE FUNCIONES

//****************************************************************************
void lcd_init(void);

// Inicializa el LCD

void lcd_puts(char * s);

// Enva una cadena ram al LCD

void lcd_gotorc(char r, char c);


void lcd_clear(void);

// Cursor a fila r, columna c

// Limpia el LCD y regresa el cursor al inicio

void lcd_data(char dat);

// Enva una instruccin de dato al LCD

void lcd_cmd(char com);


char lcd_read(char RS);

// Enva una instruccin de comando al LCD


// Lee un dato del LCD

void lcd_write(char inst, char RS); // Escribe una instruccin en el LCD


void lcd_nibble(char nibble);
void ldelay_ms(unsigned char );

Tabla 18: Librera LCD de Shawn Johnson - lcd.h


Lcd.c

/******************************************************************************
* FileName: lcd.c
* Purpose:
*

Librera de funciones para controlar un display LCD con chip

Hitachi HD44780 o compatible. La interface es de 4 bits.

* Processor: ATmel AVR


* Compiler: AVR IAR C y AVR GCC (WinAVR)
* Author:

Shawn Johnson. http://www.cursomicros.com.

*
* Copyright (C) 2008 - 2013 Shawn Johnson. All rights reserved.
*
* License:

Se permiten el uso y la redistribucin de este cdigo con

modificaciones o sin ellas, siempre que se mantengan esta

licencia y las notas de autor y copyright de arriba.

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

#include "lcd.h"

//****************************************************************************
// Ejecuta la inicializacin software completa del LCD. La configuracin es
// de: interface de 4 bits, despliegue de 2 lneas y caracteres de 5x7 puntos.
//****************************************************************************
void lcd_init(void)
{
/* Configurar las direcciones de los pines de interface del LCD */
lcd_DATAddr |= 0xF0;
lcd_CTRLddr |= (1<<lcd_E)|(1<<lcd_RW)|(1<<lcd_RS);

/* Secuencia de inicializacin del LCD en modo de 4 bits*/


lcd_CTRLout &= ~((1<<lcd_E)|(1<<lcd_RW)|(1<<lcd_RS));
ldelay_ms(45);
lcd_nibble(0x30);
ldelay_ms(5);
lcd_nibble(0x30);
ldelay_ms(1);
lcd_nibble(0x30);
ldelay_ms(1);
lcd_nibble(0x20);
ldelay_ms(1);

// > 40 ms
// Function Set: 8-bit
// > 4.1 ms
// Function Set: 8-bit
// > 100 s
// Function Set: 8-bit
// > 40 s
// Function Set: 4-bit
// > 40 s

lcd_nibble(0x20);

// Function Set: 4-bit, 2lines, 47font

lcd_nibble(0x80);

//

lcd_write(0x0C, 0); // Display ON/OFF Control: Display on, Cursor off, Blink off
lcd_write(0x01, 0);

// Clear Display

lcd_write(0x06, 0);

// Entry Mode Set

//****************************************************************************
// Escribe una instruccin en el LCD:
// Si RS = 0 la instruccin es de comando (Function Set, Entry Mode set, etc).
// Si RS = 1 la instruccin es de dato y va a la DDRAM o CGRAM.
//****************************************************************************
void lcd_write(char inst, char RS)
{
while(lcd_read(0)&0x80);

// Esperar mientras LCD est ocupado

if(RS)
lcd_CTRLout |= (1<<lcd_RS); // Para escribir en DDRAM o CGRAM
else
lcd_CTRLout &= ~(1<<lcd_RS); // Para escribir en Registro de Comandos
_delay_us(5);

// Permite actualizar el Puntero de RAM

lcd_nibble(inst);

// Enviar nibble alto

lcd_nibble(inst<<4);

// Enviar nibble bajo

//****************************************************************************
// Enva el nibble alto de 'nibble' al LCD.
//****************************************************************************
void lcd_nibble(char nibble)
{
lcd_CTRLout &= ~(1<<lcd_RW);
lcd_DATAddr |= 0xF0;

// Establecer Modo de escritura

// Hacer nibble alto de bus de datos salida

lcd_DATAout = (nibble&0xF0)|(lcd_DATAout&0x0F); // Colocar dato


_delay_us(2);

// tAS, set-up time > 140 ns

lcd_CTRLout |= (1<<lcd_E);
_delay_us(2);

// Pulso de Enable

// Enable pulse width > 450 ns

lcd_CTRLout &= ~(1<<lcd_E);


lcd_DATAddr &= 0x0F;

//
// Hacer nibble alto entrada

//****************************************************************************
// Lee un byte de dato del LCD.
// Si RS = 1 se lee la locacin de DDRAM o CGRAM direccionada actualmente.
// Si RS = 0 se lee el 'bit de Busy Flag' + el 'Puntero de RAM'.
//****************************************************************************
char lcd_read(char RS)
{
char high, low;
if(RS)

lcd_CTRLout |= (1<<lcd_RS); // Para leer de DDRAM o CGRAM


else
lcd_CTRLout &= ~(1<<lcd_RS); // Para leer Busy Flag + Puntero de RAM
lcd_CTRLout |= (1<<lcd_RW);
lcd_DATAddr &= 0x0F;

// Establecer Modo Lectura


// Hacer nibble alto entrada

_delay_us(2);

// tAS, set-up time > 140 ns

lcd_CTRLout |= (1<<lcd_E);
_delay_us(2);

// Habilitar LCD

// Data Delay Time > 1320 ns

high = lcd_DATAin;

// Leer nibble alto

lcd_CTRLout &= ~(1<<lcd_E);


_delay_us(2);

// Para que el LCD prepare el nibble bajo

// Enable cycle time > 1200 ns

lcd_CTRLout |= (1<<lcd_E);
_delay_us(2);

// Habilitar LCD

// Data Delay Time > 1320 ns

low = lcd_DATAin;

// Leer nibble bajo

lcd_CTRLout &= ~(1<<lcd_E);


return (high&0xF0)|(low>>4);

//
// Juntar nibbles ledos

//****************************************************************************
// Envan cadenas RAM terminadas en nulo al LCD.
//****************************************************************************
void lcd_puts(char * s)
{
unsigned char c, i=0;
while(c = s[i++])
lcd_write(c, 1);

// Instruccin 'Write Data to DDRAM/CGRAM'

//****************************************************************************
// Ubica el cursor del LCD en la columna c de la lnea r.
//****************************************************************************
void lcd_gotorc(char r, char c)
{
if(r==1) r = LCD_LINE1;
else

r = LCD_LINE2;

lcd_write(r+c-1, 0);

// Instruccin 'Set DDRAM Address'

//****************************************************************************
// Limpia la pantalla del LCD y regresa el cursor a la primera posicin
// de la lnea 1.
//****************************************************************************
void lcd_clear(void)

{
lcd_write(LCD_CLEAR, 0);

// Instruccin 'Clear Display'

//****************************************************************************
// Envan instrucciones de comando y de datos al LCD.
//****************************************************************************
void lcd_cmd(char com)
{
lcd_write(com, 0);

// Cualquier instruccin de comando

}
void lcd_data(char dat)
{
lcd_write(dat, 1);

// Instruccin 'Write Data to DDRAM/CGRAM'

//****************************************************************************
// Genera un delay de n milisegundos
//****************************************************************************
void ldelay_ms(unsigned char n)
{
while(n--)
_delay_us(1000);
}

Tabla 19: Librera lcd de Shawn Johnson -lcd.c


Circuito que se ensamblar :

Prctica fsica. A travs del uso de interrupciones externas, controla el arranque, paro y sentido de giro
de un motor indicando en una pantalla de cristal lquido alfanumrica de 16 caracteres por 2 lneas

Inicialmente el motor debe estar detenido y en la pantalla de indicar el mensaje Motor


Detenido

Si el usuario presiona el botn de inicio, el motor deber girar en el sentido indicado por el
botn Der (Interrupcin 0 ) o Izq (Interrupcin 1). Inicialmente el giro deber ser a la Izquierda.

Una vez arrancado el motor, mediante el empleo de interrupciones, cambie el sentido de giro
del motor, con los botones Der e Izq.

Al presionar el botn de STOP, el motor debe detenerse e indicar lo consecuente en la pantalla


LCD.

Si se mantiene presionado el botn de STOP, el motor no debe de arrancar, con botn alguno, ni
causar ningn tipo de indicacin en la pantalla LCD.

El circuito a ensamblar es el siguiente:

figura 59: circuito con LCD e interrupciones


El cdigo fuente a utilizar es:

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"

#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=(_BV(bit)))


#define clearbit(sfr,bit) (_SFR_BYTE(sfr) &= ~ (_BV(bit)))

/**
* @brief Definicin para crear el tipo de datos booleano
* se utiliza como
*
* boolean variable = {valor binario}
*/

/**
* @brief Macros para definir puertos de conexion del motor
*/
#define start

PINC1

#define pstart

PINC

#define rpstart PORTC


#define stop

PINC2

#define pstop

PINC

#define rpstop PORTC


#define I_nD

PIND2

#define pI_nD

PIND

#define rpI_nD PORTD

#define a

PC3

#define Pa
#define b

PORTC
PC4

#define Pb

PORTC

#define En

PC5

#define pEn

PORTC

/*Defincion para configuracin de entradas y salidas*/


#define cstart

DDC1

#define cpstart

DDRC

#define cstop

DDC2

#define cpstop

DDRC

#define cI_nD

DDD2

#define cpI_nD

DDRD

#define ca

DDC3

#define cPa

DDRC

#define cb

DDC4

#define cPb

DDRC

#define cEn
#define cpEn

DDC5
DDRC

/*
* Se crea una variale del tipo booleano para indicar el sentido de
* giro del motor
*/

typedef enum {false, true} boolean;


boolean Derecha = false;

/**
* @brief Rutina de Interrupcin Externa 1
* Cuando se activa la interrupcion permite cambiar un flag
* a fin de dar sentido de giro a la izquierda al motor
*/
ISR(INT1_vect)
{
Derecha = false;

/**
* @brief Rutina de Interrupcin Externa 0
* Cuando se activa la interrupcion permite cambiar un flag
* a fin de dar sentido de giro a la derecha al motor*/
ISR(INT0_vect)
{
Derecha = true;

int main(void)
{

/*
* Configuracion de E/S y Resistencias de pullup
*/
lcd_init();
clearbit(cpstart,cstart);
clearbit(cpstop,cstop);
clearbit(cpI_nD,cI_nD);

setbit(rpstart, start);
setbit(rpstop,stop);
setbit(rpI_nD,I_nD);
setbit(PORTD,PD3);

setbit(cPa,ca);
setbit(cPb,cb);
setbit(cpEn,cEn);

/*
* Habilitar y configurar la interrupcin INT0 para que se dispare con
* cada flanco de bajada detectado en INT0 (PD2)
*/
setbit(EIMSK,INT0);
setbit(EICRA,ISC01);
clearbit(EICRA,ISC00);

setbit(EIMSK,INT1); //habilita la int1


setbit(EICRA,ISC11); //peticion de interrupcion en flanco de bajada
clearbit(EICRA,ISC10);

sei();

while(1)
{
lcd_gotorc(1,5);
lcd_puts("MOTOR");
lcd_gotorc(2,4); //renglon 2 columna 4
lcd_puts(" DETENIDO ");
clearbit(pEn,En);

if(bit_is_clear(pstart,start) && bit_is_set(pstop,stop))


{
while(bit_is_set(pstop,stop))

{
while(Derecha == false && bit_is_set(pstop,stop))
{
lcd_gotorc(2,4);
lcd_puts("IZQUIERDA");
setbit(Pa,a);
clearbit(Pb,b);
setbit(pEn,En);
}
while(Derecha == true && bit_is_set(pstop,stop))
{
lcd_gotorc(2,4);
lcd_puts(" DERECHA ");
clearbit(Pa,a);
setbit(Pb,b);
setbit(pEn,En);
}

}
}
clearbit(pEn,En);

}
}

Tabla 20: Cdigo para control de puente H

6.3 Fuentes internas de interrupciones


6.3.1 De los timer y contadores
Los Timers son mdulos que trabajan en paralelo con el procesador, permitiendo que las operaciones
de temporizacin y conteo se puedan llevar a cabo de manera eficiente, mientras el procesador se ocupa
de otras tareas.
Normalmente los megaAVR cuentan con tres Timers, llamados Timer0, Timer1 y Timer2. A veces
desaparece el Timer2 y otras veces aparece adicionalmente el Timer3 o el Timer4. Todos los Timers
pueden trabajar en modo de PWM pero esta funcionalidad est mejor implementada en unos Timers (1
y 3) que en otros. Por su relativa limitacin, el Timer0 est ms destinado a las temporizaciones y otro
tanto a los conteos. El Timer2 por su parte fue diseado con la caracterstica adicional para trabajar con
un XTAL de reloj externo, de 32kHz.
En primer lugar nos ocuparemos de los Timers de 8 bits, o sea, del Timer0 y del Timer2.

Luego estudiaremos los Timers de 16 bits, que son el Timer1 y el Timer3. De hecho, solo trataremos el
Timer1 porque el Timer3 es su perfecto clon, si vale la expresin.
El Timer0 y el Timer2
Dada la paridad de caractersticas entre el Timer0 y el Timer2, no las vamos a mencionar
simultneamente para no fatigarnos de trminos. Simplemente vamos a referirnos al Timer0 y se dar
por hecho que lo mismo es aplicable para el Timer2, salvo que se indique explcitamente lo contario.
Las principales diferencias se dejarn notar solo al inicio y al final, luego el tratamiento ser muy
parejo.
Naturalmente, el control de cada Timer a nivel de programacin requiere del trato especfico de sus
registros de configuracin. Pero tampoco esto es de preocupacin pues lo nico que cambia es el
nmero 0 por el nmero 2 en cada registro y bit de registro. Por ejemplo, los registros de E/S del
Timer0 son:
TCNT0. TCCR0A, TCCR0B, OCR0A, OCR0B, TIMSK0 y TIFR0.
En tanto que para el Timer2 son:
TCNT2. TCCR2A, TCCR2B, OCR2A, OCR2B, TIMSK2 y TIFR2.
Aparte de ellos, tenemos al registro GTCCR, el cual es de uso comn para todos los Timers desde el
Timer0 hasta el Timer3, y el registro ASSR, que es de uso exclusivo del Timer2 y que controla las
caractersticas distintivas del funcionamiento asncrono de este Timer.
Del mismo modo, en los nombres de los bits de cada registro, solo cambian el nmero 0 por el 2. Por
ejemplo, los mapas de bits de los registros TCCR0A y TCCR2A son, respectivamente:
Registro TCCR0A
TCCR0A COM0A1 COM0A0 COM0B1 COM0B0 --- --- WGM00 ADPS0
Registro TCCR2A
TCCR2A COM2A1 COM2A0 COM2B1 COM2B0 --- --- WGM21 WGM20
Queda claro entonces que bastar con referirnos al Timer0, entendiendo que las mismas caractersticas,
ventajas y limitaciones citadas sern igualmente aplicables al Timer2, salvo, repito, que se indique lo
contrario. Empecemos, entonces.
El nombre completo del Timer0 es Timer/Counter0 o Temporizador/Contador 0, pero por comodidad
nos referimos a l simplemente como Timer0.
El siguiente esquema ayudar para entender la operacin comn del Timer0. Las operaciones
especficas de cada modo particular las describiremos en su momento.

figura 60: Arquitectura del Temporizador 0

El

elemento central del Timer0 es su contador, que es el mismo registro TCNT0. Como es un
registro de 8 bits, decimos que el Timer0 es de 8 bits. El Timer0 puede avanzar hacia adelante o
hacia atrs, segn se programe, impulsado por la seal de su reloj, el cual puede ser interno o
externo. Cuando nos referirnos al avance del Timer en realidad nos referimos al avance de su
contador, el registro TCNT0.
Con sus 8 bits, el Timer0 puede contar en todo su rango, o sea, entre 0 y 255. Cuando el Timer0
opera solo en modo ascendente y llega a su valor mximo de 255, continuar despus contando
desde 0 otra vez, cclicamente. Esta transicin de 255 a 0 es el famoso Desbordamiento y es un
concepto clave en los Timers. El desbordamiento del Timer0 activa el bit de flag TOV0.
Tambin es posible hacer que el Timer0 cuente solo hasta un tope establecido por el registro
OCR0A.
El Timer0 tiene dos comparadores que en todo momento estn comparando el valor del registro
TCNT0 con los registros OCR0A y OCR0B. Cada igualdad detectada entre los registros
indicados se conoce como Coincidencia y es el segundo concepto clave de los Timers del AVR.
La coincidencia entre TCNT0 y OCR0A activa el bit de flag OCF0A y la coincidencia entre
TCNT0 y OCR0B activa el bit de flag OCF0B.
El Desbordamiento del Timer0 y cada una de sus dos Coincidencias se pueden programar para
disparar interrupciones. Los detalles de las interrupciones sern vistos con paciencia en su
seccin respectiva.
Desde el punto de vista de la programacin, podemos controlar el Timer0 con tres tipos de bits:
Los bits CS (de Clock Select). Los bits CS02, CS01 y CS00 se encargan de configurar todo lo
relacionado con el reloj y el prescaler del Timer.
Los bits WGM (de Waveform Generator Mode). Los bits WGM02, WGM01 y WGM00
trabajan con los comparadores para producir ondas cuadradas de acuerdo con la configuracin
de los bits. En realidad, su funcin implica ms que eso, pues establecen el modo en que operar
el Timer0, ya sea modo Normal, CTC o PWM.
Los bits COM (de Compare Output Mode). Son los bits COM0A1 y COM0A0 los que en
ltima instancia deciden si las ondas generadas por los comparadores salen o no por los pines
OC0A y OC0B del AVR. El tipo de onda ms popular es PWM y es habitualmente el nico caso
en que se dejan salir las ondas. Cuando el Timer0 va a trabajar como simple contador o
temporizador, los bits COM quedan con su valor por defecto de 0, con lo cual los pines OC0A y
OC0B quedan desconectados del Timer y se pueden seguir usando como puertos de E/S
generales.
El reloj del Timer0 es la seal digital, peridica o no, cuyos pulsos hacen avanzar el Timer. La fuente
de reloj del Timer0 puede ser interna o externa.
Reloj Interno. Aqu el reloj del Timer0 deriva del mismo oscilador interno del sistema F_CPU.
Como se ve en la figura, en este caso la seal pasa previamente por el prescaler, que puede
dividir la frecuencia de F_CPU por un valor seleccionado por nosotros. Los prescalers del
Timer0 y del Timer2 no son idnticos, aunque tengan los bits de control similares. Pero siendo
este reloj el que se usa con regularidad, ya sea para las temporizaciones o para generar ondas
PWM, sobrar espacio para familiarizarnos con estas ligeras diferencias.
Reloj Externo. He aqu la brecha ms grande que separa al Timer0 del Timer2. La forma como
la seal externa se aplica al microcontrolador depende de cada Timer.
En el Timer0 la seal externa se conecta al pin T0 del megaAVR. Con esto el programador
decide si el Timer0 avanzar con cada flanco de subida o de bajada detectado en dicho pin.
Notemos en el diagrama que la seal externa no pasar por su prescaler.

En el Timer2 su reloj externo puede ser de dos tipos: o es una seal aplicada al pin TOSC1 del
megaAVR, en cuyo caso el Timer2 avanzar con cada flanco de bajada de ese pin; o es la seal
de un oscilador de XTAL conectado entre los pines TOSC1 y TOSC2 del megaAVR. En ambos
casos, la seal de reloj pasar por el prescaler del Timer2.
El modo donde el Timer0/2 trabaja con un reloj externo aplicado al pin T0 (para el Timer0) o TOSC1
(para el Timer2) se conoce como modo Contador porque de alguna forma el Timer contar los pulsos
detectados en dicho pin. Sin embargo, el hecho de que el reloj provenga de una fuente externa no le
quita sus otras funcionalidades, como por ejemplo, poder generar ondas PWM, interrupciones, etc.,
claro que sera conveniente que para tal caso la seal fuera peridica.

figura 61: Arquitectura del Timer 0

El prescaler es un circuito contador por el que se puede hacer pasar el reloj del Timer para dividir su
frecuencia. De ese modo el Timer avanzar ms lento, segn las necesidades del diseador.
El prescaler es parte del reloj del Timer, as que para configurarlo se usan los bits de Seleccin de Reloj
o bits CS (por Clock Select).
Registro TCCR0B
TCCR0B FOC0A FOC0B --- --- WGM02 CS02 CS01 CS00
Registro TCCR2B
TCCR2B FOC2A FOC2B --- --- WGM22 CS22 CS21 CS20
Como puedes ver, los bits CS se encuentran en los registros TCCRxB de cada Timer, sin embargo, por
ms que sean casi iguales, tiene efectos diferentes debido a que los prescalers son diferentes. El
prescaler del Timer2 es ms sencillo y completo, pero empezaremos por explicar el prescaler del
Timer0.
El prescaler del Timer0 es compartido con el Timer1 (y qu tiene que ver en todo esto el Timer1?). De
acuerdo con la figura, es posible que los dos Timers operen simultneamente con el prescaler y
utilizando diferentes factores de divisin puesto que cada Timer tiene sus propios bits CS (de Clock
Select). El nico reparo sera que se debe tener cuidado al resetear el prescaler porque para esto se
dispone de una nica seal PSRSYNC. Es un reset SYNCrono porque el Timers0 y el Timer1 trabajan
siempre sincronizados con el reloj del sistema F_CPU, hasta cuando su reloj proviene de los pines T0 o
T1, respectivamente. El bit PSRSYNC se encuentra en el registro GTCCR.

figura 62: Prescaladores y relojes del timer0 y timer1

Notemos que el prescaler divide el reloj del sistema por 8, 64, 256 1024. Estos divisores se conocen
como factores de prescaler. Observemos adems que de usar un reloj proveniente del pin T0, entonces
no ser posible usar el prescaler.
Registro TCCR0B
TCCR0B FOC0A FOC0B --- --- WGM02 CS02 CS01 CS00
CS02 CS01 CS00

Tabla CS02
Fuente de reloj del Timer0

Sin fuente de reloj (Timer0 detenido)

F_CPU (Sin prescaler)

F_CPU/8 (con prescaler)

F_CPU/64 (con prescaler)

F_CPU/256 (con prescaler)

F_CPU/1024 (con prescaler)

Reloj
externo
en
pin
T0.
El Timer0 avanza con el flanco de bajada.

Reloj
externo
en
pin
T0.
El Timer0 avanza con el flanco de subida.

Ahora revisemos el prescaler del Timer2. Este prescaler ofrece ms factores de divisin, con lo que las
temporizaciones podrn ser ms flexibles. A diferencia del Timer0/1, si optamos por un reloj externo
aplicado al pin TOSC1, dicha seal s podr pasar por el prescaler. Esta vez el prescaler se puede
resetear con la seal PSRASY. Su nombre indica que se trata de naturaleza ASYncrona porque si el
reloj del Timer2 viene del exterior, no habr circuito que lo sincronice con el reloj del sistema F_CPU.
Los bits AS2 y PSRASY se encuentran en el registro GTCCR.

figura 63: Preescalador del timer 2


TCCR2B FOC2A FOC2B --- --- WGM22 CS22 CS21 CS20
En la siguiente tabla la seal clkT2S puede ser F_CPU o el reloj proveniente del exterior.
Tabla CS22
Fuente de reloj del Timer2

CS22 CS21 CS20


0

Sin fuente de reloj (Timer detenido).

clkT2S (Sin prescaler)

clkT2S/8 (Desde el prescaler)

clkT2S/32 (Desde el prescaler)

clkT2S/64 (Desde el prescaler)

clkT2S/128 (Desde el prescaler)

clkT2S/256 (Desde el prescaler)

clkT2S/1024 (Desde el prescaler)

Registro GTCCR
GTCCR TSM --- --- --- --- --- PSRASY PSRSYNC
En general existen 3 modos en que pueden trabajar los Timers:
Modo Normal

Modo CTC
Modo PWM
Cada modo tendr sus variantes dependiendo del Timer. Por ejemplo, en el Timer1 existen hasta 12
modos PWM, pero bueno, de eso nos ocuparemos en su momento.

El timer 0 y el timer 2 en modo normal


Este modo queda seleccionado cuando todos los bits WGM valen 0, es decir, es el modo por defecto del
Timer0. De hecho, lo es en todos los Timers.
Tabla WGM02
WGM02 WGM01 WGM00 Modo de Operacin de Timer0 Inicio del Conteo Tope del Conteo
0

Normal

0x00

0xFF

En modo Normal el Timer0, habilitado, avanza libre y cclicamente en todo su rango, es decir, su
registro TCNT0 cuenta desde 0x00 hasta 0xFF, luego se desborda para volver a iniciar desde 0x00.
El desbordamiento del Timer activa el flag TOV0 del registro TIFR0 el cual puede programarse para
disparar interrupciones. Como el registro TCNT0 es de lectura y escritura podemos en cualquier
momento modificar su valor y as recortar los periodos de conteo para calibrar o ajustar las
temporizaciones.
Registro TCCR0A
TCCR0A COM0A1 COM0A0 COM0B1 COM0B0 --- --- WGM01 WGM00
Registro TCCR0B
TCCR0B FOC0A FOC0B --- --- WGM02 CS02 CS01 CS00
Registro TIFR0
TIFR0 --- --- --- --- --- OCF0B OCF0A TOV0
El Timer0 siempre inicia detenido, as que para que se cumpla todo lo descrito primero habr echarlo a
andar configurando los bits de reloj CS, segn lo estudiado en El Reloj del Timer0 y del Timer2.
Recordemos que los comparadores del Timer0 pueden sacar por los pines OC0A y OC0B unas seales
que se pueden configurar con los bits COM. En los modos Normal o CTC esta seal se forma poniendo
a cero, a uno, o conmutando el valor de OC0A/OC0B. Todas las opciones posibles se muestran en la
siguiente tabla. Para temas de temporizacin, que es normalmente el propsito del modo Normal o
CTC, debemos escoger la primera opcin, que es la predeterminada y que nos dejar los pines
OC0A/OC0B libres para seguir usndolos como puertos de E/S generales.
COM0A1 COM0A0

Tabla COM0A1
Descripcin

Pin OC0A desconectado. Operacin normal del pin

Pin OC0A conmuta en Coincidencia entre TCNT0 y OCR0A

Pin OC0A se limpia en Coincidencia entre TCNT0 y OCR0A

Pin OC0A se setea en Coincidencia entre TCNT0 y OCR0A

La tabla solo muestra la configuracin de la onda generada para el pin OC0A pero es la misma que se
obtiene para el pin OC0B con los bits COM0B1 y COM0B0.

Clculo de la Temporizacin en Modo Normal


Temporizar con el Timer0 implica cargar su registro TCNT0 con un valor adecuado y dejar que siga
contando hasta que se desborde. Es el tiempo que demora en desbordarse lo que nos interesa conocer
para aplicarlo a nuestras necesidades; y son el clculo y la programacin de ese tiempo el objetivo de
esta seccin.
Bueno, asumo que en este momento ya sabemos cmo configurar el reloj del Timer0 (bits CS), que
sabemos cmo programar el Timer0 en modo Normal (bits WGM) y que entendemos su operacin en
ese modo. Ahora aprenderemos a escoger la opcin de reloj ms adecuada para nuestras
temporizaciones.
Para empezar, debemos usar el reloj interno derivado de F_CPU (cuyo valor es tericamente igual a la
frecuencia del XTAL del megaAVR.), salvo que tengamos una seal externa peridica. Como sabemos,
si la fuente de reloj es interna, el Timer0 y el Timer2 se programan igual. Lo nico que cambiar sern
los factores de prescaler.
CS02 CS01 CS00

Tabla CS02
Fuente de reloj del Timer0

Sin fuente de reloj (Timer0 detenido)

F_CPU (Sin prescaler)

F_CPU/8 (con prescaler)

F_CPU/64 (con prescaler)

F_CPU/256 (con prescaler)

F_CPU/1024 (con prescaler)

Reloj externo en pin T0. El Timer0 avanza con el flanco de bajada.

Reloj externo en pin T0. El Timer0 avanza con el flanco de subida.

En primer lugar veamos cmo avanza el Timer0. Por ejemplo, si tenemos un XTAL de 8 MHz y no
usamos prescaler, entonces el reloj del Timer0 ser de 8 MHz y el registro TCNT0 se incrementar
cada 1/8MHz = 128ns, lo mismo que un ciclo de instruccin bsica. Pero si usamos el factor de
prescaler 8, TCNT0 avanzar cada 1us. Si usamos el factor de prescaler de 256, TCNT0 avanzar cada
32us. Y si cambiamos de XTAL, los tiempos sern otros.
Ahora entonces, suponiendo que seguimos con nuestro XTAL de 8MHz, el registro TCNT0 avanzar
desde 0 hasta 255 en 32us (sin prescaler). Pero si cargamos TCNT0 con 200, llegar al desbordamiento
despus de 7us; y si usamos prescaler de 8, lo har despus de 78 = 56us.
Al inicio todos vemos en esto un enredo de nmeros. Parece complejo pero solo es cuestin de
encontrar el hilo de la madeja para suspirar diciendo Ah, era as de fcil! Sin embargo, hay quienes
se rinden y prefieren usar frmulas y clculos directos como los descritos a continuacin.
Bueno, vamos al grano. El Tiempo que pasar el Timer0 contando desde un valor inicial TCNT0 hasta
255 y se produzca el desbordamiento est dado por la frmula:

Tiempo=

N (256TCNT0 )
F CPU

donde:

Tiempo = Valor de temporizacin deseada

F_CPU = Frecuencia del reloj principal seleccionado del AVR

N = Factor de divisin de frecuencia o Prescalamiento (1, 8, 64, 256, 1024)

TCNT0 = Valor inicial de precarga.

Nota: los factores de prescaler N del Timer2 son 1, 8, 32, 64, 128, 256 y 1024. Eso podra dar otras
soluciones para N y TCNT2.
Como ves, sta es una ecuacin con dos incgnitas (N y TCNT0) y es posible encontrar ms de una
solucin para ambas. Sin embargo, no todas sern igualmente adecuadas. Los valores ms apropiados
sern los que nos permitan realizar un mejor posterior ajuste de precisin.
Pero si no quieres ir tanteando, puedes emplear las siguientes dos frmulas:
N=

tiempoF CPU
256

Lo ms probable es que el valor obtenido con esta frmula no est disponible como factor de prescaler
vlido (1, 8, 64, 256 1024 para el Timer0 o 1, 8, 32, 64, 128, 256 y 1024 para el Timer2). En tal caso
deberemos tomar el factor superior ms cercano (redondear para arriba). La otra frmula es:
TCNT0=256

tiempoF CPU
N

Como antes, si el resultado no fuera un nmero entero, habra que redondearlo para arriba.
Si el factor de prescaler obtenido estuviera fuera del rango permitido (ms alto que 1024), se puede
optar por buscar otro camino, como fragmentar la temporizacin. Por otro lado, si la temporizacin es
muy fina, puede que sea necesario subir un poquito el valor de inicio del TCNT0 para realizar una
calibracin aadiendo algunas instrucciones de relleno como nops. Estas dos situaciones las veremos
en las prcticas; as que pierde cuidado si no las dej muy claro.
A modo de ejemplo, hallemos el factor de prescaler N y el valor de inicio de TCNT0 para generar una
temporizacin de 5 ms si el megaAVR trabaja con un XTAL de 10 MHz.
N=

5ms10 MHz 50000


=
=195,31256 ( factor superior ms cercano)
256
256

Y el valor de inicio del registro TCNT0 ser:


TCNT0=256

5 ms10 MHz
50 000
=256
=60,67=61(redondear hacia arriba)
256
256

La secuencia de conteo resultara as:


61 62 63 - ... - 253 254 255 0 1 -2 - ...
Desborde

Otro ejemplo. Cules son la razn de prescaler y el valor inicial de TCNT0 para conseguir una
temporizacin de 200 s si nuestro megaAVR tiene un XTAL de 4 MHz?
El factor de prescaler N sera:
N=

200 s4 MHz 800


=
=3,1258
256
256

Y el valor inicial de TCNT0 ser:


TCNT0=256

200 s4MHz
800
=256
=156
8
8

Luego, la secuencia de conteo quedara as:


156 157 158 - ... - 253 254 255 0 1 - 2
Finalmente, cules son la razn de prescaler y el valor inicial de TCNT0 para conseguir una
temporizacin de 50 ms si se tiene un megaAVR con un XTAL de 20 MHz?
El factor de prescaler sera:
N=

50 ms20 MHz 1000 000


=
=3906,25? ??
256
256

Y ahora de dnde vamos a sacar un factor de prescaler mayor que 3906.25 si el mximo es de 1024?
Buscamos otro Timer? Bueno, quiz podramos temporizar 10 veces 5 ms.
Interrupciones del Timer 0 y del timer 2
La real potencia del Timer0 se deja apreciar al emplear su caracterstica ms notable: las interrupciones.
El Timer0 tiene dos tipos de interrupciones: una por el desbordamiento de su registro TCNT0 y dos en
las coincidencias de su registro TCNT0 con los registros OCR0A y OCR0B. Estas interrupciones se
controlan por los bits de los registros TIMSK0 y TIFR0:
TIMSK0 (Timer Interrupt Mask Register 0). Contiene los bits Enable de interrupciones.
TIFR0 (Timer Interrupt Flags Register 0). Contiene los bits de Flag de interrupciones.
Para quienes an trabajan con los viejos megaAVR, ellos no tienen interrupcin en coincidencia B, los
bits de la coincidencia A son simplemente OCIE0 y OCF0, y los siguientes registros se llaman TIMSK
y TIFR. No llevan el 0 porque tambin controlan las interrupciones del Timer1 y del Timer2.
Registro TIMSK0
TIMSK0 --- --- --- --- --- OCIE0B OCIE0A TOIE0
Registro TIFR0
TIFR0 --- --- --- --- --- OCF0B OCF0A TOV0
Interrupcin por Desbordamiento del Timer0. El evento que puede disparar esta interrupcin es el
desbordamiento del registro TCNT0, o sea, la transicin de 255 a 0. Esto implica la operacin
incremental del Timer0, sin importar si est contando en modo Normal, CTC o Fast PWM. En modo
PWM de Fase Correcta el Timer0 cuenta en sube y baja sin pasar por la transicin 255 a 0, as que en
este modo no hay desbordamiento.
El desbordamiento de Timer0 activar el flag TOV0 y si la interrupcin est habilitada, se disparar. El
bit TOV0 se limpia automticamente al ejecutarse su funcin de interrupcin ISR, pero tambin se
puede limpiar por software, como de costumbre, escribindole un 1 y sin usar instrucciones de lectura-

modificacin-escritura como las generadas por las sentencias con el operador OR binario (|).
Para habilitar la interrupcin por Desbordamiento del Timer0 se setean los bits TOIE0 y obviamente, el
bit enable general de interrupciones I, del registro SREG. La instruccin del ensamblador dedicada a
esta operacin es SEI y que en lenguaje C se puede incrustar mediante la funcin macro del mismo
nombre sei(). (No s por qu repito estas cosas.)
Interrupcin en Coincidencia del Timer0. Como sabemos, los comparadores del Timer0 son circuitos
que en todo momento estn comparando los valores del registro TCNT0 con los registros OCR0A y
OCR0B. Pues bien, el evento que puede disparar esta interrupcin es la coincidencia entre los registros
mencionados. Como puede haber dos coincidencias, aqu podemos tener hasta dos interrupciones.
Especificando, cuando se detecte la igualdad entre TCNT0 y OCR0A se activar el flag OCF0A
(Output Compare Flag 0 A), y cuando sean iguales TCNT0 y OCR0B se activar el flag OCF0B
(Output Compare Flag 0 A). De nuevo, los flags se ponen a 1 independientemente de si sus
interrupciones estn habilitadas o no. Si lo estn, se dispararn sus interrupciones, se ejecutarn las
funciones ISR respectivas y los flags OCF0A y/o OCF0B se limpiarn por hardware. Ya sobra decir
que tambin se pueden limpiar por software escribindoles un uno.
Ambas interrupciones son gemelas pero no son siamesas, es decir, funcionan exactamente igual pero no
necesariamente se tienen que habilitar las dos al mismo tiempo. Se habilitan por separado seteando el
bit OCIE0A para una y OCIE0B para la otra.
Una observacin: el circuito comparador (llamado Output Compare) trabaja siempre sin importar en
qu modo est operando el Timer0 (Normal, CTC o PWM), aunque las implicatorias no sern las
mismas. Explico: una coincidencia en modo CTC resetea el registro TCNT0, mientras que en los otros
modos el registro TCNT0 sigue su marchar sin hacer caso. Si captaste mi chchara, habrs descubierto
que es posible temporizar con la Interrupcin en Coincidencia incluso si el Timer trabaja en modo
PWM.
Clculo en modo CTC del timer 0
La ecuacin que permite definir el tiempo que tarda en el modo ctc, esta dado de la siguiente manera
Tiempo=

NOCR nx
F CPU

6.3.2 ADC
El Convertidor Analgico Digital del ATmega48 es por Aproximaciones Sucesivas con una resolucin
de 10 bits. El ADC se conecta a un multiplexor de 8 canales anlogos el cual permite 8 voltajes de
entrada en una sola terminacin construido en los pines delpuerto A. El voltaje de entrada de una sola
terminacin se refiere a 0 V (GND).
La interrupcin por Conversin completa, resulta til cuando se desea cancelar el ruido en la
conversin. Para hacer uso de esta caracterstica, el siguiente procedimiento deber usarse.
1. Asegrese que el ADC este habilitado y no se encuentre ocupado en una conversin. En el
modo de conversin nica debe ser seleccionado y la interrupcin de conversin completa del
ADC debe ser habilitada.
2. Entre al modo de reduccin de ruido del ADC. El ADC iniciar una conversin una vez que el
CPU ha sido detenido.
3. Si ninguna interrupcin ocurre antes de que la conversin del ADC se complete,la interrupcin
del ADC despertara al CPU y ejecutara la rutina de interrupcin de conversin completa del
ADC. Si otra interrupcin activa al CPU antes de que la conversin del ADC se complete, esa
interrupcin ser ejecutada, y una solicitud de interrupcin de conversin completa del ADC
ser generada cuando la conversin del ADC se completa. El CPU permanecer en modo activo
hasta que un nuevo comando de sleep se ejecute.
El registro ADCSRA Es el encargado del control y estado del ADC.
ADEN ADSC ADATE ADIF

ADIE

ADPS2 ADPS1

ADPS0

El bit ADIE al ser seteado, permite habilitar la interrupcin por conversin completada.
El bit ADIF se pone en estado alto cuando la una conversin analgico a digital ha sido completada y
el registro de datos es actualizado.

6.3.3 De la comunicacin serial

El Transmisor/Receptor Universal Sncrono y Asncrono (USART) es un dispositivo altamente flexible para


comunicacin serial. Las principales caractersticas son:

Operacin Full Duplex (Registros independientes de recepcin y transmisin serial).

Operacin Asncrona y Sincrona.

Operacin sincrona Maestro-Esclavo.

Generador de alta resolucin de Baud rate.

Soporte de frames con 5, 6, 7, 8 o 9 bits de datos y 1 o 2 bits de stop.

Generacin de paridad Par o Impar y Chequeo soportado por hardware.

Deteccin de datos OverRun.

Deteccin de framing de error.

Filtrado de ruido incluid, deteccin de bit de inicio falso y filtro pasa-bajo ideal.

Tres interrupciones separadas: Finalizacin de Tx, Registro de datos vaco Tx,Recepcin Completa Rx.

Modo de comunicacin Multiprocesador.

Modo de comunicacin de doble velocidad Asncrona

Ya que la USART tiene 3 fuentes de interrupcin, a continuacin se describen los bits de configuracin
para cada una de ellas:
Transmisin de datos
El transmisor de la USART se habilita mediante la puesta en Alto del bit TXEN en el Registro
UCSRnB. Cuando la transmisin es habilitada, la operacin normal del puerto donde se ubica la
terminal TxDn es controlada por la USART y se configura como salida de transmisin serial.
Banderas de Transmisin e Interrupciones
El transmisor de la USART tiene dos banderas que indican su estado: (UDREn) Registro de Datos de
USART vacio y (TXCn) Transmisin completa. Ambas banderas pueden ser utilizadas para generar
interrupciones.
La bandera UDREn indica que el buffer para transmisin de datos se encuentra listo para recibir un
nuevo dato. Este bit se pone en estado alto cuando el buffer de trasmisin se encuentra vaci y se pone
en estado bajo cuando el buffer contiene datos a ser transmitido.
Cuando al bit de habilitacin de Interrupcin por Registro de Datos vaco se le escribe un uno, la
interrupcin de registro de datos vaco se ejecuta tan pronto como UDREn sea alto. Cuando se usa una
transmisin de datos dirigida por interrupcin, la rutina de interrupcin de registro vaco debe ya sea escribir un nuevo
dato a UDRn para limpiar UDREn o deshabilitar lainterrupcin de datos de registro vaco, de lo contrario una nueva
interrupcin puede ocurrir una vez que la rutina de interrupcin termine.
El bit de la bandera de la transmisin completada (TXCn) se coloca a uno cuando el frame entero en el registro de
corrimiento de transmisin ha sido enviado serialmente y ningn dato actualmente se encuentra en el buffer de
transmisin. El bit de la bandera TXCn automticamente se limpia cuando una interrupcin de trasmisin completa se
ejecute, o puede ser borrado escribiendo a uno en esa localidad del bit. La bandera TXCn es til para interfaces de
comunicacin half-duplex (como el estndar RS485),donde una transmisin debe entrar a modo de recepcin y se libere
el bus de comunicacin inmediatamente despus de completar la transmisin.
Cuando el bit de habilitacin de interrupcin de transmisin completa en el UCSRnB se ponga a uno, la interrupcin de

transmisin completa del USART ser ejecutada cuando la bandera TXCn llegue a ponerse a uno (siempre y cuando las
interrupciones globales estn habilitadas). Cuando la interrupcin de transmisin completa se use, la rutina del manejo de
interrupcin no tiene que limpiar la bandera TXCn, esto se realiza automticamente cuando la interrupcin se ejecute.
Recepcin de datos Receptor de la USART
La recepcin inicia se detecta un bit de inicio vlido, cada bit que sigue al bit de inicio ser muestreado
a la velocidad del generador de Baudios, y es desplazado hacia el registro de corrimiento de recepcin.
Cuando el primer bit de paro es recibido, es decir, cuando el cuadro de recepcin serial est completo,
el contenido del registro de desplazamiento es movido hacia el registro de recepcin, el cual puede ser
ledo desde la localidad UDRn
Bandera de Recepcin completa e Interrupcin.
La bandera Recepcin Terminada (RXCn) indica la presencia de un dato sin leer en el buffer de
recepcin
Cuando el bit de habilitacin de interrupcin de recepcin completa (RXCIEn) en el UCSRnB es puesto a uno, la
interrupcin de recepcin completa del USART ser ejecutada tan pronto como la bandera RXCn se ponga a uno
(siempre y cuando las interrupciones globales estn habilitadas). Cuando se usa la recepcin de datos dirigida por
interrupcin, la rutina de recepcin completa debe leer el dato recibido de UDRn para limpiar la bandera de RXC, de lo
contrario una nueva interrupcin puede ocurrir una vez que la rutina de interrupcin termina.

6.3.4 Del comparador analgico.


El comparador analgico permite comparar valores de entrada entre la terminal positiva AIN0 y la
terminal negativa AIN1. El usuario puede seleccionar disparo por interrupcin en flanco de subida, de
bajada o por cambio a la salida.
La interrupcin del comparador analgico se habilita mediante el bit ACIE del registro ACSR, al
ponerse en estado alto.
El modo de Interrupcin se elige mediante los bits ACIS1 y ACIS0
ACIS1

ACIS0

Modo de Interrupcin

Interrupcin en cambio a la salida

Reservado

Interrupcin en flanco de bajada a la salida

Interrupcin en flanco de subida a la salida

Tabla 21: Bits para configuracin de Interrupciones del comparador analgico

6.3.5 De la EEPROM
El ATmega48 contiene 256 bytes de memoria de datos EEPROM, la cual se encuentra se organizada
como un espacio de datos separado, en el cual, bytes pueden ser ledos o escritos.
La interrupcin que genera la EEPROM se habilita mediante el bit EERIE al ponerlo en estado alto,
esto en el registro EECR

6.4 Ejemplos de aplicaciones de las interrupciones.


Prctica.- Haciendo uso de la interrupcin por coincidencia del timer 0, elaborar un reloj digital que
muestre segundos, minutos y horas, haga uso del temporizador interno de 8 Mhz prescalado por 8, y
agregue dos botones que permitan ajustar los minutos y las horas del reloj.

figura 64: Reloj Digital Simple


El cdigo fuente es el que se muestra a continuacin

#include <avr/io.h>
#define clearbit(sfr,bit) (_SFR_BYTE(sfr) &= ~(_BV(bit)))
#define setbit(sfr, bit) (_SFR_BYTE(sfr) |= (_BV(bit)))
#define togglebit(sfr,bit) (_SFR_BYTE(sfr)^=(_BV(bit)))
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#define SegDataPort
#define SegDataPin
#define SegDataDDR
#define SegCntrlPort
#define SegCntrlPin
#define SegCntrlDDR

PORTB
PINB

DDRB

PORTC
PINC
DDRC

unsigned char tick_100ms;


unsigned char hora = 0;
unsigned char minuto = 0;
unsigned char segundo = 0;
#define PinH PD2
#define PinM PD3
#define pPinH PIND
#define rpPinH PORTD
#define pPinM PIND
#define rpPinM PORTD
#define cpPinH DDRD
#define cpPinM DDRD
/*Funcin para codificar un decimal a siete segmentos de catodo comun*/
unsigned char DigTo7Seg(unsigned char digit, unsigned char comun);
/*
* Rutina de servicio de interrupcin en coincidencia
*/
ISR(TIMER0_COMPA_vect)
{
static unsigned char i;
tick_100ms++;
if(++i >=10)
{
segundo++;
i=0;
}
if(segundo == 60)
{
segundo = 0;
minuto++;
}
if(minuto == 60)
{
minuto = 0;
hora++;
}
if(hora > 23)
hora = 0;
_delay_us(670);
//togglebit(PORTB,PB7);
}
int main(void)
{

SegDataDDR = 0xFF; //Es salida


SegCntrlDDR = 0xFF; // Salidas para encender un solo display a la vez
SegCntrlPort = 0xFF;
clearbit(cpPinH, PinH);
clearbit(cpPinM, PinM);
setbit(rpPinH, PinH); //Se habilitan resistencias de Pull up
setbit(rpPinM, PinM);
setbit(DDRB,PB7);
clearbit(PORTB,PB7);
/*
* configuracion del timer 0
*
* Modo de operacion: CTC [Clear Timer On Compare Match]
* Factor de Preescalamiento: 1024
* Valor de precarga: 96
* Periodo de auto reset: 0.1 s
*/
setbit(TCCR0A, WGM01); //modo ctc pagina 103
setbit(TCCR0B, CS02); // Preescalamiento 1024 --> 101
clearbit(TCCR0B, CS01);
setbit(TCCR0B, CS00);
OCR0A = 96; //Precarga de comparacion
/*Habilitando la interrupcion por coincidencia del timer*/
setbit(TIMSK0, OCIE0A);
sei();
while(1)
{
/*Ajuste de minutos */
if(bit_is_clear(pPinM,PinM))
{
_delay_ms(200);
if(minuto < 59)
minuto++;
else
minuto = 0;
}
/*Ajuste de las horas*/
if(bit_is_clear(pPinH,PinH))
{
_delay_ms(200);
if(hora < 23)
hora++;
else
hora = 0;
}
SegDataPort = DigTo7Seg(segundo%10,1); //envia unidades
SegCntrlPort = ~0x01;
_delay_ms(15);
SegDataPort = DigTo7Seg(segundo/10,1); //envia decenas
SegCntrlPort = ~0x02;
_delay_ms(15);
SegDataPort = DigTo7Seg(minuto%10,1); //envia unidades
SegCntrlPort = ~0x04;
_delay_ms(15);
SegDataPort = DigTo7Seg(minuto/10,1); //envia decenas
SegCntrlPort = ~0x08;
_delay_ms(15);
SegDataPort = DigTo7Seg(hora%10,1); //envia unidades
SegCntrlPort = ~0x10;

_delay_ms(15);
SegDataPort = DigTo7Seg(hora/10,1); //envia decenas
SegCntrlPort = ~0x20;
_delay_ms(15);
}

/*
* Function Description:
* Encode a Decimal Digit 0-9 to its Seven Segment Equivalent.
*
* Function Arguments:
* digit - Decimal Digit to be Encoded
* common - Common Anode (0), Common Cathode(1)
* SegVal - Encoded Seven Segment Value
*
* Connections:
* Encoded SegVal is return in the other G-F-E-D-C-B-A that is A is the least
* significant bit (bit 0) and G bit 6.
*/
unsigned char DigTo7Seg(unsigned char digit, unsigned char common)
{
unsigned char SegVal=0;
switch(digit)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:

}
return (SegVal);

if(common == 1)
else
break;
if(common == 1)
else
break;
if(common == 1)
else
break;
if(common == 1)
else
break;
if(common == 1)
else
break;
if(common == 1)
else
break;
if(common == 1)
else
break;
if(common == 1)
else
break;
if(common == 1)
else
break;
if(common == 1)
else

SegVal = 0b00111111;
SegVal = ~0b00111111;
SegVal = 0b00000110;
SegVal = ~0b00000110;
SegVal = 0b01011011;
SegVal = ~0b01011011;
SegVal = 0b01001111;
SegVal = ~0b01001111;
SegVal = 0b01100110;
SegVal = ~0b01100110;
SegVal = 0b01101101;
SegVal = ~0b01101101;
SegVal = 0b01111101;
SegVal = ~0b01111101;
SegVal = 0b00000111;
SegVal = ~0b00000111;
SegVal = 0b01111111;
SegVal = ~0b01111111;
SegVal = 0b01101111;
SegVal = ~0b01101111;

Tabla 22: Cdigo fuente Reloj digital con display de 7 segmentos basado en ATmega48
El siguiente programa para microcontrolador AVR, muestra la forma en la que se declaran, una
interrupcin ocasionada por el Timer0 (de 8 bits) y otra por el Timer1 (de 16 bits), por medio de la

implementacin de dos libreras, una denominada timer0.h y la otra timer1.c


/**
@code #include <timer0.h> @endcode
@brief
Rutina para la configuracin del timer 0 de 8 bits
Este temporizador cuenta con 8 modos de operacin clasificados en 4 grupos
* Normal
* CTC (limpia a la captura)
* Fast PWM
* PWM de Fase Correcta
*
*/

modo{0}
modo{2}
modo{3,7}
modo{1,5}

#ifndef TIMER0_H_INCLUDED
#define TIMER0_H_INCLUDED
/**
* @name Definicion para la variable byte
* para usar en lugar de unsigned char
*/
#define byte uint8_t /**< definicin del tipo de dato byte */
/**
* @name Functions
*/
/**
@brief Ajusta los valores del temporizador 0 para sus diferentes modo y activacion
de las terminales externas de comparacin
@param mode Se refiere uno de los siete modos de operacion del timer
@param prescale Se refiere al valor de p rescalamiento para el temporizador
@param outmode_A Se refiere al comportamiento que pueden tener los bits de comparacion
del modulo A
@param outmode_B Se refiere al comportamiento que pueden tener los bits de comparacion
del modulo B
@return none
*/
void timer0_setup(byte mode, int prescale, byte outmode_A, byte outmode_B);
#endif // TIMER0_H_INCLUDED

Tabla 23: Librera para configuracin del timer0 - timer0.h


A continuacin se muestra el fuente para esta librera

#include <avr/io.h>
#include "timer0.h"
void timer0_setup(byte mode, int prescale, byte outmode_A, byte outmode_B)
{
mode&=7;
outmode_A&=3;
outmode_B&=3;
byte clock_mode = 0;
switch(prescale)
{
case 1: clock_mode = 1; break;
case 8: clock_mode = 2; break;
case 64: clock_mode = 3; break;
case 256: clock_mode = 4; break;
case 1024: clock_mode = 5; break;
default:
if(prescale < 0)
clock_mode = 7;
}

TCCR0A = (outmode_A << 6) | \


(outmode_B << 4) | \
(mode & 0x03);
TCCR0B = ((mode & 0x04)<<1) | (clock_mode);

Tabla 24: Librera para configuracin del timer0 - timer0.c


En este apartado se muestra el archivo de cabecera timer1.h
/**
@code #include <timer1.h> @endcode
@brief
Rutina para la configuracin del timer 1 de 16 bits
Este temporizador cuenta con 16 modos de operacin clasificados en 5 grupos
* Normal
modo{0}
* CTC (limpia a la captura)
modo{4,12}
* Fast PWM
modo{5,6,7,14,15}
* PWM de Fase Correcta
modo{1,2,3,10,11}
* PWM de fase correcta, frecuencia correcta modo{8,9}
*/
#ifndef TIMER1_H_INCLUDED
#define TIMER1_H_INCLUDED
#define byte uint8_t
void timer1_setup(byte mode, int prescale, unsigned char outmode_A, unsigned char outmode_B, unsigned char capture);
#endif // TIMER1_H_INCLUDED

Tabla 25: Librera para configuracin del timer1 - timer1.h


y aqu su cdigo fuente

#include <avr/io.h>
#include "timer1.h"
void timer1_setup(unsigned char mode, int prescale, unsigned char outmode_A, unsigned char outmode_B, unsigned char capture)
{
/*
*Ajustando el ancho de los campos de bit
*/
mode &= 15;
outmode_A &= 3;
outmode_B &= 3;
capture &= 3;
unsigned char clock_mode = 0;
//El cero significa que el temporizador est apagado
switch(prescale)
{
case 1: clock_mode = 1; break;
case 8: clock_mode = 2; break;
case 64: clock_mode = 3; break;
case 256: clock_mode = 4; break;
case 1024: clock_mode = 5; break;
default:
if(prescale < 0) //Habilitar conexion por reloj externo
clock_mode = 7;
}
TCCR1A = (outmode_A << 6) | \
(outmode_B << 4) | \
(mode & 3);
}

TCCR1B = (capture << 6) | ((mode & 0x0C) << 1) | clock_mode;

Tabla 26: Librera para configuracin del timer1 - timer1.c


La forma de usar esta librera se propone en este apartado, en donde dos leds conectados a terminales
diferentes encienden y apagan a tiempos determinados de la siguiente manera:
Tiempo=

N (OCRxA)
F CPU

en donde OCRxA es el valor (de 16 bits para el timer 1 y 8 bits para el timer0) con el que se va a
compara el registro TCNTx, para ser reseteado en modo CTC y que se active la rutina de servicio de
interrupcin.
La determinacin de un tiempo deseado se puede verificar de forma similar a la explicada en la pgina
135 solo que una vez definido el valor de prescalamiento (que solo puede ser 1,8,64,256 o 1024), se
procede a calcular el valor de OCRxA de acuerdo a la siguiente ecuacin:
OCRxA=

F CPUTiempo
N

Por ejemplo para un tiempo de 21.68ms a una frecuencia de reloj de 1MHz, los valores de
prescalamiento y de carga de comparacin (OCR1A) en el temporizador de 16 bits, se tiene que
determinar primero el factor de prescalamiento.
N=

21.68ms1 MHz
=0.333
65536

Al dar un factor de prescalamiento menor a uno, podemos redondearlo hacia arriba a 1, de esta forma el

valor que se debe cargar al OCR1A ser determinado como sigue:


OCR1A=

(1MHz)(21.68ms)
=21680=0x54B0
1

De esta forma, el cdigo fuente queda de la manera siguiente:


/*
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "timer1.h"
#include "timer0.h"
ISR(TIMER1_COMPA_vect)
{
PORTD^=(1 << PD5);
}
ISR(TIMER0_COMPA_vect)
{
PORTD^=(1 << PD2);
}
int main(void)
{
// Insert code
DDRD|=(1<<DDD5); //salida del Timer 1
DDRD|=(1<<DDD2); //salida del Timer 0
/*
configuracion del timer 1
Modo de operacion: CTC (4)
Factor de Prescalamiento: 1
Valor de Precarga: 0x54B0 (OCR1A)
Periodo de AutoReset: 21.68ms
F_CPU = 1MHz
Tiempo = N(OCR1A)/F_CPU
*/
timer1_setup(4,1,0,0,0);
OCR1A=0x54B0;
TIMSK1|=(1<<OCIE1A); //interrupcion por comparacion en modulo A
/*
configuracion del timer 0
Modo de operacion: CTC
Factor de Prescalamiento: 1024
Valor de Precarga: 99 (OCR0A)
Periodo de AutoReset: 101.3 ms
F_CPU: 1MHz
Tiempo = N(OCR0A)/F_CPU
*/
timer0_setup(2,1024,0,0);
OCR0A=99;
TIMSK0|=(1<<OCIE0A); //interrupcion por comparacion en modulo A
sei();
while(1)
;
}

return 0;

Tabla 27: Cdigo fuente para configurar el timer 0 en modo CTC

Para el timer 0, el clculo es similar, se deja al lector que estime los tiempos que son sealados en el
cdigo fuente.

Prctica propuesta
Elaborar de nuevo el reloj, pero usando esta vez una pantalla LCD, en lugar de los cuatros displays de 7
segmentos, tal y como se muestra en la siguiente figura:

figura 65: Reloj con base en Timer 0


Es recomendable tambin que se haga uso de la libreria de peter Fleury, en conjunto con la libreria
clk.h para el manejo de la LCD de esta prctica:

#ifndef LCD_H
#define LCD_H
/*************************************************************************
Title

: C include file for the HD44780U LCD library (lcd.c)

Author:

Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury

File:

$Id: lcd.h,v 1.13.2.2 2006/01/30 19:51:33 peter Exp $

Software: AVR-GCC 3.3


Hardware: any AVR device, memory mapped mode only for AT90S4414/8515/Mega
***************************************************************************/

/**
@defgroup pfleury_lcd LCD library
@code #include <lcd.h> @endcode

@brief Basic routines for interfacing a HD44780U-based text LCD display

Originally based on Volker Oth's LCD library,


changed lcd_init(), added additional constants for lcd_command(),
added 4-bit I/O mode, improved and optimized code.

Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in


4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported.

Memory mapped mode compatible with Kanda STK200, but supports also
generation of R/W signal through A8 address line.

@author Peter Fleury pfleury@gmx.ch http://jump.to/fleury

@see The chapter <a href="http://homepage.sunrise.ch/mysunrise/peterfleury/avr-lcd44780.html" target="_blank">Interfacing a HD44780


Based LCD to an AVR</a>
on my home page.

*/

/*@{*/

#if (__GNUC__ * 100 + __GNUC_MINOR__) < 303


#error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !"
#endif

#include <inttypes.h>
#include <avr/pgmspace.h>

/**
* @name Definitions for MCU Clock Frequency
* Adapt the MCU clock frequency in Hz to your target.
*/
#define XTAL F_CPU

/**< clock frequency in Hz, used to calculate delay timer */

/**
* @name Definition for LCD controller type
* Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller.
*/
#define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */

/**
* @name Definitions for Display Size
* Change these definitions to adapt setting to your display
*/
#define LCD_LINES

#define LCD_DISP_LENGTH

/**< number of visible lines of the display */


16

/**< visibles characters per line of the display */

#define LCD_LINE_LENGTH 0x40

/**< internal line length of the display

#define LCD_START_LINE1 0x00

/**< DDRAM address of first char of line 1 */

#define LCD_START_LINE2 0x40

/**< DDRAM address of first char of line 2 */

#define LCD_START_LINE3 0x14

/**< DDRAM address of first char of line 3 */

#define LCD_START_LINE4 0x54

/**< DDRAM address of first char of line 4 */

#define LCD_WRAP_LINES

#define LCD_IO_MODE

*/

/**< 0: no wrap, 1: wrap at end of visibile line */

/**< 0: memory mapped mode, 1: IO port mode */

#if LCD_IO_MODE
/**
* @name Definitions for 4-bit IO mode
* Change LCD_PORT if you want to use a different port for the LCD pins.
*
* The four LCD data lines and the three control lines RS, RW, E can be on the
* same port or on different ports.
* Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
* different ports.
*
* Normally the four data lines should be mapped to bit 0..3 on one port, but it
* is possible to connect these data lines in different order or even on different
* ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
*
*/

#define LCD_PORT

PORTD

/**< port for the LCD lines */

#define LCD_DATA0_PORT PORTD

/**< port for 4bit data bit 0 */

#define LCD_DATA1_PORT PORTB

/**< port for 4bit data bit 1 */

#define LCD_DATA2_PORT PORTB

/**< port for 4bit data bit 2 */

#define LCD_DATA3_PORT PORTD

/**< port for 4bit data bit 3 */

#define LCD_DATA0_PIN

/**< pin for 4bit data bit 0 */

#define LCD_DATA1_PIN

/**< pin for 4bit data bit 1 */

#define LCD_DATA2_PIN

/**< pin for 4bit data bit 2 */

#define LCD_DATA3_PIN

/**< pin for 4bit data bit 3 */

#define LCD_RS_PORT

LCD_PORT

#define LCD_RS_PIN

#define LCD_RW_PORT

/**< pin for RS line


LCD_PORT

#define LCD_RW_PIN

#define LCD_E_PORT

LCD_PORT

#define LCD_E_PIN

/**< port for RS line


*/

/**< port for RW line

/**< pin for RW line

*/

*/

*/

/**< port for Enable line

/**< pin for Enable line

*/

*/

#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || \


defined(__AVR_ATmega8515__)|| defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || \
defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__)
/*
* memory mapped mode is only supported when the device has an external data memory interface
*/
#define LCD_IO_DATA

0xC000

/* A15=E=1, A14=RS=1

#define LCD_IO_FUNCTION 0x8000


#define LCD_IO_READ

0x0100

*/

/* A15=E=1, A14=RS=0

*/

/* A8 =R/W=1 (R/W: 1=Read, 0=Write */

#else
#error "external data memory interface not available for this device, use 4-bit IO port mode"

#endif

/**
* @name Definitions for LCD command instructions
* The constants define the various LCD controller instructions which can be passed to the
* function lcd_command(), see HD44780 data sheet for a complete description.
*/

/* instruction register bit positions, see HD44780U data sheet */


#define LCD_CLR

#define LCD_HOME

/* DB0: clear display


1

#define LCD_ENTRY_MODE
#define LCD_ENTRY_INC
#define LCD_ENTRY_SHIFT

*/

/* DB1: return to home position

*/

*/

/* DB2: set entry mode

/* DB1: 1=increment, 0=decrement


0

/* DB2: 1=display shift on

*/

*/

#define LCD_ON

/* DB3: turn lcd/cursor on

#define LCD_ON_DISPLAY

#define LCD_ON_CURSOR

/* DB2: turn display on

*/

/* DB1: turn cursor on

*/

#define LCD_ON_BLINK

#define LCD_MOVE

/*

DB0: blinking cursor ?

#define LCD_MOVE_RIGHT

/* DB2: move right (0-> left) ?


/* DB5: function set

#define LCD_FUNCTION_8BIT

#define LCD_BUSY

*/

/* DB3: two lines (0->one line)

#define LCD_FUNCTION_10DOTS 2
6

/* DB7: LCD is busy

*/

*/

/* DB7: set DD RAM address

*/

/* DB2: 5x10 font (0->5x7 font)

/* DB6: set CG RAM address

*/

/* DB4: set 8BIT mode (0->4BIT mode) */

#define LCD_FUNCTION_2LINES 3

#define LCD_DDRAM

*/

/* DB3: move display (0-> cursor) ? */

2
5

#define LCD_CGRAM

*/

/* DB4: move cursor/display

#define LCD_MOVE_DISP

#define LCD_FUNCTION

*/

*/
*/

/* set entry mode: display shift on/off, dec/inc cursor move direction */
#define LCD_ENTRY_DEC

0x04 /* display shift off, dec cursor move dir */

#define LCD_ENTRY_DEC_SHIFT
#define LCD_ENTRY_INC_

0x05 /* display shift on, dec cursor move dir */

0x06 /* display shift off, inc cursor move dir */

#define LCD_ENTRY_INC_SHIFT

0x07 /* display shift on, inc cursor move dir */

/* display on/off, cursor on/off, blinking char at cursor position */


#define LCD_DISP_OFF

0x08 /* display off

#define LCD_DISP_ON

0x0C /* display on, cursor off

#define LCD_DISP_ON_BLINK

*/
*/

0x0D /* display on, cursor off, blink char

#define LCD_DISP_ON_CURSOR

0x0E /* display on, cursor on

*/
*/

#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char

*/

/* move cursor/shift display */


#define LCD_MOVE_CURSOR_LEFT

0x10 /* move cursor left (decrement)

#define LCD_MOVE_CURSOR_RIGHT
#define LCD_MOVE_DISP_LEFT

0x14 /* move cursor right (increment)

0x18 /* shift display left

#define LCD_MOVE_DISP_RIGHT

*/
*/

*/

0x1C /* shift display right

*/

/* function set: set interface data length and number of display lines */
#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */
#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */
#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */
#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */

#define LCD_MODE_DEFAULT

((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )

/**
* @name Functions
*/

/**
@brief Initialize display and select type of cursor
@param

dispAttr \b LCD_DISP_OFF display off \n


\b LCD_DISP_ON display on, cursor off \n
\b LCD_DISP_ON_CURSOR display on, cursor on\n
\b LCD_DISP_ON_CURSOR_BLINK display on, cursor on flashing

@return none
*/
extern void lcd_init(uint8_t dispAttr);

/**
@brief Clear display and set cursor to home position
@param

void

@return none
*/
extern void lcd_clrscr(void);

/**
@brief Set cursor to home position
@param

void

@return none
*/
extern void lcd_home(void);

/**
@brief Set cursor to specified position

@param

x horizontal position\n (0: left most position)

@param

y vertical position\n (0: first line)

@return none
*/
extern void lcd_gotoxy(uint8_t x, uint8_t y);

/**
@brief Display character at current cursor position
@param

c character to be displayed

@return none
*/
extern void lcd_putc(char c);

/**
@brief Display string without auto linefeed
@param

s string to be displayed

@return none
*/
extern void lcd_puts(const char *s);

/**
@brief Display string from program memory without auto linefeed
@param

s string from program memory be be displayed

@return none
@see

lcd_puts_P

*/
extern void lcd_puts_p(const char *progmem_s);

/**
@brief Send LCD controller instruction command
@param

cmd instruction to send to LCD controller, see HD44780 data sheet

@return none
*/
extern void lcd_command(uint8_t cmd);

/**
@brief Send data byte to LCD controller

Similar to lcd_putc(), but without interpreting LF


@param

data byte to send to LCD controller, see HD44780 data sheet

@return none
*/
extern void lcd_data(uint8_t data);

/**
@brief Print a float number in LCD from http://extremeelectronics.co.in/avr-tutorials/using-module-with-avrs/
for example
lcd_writeFloat(68.198,3,2)

will display 068.19


@param val floating data, double type here
@param flbp field length before point
@param flap field length after point
@return none
*/

extern void lcd_writeFloat(double val, unsigned int flbp, unsigned int flap);

/**
@brief macros for automatically storing string constant in program memory
*/
#define lcd_puts_P(__s)

lcd_puts_p(PSTR(__s))

/*@}*/
#endif //LCD_H

Tabla 28: Librera lcd.h de Peter Fleury


Archivo lcd.c

/****************************************************************************
Title

: HD44780U LCD library

Author:

Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury

File:

$Id: lcd.c,v 1.14.2.2 2012/02/12 07:51:00 peter Exp $

Software: AVR-GCC 3.3


Target:

any AVR device, memory mapped mode only for AT90S4414/8515/Mega

DESCRIPTION
Basic routines for interfacing a HD44780U-based text lcd display

Originally based on Volker Oth's lcd library,


changed lcd_init(), added additional constants for lcd_command(),
added 4-bit I/O mode, improved and optimized code.

Library can be operated in memory mapped mode (LCD_IO_MODE=0) or in


4-bit IO port mode (LCD_IO_MODE=1). 8-bit IO port mode not supported.

Memory mapped mode compatible with Kanda STK200, but supports also
generation of R/W signal through A8 address line.

USAGE
See the C include lcd.h file for a description of each function

*****************************************************************************/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "lcd.h"

/*
** constants/macros
*/
#define DDR(x) (*(&x - 1))

/* address of data direction register of port x */

#if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)


/* on ATmega64/128 PINF is on port 0x00 and not 0x60 */
#define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) )
#else
#define PIN(x) (*(&x - 2))
#endif

/* address of input register of port x

*/

#if LCD_IO_MODE
#define lcd_e_delay() __asm__ __volatile__( "rjmp 1f \n 1:" ); //#define lcd_e_delay() __asm__ __volatile__( "rjmp 1f \n 1: rjmp 2f \n 2:" );
#define lcd_e_high()

LCD_E_PORT |= _BV(LCD_E_PIN);

#define lcd_e_low()

LCD_E_PORT &= ~_BV(LCD_E_PIN);

#define lcd_e_toggle() toggle_e()


#define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN)
#define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN)
#define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN)
#define lcd_rs_low()

LCD_RS_PORT &= ~_BV(LCD_RS_PIN)

#endif

#if LCD_IO_MODE
#if LCD_LINES==1
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE
#else
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES
#endif
#else
#if LCD_LINES==1
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE
#else
#define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES
#endif
#endif

#if LCD_CONTROLLER_KS0073
#if LCD_LINES==4

#define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x2C /* |0|010|1100 4-bit mode, extension-bit RE = 1 */


#define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x28 /* |0|010|1000 4-bit mode, extension-bit RE = 0 */
#define KS0073_4LINES_MODE

#endif
#endif

/*
** function prototypes
*/
#if LCD_IO_MODE
static void toggle_e(void);
#endif

/*

0x09 /* |0|000|1001 4 lines mode */

** local functions
*/

/*************************************************************************
delay loop for small accurate delays: 16-bit counter, 4 cycles/loop
*************************************************************************/
static inline void _delayFourCycles(unsigned int __count)
{
if ( __count == 0 )
__asm__ __volatile__( "rjmp 1f \n 1:" );

// 2 cycles

else
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t"
"brne 1b"

// 4 cycles/loop

: "=w" (__count)
: "0" (__count)
);
}

/*************************************************************************
delay for a minimum of <us> microseconds
the number of loops is calculated at compile-time from MCU clock frequency
*************************************************************************/
#define delay(us) _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 )

#if LCD_IO_MODE
/* toggle Enable Pin to initiate write */
static void toggle_e(void)
{
lcd_e_high();
lcd_e_delay();
lcd_e_low();
}
#endif

/*************************************************************************
Low-level function to write byte to LCD controller
Input:

data byte to write to LCD

rs

1: write data
0: write instruction

Returns: none
*************************************************************************/
#if LCD_IO_MODE
static void lcd_write(uint8_t data,uint8_t rs)
{
unsigned char dataBits ;

if (rs) { /* write data

(RS=1, RW=0) */

lcd_rs_high();
} else {

/* write instruction (RS=0, RW=0) */

lcd_rs_low();
}
lcd_rw_low();

if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT ==


&LCD_DATA3_PORT )
&& (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
{
/* configure data pins as output */
DDR(LCD_DATA0_PORT) |= 0x0F;

/* output high nibble first */


dataBits = LCD_DATA0_PORT & 0xF0;
LCD_DATA0_PORT = dataBits |((data>>4)&0x0F);
lcd_e_toggle();

/* output low nibble */


LCD_DATA0_PORT = dataBits | (data&0x0F);
lcd_e_toggle();

/* all data pins high (inactive) */


LCD_DATA0_PORT = dataBits | 0x0F;
}
else
{
/* configure data pins as output */
DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);

/* output high nibble first */


LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
lcd_e_toggle();

/* output low nibble */


LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
lcd_e_toggle();

/* all data pins high (inactive) */


LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
}
}
#else
#define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d;
/* rs==0 -> write instruction to LCD_IO_FUNCTION */
/* rs==1 -> write data to LCD_IO_DATA */
#endif

/*************************************************************************
Low-level function to read byte from LCD controller
Input:

rs

1: read data

0: read busy flag / address counter


Returns: byte read from LCD controller
*************************************************************************/

#if LCD_IO_MODE
static uint8_t lcd_read(uint8_t rs)
{
uint8_t data;

if (rs)
lcd_rs_high();

/* RS=1: read data

*/

else
lcd_rs_low();
lcd_rw_high();

/* RS=0: read busy flag */


/* RW=1 read mode

*/

if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT ==


&LCD_DATA3_PORT )
&& ( LCD_DATA0_PIN == 0 )&& (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
{
DDR(LCD_DATA0_PORT) &= 0xF0;

/* configure data pins as input */

lcd_e_high();
lcd_e_delay();
data = PIN(LCD_DATA0_PORT) << 4;

/* read high nibble first */

lcd_e_low();

lcd_e_delay();

/* Enable 500ns low

*/

lcd_e_high();
lcd_e_delay();
data |= PIN(LCD_DATA0_PORT)&0x0F;

/* read low nibble

*/

lcd_e_low();
}
else
{
/* configure data pins as input */
DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN);
DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN);
DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN);
DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN);

/* read high nibble first */


lcd_e_high();
lcd_e_delay();
data = 0;
if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10;

if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20;


if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40;
if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80;
lcd_e_low();

lcd_e_delay();

/* Enable 500ns low

*/

/* read low nibble */


lcd_e_high();
lcd_e_delay();
if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01;
if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02;
if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04;
if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08;
lcd_e_low();
}
return data;
}
#else
#define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ)
/* rs==0 -> read instruction from LCD_IO_FUNCTION */
/* rs==1 -> read data from LCD_IO_DATA */
#endif

/*************************************************************************
loops while lcd is busy, returns address counter
*************************************************************************/
static uint8_t lcd_waitbusy(void)

{
register uint8_t c;

/* wait until busy flag is cleared */


while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}

/* the address counter is updated 4us after the busy flag is cleared */
delay(2);

/* now read the address counter */


return (lcd_read(0)); // return address counter

}/* lcd_waitbusy */

/*************************************************************************
Move cursor to the start of next line or to the first line if the cursor
is already on the last line.
*************************************************************************/
static inline void lcd_newline(uint8_t pos)
{
register uint8_t addressCounter;

#if LCD_LINES==1
addressCounter = 0;
#endif
#if LCD_LINES==2
if ( pos < (LCD_START_LINE2) )
addressCounter = LCD_START_LINE2;
else
addressCounter = LCD_START_LINE1;
#endif
#if LCD_LINES==4
#if KS0073_4LINES_MODE
if ( pos < LCD_START_LINE2 )
addressCounter = LCD_START_LINE2;
else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3) )
addressCounter = LCD_START_LINE3;
else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) )
addressCounter = LCD_START_LINE4;
else
addressCounter = LCD_START_LINE1;
#else
if ( pos < LCD_START_LINE3 )
addressCounter = LCD_START_LINE2;
else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) )
addressCounter = LCD_START_LINE3;
else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) )
addressCounter = LCD_START_LINE4;
else
addressCounter = LCD_START_LINE1;
#endif
#endif
lcd_command((1<<LCD_DDRAM)+addressCounter);

}/* lcd_newline */

/*
** PUBLIC FUNCTIONS
*/

/*************************************************************************
Send LCD controller instruction command
Input: instruction to send to LCD controller, see HD44780 data sheet
Returns: none
*************************************************************************/
void lcd_command(uint8_t cmd)
{
lcd_waitbusy();
lcd_write(cmd,0);
}

/*************************************************************************
Send data byte to LCD controller
Input: data to send to LCD controller, see HD44780 data sheet
Returns: none
*************************************************************************/
void lcd_data(uint8_t data)
{
lcd_waitbusy();
lcd_write(data,1);
}

/*************************************************************************
Set cursor to specified position
Input:

x horizontal position (0: left most position)

y vertical position

(0: first line)

Returns: none
*************************************************************************/
void lcd_gotoxy(uint8_t x, uint8_t y)
{
#if LCD_LINES==1
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
#endif

#if LCD_LINES==2
if ( y==0 )
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
else
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
#endif
#if LCD_LINES==4
if ( y==0 )
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
else if ( y==1)
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
else if ( y==2)
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE3+x);
else /* y==3 */
lcd_command((1<<LCD_DDRAM)+LCD_START_LINE4+x);
#endif

}/* lcd_gotoxy */

/*************************************************************************
*************************************************************************/
int lcd_getxy(void)
{
return lcd_waitbusy();
}

/*************************************************************************
Clear display and set cursor to home position
*************************************************************************/
void lcd_clrscr(void)
{
lcd_command(1<<LCD_CLR);
}

/*************************************************************************
Set cursor to home position
*************************************************************************/
void lcd_home(void)
{
lcd_command(1<<LCD_HOME);

/*************************************************************************
Display character at current cursor position
Input:

character to be displayed

Returns: none
*************************************************************************/
void lcd_putc(char c)
{
uint8_t pos;

pos = lcd_waitbusy(); // read busy-flag and address counter


if (c=='\n')
{
lcd_newline(pos);
}
else
{
#if LCD_WRAP_LINES==1
#if LCD_LINES==1
if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
}
#elif LCD_LINES==2
if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);
}else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ){
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
}
#elif LCD_LINES==4
if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);
}else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE3,0);
}else if ( pos == LCD_START_LINE3+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE4,0);
}else if ( pos == LCD_START_LINE4+LCD_DISP_LENGTH ) {
lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
}
#endif
lcd_waitbusy();

#endif
lcd_write(c, 1);
}

}/* lcd_putc */

/*************************************************************************
Display string without auto linefeed
Input:

string to be displayed

Returns: none
*************************************************************************/
void lcd_puts(const char *s)
/* print string on lcd (no auto linefeed) */
{
register char c;

while ( (c = *s++) ) {
lcd_putc(c);
}

}/* lcd_puts */

/*************************************************************************
Display string from program memory without auto linefeed
Input:

string from program memory be be displayed

Returns: none
*************************************************************************/
void lcd_puts_p(const char *progmem_s)
/* print string from program memory on lcd (no auto linefeed) */
{
register char c;

while ( (c = pgm_read_byte(progmem_s++)) ) {
lcd_putc(c);
}

}/* lcd_puts_p */

/*************************************************************************
Initialize display and select type of cursor

Input:

dispAttr LCD_DISP_OFF
LCD_DISP_ON

display off
display on, cursor off

LCD_DISP_ON_CURSOR

display on, cursor on

LCD_DISP_CURSOR_BLINK display on, cursor on flashing


Returns: none
*************************************************************************/
void lcd_init(uint8_t dispAttr)
{
#if LCD_IO_MODE
/*
* Initialize LCD to 4 bit I/O mode
*/

if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT ==


&LCD_DATA3_PORT )
&& ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT)
&& (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)
&& (LCD_RS_PIN == 4 ) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6 ) )
{
/* configure all port bits as output (all LCD lines on same port) */
DDR(LCD_DATA0_PORT) |= 0x7F;
}
else if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT ==
&LCD_DATA3_PORT )
&& (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
{
/* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */
DDR(LCD_DATA0_PORT) |= 0x0F;
DDR(LCD_RS_PORT)

|= _BV(LCD_RS_PIN);

DDR(LCD_RW_PORT)

|= _BV(LCD_RW_PIN);

DDR(LCD_E_PORT)

|= _BV(LCD_E_PIN);

}
else
{
/* configure all port bits as output (LCD data and control lines on different ports */
DDR(LCD_RS_PORT)

|= _BV(LCD_RS_PIN);

DDR(LCD_RW_PORT)

|= _BV(LCD_RW_PIN);

DDR(LCD_E_PORT)

|= _BV(LCD_E_PIN);

DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
}
delay(16000);

/* wait 16ms or more after power-on

*/

/* initial write to lcd is 8bit */


LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // _BV(LCD_FUNCTION)>>4;
LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // _BV(LCD_FUNCTION_8BIT)>>4;
lcd_e_toggle();
delay(4992);

/* delay, busy flag can't be checked here */

/* repeat last command */


lcd_e_toggle();
delay(64);

/* delay, busy flag can't be checked here */

/* repeat last command a third time */


lcd_e_toggle();
delay(64);

/* delay, busy flag can't be checked here */

/* now configure for 4bit mode */


LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4
lcd_e_toggle();
delay(64);

/* some displays need this additional delay */

/* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */
#else
/*
* Initialize LCD to 8 bit memory mapped mode
*/

/* enable external SRAM (memory mapped lcd) and one wait state */
MCUCR = _BV(SRE) | _BV(SRW);

/* reset LCD */
delay(16000);

/* wait 16ms after power-on

*/

lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */


delay(4992);

/* wait 5ms

*/

lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */


delay(64);

/* wait 64us

*/

lcd_write(LCD_FUNCTION_8BIT_1LINE,0); /* function set: 8bit interface */


delay(64);

/* wait 64us

*/

#endif

#if KS0073_4LINES_MODE
/* Display with KS0073 controller requires special commands for enabling 4 line mode */
lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON);
lcd_command(KS0073_4LINES_MODE);

lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF);
#else
lcd_command(LCD_FUNCTION_DEFAULT);

/* function set: display lines */

#endif
lcd_command(LCD_DISP_OFF);
lcd_clrscr();

/* display off

/* display clear

lcd_command(LCD_MODE_DEFAULT);
lcd_command(dispAttr);

*/

*/
/* set entry mode

/* display/cursor control

*/
*/

}/* lcd_init */

Tabla 29: Librera lcd.c de Peter Fleury


La librera clk funciona como un medio para inicializar el preescalamiento del reloj de Sistema del
ATMega32u4, as como para ajustar el uso de la funcin _delay_ms(x), adems provee macros que
permiten la declaracin y uso de un puerto, tanto como para configurarlo, como para leerlo o escribirlo.

#ifndef CLK_H
#define CLK_H
/**
@defgroup atmega32u4_clk Prescaler_Macros
@code #include <clk.h> @endcode

@brief Macros para definir la frecuencia de oscilacion del reloj


principal
*/

/*@{*/

/**
* @name Definitions for MCU Clock Frequency
* Adapt the MCU clock frequency in Hz to your target.
* Revisa las paginas 37-39
*/

#define F_CPU 16000000L


#if F_CPU == 16000000L
#define ADC_PRESCALER 0x07 /**<Factor de division 128 F_ADC = 125kHz*/
#define CPU_PRESCALER 0x00
#elif F_CPU == 8000000L
#define ADC_PRESCALER 0x06 /**<Factor de division 64 F_ADC = 125kHz*/
#define CPU_PRESCALER 0x01
#elif F_CPU == 4000000L
#define ADC_PRESCALER 0x05 /**<Factor de division 32*/
#define CPU_PRESCALER 0x02
#elif F_CPU == 2000000L
#define ADC_PRESCALER 0x04 /**<Factor de division 16*/
#define CPU_PRESCALER 0x03
#elif F_CPU == 1000000L
#define ADC_PRESCALER 0x03 /**<Factor de division 8*/
#define CPU_PRESCALER 0x04
#else
#error "Teensyduino only supports 16, 8, 4, 2, 1 MHz. Please edit boards.txt"
#endif

/**
* @name Macros para sustituir el seteo de bits individuales
*/

#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=_BV(bit)) /**<Pone en set un bit*/


#define clrbit(sfr,bit) (_SFR_BYTE(sfr)&=~_BV(bit)) /**<Pone en clear un bit*/
#define togglebit(sfr,bit) (_SFR_BYTE(sfr)^=_BV(bit)) /**<Cambia el estado de bit*/
#define DDR(x) (*(&x -1))
#define PIN(x) (*(&x -2))

/**
* @name Functions
*/

/**
@brief Funcion para inicializar los tiempos en el ATMega32U4
@param

none

@return none
*/

void _init_Teensyduino_internal_(void);

void delay_ms(unsigned int time_ms);

/*@}*/
#endif //end clk.h

Tabla 30: Librera clk.h

#include "clk.h"
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include "clk.h"

void _init_Teensyduino_internal_(void)
{

cli();
CLKPR = 0x80;
CLKPR = CPU_PRESCALER;
}

void delay_ms(unsigned int time_ms)


{
unsigned int i;
for(i=0; i<time_ms; i++)
_delay_ms(1);
}

Tabla 31: Librera clk.c

Unidad 7
Programacin del microcontrolador con aplicaciones

Unidad 7 Programacin del microcontrolador con aplicaciones


7.1 Tcnicas de control de motores usando:
7.1.1 PWM
7.1.2 Encoders incrementales como sensor de velocidad, posicin y sentido de giro.
7.2 Control de sentido de giro, de posicin de velocidad en:
7.2.1 Motores de DC
7.2.2 Motores de pasos

Competencia especfica
Resolver problemas mediante la programacin del microcontrolador.
Conocer y conectar motores con microcontroladores.
Actividades de aprendizaje:

Mapa Conceptual: Catalogar mediante un mapa conceptual los usos de los puertos para manejo
de potencia con interfaces de transistores, Darlington, MOSFETS, relevadores,
Optoacopladores, puentes H discretos y de Circuito Integrado.

7.1 Tcnicas de control de motores usando:


7.1.1 PWM
Las notas que se presentan en esta seccin corresponden a NeoTeo (Mario, 2010)
Cuando trabajamos con motores de corriente continua no siempre las aplicaciones se limitan a una
funcin de marcha plena en alguno de los dos sentidos posibles (CW y CCW). En la mayora de los
diseos debemos controlar las revoluciones por minuto de los motores de acuerdo al desarrollo
efectuado y el sentido de giro que esta rotacin debe tener. Es por esto que, cuando necesitamos invertir
el movimiento mecnico del sistema debemos apelar a utilizar un puente H.
Una de las tcnicas ms efectivas para conectar o desconectar una carga a una fuente de energa
elctrica ha sido siempre la utilizacin de simples llaves interruptoras manuales, o un rel activado por
un circuito de control muy sencillo. Utilizar otros elementos para este trabajo (por ejemplo,
transistores), acarrean necesidades de clculos de corrientes a conmutar, tensiones de trabajo, y otras
variables que una llave o un rel resuelven sin inconvenientes ni consecuencias. Sin embargo, cuando
la aplicacin requiere el control variable de una carga, comenzamos a imaginar un restato enorme y
gigante, capaz de manejar muchos amperios y con la capacidad de disipar grandes cantidades de
temperatura. Por supuesto que as no se resuelve la situacin sino que se emplea una tcnica muy
sencilla y prctica llamada PWM.
ongamos como ejemplo que queremos hacer trabajar a un motor de 12Volts a la mitad de su rgimen
nominal. Lo primero que a muchos se le viene a la mente es aplicarle 6Volts de alimentacin. Sin
embargo, en la vida real, un motor de levalunas de coche, o un motor que impulsa una bomba de
lquido refrigerante en una maquinaria, que debe tener su temperatura de trabajo controlada, no seran
capaces de moverse del modo esperado al actuar de este modo. Muy por el contrario, quedaran
inmviles sufriendo un incremento notable de temperatura al ser atravesados por una corriente que no
logra movilizar el eje en rotacin debido a la carga que el motor tiene acoplada y debe impulsar. Si en
cambio aplicamos por un pequeo lapso de tiempo la tensin de alimentacin de 12Volts (la nominal
de trabajo del motor del ejemplo), ste comenzara a girar, o hara el intento de hacerlo, hasta volver a
detenerse.
Si aplicamos muchos impulsos en forma reiterada, es decir, conectar desconectar la alimentacin
varias veces en un segundo, el motor comenzara a girar y por la propia inercia del sistema acoplado
a su eje, se mantendra en marcha segn el rgimen de eventos de conexin desconexin que le
apliquemos durante un segundo. El mtodo PWM basa su funcionamiento en este principio. En
conectar de manera controlada y durante tiempos ajustables la alimentacin, en este ejemplo a un
motor, para de este modo poder variar la velocidad sin perder capacidad de traccin, o fuerza. Tambin
encontraremos algunos textos que utilicen el trmino torque para esta propiedad motriz. La mejor
manera entonces es disponer de una llave o rel controlados de manera inteligente y que conecten
desconecten la carga muchas veces en un segundo. Pero, cuntas veces es lo aconsejable?
Si aplicamos muchos impulsos en forma reiterada, es decir, conectar desconectar la
alimentacin varias veces en un segundo, el motor comenzara a girar y por la propia inercia del
sistema acoplado a su eje, se mantendra en marcha segn el rgimen de eventos de conexin
desconexin que le apliquemos durante un segundo. El mtodo PWM basa su funcionamiento en
este principio. En conectar de manera controlada y durante tiempos ajustables la alimentacin,
en este ejemplo a un motor, para de este modo poder variar la velocidad sin perder capacidad de

traccin, o fuerza. Tambin encontraremos algunos textos que utilicen el trmino torque para
esta propiedad motriz. La mejor manera entonces es disponer de una llave o rel controlados de
manera inteligente y que conecten desconecten la carga muchas veces en un segundo. Pero,
cuntas veces es lo aconsejable?

figura 66: Conmutando la alimentacin de una


carga podemos lograr un rgimen de trabajo
variable
En una aplicacin de iluminacin, si conmutamos (conectamos - desconectamos) la tensin de
alimentacin menos de 20 veces por segundo, podemos llegar a notar parpadeos molestos a la vista y
en el caso de un motor quizs podamos observar o percibir, un accionar muy irregular cual si fuese a
los golpes o con impulsos que pueden generar problemas mecnicos a largo plazo, adems de entregar
una marcha desagradable e incorrecta. Si en cambio elevamos la frecuencia de conmutacin por encima
de las 50 activaciones por segundo para lograr una marcha estable, caeremos en el problema de
comenzar a generar sonidos audibles provocados por el bobinado del motor. Recuerda que el
espectro de audicin humana se establece entre los 20 ciclos por segundo y los 20 mil. (20Hz.
20.000Hz.) Por supuesto que el bobinado de un motor no se comportar como un parlante o altavoz tan
efectivo como para abarcar toda esta gama de frecuencias con absoluta fidelidad, pero existirn
segmentos de resonancia donde algunas frecuencias hagan vibrar los bobinados ms que otras,
provocando
un
desagradable
sonido
que
no
debiera
existir.
Si analizamos este razonamiento, llegamos a la conclusin que para obtener un funcionamiento suave,
sin golpes, parpadeos ni sonidos extraos, debemos trabajar con frecuencias superiores a las que un
bobinado de motor pueda resonar. Estas frecuencias se ubican, en la mayora de los casos, por
encima de los 10Khz. Una vez encontrada la frecuencia apropiada de funcionamiento para nuestro
sistema, observaremos que quizs sean demasiadas conexiones en un segundo para la velocidad
mnima deseada. Digmoslo de este modo: es probable que el motor gire demasiado rpido y
nosotros necesitemos una velocidad menor. Bajar la frecuencia de conmutacin es impracticable
porque comenzaran los ruidos, entonces, qu opcin nos queda?: El PWM. Variar el ciclo de trabajo
de la seal conmutada que sirve de activacin del sistema. Manipular el ancho del impulso de
conexin
a
la
carga.
De este modo, podemos trabajar con frecuencias tan altas como 10Khz. y obtener un ancho de impulso

del 1% (o menor) de la seal. A medida que este ancho del impulso comienza a aumentar, la energa
promedio que se entrega a la carga tambin lo hace, pudiendo ser calculada y controlada de manera
muy precisa. En el caso de utilizar un microcontrolador, obtendremos mediante su programacin, una
secuencia de unos y ceros que respetarn una frecuencia fija pero que pueden tener un ciclo de
trabajo variable. Este trmino, tambin conocido como Duty, har variar el ancho del impulso de
conexin para obtener as un funcionamiento controlado desde la detencin absoluta hasta la marcha a
mxima potencia. Para esto, dentro de la programacin del microcontrolador, asignaremos una variable
al ciclo de trabajo o duty, que ser del tipo BYTE y podr adquirir valores entre 0 y 255. Para un duty
igual a cero, el motor estar detenido. Lo mismo que para un valor de 1 o 2. A pesar de ser impulsos
enviados al motor que poseen su tensin nominal de trabajo y que se ejecutan a una frecuencia de ms
de 10Khz., no tendrn el ancho suficiente para entregar la energa necesaria que el motor necesitara
para comenzar a girar, o la luminaria comenzar a encender.

figura 67: Acumulacin de tiempos controlable


por microcontrolador
Si en cambio incrementamos el valor de la variable duty a 100, la relacin ser 100/255 = 0,392 = 39%.
Con este nivel de energa aplicada al motor podemos llegar a alcanzar el esfuerzo suficiente como para
movilizarlo y mantenerlo funcionando en un rgimen aproximado al 40% de la velocidad mxima. Por
otro lado, debemos tener en claro que al momento de realizar un programa dentro de un
microcontrolador, el desarrollador puede dar marcha al sistema con un duty mximo (255) durante
algunos instantes para obtener un arranque a mxima potencia para luego descender de manera
suave y progresiva al 40% antes elegido, o tambin puede hacerlo de manera abrupta, de un instante a
otro, aprovechando que no se notar una disminucin brusca en la velocidad gracias a la inercia
mecnica del sistema acoplado al eje del motor. Para el caso de una luminaria, esta variacin brusca no
podr disimularse, pero si el arranque a un duty mximo es lo suficientemente corto, el fenmeno no
alcanzar a notarse. De todos modos, en el caso de las luminarias siempre ser deseable iniciar con baja
potencia para luego incrementarla, es decir, a la inversa de los motores elctricos. Por lo tanto, el PWM
es una herramienta que posee el desarrollador/programador para variar el rgimen de trabajo de
motores o luminarias con la mayor eficiencia posible.
Para el tipo de conmutacin mencionado hasta aqu y para obtener un funcionamiento satisfactorio a
una frecuencia tan elevada, una llave mecnica o un rel se vuelven imposibles de utilizar. Es aqu
donde hace su presentacin el IRFZ44N. Qu es el IRFZ44N? Es un transistor de tecnologa MOSFET (MetalOxideSemiconductor Field Effect Transistor) que posee destacadas caractersticas que
lo hacen ideal para este tipo de aplicaciones. Queremos tambin aclarar que PWM se puede realizar

con transistores bipolares (NPN - PNP), con tiristores, triacs, o IGBT segn la conveniencia de la
aplicacin, es decir, el PWM no se hace slo con un transistor MOS-FET como veremos ahora sino
que puedes encontrar aplicaciones que utilizan sistemas electrnicos de conmutacin muy variados y
como mencionamos antes, ajustables a las necesidades de la aplicacin.

figura 68: El IRFZ44N en su hoja de datos


Entre las caractersticas ms destacadas de este transistor encontramos que es capaz de manejar
corrientes de hasta 50 Amperes ofreciendo una resistencia tan baja como 0,017 Ohms. Esto permite
un rgimen de trabajo extraordinario ya que trabajando al mximo de sus posibilidades no desarrollar
una potencia mayor a los 45 Watts. Nada extraordinario para un generoso disipador que pueda irradiar
el calor generado por semejante corriente circulando a travs del dispositivo. Para que tengas una idea,
trabajando con 12 Volts, una lmpara incandescente de 100W consumir 8,33 Amperes. Es decir, la
sexta parte de sus posibilidades extremas y claro est, a 100W, es decir, a la potencia mxima o a un
duty
de
255.
Una sencilla y prctica explicacin del funcionamiento de un transistor MOS-FET puede resumirse a
comprender el comportamiento de la circulacin de corriente dentro del transistor. Al aplicar una
determinada tensin sobre la compuerta, puerta o Gate (positiva respecto a GND), se genera dentro
del transistor un campo elctrico que permite la circulacin de corriente entre el terminal identificado
como Drain y el terminal Source. Tan simple como eso. Al aplicar tensin al Gate, el campo elctrico
aporta huecos o lagunas, hecho que favorece y activa la circulacin de electrones entre Drain y
Source. Cuando la tensin en Gate se interrumpe o se coloca a un bajo potencial, la corriente entre
Drain y Source se interrumpe. Tenemos de este modo una llave electrnica comandada por tensin
(no por corriente, atentos a este punto) que no tendr inconvenientes en conmutar a frecuencias tan
altas como las que necesitamos para controlar una carga.

figura 69: Efecto del voltaje Vgs en un


MOSFET
La tensin mnima de Gate para que el transistor comience a conducir (segn su hoja de datos que
encontrars al final del artculo) est ubicada entre 2 y 4 Volts mientras que la mxima tensin aplicable
respecto al terminal Source, es de 20 Volts. Con 10 Volts de tensin sobre el Gate el transistor alcanza
la mnima resistencia entre Drain y Source. Si se sobrepasa la tensin Vgs (tensin de Gate respecto a
Source) mxima de 20 Volts el transistor se rompe y si no se alcanza la tensin mnima de 2 a 4 Volts,
el transistor no entra en conduccin. Una situacin a destacar es que si trabajamos siempre con 5
Volts, estaremos sobre el lmite de activacin del transistor, mientras que si trabajamos con mayor
tensin sobre el Gate lograremos un mejor desempeo con menor disipacin de calor al ofrecer menor
resistencia a la circulacin de corriente entre Drain y Source.

figura 70: Fotografa de IRFZ44N


Otro de los detalles importantes a considerar en un diseo que utilice PWM con un MOS-FET es el
manejo de los tiempos y las formas de los flancos de subida y bajada de la seal aplicada al Gate. No
respetar con fidelidad la forma de onda con la que se debe activar el Gate de un MOS-FET puede
llevarte a disipaciones anormales de temperatura y funcionamientos al lmite de los mrgenes de
seguridad trmica. El circuito mostrado permite un ptimo trabajo del transistor. En cambio, si la
alimentacin desciende a 5 Volts (puede suceder por diseo) la resistencia de Gate debe bajar a
valores entre 2,2 y 5 Ohm ya que la tensin de activacin del Gate estar al lmite de los valores

mnimos de operacin. Recuerda observar siempre la hoja de datos para lograr un diseo apropiado.

figura 71: Circuito de Aplicacin


Con esta sencilla aplicacin puedes controlar la intensidad de iluminacin, la velocidad de motores
para tu robot o tu prxima CNC sin mayores inconvenientes. Cambiando los valores de una simple
variable BYTE dentro de un microcontrolador, tienes el problema resuelto. Tu genialidad, creatividad e
imaginacin, determinarn el mtodo a aplicar para realizar la tarea de control dentro del programa.
Mientras tanto, ya tienes algo muy importante: El hardware y la explicacin de su funcionamiento
aplicando el IRFZ44N, un transistor que puede brindarte infinitas satisfacciones si lo utilizas de manera
correcta como hemos visto en este artculo. Ya has pensado en que aplicars el PWM? En
iluminacin? En motores?

7.1.1.1 Configurando el PWM en el ATMega32U4 con el Timer 0

El modo Fast PWM (3 o 7) es una opcin para generar una forma de onda PWM de alta frecuencia,
esta opcin difiere de otras formas de generar ondas PWMya que es una operacin de una sola rampa.
En este modo el contador va de BOTTOM hacia TOP, quedando de la siguiente forma:
TOP = 0xFF

cuando WGM3:0 = 3

TOP = OCRX cuando WMG3:0 = 7


En el modo de comparacin a la salida no Inversora, el pin de salida OCx es igual a cero cuando son
iguales los registros TCNT0 y OCRX y puesto en uno cuando se llega al valor BOTTOM.
Se considera importante mencionar que la frecuencia de funcionamiento pueda ser el doble de la
frecuencia generada por el modo PWM de fase correcta.
La alta frecuencia de operacin de este modo, permite su uso eficaz en aplicaciones tales como:

Regulacin de potencia

Rectificacin

Conversin Digital a analgica

De la grfica siguiente, en el modo complemento, si OCRx = TOP, los bits de salida estarn en estado
bajo. Conforme decrece el valor de OCRx, el tiempo de permanencia en alto del pin OCn ser mayor.
Todo lo contrario suceder para el modo no complementario.

La frecuencia PWM de salida puede ser calculada de la siguiente manera


f OC

nxPWM

f clk I/ O
N256

Ejemplo: Usando el modo PWM FAST generar una seal pwm cuya frecuencia sea superior a 20kHz,
suponga que el reloj del sistema est 8 Mhz
Primero determinamos el valor del preescalador que se utilizar para un valor supuesto de frecuencia
deseada, este valor se puede determinar a partir de la expresin siguiente:
N=

f clk I /O
8 MHz
=
1.42
f deseada256 (22 kHz)(256)

Para este caso, se debe redondear N = 1, con lo cual se obtiene una frecuencia de salida de
f OC

xPWM

8 MHz
=31.25 kHz
256

En el siguiente ejemplo se muestra la codificacin para generar seales de tipo PWM con el Timer 0 y
el Timer 1

/*
*/

#include "clk.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include "timer0/timer0.h"
#include "timer1/timer1.h"

int main(void)
{
_init_Teensyduino_internal_();
// Insert code
delay_ms(100);
setbit(DDRB,0); //led verde
setbit(DDRD,0); //OC0B
setbit(DDRB,6); //OC1B
setbit(DDRB,5); //OC1A

/*
configuracion del timer 1
Modo de operacion: FAST PWM (5)
Resolucion: 8 bits
Factor de prescalamiento: 1024
Comportamiento de OC1A: No inversor
Frecuencia de PWM = F_CPU/(N(1+TOP)) = 1Mhz/(1024(1+255) = 3.81Hz
Periodo de PWM = 1/Freq de PWM = 262.14ms
Ciclo de trabajo = 39% = OCR1A*100/TOP
timer1_setup(5,1024,3,3,0);
OCR1A = 100;
*/
timer1_setup(5,1024,2,2,0); //modo PWM de 8 bit frecuencia de 3906.25Hz PB5
OCR1A = 100;
OCR1B = 255;

/*
configuracion del timer 0 (2)
Modo de operacion: CTC
Factor de Prescalamiento: 1024
Valor de Precarga: 99 (OCR0A)

Periodo de AutoReset: 101.3 ms


F_CPU: 1MHz
Tiempo = N(OCR0B+1)/F_CPU
COM0A = 0 (SE DESCONECTA LA SALIDA DEL WMG AL PIN OC0A)
COM0B = 1 (CAMBIA DE ESTADO CADA VEZ QUE DESBORDA)
*/
timer0_setup(2,1,0,1); //modo CTC interrupcion en PD0
OCR0A = 99;

while(1)
{
togglebit(PORTB,0);
delay_ms(1000);
}

return 0;
}

Tabla 32: Cdigo configuracin de timers con PWM

7.1.2 Encoders incrementales como sensor de velocidad y sentido de giroscopio


Un elemento imprescindible a la hora de controlar un servosistema es el la realimentacin de posicin y
velocidad (Motion Control, 2010).
Cierto es que existen sistemas (variadores pricipalmente) que funcionan sin realimentacin de posicin
(lazo abierto) , pero dichos variadores se utilizan bsicamente para control de velocidad o par. Para un
control preciso de velocidad y posicin, la realimentacin del motor o la carga hacia el dispositivo de
control, es absolutamente necesaria.
Encoder o Resolver?
Generalmente utilizamos el trmino ingls encoder para referirnos al sistema de realimentacin.
Cabe decir, que existen gran variedad de encoders: rotativos, llineales, incrementales, absolutos, semiabsolutos, y de hecho en muchas ocasiones hablamos de encoder cuando en realidad lo que
tenemos es un resolver.
La diferencia fundamental entre encoder y resolver estriba en que el primero es un sistema digital y el
segundo un sistema analgico.
-El encoder rotativo normalmente consta de un disco fijado al eje del motor, con una serie de marcas
(normalmente codificadas en gray para minimizar errores), y un dispositivo optico capaz de leer dichas
marcas. La combinacin binaria de la lectura de dichas marcas nos dar como resultado la posicin del
rotor respecto al estator. Posteriormente y segn el tipo de encoger, esta informacin ser codificada y
transmitida al servoamplificador o controlador de movimiento.
En su versin ms simple el encoder nos enviar dos trenes de pulsos con un desfase conocido,
contando los pulsos podremos saber la posicin del motor y examinando qu fase es la primera,
podremos saber la direccin, es el tipico encoder de cuadratura A,/A, B, /B. Normalmente una seal
adicional Z,/Z nos informar de una marca nica en el disco que servir para definir el origen (Homing)
-El resolver (rotativo), es un sistema analgico, grosso modo lo que nos est enviando es el voltaje
inducido de dos espiras, que por razones constructivas daran como resultado dos senoides (en lugar de
pulsos digitales aqu tenemos una senoide), examinando la senoide podremos conocer la posicin, y
examinando el desfase la direccin.
Hoy en da se utilizan tanto resolvers como encoders. Tradicionalmente el resolver se ha considerado
ms robusto desde el punto de vista mecnico, pero al tratarse de una seal analgica es ms sensible
desde el punto de vista electromagntico. El encoder a su vez es ms sensible desde el punto de vista
mecnico: fuerzas excesivas perpendiculares al eje pueden daar el disco lector, pero en sus versiones
ms avanzadas codifica los datos digitalmente por lo que la deteccin y correccin de errores de
comunicacin es posible a nivel de protocolo.
Creo que existe ifinidad de literatura respecto al encoder de cuadratura y el resolver, por lo que no me
extender ms y os referencio a : http://es.wikipedia.org/wiki/Codificador_rotatorio para ms
informacin.
En este artculo mi intencin es no tanto explicar qu es un encoder o un resolver (para eso est la
Wiki), sin hacer un pequeo repaso de los diferentes tipos de encoders y protocolos y su campo de
aplicacin.
Encoder incremental o absoluto?
La respuesta est clara: Absoluto ! Siempre que el presupuesto nos lo permita.

El encoder incremental nos informa de los incrementos de posicin y a cada vuelta nos enva una
marca especial Z que utilizaremos para referenciar o hacer el Homing de una mquina.
Qu es el Homing?
Lo razonable es dedicar uno o ms artculos al Homing, aqu slo mencionar que el homing es una
secuencia inicial para cualquier sistema de posicionado en el que el controlador necesita conocer la
posicin absoluta del motor respecto a la mquina.
Imaginemos una mesa rotativa, con posiciones de trabajo situadas a 90, y 180 grados respectivamente
respecto al punto en el que depositamos la pieza que queremos manipular (Posicin 0)
Al poner en marcha la mquina, el controlador de movimiento necesita saber, cual es la posicin actual
del eje del motor, respecto de la posicin 0 de la mquina, para ello, si no se dispone de un encoder
absoluto el controlador comandar uno o varios movimientos al eje, hasta que pueda detectar la marca
Z.
Posiblemente la marca Z no estar en la posicin 0 de la mquina, pero una vez detectada la seal
Z del encoder motor solidario a la mesa (imaginemos que se ha pasado 37 del cero de mquina) ,
podremos podremos referenciar el sistema y decirle al motor, muvase 37 en sentido contratio, pues
ese es el cero de la mquina y donde debe colocarse usted para recibir la primera pieza a trabajar.
El ejemplo que he expuesto es muy simplificado (sera el caso de un direct-drive) sin transmisin
alguna entre motor y mesa, por tanto una revolucin de motor, correspondera con una revolucin de la
mesa. En la mayora de los casos nos encontraremos con transmisiones intermedias, por lo que una
revolucin de motor no corresponder con una revolucin de mesa, en este caso, se utilizan seales
adicionales (sensor de proximidad) para determinar la posicin.

Encoder Incremental
Los encoders incrementales son probablemente el tipo ms comn de encoder utilizado en la industria,
por
la
gran
variedad
de
aplicaciones
que
su
uso
abarcan.
Cada encoder incremental tiene en su interior un disco, marcado con una serie de lneas uniformes a

travs de una nica pista alrededor de su permetro, las lneas impermeables a la luz de anchura igual a
los huecos transparentes, trabajando con una unidad emisora de luz y una unidad de captacin de la
misma, al girar el disco, generan unas seales que debidamente tratadas proporcionan las seales de
salida de un encoder incremental.
Las seales de salida de un encoder pueden ser un tren de impulsos, en forma de seal cuadrada, donde
el nmero de impulsos que se generarn en una vuelta coincidir con el nmero de impulsos del disco
en el interior del encoder, nos referimos a encoders de un solo canal (seal A).
Una segunda seal (seal B) suministra un tren de impulsos idntico al que suministra la seal A pero
desfasada 90 respecto de esta, nos referimos al encoder de dos canales.
Tambin cabe la posibilidad de una seal de referencia o cero que proporciona un pulso a cada vuelta,
esta seal puede sincronizarse respecto de la seal A (A+0), respecto la seal B (A+B+0) o respecto a
ambas.
Encoder Absoluto, y Absoluto multi-vuelta
En un sistema con encoder absoluto, no es necesario realizar la secuencia de Homing, puesto que al
poner en marcha la mquina y sin necesidad de movimiento alguno, el encoder del motor informar al
controlador de su posicin: Estoy en la posicin 37.
El encoder absoluto necesita de algn mecanismo mecnico o electrnico para memorizar su posicin:
dentro de una revolucin del motor. Muy habitualmente cuando hablamos de un encoder absoluto, en
realidad se trata de un encoder absoluto-multivuelta, pues en muchas aplicaciones necesitamos conocer
no slo la posicin absoluta dentro de una vuelta, tambin en nmero de vueltas que ha dado el motor,
para poder determinar la posicin absoluta.
Tradicionalmente existen dos enfoques a la hora de implementar un encoder absoluto multivuelta:
-Un
sistema
mecnico
de
discos
(algo
as
-Una batera capaz de mantener la posicin durante varios aos

como

un

reloj

suizo)

La ventaja est clara: con un encoder absoluto no es necesario ningn movimiento para determinar la
posicin del motor, por lo que se gana tiempo en el arranque de la mquina y se evitan movimientos
inconvenientes para algunas mquinas.
Contrapartida: Un encoder incremental resulta ms econmico.
En el caso de encoders absolutos multivuelta con batera, debemos ser conscientes de que desconectar
la batera implicar perder la posicin absoluta
Full-close loop encoder
El encoder en s mismo, lo que nos da es una realimentacin de posicin.
El servoamplificador derivar la posicin respecto al tiempo para calcular la velocidad.
Como ya se coment en artculos anteriores, el amplificador necesita la realimentacin del encoder
para poder cerrar el lazo de velocidad y efectuar un buen control vectorial.
Normalmente la misma seal de encoder es retransmitida al controlador de posicin para cerrar el lazo
de posicin y/o controlar la desviacin (error).
En ocasiones ser necesario utilizar un encoder adicional para cerrar el lazo de posicin e ignorar el
encoder del motor.
Tpicamente esto ocurre cuando:
-La mecnica entre el motor y la carga es mala o complicada (resulta ms sencillo utilizar un

encoder adicional cerca de la carga, y evitar toda la cadena cinemtica entre motor y carga
-Aplicaciones en las que positivamente sabemos que existen variaciones difcilmente controlables entre
la posicin del motor y la carga: p.e. cuando la carga desliza sobre rodillos, a veces es mejor leer la
posicin con una encoder en contacto directo con la carga.
La utilizacin de este tipo de encoder adicional, se conoce como full-close loop feedback, aunque
dependiendo del fabricante puede tener nombres comerciales diferentes.
Encoder rotativo y encoder lineal
En gran numero de ocasiones el movimiento rotativo del motor se traduce en un movimiento lineal.
A raz de que que los ciclos de trabajo se han vuelto ms exigentes (mayor productividad) y la demanda
de precisin (mayor calidad), cada vez sn ms las aplicaciones que integran motores lineales en lugar
de utilizar motores rotativos que posteriormente pirden eficiencia y precisin al transformarse en un
movimiento lineal, p.e. tornillo sin fin.
Cabe decir que hay dos grandes familias de motores lineales:
-Motores lineales montados sobre guas : El motor (o los imanes) se desliza sobre guas (sliders) a
gran velocidad varios m/s, con aceleraciones de varios g y con una precisin sub-micra. (No se trata
de cincia ficcin, esta tecnologa existe y ha evolucionado mucho en los ltimos aos: Si teneis
alguna de TV pantalla plana 32 o ms en casa, con toda seguridad os digo que se han utilizado este
tipo de motores tanto en su fabricacin como en su control de calidad, demasiados pxels y demasiada
precisin para un motor convencional), otro mercado habitual para este tipo de motor es el del semiconductor y, en los ltimos aos est generalizando su uso en la fabricacin de paneles fotovoltaicos.
En los ltimos tiempos se estn empezando a utilizar este tipo de motores en otros sectores, como el
embalage, la manipulacin y conformacin de objetos, etc, el motivo es claro: calidad y velocidad!
En configuraciones ms avanzada estos motores pueden trabajar cooperando sobre la misma gua, o en
tandem paralelo p.e. puentes grua, o en conformaciones cartesianas XY, XYZ, XYZ+R (R=motor
rotativo)
-Motores lineales con eje cilndico (motores lineales de fuerza): Existen varios nombres comerciales
para este tipo de motor, pero en mi opinin la caracterstica comn a todos estos motores es que
reemplazan la funcin de un cilndro pneumtico. Este tipo de motor acostumbra a tener un eje
cilndico en su interior, se trata efectivamente de un motor lineal, y su caracterstica principal no es
tanto la precisin como la fuerza que pueden desarrollar. Este tipo de motores tiene un recorrido
(strocke) limitado comparado con el primer tipo de motores que pueden alcanzar varios metros de
longitud.
Los encoders lineales son la evolucin de las escalas lineales, ahora ya no hablamos de milmetros sin
de sub-micras de precisin, este tipo de encoders sn utilizados en motores con guas, (los motores
lineales cilndicos acostumbran a tener su propio encoder integrado).
Estos encoders tienen una serie de marcas equidistantes que un sensor ptico o magntico puede leer.
Resulta interesante el caso de los encoders lineales semi-absolutos o de marcas codificadas. Este tipo
de encoder es muy ingenioso, ya que utiliza marcas no equidistantes, estas estn separadas siguiendo
un patron numrico (generalmente dos series numricas superpuestas), de manera que la distancia entre
dos marcas es nica, por tanto leyendo dos marcas consecutivas podemos saber la posicin absoluta. Su
utilizacin resulta muy interesante en guas lineales de varios metros, o p.e, cuando varios motores
colaboran en una misma gua lineal.
En pocas palabras, tenemos sistemas de realimentacin de posicin (velocidad) que en funcin de :

Su principio fsico de funcionamiento sern:


-Resolvers
-Encoders (digitales)
Su capacidad de reverenciarse:
-Incrementales
-Absolutos (Absolutos multi-vuelta) ya sea mediante mecnica o electrnica con batera.
La naturaleza del motor a utilizar:
-Rotativos
-Incrementales

(analgicos)

7.2 Control de sentido de giro, de posicin y de velocidad


Para iniciar este tema, se colocar un ejemplo de control de los timers 0 y 1 del un microcontrolador
ATMega48 para generar seales PWM y de temporizado, que mas adelante podrn ser usadas para el
control de sentido de giro, posicin y de velocidad de motores
El circuito es el siguiente

figura 72: Circuito para generar PWM en ATMega48


El cdigo fuente se coloca a continuacin

#include <avr/io.h>
#include <avr/interrupt.h>
#include "timer1.h"
#include "timer0.h"
ISR(TIMER1_COMPA_vect)
{
PORTD^=(1 << PD5);
}
ISR(TIMER0_COMPA_vect)
{
PORTD^=(1 << PD2);
}
int main(void)
{
// Insert code
DDRD|=(1<<DDD5); //salida del Timer 1
DDRD|=(1<<DDD2); //salida del Timer 0
DDRB|=(1<<DDB1); //salida OC1A
/*
configuracion del timer 1
Modo de operacion: CTC (4)
Factor de Prescalamiento: 1
Valor de Precarga: 0x54B0 (OCR1A)
Periodo de AutoReset: 21.68ms
F_CPU = 1MHz
Tiempo = N(OCR1A+1)/F_CPU
Se habilita salida del OC1A
*/
timer1_setup(4,1,3,0,0);
/*
configuracion del timer 1
Modo de operacion: FAST PWM (5)
Factor de prescalamiento: 1
Comportamiento de OC1A: No inversor
Frecuencia de PWM = F_CPU/(N(1+TOP)) = 1Mhz/(1(1+255) = 3.9kHz
Periodo de PWM = 1/Freq de PWM = 256 us
Ciclo de trabajo = 39% = OCR1A*100/TOP
timer1_setup(5,1,2,0,0);
OCR1A = 100;
*/
OCR1A=100;
TIMSK1|=(1<<OCIE1A); //interrupcion por comparacion en modulo A
/*
configuracion del timer 0
Modo de operacion: CTC
Factor de Prescalamiento: 1024
Valor de Precarga: 99 (OCR0A)
Periodo de AutoReset: 101.3 ms
F_CPU: 1MHz
Tiempo = N(OCR0A+1)/F_CPU
*/
timer0_setup(4,64,0,0);
OCR0A=99;
TIMSK0|=(1<<OCIE0A); //interrupcion por comparacion en modulo A
sei();
while(1)
;

return 0;

Tabla 33: Cdigo para la configuracin de timers

7.2.1 Motores de corriente directamente


Ejemplo.- Elabora un programa para el microcontrolador ATMega32U4 permita el control de paro y
arranque de un motor de corriente directa (usando interrupciones), a travs de un circuito L293, ademas
de que tenga control sobre la rotacin y sobre la velocidad del motor (con modo FAST PWM del
temporizador 0). Siga el diagrama de conexiones que se muestra a continuacin

figura 73: circuito para control PWM de motor DC con L293D

Cdigo fuente de ejemplo


/*
*/
#define F_CPU 8000000L

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <clk.h>
#include <timer0/timer0.h>

#define start 0
#define pstart PORTB
#define stop 1
#define pstop PORTB
#define Vplus 4
#define pVplus PORTD
#define Vminus 6
#define pVminus PORTD

typedef enum {FALSE, TRUE} boolean ;


boolean Derecha = TRUE;
unsigned char velocidad=0;

ISR(INT0_vect)
{
Derecha = FALSE;
}

ISR(INT1_vect)
{
Derecha = TRUE;
}

void M_adelante(unsigned char pwm);


void M_reversa(unsigned char pwm);
void motor_init(void);
void setVelocidad(void);
void board_init(void);

int main(void)
{

// Insert code
_init_Teensyduino_internal_();
delay_ms(100);
velocidad = 0;
motor_init();
board_init();

while(1)
{
if((bit_is_clear(pstart,start) && bit_is_set(pstop,stop))== TRUE)
{
while(bit_is_set(pstop,stop))
{
while(Derecha == FALSE && bit_is_set(pstop,stop))
{
setVelocidad();
}
while(Derecha == TRUE && bit_is_set(pstop,stop))
{
setVelocidad();
}
}
}
}

return 0;
}

void M_adelante(unsigned char pwm)


{
OCR0A = 0;
OCR0B = pwm;
}

void M_reversa(unsigned char pwm)


{
OCR0A = pwm;
OCR0B = 0;

void motor_init()
{
//Configure para salida PWM Inversa
//Ajuste OCxx en Comparacion, limpia el timer en sobreflujo
//Contador desde 0 hasta 255
//Ciclo de reloj 8MHz Prescalamiento = 1
timer0_setup(3,1,3,3);

//inicializa todos los PWM al 0% de ciclo de trabajo


OCR0A = OCR0B = 0;

//Ajusta los pines PWM como salidas digitales


DDRD |= (1<<DDD0);
DDRB |= (1<<DDB7);
}

void setVelocidad(void)
{
if(bit_is_clear(pVplus,Vplus) == TRUE)
{
delay_ms(20);
velocidad++;
}
if(bit_is_clear(pVminus,Vminus)== TRUE)
{
delay_ms(20);
velocidad--;
}
}

void board_init(void)
{
DDRB &= ~(1<<PB0);
DDRB &= ~(1<<PB1);
DDRD &= ~(1<<PD4);
DDRD &= ~(1<<PD6);
DDRD &= ~(1<<PD1);
DDRD &= ~(1<<PD2);

//Habilitando las pullups


PORTB |= (1<<PB0); //start

PORTB |= (1<<PB1); //stop


PORTD |= (1<<PD4); //Vplus
PORTD |= (1<<PD6); //Vminus
PORTD |= (1<<PD1); //Derecha
PORTD |= (1<<PD2); //Izquierda

Tabla 34: Cdigo control PWM de puente H

Ejercicio.- Agregue al diagrama una pantalla LCD y que en ella se muestre la velocidad del motor en
trminos de porcentaje, considere el siguiente diagrama de estados:

figura 74: Diagrama de estados para prctica con PWM


En la siguiente figura se muestra una fotografa del circuito funcionando

figura 75: Funcionamiento de PWM con motor DC

7.2.2 Motores de pasos


Una descripcin de los motores a pasos podr encontrarse en la seccin 5.5.2 Motores a pasos donde se
describen a grosso modo las caractersticas de los motores a pasos.
7.2.2.1 Clculo de la potencia disipada en un controlador MOSFET para un motor a
pasos usando la tcnica de medios pasos

Resumen
En el presente trabajo se muestra el clculo de disipacin de potencia en los transistores de las ramas
superiores de un puente H cuando se controla un motor a pasos, desde un enfoque de disipacin de la
energa.
Desarrollo. Considere un motor a pasos cuyas caractersticas se encuentran definidas por:
Caractersticas del motor a pasos
Rfase = 0.29
MMOTOR = 3.2 Nm
Lfase = 1.7 mH
Ifase = 6 A
Paso = 1.8
Inercia = 1000 gcm2
VNOM = 1.74 V
Para determinar la potencia disipada en el motor por sobre-Tensin, primero se debe considerar la
siguiente forma de onda de corriente, en la cual se describen los tiempos donde se suministra energa a
los embobinados del motor a pasos:
donde
Tr.- Corresponde al tiempo que tarda la bobina del motor en alcanzar la corriente mxima (IL).
TLD.- Tiempo en el que la bobina permanece en el valor mximo de corriente.
Nota.- Si se usan medios pasos. Cada bobina est excitada 3 pasos y un cuarto descansa. La duracin
de cada paso viene dada por la ecuacin:
T LD =3T (paso)T r
Para ser mas claro en cuanto a este trmino observe la tabla Tabla 35: Secuencia de energizacin de
bobinas de motor bipolar en medios pasos, en la cual las letras de A,..D corresponden a las bobinas y el
nmero uno, corresponde a su estado excitado:

PASO

Tabla 35: Secuencia de energizacin de bobinas de motor bipolar en medios pasos


Las reas en gris de la tabla corresponden a la energizacin de las bobinas del motor a pasos bipolar.
Otra forma de visualizar la tabla anterior, refirase a la figura 76: Secuencia de activacin en bobina:

figura 76: Secuencia de activacin en


bobina
Tf y Td.- Corresponden al tiempo de cada y de carga nula. Considera que Tf +Td es el tiempo donde la
bobina no est excitada.
Chopping Period.- Es el periodo de troceo que genera el driver para limitar la corriente en las bobinas,
de acuerdo a la hoja de datos del circuito L297, la frecuencia del troceo (chopping) de la corriente es:
f switch =

1
0.7 RC

Un trmino ms a considerar es el del tiempo de conmutacin del MOSFET controlador del motor, la
cual se define como TCOM
7.4.2.2 Clculo de la energa disipada durante el tiempo Tr
La ecuacin siguiente define la energa que disipa un transistor MOSFET que se encuentra conectado a
una bobina:

EOFF /ON =[R DS (ON )I 2LT r ]2/ 3 [Joules]1


a saber que la potencia se puede expresar como el producto de la corriente al cuadrado por la
Resistencia del total del sistema y que la potencia al multiplicarse por el tiempo, se obtiene la energa.
Luego se considera que la constante de tiempo del motor se define mediante
=Lfase / Rmotor
Si consideramos en esta ecuacin el valor de las resistencias de los MOSFET cuando estn saturados,
se tiene entonces que, para que este circuito alcance el estado estable, el tiempo queda determinado por
la ecuacin:

T estable3 3

L fase
R FASE +2R DS (ON)

considera la siguiente imagen en la figura 77: Circuito equivalente de bobina en Tr, que corresponde al
modelo elctrico de las ecuaciones anteriormente descritas.

figura
77:
Circuito
equivalente de bobina en Tr
Este sistema, debido a sus caractersticas debe ser alimentado por una fuente de alimentacin cuyo
valor,es mayor que el definido por el parmetro VNOM. Elaborando una aproximacin y considerando
que el embobinado se comporta como un cortocircuito en DC (Referencia de libro fundamentos de
analisis de circuitos electricos de Alexander) entonces se tiene que
di
+ R i=V alimentacin como el voltaje aplicado a las terminales de la bobina energizada del motor de
dt
pasos, y argumentando la referencia antes mencionada, entonces la ecuacin se ve reducida a la forma
L

di
V
dt

despejando y agrupando trminos, se tiene entonces que

V alimentacin di

Lfase
dt

La ecuacin anterior, por sus unidades de medicin, establece que el voltaje dividido entre la
inductancia tiene una equivalencia a la relacin de Amperes sobre segundo. De tal modo que a partir
de esta ecuacin el tiempo Tr se puede definir a partir de la corriente que se desea pasar a travs de la
bobina de acuerdo a la ecuacin siguiente:
1

El factor 2/3 es una aproximacin, ya que en el circuito equivalente del puente H cuando la bobina se encuentra
energizada, se va a dividir en 2 Resistencias Rds(on) de los mosfet y una Rmotor del embobinado.

I deseada
I deseadaL fase

V alimentacin / Lfase V alimentacin


al encendido.
T r

con este ultimo valor se obtiene la energa disipada por el sistema

Para fines de practicidad, es posible considerar que esta misma cantidad de energa es la que el sistema
disipa al apagado, es decir
EOFF /ON =EON / OFF
7.2.2.3 Determinacin de la energa disipada en TLD

La energa disipada durante el tiempo TLD se encuentra definida por la ecuacin


E LD =I 2LR DS (ON )2T LD Recuerde que aqu solo se considera la resistencia del MOSFET en
conduccin a consecuencia de que ya la bobina del motor a pasos est en un estado estable y por lo
tanto, la resistencia de la misma se considera cero y que el nmero 2 es un factor de seguridad.
Considerando adems que el TLD se encuentra definido a travs de T LD =3T (paso)T r , entonces para
una frecuencia de paso dada, la ecuacin anterior se define como

E LD =I 2LR DS (ON )6T ( paso)

I deseadaL fase
V alimentacin

siendo
T ( paso) =

1
f paso

Adems de la energa disipada en TLD haciendo referencia al estado estable, es importante considerar la
energa que ocasiona el rizo generado por el conmutador que se encarga de mantener una corriente
constante sobre las bobinas del motor a pasos durante el estado de activacin. Para determinar esa
energa disipada en los mosfet de conmutacin, considere la siguiente ecuacin:
ECOM =V SI LT comf switchT LD
Por lo tanto la energa que se disipa en los MOSFET de conmutacin a durante el intervalo de tiempo
TLD es la suma de estas dos energas, por lo tanto la expresin de ambas se define por medio de
E LD(Total) =E LD + ECOM
7.2.2.4 Determinacin de la energa disipada en el tiempo de espera
Podra considerarse que cuando las bobinas no se encuentran energizadas, habr una disipacin nula de
energa en el controlador MOSFET, sin embargo, si consideramos la corriente quiscent que est
definida por lo portadores minoritarios en cualquier dispositivo semiconductor, tal energa disipada
durante el periodo de espera se encuentra definido por:

Equiescent =I quiescentV alimentacinT D


7.2.2.5 Determinacin de la energa total disipada y potencia total disipada en el mosfet
de conmutacin
La energa total disipada, se determina por la sumatoria de todas las energas anteriormente calculadas,
en consecuencia, la ecuacin para realizar tal clculo queda definido de la siguiente manera

ETOTAL=E OFF /ON + E LD(Total) + EON /OFF + Equiescent


En conformidad con el valor obtenido, la potencia disipada, por definicin se puede calcular de la
forma siguiente:
PDISIPADA =

ETOT
T CICLO

Unidad 8
El convertidor ADC y DAC

Unidad 8 El convertidor ADC y DAC


8.1 Arquitectura Interna.
8.2 Configuracin y programacin.

Competencia especfica
Utilizar el convertidor ADC y DAC para fines de control.
Actividades de aprendizaje:

Mapa Conceptual: Elaborar un mapa conceptual a partir de los componentes relevantes del
convertidor, su configuracin y su programacin.

8.1 Arquitectura Interna.


Los Convertidores Analgicos Digitales permiten una comunicacin eficaz entre los sistemas
analgicos y los sistemas digitales, tomando muestras del mundo real para generar datos que puedan
ser manipulados por un microcontrolador por ejemplo, obteniendo de sta manera cualquier tipo de
seal fsica en tensiones elctricas cuyos datos podrn ser procesados por el dispositivo electrnico.
Adems fueron creados para poder aumentar la velocidad del procesamiento de las seales
logrando as acoplar los sistemas analgicos con los sistemas digitales.
Actividad de aprendizaje.- realiza la lectura de las pginas 244-259 Analog-to-Digital converter y
elabora:
Mapa Conceptual: Elaborar un mapa conceptual a partir de los componentes relevantes del convertidor.

8.2 Configuracin y programacin.


El ADC convierte un voltaje analgico de entrada en un valor digital de 10 bits a travs de
aproximaciones sucesivas. El valor mnimo representa a GND y el valor mximo representa al voltaje
en el pin AREF menos 1 LSB. Opcionalmente, AVCC o un voltaje de referencia interna de 1.1V puede
conectarse al pin AREF escribiendo en los bits REFSn en el Registro ADMUX. La referencia de voltaje
interna puede ser desacoplada por un condensador externo en el pin AREF para mejorar la inmunidad
al ruido.
El ADC genera un resultado de 10 bits que se presenta en los Registros de Datos del ADC (ADC Data
Registers), ADCH y ADCL. Por defecto, el resultado se presenta ajustado hacia la derecha, pero
opcionalmente puede presentarse ajustado hacia la izquierda configurando el bit ADLAR en el
ADMUX.
Si el resultado est ajustado hacia la izquierda y no se requiere ms que 8 bits, es suficiente leer el
ADCH. De otro modo, ADCL debe leerse primero, luego ADCH, para asegurarse de que el contenido
de los Registros de Datos correspondan a la misma conversin. Una vez que el ADCL es ledo, se
bloquea el acceso del ADC a los Registros de Datos. Esto significa que si se ha ledo el ADCL, y una
conversin se completa antes de que se lea el ADCH, ni el registro es actualizado ni el resultado de la
conversin se pierde. Cuando el ADCH es ledo, el acceso del ADC a los Registros ADCH y ADCL se
habilita nuevamente.
El ADC tiene su propia interrupcin que puede activarse cuando una conversin se ha completado.
Cuando se prohbe el acceso del ADC a los Registros de Datos en medio de la lectura del ADCH y del
ADCL, la interrupcin se activar an si el resultado se pierde.

Ejemplo de diagramas de flujo para el uso del ADC

Diagrama de flujo para lectura de temperatura con promedios

figura 78: diagrama de flujo para promediado de


lecturas de ADC

Prctica. Programar un microcontrolador ATmega48 para leer el ADC conectado en el canal cero,
usando formato de 8 bits, y mostrar el resultado en una pantalla LCD. De acuerdo a los siguientes
diagramas:

figura 79: Lectura de ADC ATmega48

Paso 1. Seleccionar el valor de preescalamiento del ADC para elegir una frecuencia de operacin del
ADC a 125kHz (aprox 14kSps) usando los bits (ADPS2:ADPS0) del registro ADCSRA. Considerando
que la frecuencia del sistema es de 1MHz (El circuito no tiene oscilador externo o cristal, por lo que se
referir al oscilador interno RC)
PRE =

F CPU 1MHz
=
=8 .
F adc 125kHz

ADPS2

ADPS1

ADPS0

Preescalamiento

16

32

64

128

Paso 2. Seleccionar los voltajes de referencia del ADC usando los bits (REFS1:REFS0) del registro
ADMUX. Para el caso especificado, se requiere que la referencia sea igual al valor de alimentacin

Vcc.
REFS1

REFS0

Descripcin

Aref, Vref interna OFF

Avcc, Vref externa

Reservado

Interna de 1.1V con capacitor en pin Aref

Paso 3. Establecer la justificacin de resultado con el bit ADLAR (ADMUX). Si ADLAR = 0 (por
defecto) realiza la justificacin a la derecha.(conversin de 10bits)
15

14

13

12

11

10

MSB(9)

ADCH
ADCL

LSB(0)

Si ADLAR= 1, se realiza la justificacin a la izquierda (Para conversin de 8 bits)


15

14

13

12

11

10

MSB(7)

LSB(0)

lsb

ADCH
ADCL

Paso 4. Seleccionar el canal o canales de entrada del ADC con los bits MUX3:MUX0. Para este caso el
canal 0, es mediante el valor MUX3:MUX0 = 0000.
MUX3:MUX0

Descripcin

MUX3:MUX0

Descripcin

0000

ADC0

1000

reservado

0001

ADC1

1001

reservado

0010

ADC2

1010

reservado

0011

ADC3

1011

reservado

0100

ADC4

1100

reservado

0101

ADC5

1101

reservado

0110

reservado

1110

1.1V (VBG)

0111

reservado

1111

0V GND

Paso 5. Encender el mdulo del ADC al setear el bit ADEN del registro ADCSRA
Paso 6. Iniciar la conversin seteando el bit ADSC en el registro ADCSRA
Paso 7. Esperar a que termine la conversin. Cuando esto sucede, el flag ADIF se pondr a uno y si la
conversin es normal y el bit ADSC se limpiar automticamente.
Paso 8. Leer el resultado de la conversin del par de registros ADCH:ADCL. Para el caso de la
prctica, solo se leer el registro ADCH en una variable tipo char, si se requiere de una lectura de
10bits, habr que justificar a la derecha y la variable receptora es de tipo int.
Paso 9. Escribir el cdigo que a continuacin se presenta:

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include "lcd.h"

#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=(_BV(bit)))


#define clearbit(sfr,bit) (_SFR_BYTE(sfr)&=~(_BV(bit)))

void adc_setup(void);
unsigned char adc_read(char channel);

int main(void)
{
unsigned char n; // variable que recibira la lectura de 8 bits
char buff[4];

//Buffer para lectura de ADC

lcd_init();
adc_setup();
lcd_gotorc(1,5);
lcd_puts("ADC0");
while(1)
{
n = adc_read(0);

sprintf(buff,"%3d",n); //campo de numeros

lcd_gotorc(2,1);
lcd_puts("val: ");
lcd_gotorc(2,5);
lcd_puts(buff);

}
}

void adc_setup(void)
{
//vref+ y Vref-: Vcc y GND
//Justificacin: Izquierda (Para lectura de 8 bits)

clearbit(ADMUX,REFS1); //Referencia a AVcc


setbit(ADMUX,REFS0);

setbit(ADMUX,ADLAR);

// Reloj del ADC0:

F_CPU/8 = 125kHz

// Estado del convertidor:

ON

// Modo:

Manual

setbit(ADCSRA,ADEN);

//ADC habilitado

clearbit(ADCSRA,ADATE);

//Modo manual (Normal)

clearbit(ADCSRA,ADPS2); //Seleccion del

Prescalador reloj

setbit(ADCSRA,ADPS1); // n = 8
setbit(ADCSRA,ADPS0);
}
unsigned char adc_read(char channel)
{
ADMUX&=0xFF;
ADMUX|=channel;
_delay_us(10); //delay para estabilizar el voltaje de entrada del ADC
setbit(ADCSRA,ADSC);

//se inicia la conversion

while(bit_is_clear(ADCSRA,ADIF));

return ADCH;
}

Tabla 36: Lectura del ADC en ATmega48

//Espera a que termine la conversion

Unidad 9
Puertos Seriales y memoria EEPROM

Unidad 9 Puertos seriales y memoria EEPROM


9.1 USART
9.2 TWI (I2C)
9.3 Leer y escribir sobre EEPROM

Competencia especfica
Comunicar dispositivos usando los puertos seriales
Utilizar la memoria EEPROM
Actividades de aprendizaje:
Mapa Conceptual: Distinguir mediante un mapa conceptual la comunicacin de dispositivos a travs de
los puertos seriales como el USART, TWI y otros protocolos.

9.1 El USART
9.1.1 Libreras para el control del puerto serial
La librera para el control del puerto serial es una modificacin de la librera ofrecida por Peter Fleury,
este cdigo permite al programador enviar caracteres en formato ASCII a travs de la USART del
microcontrolador ATMega32u4, pero adems de ello, se caracteriza por el hecho de que cuenta con la
creacin de un buffer, el cual puede ser modificado a voluntad del usuario.
Tal buffer puede ser usado con el fin de recibir datos complejos desde una aplicacin o desde otro
microcontrolador.
Anexo a esto, la misma rutina permite la recepcin de tres caracteres especiales, tales como
Escape.- La funcionalidad de esta tecla es que permite el borrado completo del buffer temporal del
microcontrolador
INTRO (Enter).- Permite la aceptacin del buffer, con el fin establecer que se ha recibido un comando.
BACKSPACE (Tecla de retroceso).- En caso de que el comando enviado por el puerto serial contenga
un error, con esta tecla es posible eliminar el ltimo caracter insertado en la cola del buffer (RedRaven,
2010).
Es importante sealar que la velocidad de comunicacin inicial es de 9600 bauds, sin embargo, el
usuario puede cambiar esta velocidad con tan solo modificar el valor de la lnea
#define USART_BAUDRATE 9600L por el valor que se desee:

#ifndef __UART_H
#define __UART_H
#include "clk.h"

# define USART_BAUDRATE 9600UL


# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

//definicion de teclas
#define INTRO 0x0D
#define RETROCESO 0x08
#define ESCAPE 0x1B

//define el tamano del buffer


#define lenbuff 10

void uart_transmit( unsigned char data );


unsigned char uart_receive(void);
void uart_init(void);
int uart_dataAvailable(void);
void uart_print(const char *s);
/**
* funcion que limpia el buffer de caracteres para la comunicacion serial
*/
void initBuff(void);
/**
* funcion para agregar un caracter al buffer de comunicacion serial
*/
void add2cbuff(unsigned char c);

/**
* funcion que imprime un echo a la terminal, solo caracteres imprimibles
*/
void echosel(unsigned char c);

#endif

Tabla 37: librera usart.h

// uart.c
// Originally for NerdKits with ATmega168, 14.7456 MHz clock
// mrobbins@mit.edu
// Modified for Adafruit ATMega32u4 Breakout, with 16.0000Mhz clock
// Note, this references serial 1, not 0, since the micro does not have 0.
// At least for the above breakout, D3 is TX, and D2 RX
// https://github.com/tomvdb/avr_arduino_leonardo/blob/master/examples/uart/main.c

#include "clk.h"
#include <avr/io.h>
#include <string.h>
#include "uart.h"
#include <util/delay.h>

//variables para el manejo de comunicacion serial


typedef enum{false, true} boolean;
boolean flagcommand= false;
unsigned char xbuff=0x00;
unsigned char cbuff[lenbuff];
char rcvchar=0x00;

// transmit a char to uart


void uart_transmit( unsigned char data )
{
// wait for empty transmit buffer
while ( ! ( UCSR1A & ( 1 << UDRE1 ) ) )
;

// put data into buffer, sends data


UDR1 = data;
}

// read a char from uart


unsigned char uart_receive(void)
{
while (!( UCSR1A & ( 1 << RXC1) ))
;

return UDR1;
}

// init uart

void uart_init(void)
{
// set baud rate
unsigned int baud = BAUD_PRESCALE;

UBRR1H = (unsigned char)(baud >> 8 );


UBRR1L = (unsigned char)baud;
//UBRR1H = 0;
//UBRR1L = 0x34;

// enable received and transmitter


UCSR1B = ( 1 << RXEN1 ) | ( 1 << TXEN1 );

// set frame format ( 8data, 2stop )


UCSR1C = ( 1 << USBS1 ) | ( 1 << UCSZ11 ) | (1 << UCSZ10);
}

// check if there are any chars to be read


int uart_dataAvailable(void)
{
if ( UCSR1A & ( 1 << RXC1) )
return 1;

return 0;
}

// write a string to the uart


void uart_print(const char *s)
{
register char c;
while((c=*s++)){
uart_transmit(c);
}
}
/*
void uart_print( char data[] )
{
int c = 0;

for ( c = 0; c < strlen(data); c++ )


uart_transmit(data[c]);
}
*/

void initBuff(void)
{
int i;
for(i=0;i<lenbuff; i++)
{
cbuff[i]=0x00;
}xbuff=0x00;
}

void add2cbuff(unsigned char c)


{
if(xbuff<lenbuff)
{
switch(c)
{
case INTRO:
flagcommand = true;
break;
case RETROCESO:
if(xbuff>0) cbuff[--xbuff] = 0x00;
break;
case ESCAPE:
initBuff();
break;
default:
cbuff[xbuff++]=c;
}
}
else
{
initBuff();
uart_print("ERROR\r\n");
}
}

void echosel(unsigned char c)


{
switch(c)
{
case INTRO:
uart_print("\r\n");
break;

case RETROCESO:
uart_transmit(RETROCESO);
break;
case ESCAPE:
uart_transmit(ESCAPE);
break;
default:
uart_transmit(c);
}
}

Tabla 38: librera usart.c

9.1.2 Ejemplo de recepcin de datos desde una terminal de comunicacin serial


GtkTerm o CuteCom hacia el microcontrolador ATmega32U4.
En el siguiente ejemplo, desde el teclado de una PC o laptop, se envia hacia el microcontrolador
ATMega32u4, los caracteres 0,1,2,3, los cuales tienen la funcin que en la tabla siguiente se muestra:
Caracter

Accin a realizar

Apagar LED Amarillo

Encender LED Amarillo

Apagar LED Rojo

Encender LED Rojo

El circuito de conexin se muestra a continuacin


Cdigo fuente Principal

#include "clk.h"
#include <avr/io.h>
#include "uart.h"

#define LED_R 0
#define PLED_R PORTB
#define LED_A 6
#define PLED_A PORTB

//variable que recibe el comando de entrada


unsigned int Byte_entrada = 0;

int main(void)
{
_init_Teensyduino_internal_();
uart_init(); //9600 8 2 bits de paro, sin paridad
setbit(DDR(PLED_A), LED_A);
setbit(DDR(PLED_R), LED_R);
clrbit(PLED_A,LED_A); //apagar los leds
clrbit(PLED_R,LED_R);

// Insert code

while(1)
{
if(uart_dataAvailable())
{
Byte_entrada = uart_receive();
if(Byte_entrada == '0')
{
clrbit(PLED_A, LED_A);
uart_print("LED Amarillo OFF");
}
else if(Byte_entrada == '1')
{
setbit(PLED_A, LED_A);
uart_print("LED Amarillo ON");
}
else if(Byte_entrada == '2')
{
clrbit(PLED_R, LED_R);
uart_print("LED Rojo OFF");
}

else if(Byte_entrada == '3')


{
setbit(PLED_R, LED_R);
uart_print("LED Rojo ON");
}
}
}

return 0;
}

Tabla 39: Encendido de leds a travs de puerto serie en microcontrolador


Si el usuario as lo desea, puede ejecutar un programa diseado en languaje Java, para interactuar con
el microcontrolador, pero para ello deber seguir las reglas que se muestran en el apartado siguiente:

9.1.3 Acceso como usuario normal al puerto serial e instalacin de RxTx


Rxtx en Manjaro Linux2
Como primer punto hay que hacer mencin que al da de hoy se encuentra caido el site de qbang el cual
nos ha facilitado las librerias de comunicacion serial de Java, por lo cual es posible acudir a pacman
para instalarles
sudo pacman -Ss rxtx

listando lo siguiente (a mi me marca que ya est instalado)


community/java-rxtx 2.2pre2-2 [instalado]
Java library for serial IO
posteriormente se instalado
$sudo pacman -S java-rxtx

Al finalizar la instalacin indicar lo siguiente:


Users need to be in 'lock' and 'uucp' groups to connect to devices
Operacin finalizada con xito
3

Lo que significa que, para que un usuario normal sin privilegios de root pueda acceder a los puertos de

Las pruebas fueron realizadas sobre una laptop Gateway NV55C con Manjaro Linux 0.8.9 x64 con RAM de 6 GB

Estos pasos sirven tambien para comunicar a Scilab con un microcontrolador por medio de los comandos que a
continuacin se presentan:

-->h=openserial("/dev/ttyUSB0","9600,n,8,2")
h =
file77

comunicacin serial, ste debe pertenecer a los grupoas lock y uucp, para ello desde la consola escriba
los siguientes comandos:
$ sudo usermod -aG uucp TunombredeUsuario
$sudo usermod -aG lock TunombredeUsuario
Preguntar sobre el estado de jdk7
[miguel@manjaro opt]$ sudo pacman -Ss jdk7
extra/jdk7-openjdk 7.u51_2.4.6-1
Free Java environment based on OpenJDK 7.0 with IcedTea7 replacing binary
plugs SDK

E instalar con:
[miguel@manjaro opt]$ sudo pacman -S extra/jdk7-openjdk

9.1.4 Construir una clase de Java para mostrar los puertos detectados en Manjaro
Para usar las librerias en Netbeans de comunicacin serial instaladas desde el repositorio se tiene que
agregar la libreria desde las propiedades del proyecto y dando clic en la opcin Libraries, en el Tab
Compile dar clic en el botn Add JAR/Folder

-->result=closeserial(h)
result =
0.

figura 80: Configuracin de libreria RxTx en Netbeans agregando JAR


Si se compila solo con esta opcin, entonces al tratar de correr la aplicacin, marcar el siguiente error4
java.lang.UnsatisfiedLinkError:
gnu.io.RXTXCommDriver

no

rxtxSerial

in

java.library.path

thrown

while

loading

esto se debe a que el Linker no apunta a la libreria dinmica librxtxSerial.so, en este caso, la libreria
instalada, se encuentra en /usr/lib/, por lo tanto se debe indicar esta direccin en el IDE, haciendo
esto de la siguiente manera:
Agregar la lnea -Djava.library.path=/usr/lib en las opciones de mquina virtual (click derecho sobre
el proyecto -> Propiedades -> Run)

La ruta donde se encuentra ubicado la librera dinmica depende de la distribucin usada, este apartado se consult el
19 de abril de 2014 desde la pgina http://ubuntuforums.org/archive/index.php/t-1747382.html

figura 81: Configuracin de librerias RxTx en netbeans

el cdigo fuente es el siguiente:

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/

package detectarpuertos;
import java.util.*;
import gnu.io.*;
/**
*
* @author miguel
*/
public class DetectarPuertos {
CommPortIdentifier ports;

void mirar()
{
Enumeration<?> puertos = CommPortIdentifier.getPortIdentifiers();
while(puertos.hasMoreElements()){
ports = (CommPortIdentifier) puertos.nextElement();
System.out.println("********\n"+ports.getName());
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
DetectarPuertos ini = new DetectarPuertos();
ini.mirar();
}

Tabla 40: Cdigo fuente de Java para verificar puertos seriales habilitados
Al dar clic en run este proyecto, la salida es la siguiente, siempre y cuando se disponga de un cable de
conversin serial a USB conectado en el equipo:
run:
********
/dev/ttyUSB0
BUILD SUCCESSFUL (total time: 0 seconds)

9.1.5 Envo de Datos del microcontrolador hacia el PC usando Scilab 5.x


El ejemplo que se muestra a continuacin permite el envio de datos desde el microcontrolador hacia el
PC para mostrarse, tanto en formato ASCII (cdigo fuente comentado) como en formato Binario, esto
con el fin de mostrar en una grfica obtenida a partir de la adquisicin de datos usando el Toolbox de
comunicacin serial de SCILAB.
El propsito es de leer una variable analgica con el microcontrolador y que ste a su vez se comunique
con el Toolbox de Scilab a fin de graficar la seal adquirida.
El circuito elctrico se muestra a continuacin
La tabla de conexiones del microcontrolador y el cdigo fuente del proyecto se colocan

/*
Debe agregarse a las opciones del linker las siguientes lineas
-lm
-u
vfprintf -lprintf_flt

Con CodeBlocks
Para agregarlas solo da clic derecho en el nombre del proyecto
elige la opcion que dice Properties....
En la ventana que se abre, da clic en el boton Project's Build options...
Te abre una nueva ventana
Da clic en el Tab Linker Setting
y del lado izquierdo encuentras las opciones del linker, ahora
solo resta agregar las librerias para que puedas hacer uso de sprintf
para imprimir numeros con punto decimal
*/

#include "clk.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#include "adc.h"
#include "timer0.h"
#include "timer1.h"
#include "lcd.h"
#include "uart.h"

//void _init_Teensyduino_internal_(void);
//ISR(TIMER0_COMPA_vect)
//{
//

//togglebit(PORTD,PD0);

//}
//
//ISR(TIMER1_COMPA_vect)
//{
// // togglebit(PORTB,5);
//}

int main(void)

{
unsigned int valor;
unsigned long reloj;
double mostrar;
char buffer[10];
char bufferfloat[10];
char lcdbuffer[10];
//char rxByte;

_init_Teensyduino_internal_();
// Insert code
delay_ms(1000);
lcd_init(LCD_DISP_ON);
setbit(DDRB,0); //led verde
setbit(DDRD,0); //OC0B
setbit(DDRB,6); //OC1B
setbit(DDRB,5); //OC1A

/*Inicializando la UART*/
uart_init();

lcd_puts("probando LCD");

if(uart_dataAvailable())
{
uart_transmit(0x00);
lcd_puts("serial dataAvalible");
delay_ms(1000);
}

uart_print("Hola :)");
lcd_gotoxy(1,2);
lcd_puts("enviando serie");
delay_ms(1000);
/*
configuracion del timer 1
Modo de operacion: FAST PWM (5)
Resolucion: 8 bits
Factor de prescalamiento: 1024

Comportamiento de OC1A: No inversor


Frecuencia de PWM = F_CPU/(N(1+TOP)) = 1Mhz/(1024(1+255) = 3.81Hz
Periodo de PWM = 1/Freq de PWM = 262.14ms
Ciclo de trabajo = 39% = OCR1A*100/TOP
timer1_setup(5,1024,3,3,0);
OCR1A = 100;
*/
timer1_setup(5,1024,3,3,0); //modo PWM de 8 bit frecuencia de 3906.25Hz PB5
OCR1A = 255;
OCR1B = 255;
//comparacion no inversa
//adc_setup(2,0,0,0);
//Prescalamiento de 2
//referencia: AREF
//justificacion: 1 (Izquierda- 8 bits de resolucion)
//canal: Leer canal 0
adc_setup(0,1,ADC0);

/*
configuracion del timer 0 (2)
Modo de operacion: CTC
Factor de Prescalamiento: 1024
Valor de Precarga: 99 (OCR0A)
Periodo de AutoReset: 101.3 ms
F_CPU: 1MHz
Tiempo = N(OCR0B+1)/F_CPU
COM0A = 0 (SE DESCONECTA LA SALIDA DEL WMG AL PIN OC0A)
COM0B = 1 (CAMBIA DE ESTADO CADA VEZ QUE DESBORDA)
*/
timer0_setup(2,1024,0,1); //modo CTC interrupcion en PD0
OCR0A = 99;

//setbit(TIMSK0,OCIE0A); //habilita la interrupcion del T0 CTC


//setbit(TIMSK1, OCIE1A);
lcd_clrscr();
lcd_puts("Medicion ADC");

//sei();

while(1)
{

valor = adc_read(ADC0);
//itoa(valor,buffer,16);
//si es utilizada la base 10
//entonces mas alla del valor medio
//el resultado dara un signo (bit de signo)
//para cualquier otra base, el valor es
// considerado como numero sin signo
//Si se desean leer solo 8 bits entonces
//recorre el numero
valor = (valor >>8);
mostrar = (valor*100.0)/256.0;
reloj = F_CPU;
sprintf(lcdbuffer,"%ld",reloj);
//itoa(valor,buffer,16);
sprintf(buffer,"%d",valor);
//mostrar = 3.14;
lcd_gotoxy(4,1);
lcd_puts("

");

lcd_gotoxy(4,1);
lcd_puts(buffer);
sprintf(bufferfloat,"%1.2f",mostrar);
lcd_gotoxy(13,0);
lcd_puts(" ");
lcd_gotoxy(13,0);
lcd_puts(bufferfloat);
setbit(PORTB,0);
delay_ms(5);
//valor++;
clrbit(PORTB,0);
delay_ms(5);
//Para adquirir el dato con scilab
//el dato convertido se debe enviar como numero
//no como caracter
uart_transmit(valor);
//

uart_print("\r");

//

uart_print("Valor de Conversion AD:");

//

uart_print(bufferfloat);

//

uart_print("\n\r");

//

uart_print("Valor de F CPU:");

//

uart_print(lcdbuffer);

//

uart_print("\n\r");

return 0;
}

Tabla 41: Cdigo para envo de datos binarios adquiridos por el ADC a travs del puerto serial
El cdigo fuente del script de Scilab para la conexin entre el microcontrolador y el software queda
definido en el marco siguiente:
clf;
//Inicializaciones
EOC = ascii([13 10])
LF = ascii(10)
dt = 20

//temporizacion ms

dtc = 1/1.2 //tiempo de caracter ms

n=500; //numero de muestras


y=ones(1,n); //vector acumulador
h=openserial("/dev/ttyUSB0","9600,n,8,2");
sleep(50);
i=1;
x=[0:1:n-1];//dominio a graficar
pot=" ";
while i<=n
pot=ascii(readserial(h))//lee lo que hay en el buffer
y(i) = pot(1)
xpause(25000) //delay en microsegundos
i=i+1;
end
k=(100/256).*y;
xx=1:length(k);
plot2d2(xx,y);
closeserial(h);

Tabla 42: Script de scilab para comunicacin con el puerto serial

9.2 TWI (I2C)


Las notas que estn a continuacin se obtuvieron del sitio web Quadruino (2014).
Qu es I2C?
I2C es un protocolo de comunicacin serie diseado por Philips que se utiliza esencialmente entre

dispositivos que pertenecen al mismo circuito, por ejemplo, sensores con un microcontrolador.
Qu es TWI?
Aunque las patentes de I2C ya han expirado, algunos vendedores utilizan los nombres TWI y TWSI
para referirse a I2C. Es exactamente lo mismo.
Caractersticas del protocolo:
Velocidad standard de 100Kbit/s (100kbaudios). Se puede cambiar al modo de alta velocidad
(400Kbit/s)
Configuracin maestro/esclavo. La direccion del esclavo se configura con software
Solo se necesitan dos lineas:
SDA (Serial Data Line): Linea de datos.
SCL/CLK (Serial Clock Line): Linea de reloj, ser el que marque el tiempo de RW
(Lectura/Escritura)
Nota: Suponemos que todos los dispositivos tienen masa comn, si no fuera as hay que
uncluir una linea de masa.
Los comunicacin siempre tiene la estructura siguiente:
Transmisor: Byte de datos (8 Bits)
Receptor: Bit llamado ACK de confirmacin.
Cmo se realizan las conexiones?SDA y SCL van a su pin correspondiente en cada dispositivo, de
manera que todos quedan en paralelo.Las lineas SDA y SCL estan independientemente conectadas a
dos resistores Pull-Up que se encargaran de que el valor logico siempre sea alto a no ser que un
dispositivo lo ponga a valor lgico bajo.
Qu tipo de comunicacin es?
Es una comunicacin de tipo half duplex. Comunicacin bidireccional por la misma linea pero no
simultneamente bidireccional.
Cual es la estructura de la comunicacin?
La estructura de la comunicacin bsica es la siguiente:
1.
2.
3.
4.
5.
6.
7.
8.
9.

START condition (Master)


7 Bits de direccion de esclavo (Master)
1 Bit de RW, 0 es Leer y 1 Escribir. (Master)
1 Bit de Acknowledge (Slave)
Byte de direccin de memoria (Master)
1 Bit de Acknowledge (Slave)
Byte de datos (Master/Slave (Escritura/Lectura))
1 Bit de Acknowledge (Slave/Master (Escritura/Lectura))
STOP condition (Master)

Esta es la base de la comunicacin pero para leer o escribir, segn el dispositivo con el que se
comunica el Master la comunicacin tendr una estructura especfica.

Qu es el bit de Acknowledge (ACK)?


Este bit es una respuesta del receptor al transmisor. Es una parte bsica de la comunicacin y tiene
diferentes sentidos segn el contexto.
Se utiliza principalmente con dos propsitos:
1. Conocer si el transmisor ha sido escuchado
2. Lecturas multidatos:
Cuando se esta leyendo de un esclavo, si el master realiza un ACK, es decir, que responde; el
esclavo pasa al siguiente valor de registro y lo enva tambin, hasta recibir un NACK (Not
Acknowledge), es decir, ninguna respuesta del master. Esto sirve para hacer mltiples lecturas.
Por ejemplo, nuestro acelermetro o giroscopio, que tienen valores de X, Y y Z.
En esencia este es el funcionamiento del protocolo de comunicacin con el que nos comunicaremos
con mltiples sensores

Ejemplos de uso de TWI


A continuacin se colocan las librerias para la comunicacin TWI para AVR

/*************************************************************************
* Title:

I2C master library using hardware TWI interface

* Author:

Peter Fleury <pfleury@gmx.ch>

* File:

$Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $

http://jump.to/fleury

* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3


* Target:

any AVR device with hardware TWI

* Usage:

API compatible with I2C Software Library i2cmaster.h

**************************************************************************/
#include <inttypes.h>
#include <compat/twi.h>

#include <i2cmaster.h>

/* define CPU frequency in Mhz here if not defined in Makefile */


#ifndef F_CPU
#define F_CPU 4000000UL

//puede cambiarse por F_CPU pero incluir a clk.h

#endif

/* I2C clock in Hz */
#define SCL_CLOCK

100000L

/*************************************************************************
Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */

TWSR = 0;

/* no prescaler */

TWBR = ((F_CPU/SCL_CLOCK)-16)/2;

/* must be > 10 for stable operation */

}/* i2c_init */

/*************************************************************************
Issues a start condition and sends address and transfer direction.
return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
uint8_t

twst;

// send START condition

TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

// wait until transmission completed


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits.


twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

// send device address


TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);

// wail until transmission completed and ACK/NACK has been received


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits.


twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;

return 0;

}/* i2c_start */

/*************************************************************************
Issues a start condition and sends address and transfer direction.
If device is busy, use ack polling to wait until device is ready

Input:

address and transfer direction of I2C device

*************************************************************************/
void i2c_start_wait(unsigned char address)
{
uint8_t

twst;

while ( 1 )
{
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

// wait until transmission completed


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits.

twst = TW_STATUS & 0xF8;


if ( (twst != TW_START) && (twst != TW_REP_START)) continue;

// send device address


TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);

// wail until transmission completed


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits.


twst = TW_STATUS & 0xF8;
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
{
/* device busy, send stop condition to terminate write operation */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

// wait until stop condition is executed and bus released


while(TWCR & (1<<TWSTO));

continue;
}
//if( twst != TW_MT_SLA_ACK) return 1;
break;
}

}/* i2c_start_wait */

/*************************************************************************
Issues a repeated start condition and sends address and transfer direction

Input:

address and transfer direction of I2C device

Return:

0 device accessible
1 failed to access device

*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start( address );

}/* i2c_rep_start */

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

Terminates the data transfer and releases the I2C bus


*************************************************************************/
void i2c_stop(void)
{
/* send stop condition */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

// wait until stop condition is executed and bus released


while(TWCR & (1<<TWSTO));

}/* i2c_stop */

/*************************************************************************
Send one byte to I2C device

Input:

byte to be transfered

Return:

0 write successful
1 write failed

*************************************************************************/
unsigned char i2c_write( unsigned char data )
{
uint8_t

twst;

// send data to the previously addressed device


TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);

// wait until transmission completed


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits


twst = TW_STATUS & 0xF8;
if( twst != TW_MT_DATA_ACK) return 1;
return 0;

}/* i2c_write */

/*************************************************************************
Read one byte from the I2C device, request more data from device

Return:

byte read from I2C device

*************************************************************************/
unsigned char i2c_readAck(void)

{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));

return TWDR;

}/* i2c_readAck */

/*************************************************************************
Read one byte from the I2C device, read is followed by a stop condition

Return:

byte read from I2C device

*************************************************************************/
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));

return TWDR;

}/* i2c_readNak */

Tabla 43: Librera Peter Fleury twimaster.c


Ahora se enlista el archivo de cabecera

#ifndef _I2CMASTER_H
#define _I2CMASTER_H

/*************************************************************************
* Title:

C include file for the I2C master interface

(i2cmaster.S or twimaster.c)

* Author:

Peter Fleury <pfleury@gmx.ch>

* File:

$Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $

http://jump.to/fleury

* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3


* Target:

any AVR device

* Usage:

see Doxygen manual

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

#ifdef DOXYGEN
/**
@defgroup pfleury_ic2master I2C Master library
@code #include <i2cmaster.h> @endcode

@brief I2C (TWI) Master Software Library

Basic routines for communicating with I2C slave devices. This single master
implementation is limited to one bus master on the I2C bus.

This I2c library is implemented as a compact assembler software implementation of the I2C protocol
which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI
hardware (twimaster.c).
Since the API for these two implementations is exactly the same, an application can be linked either
against the
software I2C implementation or the hardware I2C implementation.

Use 4.7k pull-up resistor on the SDA and SCL pin.

Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
i2cmaster.S to your target when using the software I2C implementation !

Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware
implementaion.

@note
The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
to GNU assembler and AVR-GCC C call interface.
Replaced the incorrect quarter period delays found in AVR300 with
half period delays.

@author Peter Fleury pfleury@gmx.ch

@par API Usage Example

http://jump.to/fleury

The following code shows typical usage of this library, see example test_i2cmaster.c

@code

#include <i2cmaster.h>

#define Dev24C02

0xA2

// device address of EEPROM 24C02, see datasheet

int main(void)
{
unsigned char ret;

i2c_init();

// initialize I2C library

// write 0x75 to EEPROM address 5 (Byte Write)


i2c_start_wait(Dev24C02+I2C_WRITE);

// set device address and write mode

i2c_write(0x05);

// write address = 5

i2c_write(0x75);

// write value 0x75 to EEPROM

i2c_stop();

// set stop conditon = release bus

// read previously written value back from EEPROM address 5


i2c_start_wait(Dev24C02+I2C_WRITE);

// set device address and write mode

i2c_write(0x05);

// write address = 5

i2c_rep_start(Dev24C02+I2C_READ);

// set device address and read mode

ret = i2c_readNak();

// read one byte from EEPROM

i2c_stop();

for(;;);
}
@endcode

*/
#endif /* DOXYGEN */

/**@{*/

#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304


#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
#endif

#include <avr/io.h>

/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_READ

/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */


#define I2C_WRITE

/**
@brief initialize the I2C master interace. Need to be called only once
@param

void

@return none
*/
extern void i2c_init(void);

/**
@brief Terminates the data transfer and releases the I2C bus
@param void
@return none
*/
extern void i2c_stop(void);

/**
@brief Issues a start condition and sends address and transfer direction

@param

addr address and transfer direction of I2C device

@retval

device accessible

@retval

failed to access device

*/
extern unsigned char i2c_start(unsigned char addr);

/**
@brief Issues a repeated start condition and sends address and transfer direction

@param

addr address and transfer direction of I2C device

@retval

0 device accessible

@retval

1 failed to access device

*/
extern unsigned char i2c_rep_start(unsigned char addr);

/**

@brief Issues a start condition and sends address and transfer direction

If device is busy, use ack polling to wait until device ready


@param

addr address and transfer direction of I2C device

@return

none

*/
extern void i2c_start_wait(unsigned char addr);

/**
@brief Send one byte to I2C device
@param

data

byte to be transfered

@retval

0 write successful

@retval

1 write failed

*/
extern unsigned char i2c_write(unsigned char data);

/**
@brief

read one byte from the I2C device, request more data from device

@return

byte read from I2C device

*/
extern unsigned char i2c_readAck(void);

/**
@brief

read one byte from the I2C device, read is followed by a stop condition

@return

byte read from I2C device

*/
extern unsigned char i2c_readNak(void);

/**
@brief

read one byte from the I2C device

Implemented as a macro, which calls either i2c_readAck or i2c_readNak

@param

ack 1 send ack, request more data from device<br>


0 send nak, read is followed by a stop condition

@return

byte read from I2C device

*/
extern unsigned char i2c_read(unsigned char ack);
#define i2c_read(ack)

/**@}*/
#endif

(ack) ? i2c_readAck() : i2c_readNak();

Tabla 44: Libreria Peter Fleury i2cmaster.h


Y Finalmente un ejemplo de uso de la librera
#include <i2cmaster.h>
#define Dev24C02

0xA2

// device address of EEPROM 24C02, see datasheet

int main(void)
{
unsigned char ret;
i2c_init();

// initialize I2C library

// write 0x75 to EEPROM address 5 (Byte


i2c_start_wait(Dev24C02+I2C_WRITE);
i2c_write(0x05);
i2c_write(0x75);
i2c_stop();

Write)
// set device address and write mode
// write address = 5
// write value 0x75 to EEPROM
// set stop conditon = release bus

// read previously written value back from EEPROM address 5


i2c_start_wait(Dev24C02+I2C_WRITE);
// set device address and write mode
i2c_write(0x05);
i2c_rep_start(Dev24C02+I2C_READ);

// write address = 5
// set device address and read mode

ret = i2c_readNak();
i2c_stop();

// read one byte from EEPROM

for(;;);
}

Tabla 45: Ejemplo de uso de libreria i2c

9.3 Leer y escribir sobre EEPROM I2C


Una memoria EEPROM I2C tiene una direccin fsicamente modificable en sus ltimos tres bits,
siendo los cuatro ms significativos valores ya dados de fabrica. El formato de una direccin para una
EEPROM I2C es la siguientes
1

A2

A1

A0

R/~W

Tabla 46: Estructura de direccin de una memoria EEPROM I2C


Donde los bits A2..A0 se cablean de forma fsica ya sea con conexin a tierra o Vcc, tal y como se
muestra en la siguiente figura

figura 82: Conexin memoria 24C512


La memoria que se muestra en figura 82: Conexin memoria 24C512 tiene una capacidad de
almacenamiento de 512kilo bits, los cuales se encuentran agrupados en palabras cuya longitud es 8, lo
cual nos da una capacidad total de 64kBytes. Cabe aclarar esto, ya que existen diversas memorias de
este tipo, pero con diferentes terminaciones, como por ejemplo la 24C128, la cual tiene una capacidad
de almacenamiento en bytes de 16k, o la 24C02 que solo puede almacenar 256 bytes.
Cabe sealar que la memoria que se muestra en la figura cuenta con jumpers los cuales permiten
modificar la direccin de la memoria a voluntad del usuario, de igual forma el pin 7 (WP) permite la
habilitacin de la proteccin contra escritura de la EEPROM si el jumper se retira.

9.3.1 Lectura y escritura simple de sobre una EEPROM I2C


Los procesos de lectura y escritura se resumen en el siguiente diagrama:

Escritura

Lectura

Enviar START

Enviar START

Enviar direccin
Del esclavo
Ms bit de
Escritura

Enviar direccin
Del esclavo
Ms bit de
Escritura

Procesos para la lectura


Y escritura simple de una
EEPROM I2C

Enviar direccin
A Leer en la
EEPROM

Enviar direccin
A escribir en la
EEPROM

Enviar direccin
Del esclavo
Ms bit de
Lectura

Enviar dato
A escribir

Enviar STOP
No
Esperar 6ms

Si
nAK recibido?

Guardar dato
De la EEPROM

Fin escritura

Enviar STOP

Fin de lectura

figura 83: Diagrama de lectura - escritura de una eeprom i2c


Las funciones que se muestran a continuacin sirven para memorias cuya longitud de direccionamiento
requiere mas de un byte; como podr apreciarse en la funcin descrita en la Tabla 47: funcin de
escritura de una EEPROM I2C la direccin es de dos bytes (tipo int) y se usa un casting para
transformar la variable a dos de tipo char, esto con el fin de posibilitar su envo por el bus I2C.
void write2EEPROM(unsigned char data, unsigned int dir)
{
unsigned char dirl, dirh;
dirh = (unsigned char) (dir >> 8);
dirl = (unsigned char) (dir);
i2c_start_wait(devAA512+I2C_WRITE);
i2c_write(dirh);
i2c_write(dirl);
i2c_write(data);
i2c_stop();
_delay_ms(10);
}

Tabla 47: funcin de escritura de una EEPROM I2C


De igual forma, se contempla a continuacin una funcin que permite la lectura de un byte de una
memoria EEPROM con tan solo indicar la direccin que desea ser leda

unsigned char read2EEPROM(unsigned int dir)


{
unsigned char leido, dirh, dirl;
dirh = (unsigned char) (dir >> 8);
dirl = (unsigned char) (dir);
i2c_start_wait(devAA512+I2C_WRITE);
i2c_write(dirh);
i2c_write(dirl);
i2c_rep_start(devAA512+I2C_READ);
leido=i2c_readNak();
i2c_stop();
return leido;
}

Tabla 48: funcin de lectura de una EEPROM I2C


Notes el uso de la macro devAA512, la cual va a indicar la direccin de la memoria que se desea
escribir o leer. Como siguiente punto se muestra un cdigo fuente de ejemplo que permite la escritura y
lectura simple de una eeprom 24AA512

/*
*/

#include <avr/io.h>
#include <util/delay.h>
#include "i2cmaster.h"

#define devAA512 0xA6

void write2EEPROM(unsigned char data, unsigned int dir);


unsigned char read2EEPROM(unsigned int dir);

int main(void)
{
unsigned char ret;
unsigned int dir;

// Insert code
i2c_init();

while(1){
for(dir=0;dir<0x10000;dir++)
{

write2EEPROM(0x75,dir);
ret=read2EEPROM(dir);
}
}

return 0;
}

void write2EEPROM(unsigned char data, unsigned int dir)


{
unsigned char dirl, dirh;
dirh = (unsigned char) (dir >> 8);
dirl = (unsigned char) (dir);
i2c_start_wait(devAA512+I2C_WRITE);
i2c_write(dirh);
i2c_write(dirl);

i2c_write(data);
i2c_stop();
_delay_ms(10);
}

unsigned char read2EEPROM(unsigned int dir)


{
unsigned char leido, dirh, dirl;
dirh = (unsigned char) (dir >> 8);
dirl = (unsigned char) (dir);
i2c_start_wait(devAA512+I2C_WRITE);
i2c_write(dirh);
i2c_write(dirl);
i2c_rep_start(devAA512+I2C_READ);
leido=i2c_readNak();
i2c_stop();
return leido;
}

Tabla 49: Lectura escritura simple de una eeprom


Como ejercicio para el lector se propone que modifique el programa anterior a fin de que en una
pantalla LCD se vaya mostrando la direccin que se escribe y su posterior lectura, as como el
contenido de tal valor de memoria.

figura 84: Escritura y lectura simple de una EEPROM sobre I2C

9.3.2 Lectura escritura controlada por el puerto de comunicacin serial


Con este experimento se va a mostrar la forma de comunicar una EEPROM externa a un MCU y

conectada a l va I2C. Con estos comandos se va a poder enviar datos (un texto) al MCU para ser
grabados en la EEPROM y sea posible leer el contenido de la misma para ser presentado en al PC, bajo
las siguientes sealizaciones:

El programa del microcontrolador va guardando lo recibido va RS232 en un buffer. Con la


tecla ENTER se enva a procesar el contenido. Con RETROCESO o ESC se puede borrar el
ltimo caracteres o el contenido de todo el buffer.

Con /r se lee todo el contenido de la EEPROM, con /i dir se escribe un ndice en la


posicin de memoria 0x00 y 0x01 de la EEPROM a partir de la cual con /w data se puede
escribir los datos enviados.

Con /B podemos dar formato al contenido de la EEPROM e inicializar el valor del ndice,
considere la siguiente figura como un mapeo de la memoria:
0x0

0x1

0x2

0x3

.....

0xE

0xF

0x000

DIRH

DIRL

0x00

0x00

.....

0x00

0x00

0x010

0x00

0x00

0x00

0x00

.....

0x00

0x00

.....

.....

0xFFE

0x00

0x00

0x00

0x00

.....

0x00

0x00

0xFFF

0x00

0x00

0x00

0x00

.....

0x00

0x00

Cdigo fuente
/*
* Este cdigo permite comunicar un AVR con una PC por medio del puerto Serie
* a fin de controlar la escritura y lectura de una memoria EEPROM por medio del
* protocolo I2C
*/

#include "clk.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#include "uart.h"
#include "i2cmaster.h"

#define devAA512 0xA6


//define el tamano del buffer
#define lenbuff 10

//variables para el manejo de comunicacion serial


typedef enum{false, true} boolean;
boolean flagcommand= false;
unsigned char xbuff=0x00;
unsigned char cbuff[lenbuff];

//funciones para la comunicacion PC - AVR


void presmenu(void);

//presenta el menu

void comando(void);

//procesa el comando recibido

/**
* funcion que limpia el buffer de caracteres para la comunicacion serial
*/
void initBuff(void);
/**
* funcion para agregar un caracter al buffer de comunicacion serial
*/
void add2cbuff(unsigned char c);

/**
* funcion que imprime un echo a la terminal, solo caracteres imprimibles
*/
void echosel(unsigned char c);

//funciones para lectura/escritura de la eeprom


void write2EEPROM(unsigned char data, unsigned int dir);
unsigned char read2EEPROM(unsigned int dir);

volatile unsigned char rcvchar;


//interrupciones
ISR(USART1_RX_vect)
{
rcvchar = 0x00;

//Se inicializa el caracter recibido

if(uart_dataAvailable()) //Existe algun dato disponible


{
rcvchar = uart_receive();//Se lee el buffer de recepcion
add2cbuff(rcvchar); //se agrega al buffer de comando
echosel(rcvchar); //Se envia un eco hacia la PC

int main(void)
{
//unsigned int dir;

// Insert code
i2c_init();
uart_init();

// Insert code
initBuff();
presmenu();

while(1)
{
if(flagcommand) comando();
}

return 0;
}

void comando()
{
int i,j,u,h;
unsigned char hh,hl; //variables para extraer la dir de memoria
boolean flagValido = false;
char buffer[5];
char buf[lenbuff];
char arg[lenbuff];
clrbit(UCSR1B, RXCIE1); //deshabilitar la recepcion de datos

for(i=0; i< lenbuff; i++){


arg[i]= 0x00;
}

//Cdigo para procesar /?


if(cbuff[0]=='/' && cbuff[1]=='?'){

flagValido = true;
presmenu();
}

//Codigo para procesar /B


if(cbuff[0]=='/' && cbuff[1]=='B'){
flagValido = true;
uart_print("\r\nFormateando");
j=0;
for( j=0;j<0x10000;j++){
write2EEPROM(0x00,i);
}
//Escribiendo la direccion indice
write2EEPROM(0x00,0);
write2EEPROM(0x02,1);
}

//Codigo para procesar /r


if(cbuff[0]=='/' && cbuff[1]=='r'){
flagValido = true;
for(i=0; i<16;i++){
sprintf(buffer,"%X",i);
uart_print(buffer);
}
uart_print("\r\n");

for( j=0; j<16;j++)


uart_print("==");
uart_print("\r\n");

for(i=0;i<0x10000;i++){
u = read2EEPROM(i);
sprintf(buffer,"%X",u);
uart_print(buffer);
}
uart_print("\r\n\r\n");
}

//Procesar comando /w dat


if(cbuff[0]=='/' && cbuff[1]=='w'){
flagValido = true;
i=3;//Se estrae la cadena a escribir n la eeprom
do{

arg[i-3] = cbuff[i];
}while(cbuff[++i]!=0x00);

hh = read2EEPROM(0x0000);
hl = read2EEPROM(0x0001);
h = hh<<8;
h = h|hl;
uart_print("Escribir ");
uart_print(arg);
uart_print(" a partir de ");
sprintf(buffer,"%X",h);
uart_print(buffer);
uart_print("\r\n\r\n");
i=0;
do{
write2EEPROM(arg[i],h);
++h;//colocate en la siguinte direccion
++i;//escribe el siguiente caracter en dat
}while(arg[i]!=0x00);

//actualizar el indice
--h;
hh=(unsigned char) (h>>8);
hl=(unsigned char) (h);

write2EEPROM(hh,0x0000);
write2EEPROM(hl,0x0001);

uart_print("Buffer escrito\r\n\r\n");
}

//procesando comando /i dir


//la direccion se procesa como hexadecimal
if(cbuff[0]=='/' && cbuff[1]=='i'){
flagValido = true;
i=3;
do{
arg[i-3] = cbuff[i];
}while(cbuff[++i]!=0x00);

h= (16*ascii2hex(arg[1]) + (ascii2hex(arg[0])) +
(16*16*ascii2hex(arg[2])) +
(16*16*16*ascii2hex(arg[3])));

//Se calcula la direccion a partir de lo recibido

//Se escribe el nuevo indice


hh=(unsigned char) (h>>8);
hl=(unsigned char) (h);
write2EEPROM(hh,0x0000);
write2EEPROM(hl,0x0001);

if(flagValido == false){
uart_print("");
sprintf(buf,"%uc",cbuff);
uart_print(buf);
uart_print("?");
}
initBuff();
setbit(UCSR1B,RXCIE1);
}

void presmenu()
{
delay_ms(25);
uart_print("\n\r");
uart_print("EEPROM Lectura Escritura por PC\n\r");
uart_print("control por buffer\n\r");
uart_print("[ENTER] procesa el comando\n\r");
uart_print("[ESC] Borra todo el buffer\n\r");
uart_print("[DEL] Borra el ultimo caracter del buffer\n\r");
uart_print("\n\r\n\r");
uart_print("Comando EEPROM\n\r");
uart_print("/? ------- Presenta menu nuevamente\n\r");
uart_print("/B ------- Formatea la memoria EEPROM\n\r");
uart_print("/r ------- lee el contenido completo de la EEPROM y lo vuelca por RS232\n\r");
uart_print("/w <dat> - Escribe la cadena <dat> en la EEPROM a partir de la direccion indice\n\r");
uart_print("/i <dir> - Coloca el indice de la EEPROM en 0x<dir> sin borrar contenido\n\r");
uart_print("\n\r");
delay_ms(25);
}

void initBuff(void)

{
int i;
for(i=0;i<lenbuff; i++)
{
cbuff[i]=0x00;
}xbuff=0x00;
}

void add2cbuff(unsigned char c)


{

if(xbuff<lenbuff)
{
switch(c)
{
case INTRO:
flagcommand = true;
break;
case RETROCESO:
if(xbuff>0) cbuff[--xbuff] = 0x00;
break;
case ESCAPE:
initBuff();
break;
default:
cbuff[xbuff++]=c;
}
}
else
{
initBuff();
uart_print("ERROR\r\n");
}

void echosel(unsigned char c)


{
switch(c)
{
case INTRO:
uart_print("\r\n");

break;
case RETROCESO:
uart_transmit(RETROCESO);
break;
case ESCAPE:
uart_transmit(ESCAPE);
break;
default:
uart_transmit(c);
}
}

void write2EEPROM(unsigned char data, unsigned int dir)


{
unsigned char dirl, dirh;
dirh = (unsigned char) (dir >> 8);
dirl = (unsigned char) (dir);
i2c_start_wait(devAA512+I2C_WRITE);
i2c_write(dirh);
i2c_write(dirl);
i2c_write(data);
i2c_stop();
delay_ms(10);
}

unsigned char read2EEPROM(unsigned int dir)


{
unsigned char leido, dirh, dirl;
dirh = (unsigned char) (dir >> 8);
dirl = (unsigned char) (dir);
i2c_start_wait(devAA512+I2C_WRITE);
i2c_write(dirh);
i2c_write(dirl);
i2c_rep_start(devAA512+I2C_READ);
leido=i2c_readNak();
i2c_stop();
return leido;
}

Librera de comunicacin serial, cabecera y fuentes


#ifndef __UART_H
#define __UART_H

//#define F_CPU 16000000L


#include "clk.h"

# define USART_BAUDRATE 9600UL


# define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL))) - 1)

//definicion de teclas
#define INTRO 0x0D
#define RETROCESO 0x08
#define ESCAPE 0x1B

void uart_transmit( unsigned char data );


unsigned char uart_receive(void);
void uart_init(void);
int uart_dataAvailable(void);
void uart_print(const char *s);

/**
* funcion para convertir un caracter ascii a hexadecimal
*/
int ascii2hex(char d);
#endif

// uart.c
// Originally for NerdKits with ATmega168, 14.7456 MHz clock
// mrobbins@mit.edu
// Modified for Adafruit ATMega32u4 Breakout, with 16.0000Mhz clock
// Note, this references serial 1, not 0, since the micro does not have 0.
// At least for the above breakout, D3 is TX, and D2 RX
// https://github.com/tomvdb/avr_arduino_leonardo/blob/master/examples/uart/main.c

#include "clk.h"
#include <avr/io.h>
#include <string.h>
#include "uart.h"

#include <util/delay.h>
#include <ctype.h>

// transmit a char to uart


void uart_transmit( unsigned char data )
{
// wait for empty transmit buffer
while ( ! ( UCSR1A & ( 1 << UDRE1 ) ) )
;

// put data into buffer, sends data


UDR1 = data;
}

// read a char from uart


unsigned char uart_receive(void)
{
while (!( UCSR1A & ( 1 << RXC1) ))
;

return UDR1;
}

// init uart
void uart_init(void)
{
// set baud rate
unsigned int baud = BAUD_PRESCALE;

UBRR1H = (unsigned char)(baud >> 8 );


UBRR1L = (unsigned char)baud;
//UBRR1H = 0;
//UBRR1L = 0x34;

// enable received and transmitter


UCSR1B = ( 1 << RXEN1 ) | ( 1 << TXEN1 );

// set frame format ( 8data, 2stop )


UCSR1C = ( 1 << USBS1 ) | ( 1 << UCSZ11 ) | (1 << UCSZ10);

// check if there are any chars to be read


int uart_dataAvailable(void)
{
if ( UCSR1A & ( 1 << RXC1) )
return 1;

return 0;
}

// write a string to the uart


void uart_print(const char *s)
{
register char c;
while((c=*s++)){
uart_transmit(c);
}
}
/*
void uart_print( char data[] )
{
int c = 0;

for ( c = 0; c < strlen(data); c++ )


uart_transmit(data[c]);
}
*/

int ascii2hex(char d)
{
int r = 0x00;
if(isxdigit(d))
{
if(isdigit(d))
{
r = d-'0';
}
if(isalpha(d))
{
d = toupper(d);
r = 10+(d-'A');

}
}
return(r);
}

Librera para la comunicacin I2C cabecera y fuentes


#ifndef _I2CMASTER_H
#define _I2CMASTER_H 1
/*************************************************************************
* Title:
*

C include file for the I2C master interface


(i2cmaster.S or twimaster.c)

* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury


* File:

$Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $

* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3


* Target: any AVR device
* Usage:

see Doxygen manual

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

#ifdef DOXYGEN
/**
@defgroup pfleury_ic2master I2C Master library
@code #include <i2cmaster.h> @endcode

@brief I2C (TWI) Master Software Library

Basic routines for communicating with I2C slave devices. This single master
implementation is limited to one bus master on the I2C bus.

This I2c library is implemented as a compact assembler software implementation of the I2C protocol
which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
Since the API for these two implementations is exactly the same, an application can be linked either against the
software I2C implementation or the hardware I2C implementation.

Use 4.7k pull-up resistor on the SDA and SCL pin.

Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
i2cmaster.S to your target when using the software I2C implementation !

Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.

@note
The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
to GNU assembler and AVR-GCC C call interface.

Replaced the incorrect quarter period delays found in AVR300 with


half period delays.

@author Peter Fleury pfleury@gmx.ch http://jump.to/fleury

@par API Usage Example


The following code shows typical usage of this library, see example test_i2cmaster.c

@code

#include <i2cmaster.h>

#define Dev24C02 0xA2

// device address of EEPROM 24C02, see datasheet

int main(void)
{
unsigned char ret;

i2c_init();

// initialize I2C library

// write 0x75 to EEPROM address 5 (Byte Write)


i2c_start_wait(Dev24C02+I2C_WRITE);

// set device address and write mode

i2c_write(0x05);

// write address = 5

i2c_write(0x75);

// write value 0x75 to EEPROM

i2c_stop();

// set stop conditon = release bus

// read previously written value back from EEPROM address 5


i2c_start_wait(Dev24C02+I2C_WRITE);

i2c_write(0x05);

// write address = 5

i2c_rep_start(Dev24C02+I2C_READ);

ret = i2c_readNak();
i2c_stop();

for(;;);
}
@endcode

*/
#endif /* DOXYGEN */

// set device address and write mode

// set device address and read mode

// read one byte from EEPROM

/**@{*/

#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304


#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
#endif

#include <avr/io.h>

/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_READ 1

/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */


#define I2C_WRITE 0

/**
@brief initialize the I2C master interace. Need to be called only once
@param void
@return none
*/
extern void i2c_init(void);

/**
@brief Terminates the data transfer and releases the I2C bus
@param void
@return none
*/
extern void i2c_stop(void);

/**
@brief Issues a start condition and sends address and transfer direction

@param

addr address and transfer direction of I2C device

@retval 0 device accessible


@retval 1 failed to access device
*/
extern unsigned char i2c_start(unsigned char addr);

/**

@brief Issues a repeated start condition and sends address and transfer direction

@param addr address and transfer direction of I2C device


@retval 0 device accessible
@retval 1 failed to access device
*/
extern unsigned char i2c_rep_start(unsigned char addr);

/**
@brief Issues a start condition and sends address and transfer direction

If device is busy, use ack polling to wait until device ready


@param

addr address and transfer direction of I2C device

@return none
*/
extern void i2c_start_wait(unsigned char addr);

/**
@brief Send one byte to I2C device
@param

data byte to be transfered

@retval 0 write successful


@retval 1 write failed
*/
extern unsigned char i2c_write(unsigned char data);

/**
@brief read one byte from the I2C device, request more data from device
@return byte read from I2C device
*/
extern unsigned char i2c_readAck(void);

/**
@brief read one byte from the I2C device, read is followed by a stop condition
@return byte read from I2C device
*/
extern unsigned char i2c_readNak(void);

/**
@brief read one byte from the I2C device

Implemented as a macro, which calls either i2c_readAck or i2c_readNak

@param

ack 1 send ack, request more data from device<br>

0 send nak, read is followed by a stop condition


@return byte read from I2C device
*/
extern unsigned char i2c_read(unsigned char ack);
#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();

/**@}*/
#endif

/*************************************************************************
* Title:

I2C master library using hardware TWI interface

* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury


* File:

$Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $

* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3


* Target: any AVR device with hardware TWI
* Usage:

API compatible with I2C Software Library i2cmaster.h

**************************************************************************/
#include <inttypes.h>
#include <compat/twi.h>

#include "i2cmaster.h"

/* define CPU frequency in Mhz here if not defined in Makefile */


#ifndef F_CPU
#define F_CPU 4000000UL
#endif

/* I2C clock in Hz */
#define SCL_CLOCK 200000L //Velocidad de comunicacion para la memoria 24AA512

/*************************************************************************
Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */

TWSR = 0;

/* no prescaler */

TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */

}/* i2c_init */

/*************************************************************************
Issues a start condition and sends address and transfer direction.
return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
uint8_t twst;

// send START condition


TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

// wait until transmission completed


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits.


twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

// send device address


TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);

// wail until transmission completed and ACK/NACK has been received


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits.


twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;

return 0;

}/* i2c_start */

/*************************************************************************
Issues a start condition and sends address and transfer direction.

If device is busy, use ack polling to wait until device is ready

Input: address and transfer direction of I2C device


*************************************************************************/
void i2c_start_wait(unsigned char address)
{
uint8_t twst;

while ( 1 )
{
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

// wait until transmission completed


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits.


twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;

// send device address


TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);

// wail until transmission completed


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits.


twst = TW_STATUS & 0xF8;
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
{
/* device busy, send stop condition to terminate write operation */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

// wait until stop condition is executed and bus released


while(TWCR & (1<<TWSTO));

continue;
}
//if( twst != TW_MT_SLA_ACK) return 1;
break;
}

}/* i2c_start_wait */

/*************************************************************************
Issues a repeated start condition and sends address and transfer direction

Input: address and transfer direction of I2C device

Return: 0 device accessible


1 failed to access device
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start( address );

}/* i2c_rep_start */

/*************************************************************************
Terminates the data transfer and releases the I2C bus
*************************************************************************/
void i2c_stop(void)
{
/* send stop condition */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

// wait until stop condition is executed and bus released


while(TWCR & (1<<TWSTO));

}/* i2c_stop */

/*************************************************************************
Send one byte to I2C device

Input:

byte to be transfered

Return: 0 write successful


1 write failed
*************************************************************************/
unsigned char i2c_write( unsigned char data )
{
uint8_t twst;

// send data to the previously addressed device


TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);

// wait until transmission completed


while(!(TWCR & (1<<TWINT)));

// check value of TWI Status Register. Mask prescaler bits


twst = TW_STATUS & 0xF8;
if( twst != TW_MT_DATA_ACK) return 1;
return 0;

}/* i2c_write */

/*************************************************************************
Read one byte from the I2C device, request more data from device

Return: byte read from I2C device


*************************************************************************/
unsigned char i2c_readAck(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));

return TWDR;

}/* i2c_readAck */

/*************************************************************************
Read one byte from the I2C device, read is followed by a stop condition

Return: byte read from I2C device


*************************************************************************/
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));

return TWDR;

}/* i2c_readNak */

Librera de ajustes generales para el ATMega32u4


#ifndef CLK_H
#define CLK_H
/**
@defgroup atmega32u4_clk Prescaler_Macros
@code #include <clk.h> @endcode

@brief Macros para definir la frecuencia de oscilacion del reloj


principal
*/

/*@{*/

/**
* @name Definitions for MCU Clock Frequency
* Adapt the MCU clock frequency in Hz to your target.
* Revisa las paginas 37-39
*/

#define F_CPU 1000000L


#if F_CPU == 16000000L
#define ADC_PRESCALER 0x07 /**<Factor de division 128 F_ADC = 125kHz*/
#define CPU_PRESCALER 0x00
#elif F_CPU == 8000000L
#define ADC_PRESCALER 0x06 /**<Factor de division 64 F_ADC = 125kHz*/
#define CPU_PRESCALER 0x01
#elif F_CPU == 4000000L
#define ADC_PRESCALER 0x05 /**<Factor de division 32*/
#define CPU_PRESCALER 0x02
#elif F_CPU == 2000000L
#define ADC_PRESCALER 0x04 /**<Factor de division 16*/
#define CPU_PRESCALER 0x03
#elif F_CPU == 1000000L
#define ADC_PRESCALER 0x03 /**<Factor de division 8*/
#define CPU_PRESCALER 0x04
#else
#error "Teensyduino only supports 16, 8, 4, 2, 1 MHz. Please edit boards.txt"
#endif

/**
* @name Macros para sustituir el seteo de bits individuales
*/
#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=_BV(bit)) /**<Pone en set un bit*/
#define clrbit(sfr,bit) (_SFR_BYTE(sfr)&=~_BV(bit)) /**<Pone en clear un bit*/
#define togglebit(sfr,bit) (_SFR_BYTE(sfr)^=_BV(bit)) /**<Cambia el estado de bit*/

/**
* @name Functions
*/

/**
@brief Funcion para inicializar los tiempos en el ATMega32U4
@param

none

@return none
*/

void _init_Teensyduino_internal_(void);

void delay_ms(unsigned int time_ms);

/*@}*/
#endif //end clk.h

#include "clk.h"
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include "clk.h"

void _init_Teensyduino_internal_(void)
{

cli();
CLKPR = 0x80;
CLKPR = CPU_PRESCALER;
}

void delay_ms(unsigned int time_ms)

{
unsigned int i;
for(i=0; i<time_ms; i++)
_delay_ms(1);
}

ndice de figuras
figura 1: MCU, MPU, microcomputadora.................................................................................................8
figura 2: Partes e interfaces de un microcontrolador.................................................................................9
figura 3: Definiciones de arquitectura de computadoras..........................................................................13
figura 4: Arquitectura Memoria Unificada...............................................................................................14
figura 5: Arquitectura Memoria Separada................................................................................................14
figura 6: Cuadro comparativo entre microcontroladores.........................................................................20
figura 7: Arquitectura AVR......................................................................................................................21
figura 8: Mapeo de memoria del ATMega32U4......................................................................................22
figura 9: Pinout del microcontrolador ATMega32U4..............................................................................26
figura 10: Sistema de reloj del ATMega32U4..........................................................................................35
figura 11: Formas de onda de reloj...........................................................................................................36
figura 12: Opciones para configurar el reloj............................................................................................37
figura 13: Conexin de cristal de bajo consumo......................................................................................37
figura 14: Palabra en FUSES para la conexin de oscilador de bajo consumo.......................................38
figura 15: Palabra para seleccionar el reloj interno..................................................................................38
figura 16: Conexin de Reloj externo......................................................................................................38
figura 17: Sistema de reloj de PLL..........................................................................................................39
figura 18: fuentes de reset........................................................................................................................40
figura 19: Relacin entre velocidad y alimentacin.................................................................................42
figura 20: Tarjeta para prcticas...............................................................................................................53
figura 21: Esquema elctrico de proteccin de una terminal E/S............................................................63
figura 22: Teclado matricial 4 x 4............................................................................................................64
figura 23: Lectura de un teclado matricial...............................................................................................65
figura 24: Conexiones display de 7 segmentos........................................................................................72
figura 25: Pinout display de 7 segmentos................................................................................................72
figura 26: Diagrama de funcionamiento de sensor ultrasnico................................................................79
figura 27: Terminales del SRF-04............................................................................................................79
figura 28: rango de deteccin...................................................................................................................80
figura 29: Transistor inversor...................................................................................................................81
figura 30: seguidor emisivo......................................................................................................................81
figura 31: Acoplamiento con transistor PNP............................................................................................82
figura 32: Conexin bsica de relevador..................................................................................................82
figura 33: Montaje Darlington.................................................................................................................83

figura 34: Doble transistor de activacin.................................................................................................83


figura 35: Clculo de conexin a Relevador............................................................................................84
figura 36: circuito saturacin...................................................................................................................85
figura 37: curva caracterstica..................................................................................................................85
figura 38: Saturacin de un MOSFET.....................................................................................................85
figura 39: Circuito equivalente en saturacin..........................................................................................86
figura 40: Circuito equivalente en corte...................................................................................................86
figura 41: Ejemplos de optoacopladores..................................................................................................87
figura 42: Optoacoplador de herradura....................................................................................................87
figura 43: Optoacoplador de reflexin.....................................................................................................87
figura 44: Empaquetados de optoacopladores..........................................................................................88
figura 45: Caractersticas mecnicas de empaquetados...........................................................................89
figura 46: pinout del ULN2803................................................................................................................90
figura 47: Pinout del L293.......................................................................................................................91
figura 48: Diagrama de estados propuesto...............................................................................................92
figura 49: circuito estados lgicos..........................................................................................................100
figura 50: motor a pasos unipolar..........................................................................................................101
figura 51: Motor a pasos bipolar............................................................................................................101
figura 52: Servomotor DC aeromodelismo............................................................................................102
figura 53: Desensamble de un servo......................................................................................................103
figura 54: Cables de un servo estndar..................................................................................................103
figura 55: Seales y posiciones de un servo...........................................................................................104
figura 56: Secuencia para leer el sensor ultrasnico..............................................................................104
figura 57: Prctica sensor ultrasnico....................................................................................................105
figura 58: circuito medidor de distancia ultrasnico..............................................................................105
figura 59: circuito con LCD e interrupciones........................................................................................123
figura 60: Arquitectura del Temporizador 0...........................................................................................128
figura 61: Arquitectura del Timer 0........................................................................................................131
figura 62: Prescaladores y relojes del timer0 y timer1...........................................................................131
figura 63: Preescalador del timer 2........................................................................................................133
figura 64: Reloj Digital Simple..............................................................................................................142
figura 65: Reloj con base en Timer 0.....................................................................................................150
figura 66: Conmutando la alimentacin de una carga podemos lograr un rgimen de trabajo variable179
figura 67: Acumulacin de tiempos controlable por microcontrolador.................................................180
figura 68: El IRFZ44N en su hoja de datos...........................................................................................181

figura 69: Efecto del voltaje Vgs en un MOSFET.................................................................................182


figura 70: Fotografa de IRFZ44N.........................................................................................................182
figura 71: Circuito de Aplicacin...........................................................................................................183
figura 72: Circuito para generar PWM en ATMega48...........................................................................192
figura 73: circuito para control PWM de motor DC con L293D...........................................................195
figura 74: Diagrama de estados para prctica con PWM.......................................................................199
figura 75: Funcionamiento de PWM con motor DC..............................................................................200
figura 76: Secuencia de activacin en bobina........................................................................................202
figura 77: Circuito equivalente de bobina en Tr.....................................................................................203
figura 78: diagrama de flujo para promediado de lecturas de ADC.......................................................210
figura 79: Lectura de ADC ATmega48...................................................................................................212
figura 80: Configuracin de libreria RxTx en Netbeans agregando JAR..............................................229
figura 81: Configuracin de librerias RxTx en netbeans.......................................................................230
figura 82: Conexin memoria 24C512...................................................................................................250
figura 83: Diagrama de lectura - escritura de una eeprom i2c...............................................................251
figura 84: Escritura y lectura simple de una EEPROM sobre I2C.........................................................254

ndice de tablas
Tabla 1: Caractersticas especiales del Puerto B en el ATMega32U4......................................................28
Tabla 2: Caractersticas especiales del Puerto C en el ATMega32U4......................................................29
Tabla 3: Caractersticas especiales del Puerto D en el ATMega32U4.....................................................30
Tabla 4: Caractersticas especiales del Puerto E en el ATMega32U4......................................................31
Tabla 5: Cdigo mquina.........................................................................................................................47
Tabla 6: Ejemplo de cdigo fuente en ensamblador................................................................................48
Tabla 7: Ejemplo de cdigo fuente en C..................................................................................................49
Tabla 8: Cdigo de ejemplo de teclado matricial.....................................................................................69
Tabla 9: Cdigo de ejemplo para display de siete segmentos..................................................................75
Tabla 10: Cdigo de AHDL para control por FSM..................................................................................92
Tabla 11: Cdigo para control por FSM...................................................................................................97
Tabla 12: Vectores de Interrupcin.........................................................................................................108
Tabla 13: Equivalencias entre vectores del datasheet y AVRGCC........................................................109
Tabla 14: Control de sensado de Interrupcin externa...........................................................................110
Tabla 15: Cdigo para configuracin de interrupciones externas - Shawn Johnson..............................111
Tabla 16: Ejemplo de uso de libreras LCD de Shawn Johnson............................................................113
Tabla 17: Librera LCD de Shawn Johnson - lcd.h................................................................................115
Tabla 18: Librera lcd de Shawn Johnson -lcd.c....................................................................................119
Tabla 19: Cdigo para control de puente H...........................................................................................125
Tabla 20: Bits para configuracin de Interrupciones del comparador analgico...................................139
Tabla 21: Cdigo fuente Reloj digital con display de 7 segmentos basado en ATmega48....................143
Tabla 22: Librera para configuracin del timer0 - timer0.h..................................................................144
Tabla 23: Librera para configuracin del timer0 - timer0.c..................................................................145
Tabla 24: Librera para configuracin del timer1 - timer1.h..................................................................145
Tabla 25: Librera para configuracin del timer1 - timer1.c..................................................................146
Tabla 26: Cdigo fuente para configurar el timer 0 en modo CTC.......................................................147
Tabla 27: Librera lcd.h de Peter Fleury.................................................................................................155
Tabla 28: Librera lcd.c de Peter Fleury.................................................................................................170
Tabla 29: Librera clk.h..........................................................................................................................172
Tabla 30: Librera clk.c..........................................................................................................................173
Tabla 31: Cdigo configuracin de timers con PWM............................................................................186
Tabla 32: Cdigo para la configuracin de timers.................................................................................194
Tabla 33: Cdigo control PWM de puente H.........................................................................................199

Tabla 34: Secuencia de energizacin de bobinas de motor bipolar en medios pasos............................202


Tabla 35: Lectura del ADC en ATmega48.............................................................................................217
Tabla 36: librera usart.h........................................................................................................................225
Tabla 37: librera usart.c.........................................................................................................................229
Tabla 38: Encendido de leds a travs de puerto serie en microcontrolador...........................................231
Tabla 39: Cdigo fuente de Java para verificar puertos seriales habilitados.........................................235
Tabla 40: Cdigo para envo de datos binarios adquiridos por el ADC a travs del puerto serial.........241
Tabla 41: Script de scilab para comunicacin con el puerto serial........................................................241
Tabla 42: Librera Peter Fleury twimaster.c...........................................................................................248
Tabla 43: Libreria Peter Fleury i2cmaster.h...........................................................................................253
Tabla 44: Ejemplo de uso de libreria i2c................................................................................................253
Tabla 45: Estructura de direccin de una memoria EEPROM I2C........................................................253
Tabla 46: funcin de escritura de una EEPROM I2C............................................................................255
Tabla 47: funcin de lectura de una EEPROM I2C...............................................................................256
Tabla 48: Lectura escritura simple de una eeprom.................................................................................258

Referencias
Biblioman. (2013). Implementacin de una Mquina de Estados Finita en un PIC. AquiHayApuntes.
Retrieved

June

6,

2014,

from

http://www.aquihayapuntes.com/indice-practicas-pic-en-

c/implementacion-de-una-maquina-de-estados-finita-en-un-pic.html
Carletti, E. (2007). Servos - Caractersticas bsicas. Robots Argentina pasin por la robtica en
Argentina. Retrieved June 6, 2014, from http://robots-argentina.com.ar/MotorServo_basico.htm
Chavarrea, G., & Chiluisa, A. (2013). construccin e implementacin de un circuito electrnico
mediante un sensor de huellas dactilares para el control de ingreso y salida del personal
autorizado al cuarto de equipos de computacin ubicado en el Instituto de Estudios del Petrolo
- Quito (Proyecto previo a la obtencin del ttulo de Tecnologo en Electrnica y
Telecomunicaciones). Quito Ecuador: Escuela Politecnica Nacional, Escuela de formacin de
Tecnolgos. Retrieved from http://bibdigital.epn.edu.ec/bitstream/15000/6359/1/CD-4882.pdf
Devantech Ltd. (2003). SRF04 Technical Documentation. Robot electronics. Retrieved March 10,
2014, from http://www.robot-electronics.co.uk/htm/srf04tech.htm
EPSA. (2001). Optoelectrnica. Laboratorio de electrnica - Escuela Politecnica Superior de
Albacete.

Retrieved

June

6,

2014,

from

http://www.info-

ab.uclm.es/labelec/solar/Componentes/OPTOELECTRONICA.html
Gadre, D. (2000). Programming and Customizing the AVR Microcontroller (1 edition.). New York:
McGraw-Hill/TAB Electronics.
Mario. (2010). IRFZ44N: El MOS-FET de batalla para PWM. NeoTeo. Retrieved June 6, 2014, from
http://www.neoteo.com/irfz44n-el-mos-fet-de-batalla-para-pwm/
Motion Control. (2010). Sistema de realimentacin de posicin (I): encoder o resolver:Motion Control.
Motion Control - Control de movimiento y accionamientos elctricos. Retrieved June 6, 2014,
from

http://www.infoplc.net/blog4/2010/12/03/sistema-de-realimentacion-de-posicion-i-

encoder-o-resolver/
Pablin. (2008). Detector Infrarrojo de proximidad. PABLIN Portal de tecnologa de habla hispana.
Retrieved June 6, 2014, from http://www.pablin.com.ar/electron/circuito/varios/proximid/

Quadruino. (2014). Protocolo I2C / TWI - Quadruino. Quadruino A free software and hardware
Quadracopter.

Retrieved

June

6,

2014,

from

http://www.quadruino.com/guia-

2/sensores/protocolo-i2c-twi
RedRaven. (2010). Procesador de comandos via RS232 (con buffer de recepcin). PicMania by
RedRaven.

Retrieved

June

6,

2014,

from

http://picmania.garcia-

cuervo.net/picc.php#COMBUF232
UNLP. (2010). Instrumentacin y Comunicaciones Industriales - Facultad de Ingeniera - UNLP.
Apuntes

de

Ctedra.

Retrieved

http://www.ing.unlp.edu.ar/electrotecnia/procesos/

June

6,

2014,

from

ndice alfabtico
A
arquitectura.............................................................................................................6, 13 ss., 19, 58, 80, 82
Arquitectura..........................................................................................................................13, 18 s., 58 s.
C
CPU............................................................................................................................................................9
Cristal oscilador de baja frecuencia.........................................................................................................34
Cristal oscilador de bajo consumo...........................................................................................................33
F
Fuentes de Reloj.......................................................................................................................................33
M
MEMORIA de PROGRAMA....................................................................................................................9
microcomputadora..................................................................................................................................6 s.
Microcomputadora................................................................................................................................6 ss.
Microcontrolador.......................................................................................................................................7
Microprocesador........................................................................................................................................7
Modelo Acumulador................................................................................................................................14
Modelo Registro-memoria.......................................................................................................................15
Modelo Registro-registro.........................................................................................................................15
Modo Idle.................................................................................................................................................37
Modo Power-down...................................................................................................................................37
Modo Power-save.....................................................................................................................................37
Modo Reduccin de ruido en ADC..........................................................................................................37
Modo Standby..........................................................................................................................................38
O
Oscilador interno RC calibrado................................................................................................................34
P
perro guardin........................................................................................................................16, 31, 34, 37
Perro guardin..........................................................................................................................................37
Perro Guardin.........................................................................................................................................37
PERRO GUARDIN..............................................................................................................................10
PLL...........................................................................................................................................................35
PORTB.....................................................................................................................................................24
Puerto C....................................................................................................................................................25

Puerto D...................................................................................................................................................26
Puerto E....................................................................................................................................................27
Puerto F....................................................................................................................................................28
puerto serial..............................................................................................................................10, 211, 214
PUERTO SERIAL...................................................................................................................................10
PUERTOS ANALGICOS.....................................................................................................................10
PUERTOS DIGITALES...........................................................................................................................10
R
ram....................................................................................................................................13, 16, 60 ss., 66
RAM...............................................................................................................................................7, 10, 16
reloj.............................................................10, 16, 22, 24, 26 ss., 37 s., 119 s., 122 s., 132, 173, 178, 186
Reloj...........................................................................................................................11, 25 ss., 32 ss., 120
RELOJ......................................................................................................................................................10
Reloj de entradas/salidas..........................................................................................................................32
Reloj del convertidor analgico-digital....................................................................................................32
Reloj del CPU..........................................................................................................................................32
Reloj del prescalador PLL........................................................................................................................33
Reloj del timer de alta velocidad..............................................................................................................33
Reloj del USB..........................................................................................................................................33
Reloj externo............................................................................................................................................34
Reloj flash................................................................................................................................................32
reset.......................................................................................................10, 24 ss., 34, 37, 86, 88, 128, 134
Reset.......................................................................................................16, 22, 29, 36, 42, 45, 100 s., 138
RESET........................................................................................................................10, 22, 29, 37, 100 s.
RTC.................................................................................................................................11, 88, 114 s., 132
T
timer..................................................10, 16, 32 ss., 99, 118, 124, 127, 132, 134 s., 137 ss., 174, 181, 185
Timer...........................................................16, 26 s., 32, 100 ss., 118 s., 122 ss., 126, 128, 134, 138, 172
TIMER.....................................................................................................................10, 101 ss., 133, 136 s.
V
Velocidad mxima vs velocidad...............................................................................................................38

Das könnte Ihnen auch gefallen