Beruflich Dokumente
Kultur Dokumente
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
Unidad 1
Conceptos introductorios a los microcontroladores
diferencias
mas
importantes
entre
Microcomputadora,
Para elaborar esta actividad, se requiere del uso de un equipo de cmputo y presentarlo en sesion.
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
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.
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
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
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
Sub Rx,B
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
Load Ry,B
Sub Rz,Rx,Ry
Store C,Rz
; Rz se almacena en la variable C
Compaia
Dispositivo
Memoria On-Chip
Otras caractersticas
Nil
Atmel Corp
ATtiny11
1-kbyte Flash
Dallas Semi
DS80C310
256- RAM
Hitachi
H8/3640
8kByte de ROM
PIC16CR54C
Motorola
68HC705KJ1
STMicro
ST6203CB1
1 kByte de ROM
64- Byte de RAM
Actividad de aprendizaje
Resumen: Acuar las principales caractersticas sobre microcontroladores de 8 bits y sus fabricantes
Unidad 2
Arquitectura interna de un 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.
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.
2.4 Perifricos
Los perifricos con los que cuenta el ATMega32u4 son los siguientes:
Un temporizado de alta velocidad con resolucin de 10 bits con PLL (64MHz) y modo de
comparacin
Seis canales PWM para operaciones de alta velocidad, con resolucin programable de 2 a 11
bits.
Instrucciones de ramificado
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
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.
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
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).
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)
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).
INT6/AIN0
( Entrada de Interrupcin externa 6, Entrada positiva del comparador analgico ).
PE2
nHWB
(Activacin del Bootloader)
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.
ANTECEDENTES
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.
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.
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.
Unidad 4
Herramientas de desarrollo de los microcontroladores
Competencia especfica
Utilizar las herramientas de desarrollo de los microcontroladores.
Actividades de aprendizaje:
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.
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.
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.
;//////////////////////////////////////////////////////////////
;/// 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
;//////////////////////////////////////////////////////////////
;
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
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();
while(1);
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
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
10. sasasa
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
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";
Escoge las librerias que te interesa instalar (yo seleccion todas y di clic en siguiente)
Una vez instalado nos aparece la ventana que indica que ya ha terminado la instalacin.
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 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
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
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.
/**
*
*
*
* @author miguel
* @date 03/03/2013
* @brief Programa que lee un teclado matricial y saca por los pines
*
*
* @file main.c
*/
#include <avr/io.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
/************************************************************************/
/* 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
DDD1
DDD2
DDD3
/************************************************************************/
/* @brief Macros para colocar un valor bajo en cada fila y ser detectada
*
en las columnas
* @params vacio
* @returns vacio
*/
/************************************************************************/
/**
* Salidas para leds
*/
#define pin_X0
PB0
PORTB
#define pin_X2
PB2
/**
* Configuracion para salidas
*/
#define cpin_X0
DDB0
DDB2
/***
* Programa Principal
*/
int main(void)
{
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
*
*
* @returns devuelve un tipo char sin signo entre 0 a 16, si no se presiona ninguna
*
*
*
Ejemplo:
\verbatim
*
*
tecla=ui8_TestKeyPad();
\endverbatim
*/
unsigned char ui8_TestKeyPad(void)
{
unsigned char k;
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);
}
/**
* @author miguel montiel mtz
* @date 03/03/2013
* @brief Programa que muestra en un display de 7 segmentos
*
*
*
* \verbatim
*
seg_b
seg_c
seg_d
seg_e
seg_f
seg_g
*
*
pseg_b
pseg_g
*
*
Del mismo modo se deben declarar los puerto para ser configurados
como salidas
*
*
cseg_b
cseg_c
cseg_g
*
*
cpseg_b
cpseg_g
*\endverbatim
*
*
* @file display.c
*/
#include <avr/io.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
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
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);
}
/**
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);
}
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):
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 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:
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.
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 :
Solucin:
VGS(on)
4,5V
ID(on)
75 mA
RDS(on)
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
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).
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.
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
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.
Para los casos anteriores al dejar de pulsar start el motor se mantiene girando en el sentido
indicado por I_nD.
Descripcin
Puerto
Tipo
start
Botn de inicio
PINC1
Entrada
stop
Botn de paro
PINC2
Entrada
I_nD
Botn de sentido
PINB0
Entrada
PD0
Salida
PD1
Salida
En
PD2
Salida
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
SUBDESIGN Motor
(clock, reset
start,stop,I_nD
:INPUT;
:INPUT;
:OUTPUT;
a,b,En
:OUTPUT;)
VARIABLE
fsm
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;
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>
PINC1
#define pstart
PINC
PINC2
#define pstop
PINC
PINB0
#define pI_nD
PINB
#define a
PD0
#define Pa
#define b
PORTD
PD1
#define Pb
PORTD
#define En
PD2
#define pEn
PORTD
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 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);
}
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);
}
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);
}
break;
}
}
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.
Unidad 6
Interrupciones en un microcontrolador
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.
Nombre de
Vector de Interrupcin
Fuente de interrupcin
0x0000
RESET
0x0002
INT0
0x0004
INT1
0x0006
INT2
0x0008
PCINT0
0x000A
PCINT1
0x000C
PCINT2
0x000E
PCINT3
0x0010
WDT
10
0x0012
TIMER2_COMPA
11
0x0014
TIMER2_COMPB
12
0x0016
TIMER2_OVF
Timer/Counter2 Overflow
13
0x0018
TIMER1_CAPT
14
0x001A
TIMER1_COMPA
15
0x001C
TIMER1_COMPB
16
0x001E
TIMER1_OVF
Timer/Counter1 Overflow
17
0x0020
TIMER0_COMPA
18
0x0022
TIMER0_COMPB
19
0x0024
TIMER0_OVF
Timer/Counter0 Overflow
20
0x0026
SPI_STC
21
0x0028
USART0_RX
USART0 Rx Complete
22
0x002A
USART0_UDRE
23
0x002C
USART0_TX
USART0 Tx Complete
24
0x002E
ANALOG_COMP
Analog Comparator
25
0x0030
ADC
26
0x0032
EE_READY
EEPROM Ready
27
0x0034
TWI
28
0x0036
SPM_READY
Nombre de
Vector de Interrupcin
Fuente de interrupcin
29
0x0038
USART1_RX
USART1 Rx Complete
30
0x003A
USART1_UDRE
31
0x003C
USART1_TX
USART1 Tx Complete
32
0x003E
TIMER3_CAPT
33
0x0040
TIMER3_COMPA
34
0x0042
TIMER3_COMPB
35
0x0044
TIMER3_OVF
Timer/Counter3 Overflow
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
ISCx0
Descripcin
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();
while(1)
// Bucle infinito
{
PINC = 0x02; // Conmutar pin PC1
delay_ms(600); // Pausa de 600ms
}
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);
}
}
/******************************************************************************
* FileName: lcd.h
* Purpose:
*
*
* Copyright (C) 2008 - 2013 Shawn Johnson. All rights reserved.
*
* License:
*****************************************************************************/
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
//****************************************************************************
//
//****************************************************************************
PINB
PINB
/* 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
//****************************************************************************
//
//****************************************************************************
#define LCD_CLEAR 0x01
// Limpiar Display
// Lnea 1 posicin 0
// Lnea 2 posicin 0
//****************************************************************************
//
PROTOTIPOS DE FUNCIONES
//****************************************************************************
void lcd_init(void);
// Inicializa el LCD
/******************************************************************************
* FileName: lcd.c
* Purpose:
*
*
* Copyright (C) 2008 - 2013 Shawn Johnson. All rights reserved.
*
* License:
*****************************************************************************/
#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);
// > 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);
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);
//****************************************************************************
// 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);
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);
lcd_nibble(inst);
lcd_nibble(inst<<4);
//****************************************************************************
// Enva el nibble alto de 'nibble' al LCD.
//****************************************************************************
void lcd_nibble(char nibble)
{
lcd_CTRLout &= ~(1<<lcd_RW);
lcd_DATAddr |= 0xF0;
lcd_CTRLout |= (1<<lcd_E);
_delay_us(2);
// Pulso de Enable
//
// 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)
_delay_us(2);
lcd_CTRLout |= (1<<lcd_E);
_delay_us(2);
// Habilitar LCD
high = lcd_DATAin;
lcd_CTRLout |= (1<<lcd_E);
_delay_us(2);
// Habilitar LCD
low = lcd_DATAin;
//
// 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);
//****************************************************************************
// 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);
//****************************************************************************
// 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);
//****************************************************************************
// Envan instrucciones de comando y de datos al LCD.
//****************************************************************************
void lcd_cmd(char com)
{
lcd_write(com, 0);
}
void lcd_data(char dat)
{
lcd_write(dat, 1);
//****************************************************************************
// Genera un delay de n milisegundos
//****************************************************************************
void ldelay_ms(unsigned char n)
{
while(n--)
_delay_us(1000);
}
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
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.
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.
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"
/**
* @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
PINC2
#define pstop
PINC
PIND2
#define pI_nD
PIND
#define a
PC3
#define Pa
#define b
PORTC
PC4
#define Pb
PORTC
#define En
PC5
#define pEn
PORTC
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
*/
/**
* @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);
sei();
while(1)
{
lcd_gotorc(1,5);
lcd_puts("MOTOR");
lcd_gotorc(2,4); //renglon 2 columna 4
lcd_puts(" DETENIDO ");
clearbit(pEn,En);
{
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);
}
}
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.
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.
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.
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
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.
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.
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
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.
Tabla CS02
Fuente de reloj del Timer0
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:
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=
5 ms10 MHz
50 000
=256
=60,67=61(redondear hacia arriba)
256
256
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 s4MHz
800
=256
=156
8
8
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.
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.
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.
ACIS0
Modo de Interrupcin
Reservado
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
#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
_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
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
#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;
}
#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);
}
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
(1MHz)(21.68ms)
=21680=0x54B0
1
return 0;
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:
#ifndef LCD_H
#define LCD_H
/*************************************************************************
Title
Author:
File:
/**
@defgroup pfleury_lcd LCD library
@code #include <lcd.h> @endcode
Memory mapped mode compatible with Kanda STK200, but supports also
generation of R/W signal through A8 address line.
*/
/*@{*/
#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
/**
* @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
#define LCD_WRAP_LINES
#define LCD_IO_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
#define LCD_DATA0_PIN
#define LCD_DATA1_PIN
#define LCD_DATA2_PIN
#define LCD_DATA3_PIN
#define LCD_RS_PORT
LCD_PORT
#define LCD_RS_PIN
#define LCD_RW_PORT
#define LCD_RW_PIN
#define LCD_E_PORT
LCD_PORT
#define LCD_E_PIN
*/
*/
*/
*/
*/
0xC000
/* A15=E=1, A14=RS=1
0x0100
*/
/* A15=E=1, A14=RS=0
*/
#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.
*/
#define LCD_HOME
#define LCD_ENTRY_MODE
#define LCD_ENTRY_INC
#define LCD_ENTRY_SHIFT
*/
*/
*/
*/
*/
#define LCD_ON
#define LCD_ON_DISPLAY
#define LCD_ON_CURSOR
*/
*/
#define LCD_ON_BLINK
#define LCD_MOVE
/*
#define LCD_MOVE_RIGHT
#define LCD_FUNCTION_8BIT
#define LCD_BUSY
*/
#define LCD_FUNCTION_10DOTS 2
6
*/
*/
*/
*/
#define LCD_FUNCTION_2LINES 3
#define LCD_DDRAM
*/
2
5
#define LCD_CGRAM
*/
#define LCD_MOVE_DISP
#define LCD_FUNCTION
*/
*/
*/
/* set entry mode: display shift on/off, dec/inc cursor move direction */
#define LCD_ENTRY_DEC
#define LCD_ENTRY_DEC_SHIFT
#define LCD_ENTRY_INC_
#define LCD_ENTRY_INC_SHIFT
#define LCD_DISP_ON
#define LCD_DISP_ON_BLINK
*/
*/
#define LCD_DISP_ON_CURSOR
*/
*/
*/
#define LCD_MOVE_CURSOR_RIGHT
#define LCD_MOVE_DISP_LEFT
#define LCD_MOVE_DISP_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
@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
@param
@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
@return none
@see
lcd_puts_P
*/
extern void lcd_puts_p(const char *progmem_s);
/**
@brief Send LCD controller instruction command
@param
@return none
*/
extern void lcd_command(uint8_t cmd);
/**
@brief Send data byte to LCD controller
@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)
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
/****************************************************************************
Title
Author:
File:
DESCRIPTION
Basic routines for interfacing a HD44780U-based text lcd display
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))
*/
#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()
#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
#endif
#endif
/*
** function prototypes
*/
#if LCD_IO_MODE
static void toggle_e(void);
#endif
/*
** 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:
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 ;
(RS=1, RW=0) */
lcd_rs_high();
} else {
lcd_rs_low();
}
lcd_rw_low();
/*************************************************************************
Low-level function to read byte from LCD controller
Input:
rs
1: read data
#if LCD_IO_MODE
static uint8_t lcd_read(uint8_t rs)
{
uint8_t data;
if (rs)
lcd_rs_high();
*/
else
lcd_rs_low();
lcd_rw_high();
*/
lcd_e_high();
lcd_e_delay();
data = PIN(LCD_DATA0_PORT) << 4;
lcd_e_low();
lcd_e_delay();
*/
lcd_e_high();
lcd_e_delay();
data |= PIN(LCD_DATA0_PORT)&0x0F;
*/
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);
lcd_e_delay();
*/
/*************************************************************************
loops while lcd is busy, returns address counter
*************************************************************************/
static uint8_t lcd_waitbusy(void)
{
register uint8_t c;
/* the address counter is updated 4us after the busy flag is cleared */
delay(2);
}/* 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:
y vertical position
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;
#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:
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
|= _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);
*/
/* 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 5ms
*/
/* wait 64us
*/
/* 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);
#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 */
#ifndef CLK_H
#define CLK_H
/**
@defgroup atmega32u4_clk Prescaler_Macros
@code #include <clk.h> @endcode
/*@{*/
/**
* @name Definitions for MCU Clock Frequency
* Adapt the MCU clock frequency in Hz to your target.
* Revisa las paginas 37-39
*/
/**
* @name Macros para sustituir el seteo de bits individuales
*/
/**
* @name Functions
*/
/**
@brief Funcion para inicializar los tiempos en el ATMega32U4
@param
none
@return none
*/
void _init_Teensyduino_internal_(void);
/*@}*/
#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;
}
Unidad 7
Programacin del microcontrolador con aplicaciones
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.
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?
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.
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.
mnimos de operacin. Recuerda observar siempre la hoja de datos para lograr un diseo apropiado.
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
Regulacin de potencia
Rectificacin
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.
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)
while(1)
{
togglebit(PORTB,0);
delay_ms(1000);
}
return 0;
}
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 :
(analgicos)
#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;
#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
ISR(INT0_vect)
{
Derecha = FALSE;
}
ISR(INT1_vect)
{
Derecha = TRUE;
}
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 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);
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);
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:
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
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:
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
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
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
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:
ETOT
T CICLO
Unidad 8
El convertidor ADC y DAC
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.
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:
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
Reservado
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)
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"
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];
lcd_init();
adc_setup();
lcd_gotorc(1,5);
lcd_puts("ADC0");
while(1)
{
n = adc_read(0);
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)
setbit(ADMUX,ADLAR);
F_CPU/8 = 125kHz
ON
// Modo:
Manual
setbit(ADCSRA,ADEN);
//ADC habilitado
clearbit(ADCSRA,ADATE);
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);
while(bit_is_clear(ADCSRA,ADIF));
return ADCH;
}
Unidad 9
Puertos Seriales y memoria 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"
//definicion de teclas
#define INTRO 0x0D
#define RETROCESO 0x08
#define ESCAPE 0x1B
/**
* funcion que imprime un echo a la terminal, solo caracteres imprimibles
*/
void echosel(unsigned char c);
#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>
return UDR1;
}
// init uart
void uart_init(void)
{
// set baud rate
unsigned int baud = BAUD_PRESCALE;
return 0;
}
void initBuff(void)
{
int i;
for(i=0;i<lenbuff; i++)
{
cbuff[i]=0x00;
}xbuff=0x00;
}
case RETROCESO:
uart_transmit(RETROCESO);
break;
case ESCAPE:
uart_transmit(ESCAPE);
break;
default:
uart_transmit(c);
}
}
Accin a realizar
#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
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");
}
return 0;
}
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.
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
/*
* 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)
/*
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
/*
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;
//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(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
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.
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.
/*************************************************************************
* Title:
* Author:
* File:
http://jump.to/fleury
* Usage:
**************************************************************************/
#include <inttypes.h>
#include <compat/twi.h>
#include <i2cmaster.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;
}/* 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;
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:
*************************************************************************/
void i2c_start_wait(unsigned char address)
{
uint8_t
twst;
while ( 1 )
{
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
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:
Return:
0 device accessible
1 failed to access device
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start( address );
}/* i2c_rep_start */
/*************************************************************************
}/* 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;
}/* i2c_write */
/*************************************************************************
Read one byte from the I2C device, request more data from device
Return:
*************************************************************************/
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:
*************************************************************************/
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}/* i2c_readNak */
#ifndef _I2CMASTER_H
#define _I2CMASTER_H
/*************************************************************************
* Title:
(i2cmaster.S or twimaster.c)
* Author:
* File:
http://jump.to/fleury
* Usage:
**************************************************************************/
#ifdef DOXYGEN
/**
@defgroup pfleury_ic2master I2C Master library
@code #include <i2cmaster.h> @endcode
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.
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.
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
int main(void)
{
unsigned char ret;
i2c_init();
i2c_write(0x05);
// write address = 5
i2c_write(0x75);
i2c_stop();
i2c_write(0x05);
// write address = 5
i2c_rep_start(Dev24C02+I2C_READ);
ret = i2c_readNak();
i2c_stop();
for(;;);
}
@endcode
*/
#endif /* DOXYGEN */
/**@{*/
#include <avr/io.h>
/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_READ
/**
@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
@retval
device accessible
@retval
*/
extern unsigned char i2c_start(unsigned char addr);
/**
@brief Issues a repeated start condition and sends address and transfer direction
@param
@retval
0 device accessible
@retval
*/
extern unsigned char i2c_rep_start(unsigned char addr);
/**
@brief Issues a start condition and sends address and transfer direction
@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
*/
extern unsigned char i2c_readAck(void);
/**
@brief
read one byte from the I2C device, read is followed by a stop condition
@return
*/
extern unsigned char i2c_readNak(void);
/**
@brief
@param
@return
*/
extern unsigned char i2c_read(unsigned char ack);
#define i2c_read(ack)
/**@}*/
#endif
0xA2
int main(void)
{
unsigned char ret;
i2c_init();
Write)
// set device address and write mode
// write address = 5
// write value 0x75 to EEPROM
// set stop conditon = release bus
// write address = 5
// set device address and read mode
ret = i2c_readNak();
i2c_stop();
for(;;);
}
A2
A1
A0
R/~W
Escritura
Lectura
Enviar START
Enviar START
Enviar direccin
Del esclavo
Ms bit de
Escritura
Enviar direccin
Del esclavo
Ms bit de
Escritura
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
/*
*/
#include <avr/io.h>
#include <util/delay.h>
#include "i2cmaster.h"
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;
}
i2c_write(data);
i2c_stop();
_delay_ms(10);
}
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:
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"
//presenta el menu
void comando(void);
/**
* 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);
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
flagValido = true;
presmenu();
}
for(i=0;i<0x10000;i++){
u = read2EEPROM(i);
sprintf(buffer,"%X",u);
uart_print(buffer);
}
uart_print("\r\n\r\n");
}
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");
}
h= (16*ascii2hex(arg[1]) + (ascii2hex(arg[0])) +
(16*16*ascii2hex(arg[2])) +
(16*16*16*ascii2hex(arg[3])));
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;
}
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");
}
break;
case RETROCESO:
uart_transmit(RETROCESO);
break;
case ESCAPE:
uart_transmit(ESCAPE);
break;
default:
uart_transmit(c);
}
}
//definicion de teclas
#define INTRO 0x0D
#define RETROCESO 0x08
#define ESCAPE 0x1B
/**
* 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>
return UDR1;
}
// init uart
void uart_init(void)
{
// set baud rate
unsigned int baud = BAUD_PRESCALE;
return 0;
}
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);
}
**************************************************************************/
#ifdef DOXYGEN
/**
@defgroup pfleury_ic2master I2C Master library
@code #include <i2cmaster.h> @endcode
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.
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.
@code
#include <i2cmaster.h>
int main(void)
{
unsigned char ret;
i2c_init();
i2c_write(0x05);
// write address = 5
i2c_write(0x75);
i2c_stop();
i2c_write(0x05);
// write address = 5
i2c_rep_start(Dev24C02+I2C_READ);
ret = i2c_readNak();
i2c_stop();
for(;;);
}
@endcode
*/
#endif /* DOXYGEN */
/**@{*/
#include <avr/io.h>
/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_READ 1
/**
@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
/**
@brief Issues a repeated start condition and sends address and transfer direction
/**
@brief Issues a start condition and sends address and transfer direction
@return none
*/
extern void i2c_start_wait(unsigned char addr);
/**
@brief Send one byte to I2C device
@param
/**
@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
@param
/**@}*/
#endif
/*************************************************************************
* Title:
**************************************************************************/
#include <inttypes.h>
#include <compat/twi.h>
#include "i2cmaster.h"
/* 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 */
}/* 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;
return 0;
}/* i2c_start */
/*************************************************************************
Issues a start condition and sends address and transfer direction.
while ( 1 )
{
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
continue;
}
//if( twst != TW_MT_SLA_ACK) return 1;
break;
}
}/* i2c_start_wait */
/*************************************************************************
Issues a repeated start condition and sends address and transfer direction
}/* 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);
}/* i2c_stop */
/*************************************************************************
Send one byte to I2C device
Input:
byte to be transfered
}/* i2c_write */
/*************************************************************************
Read one byte from the I2C device, request more data from device
return TWDR;
}/* i2c_readAck */
/*************************************************************************
Read one byte from the I2C device, read is followed by a stop condition
return TWDR;
}/* i2c_readNak */
/*@{*/
/**
* @name Definitions for MCU Clock Frequency
* Adapt the MCU clock frequency in Hz to your target.
* Revisa las paginas 37-39
*/
/**
* @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);
/*@}*/
#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;
}
{
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
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
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