Professional Documents
Culture Documents
C (entradas analgicas)
Todos los registros y los bits de referencia se escriben en forma general. Los
registros indicados en la siguiente descripcin nos permiten emplearlos para un
uso especfico en funcin de la operacin deseada por el usuario. A
continuacin se muestra el esquemtico del Puerto como entrada y salida de
propsito general.
PUERTO C.
PUERTO D.
Otros macros disponibles en las libreras del AVR Libc se pueden encontrar en:
http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr.html
Ejemplo:
1 = OUTPUT
0 = INPUT
DDRX = B11111110;
donde X es la letra del puerto a usar (BCD). Sin embargo si queremos tener
comunicacin Serial tendramos que hacer esto:
DDRX = DDRX | B11111100;
Esta manera es ms segura ya que configura los pines del 2 al 7 como salidas
sin cambiar los pines 0 y 1, que como mencionamos son RX y TX Para tener
ms referencia de los operadores bit a bit tipo AND, visita el siguiente post de
Arduino:
Tutorial de operaciones con bits.
Tenemos el siguiente cdigo:
B11111110;
Colocamos B, porque el nmero a marcar es Binario. Para ampliar ms sobre
los tipos de datos en Arduino visitemos el siguiente blog:
Tipos de Datos en Arduino.
Para saber el estado que le daremos al pin siempre lo pondremos escribiendo
de derecha a izquierda.
Nmero
a
marcar
1
1
1
1
1
1
1
0
Ubicacin 7
6
5
4
3
2
1
0
del pin en
Arduino.
Segunda instruccin: es la escritura del puerto (esta variar en funcin
del programa que estemos desarrollando). Lo localizamos en la
funcin void loop().
Ejemplo:
1 =HIGH
PORTX= B11111110;
0 = LOW
Para ver otro ejemplo utilizando Registro PORT (Puerto), visitemos el siguiente
post:
Control de Display 7 Segmentos mediante Pulsadores.
Ventajas y Desventajas que nos ofrece al utilizar el Registro PORT (Puerto):
Desventajas:
El cdigo es mucho ms difcil de depurar y mantener, y es mucho ms
difcil de entender para la gente. Solo lleva algunos microsegundos al
procesador ejecutar cdigo, pero podra llevarte horas descubrir por qu
no funciona y arreglarlo.
Es mucho ms fcil causar mal funcionamiento no intencionado usando
el acceso directo a un puerto. Observa como la lnea DDRD =
B11111110, de arriba, menciona que el pin 0 se debe dejar como una
entrada. El pin 0 la lnea de recepcin (RX) en el puerto serial. Podra ser
muy fcil causar que tu puerto serial deje de funcionar por cambiar el
pin 0 a una salida.
Ventajas:
Puede que puedas cambiar los pines de estado muy rpido, en
fracciones de microsegundos. Las funciones digitalRead() y digitalWrite()
son cada una cerca de una docena de lneas de cdigo, lo cual al ser
compilado se convierte en unas cuantas instrucciones mquina.
Cada instruccin maquina necesita un ciclo de reloj a 16MHz, lo cual puede
sumar mucho tiempo en aplicaciones muy dependientes del tiempo. El Registro
PORT (Puerto) puede hacer el mismo trabajo en muchos menos ciclos de
trabajo.
Reset.
El pin 1 del ATMega328P es el pin de RESET del cual podemos mencionar que
es una interrupcin de alta prioridad, este debe tener un estado Alto (HIGH)
para evitar que el microcontrolador se reinicie, para ello ponemos una
resistencia de 10k entre el pin 1 y positivo (5v). Si no ponemos la resistencia el
microcontrolador funcionar igualmente, pero para evitar posibles reseteos
aleatorios es mejor asegurar el nivel lgico por lo que hay que ponerla.
Para poder resetear el microcontrolador cuando uno desee se pone un pulsador
(PUSH BOTTON) conectado entre el pin 1, justo antes de la resistencia de 10k,
y negativo (GND). As cuando lo pulsemos el microcontrolador detectar el
estado bajo (LOW) en el pin 1 (RESET) y se reiniciar.
Verificar que el pin 7 est conectado a VCC del ATMega328P o sea a positivo
(5v) y el pin 8 a negativo (GND), con estas 2 conexiones se alimenta al
microcontrolador. El pin 22 tambin va conectado a negativo (GND) y los pines
20 (AVCC) y 21 (AREF), que son los voltajes de referencia.
Tambin podemos ver que el pin 9 (TOSC1) y el pin 10 (TOSC2) se tiene
conectador el oscilador de 16MHz, el oscilador no tiene polaridad, as que se
puede colocar como uno desee. En cada extremo del oscilador se tiene
conectado un condensador de 22pF a negativo (GND) para darle estabilidad
al microcontrolador, en circuitos bsicos estos condensadores de 22pF no son
necesarios, pero si es recomendable ponerlos.
Se pueden tener diferentes maneras de dar un RESET al microcontrolador, la
anterior mencionada se conoce como RESET externo, pero tambin se puede
tener RESET interno ya sea por programa o cuando uno de los mdulos se
RESETEA porque as est configurado. Los casos pueden ser:
wdt_disable();
Serial.begin(9600);
Serial.println("Setup..");
Serial.println("Wait 5 sec..");
delay(5000);
wdt_enable (WDTO_8S);
Serial.println("Watchdog enabled.");
// deshabilito el watchdog
}
int timer = 0;
void loop(){
// Cada 1 segundo se incrementara un contador (que sera mostrado por el monitor serial) y parpadeara el led
if(!(millis()%1000)){
timer++;
Serial.println(timer);
digitalWrite(13, digitalRead(13)==1?0:1); delay(1);
}
// wdt_reset();
// si se llamara a esta funcion todo andaria correctamente, ya que se resetearia el
// watchdog.
// Est remarcada para que se resetee el arduino a los 8 segundos y veamos que
// pasa.
}
Comportamiento esperado:
Se deberian ver por monitor serial los valores del 1 al 9, un reset del arduino y
otra vez los valores, esto en un bucle infinito.
Comportamiento en arduinos que no funcionan correctamente:
Se ve por monitor serial los valores del 1 al 9 y luego se cuelga el arduino
parpadenado todos los leds como loco.
Interrupciones
Las interrupciones son eventos especiales que se generan interna o
externamente en el microcontrolador que pausa momentneamente la
ejecucin del programa para realizar una tarea breve, y despus volver al
punto donde se qued ejecutando el programa. Esto sirve para que el
microcontrolador no est siempre trabajando, por ejemplo, en checar el estado
de una entrada constantemente, y solo poner atencin cuando el evento
deseado ocurre.
En esta entrada se tratar de explicar cmo funciona el sistema de
interrupciones de los AVRs, los vectores y registros que lo componen tanto
como su programacin en C con el compilador avr-gcc y avr-libc.
Imaginen que estn en la mesa de su casa tomando el desayuno, de repente el
telfono suena, te levantas, atiendes la llamada, cuelgas y vuelves a la mesa a
desayunar, esa sera una analoga de lo que es una interrupcin.
Lo mismo pasa con los microcontroladores y microprocesadores, tienen un
mtodo de que otros dispositivos externos (o internos) al micro, puedan
mandarle una alerta sobre algo, y este atienda la alerta y contine su proceso.
Los microcontroladores AVR tienen no tiene interrupciones por software, lo que
es til para tareas especiales de sistemas operativos, como intercambio de
PCIE2 (Pin Change Interrupt Enable 2): habilita las interrupciones de los pines
entre PCINT23:16, los pines son habilitados uno a uno en el registro PCMSK2.
Cuando una de estas interrupciones ocurre se activa la bandera (flag)
correspondiente y se salta al vector de interrupcin $0016 si todo lo necesario
est habilitado.
PCIE1: lo mismo con PCINT15:8, PCI1, PCMSK1. $0014.
PCIE0: PCINT7:0, PCI0, PCMSK0. $0012.
Estos bits son los flags de las interrupciones habilitadas en el registro anterior,
cuando una interrupcin ocurre se pone a 1 el bit de este registro que se
corresponde con la interrupcin para indicar al microcontrolador que la
interrupcin ha tenido lugar. EL flag es limpiado cuando la rutina de
interrupcin ha sido ejecutada. Para limpiar un flag debemos escribir un uno
lgico en el bit.
La mscara para PCIE2. Si uno de estos bits est activado y el bit PCIE2 del
registro PCICR est activado, la interrupcin est habilitada en el pin de
entrada/salida correspondiente, y cuando hay un cambio en ste se dispara la
interrupcin de PCIE2.
De la misma forma con PCIE1 y PCIE0:
External Interrupt.
En este registro cada bit tiene su vector de interrupcin, no es como el caso
anterior que todos los bits del registro hacan saltar la misma interrupcin.
{
//code
}
Donde NOMBRE_vect identifica el vector de interrupcin, puede tener ms
argumentos adems del nombre segn lo que queramos que haga la ISR, las
opciones
estn
en
el
link
anterior.
Debomos aadir el #include <avr/interrupt.h> al programa.
Con sei() y cli() de avr/interrupts.h habilitamos y deshabilitamos todas las
interrupciones poniendo a 1 0 el bit de Global Interrupt Enable. Al entrar en
una ISR se deshabilita el bit GIE a no ser que indiquemos lo contrario y al salir
se habilita.
En nuestro programa tenemos 3 botones, y por tanto deberemos configurar
una interrupcin para cada uno si usamos las interrupciones externas o
tambin podemos seleccionar una misma interrupcin para los tres utilizando
las Pin On Change Interrupt, luego tendremos que leer los botones uno a uno
para determinar cul ha sido pulsado. En este caso se van a usar las
interrupciones
externas.
Cuando se pulsa un botn no se pasa de uno a cero o viceversa en el
momento, si no que tenemos rebotes, podemos tener una seal compuesta por
varios pulsos de 1 y 0 que pueden hacer saltar a la interrupcin varias veces, lo
mismo al soltar el botn que mantenemos pulsado. Para ello lo mejor es aadir
electrnica adicional para eliminar los rebotes, como puede ser un filtro RC o
varios circuitos que se pueden encontrar buscando un poco diseados para tal
fin. En este caso no hay electrnica adicional, por lo que la nica opcin que
tenemos es eliminarlos por software, para ello se puede hacer un delay de 3040 ms en la ISR de tal forma que cuando salgamos de la interrupcin y sta
est otra vez lista para ser disparada los rebotes ya han desaparecido. En los
PCBs finales habr electrnica adicional en los botones para eliminar los
posibles rebotes, no cuesta nada hacerlo y facilitamos la programacin, y
cuando tenemos un programa complejo con varias interrupciones y muchos
tiempos cuanto ms facilitemos el programa mejor.
Para comprobar el funcionamiento de lo anterior un ejemplo sencillo:
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"
//Botones del LCD, interrupciones externas.
//#define boton1 PORTD2 //INT0
//#define boton2 PORTD3 //INT1
void botones_inicializar();
int main(void)
{
lcd_inicializar();
botones_inicializar();
char linea1[]="Proyecto FireFly";
char linea2[]="Pulse un boton para";
char linea3[]="comenzar";
posicionar_cursor(1,3);
lcd_escribir(linea1);
posicionar_cursor(3,1);
lcd_escribir(linea2);
posicionar_cursor(4,7);
lcd_escribir(linea3);
while(1)
{
}
}
void botones_inicializar()
//Configurar registros del micro.
{
//Tipo de evento que dispar la interrupcin, 10, flanco de bajada.
EICRA &= ~(1<<ISC20); //INT02
EICRA |= (1<<ISC21);
EICRA &= ~(1<<ISC30); //INT1
EICRA |= (1<<ISC31);
EIMSK |= ((1<<INT0)|(1<<INT1));
//Habilitar interrupciones externas 0 y 1.
sei();
//Habilitar todas las interrupciones
}
//ISRs. Rutinas de atencin a las interrupciones.
ISR(INT0_vect)
{
char linea[]="Pulsado boton 1";
lcd_comando(0x01);
//Limpiar pantalla LCD.
posicionar_cursor(1,3);
lcd_escribir(linea);
// _delay_ms(40); //Rebotes
}
ISR(INT1_vect)
{
char linea[]="Pulsado boton 2";
lcd_comando(0x01);
//Limpiar pantalla LCD.
posicionar_cursor(2,3);
lcd_escribir(linea);
// _delay_ms(40); //Rebotes
Reloj Configuracin.
Se tienen diferentes fuentes para generar la seal de reloj en el MCU y a la vez,
la seales de reloj se distribuyen por los diferentes mdulos.
Oscilador RC Externo.
La frecuencia se determina como f = 1/(3RC).
C debe ser al menos de 22 pF.
Temporizacin
Introduccin
TCNTn puede ser pre-cargado con un valor entre 0 y MAXVAL para que la
bandera TOVn se genere a intervalos de tiempo.
Eventos en los Temporizadores. (Coincidencia de comparacin [Compare
match]).
Un registro puede ser cargado con un valor entre 0 y MAXVAL (OCRn - Output
Compare Register) y es comparado con el valor del timer en cada ciclo de reloj,
una coincidencia produce un evento. El evento se indica con la bandera OCFn
(Output Compare Flag).
Temporizacin externa
Los temporizadores 0 y 1 permiten el manejo de una seal externa para su
incremento (T0 T1). En estos casos se les denomina contadores de eventos.
Se puede configurar para detectar flancos de bajada o subida.
Los eventos externos se sincronizan con la seal de reloj interna, por lo que no
pueden tener una frecuencia mxima de f CLKIO/2.