Documentos de Académico
Documentos de Profesional
Documentos de Cultura
CURSO BSICO-INTERMEDIO DE
PROGRAMACIN EN C DE LOS
MICROCONTROLADORES ATMEL
POR DAVID INFANTE SNCHEZ
dinfante29@hotmail.com
dinfante@itmorelia.edu.mx
Web site: www.comunidadatmel.com
Revisin 8.0
Septiembre del 2008
INFORMACIN IMPORTANTE
ESTAS NOTAS FUERON CREADAS POR DAVID INFANTE
SNCHEZ, PROFESOR DEL INSTITUTO TECNOLGICO DE
MORELIA. SE PROHIBE SU MODIFICACIN O SU VENTA,
FUE REALIZADO CON FINES DIDCTICOS.
SI SE UTILIZA INFORMACIN DE ESTE CURSO EN
TRABAJOS DE TESIS, ARTCULOS, ETC. DEBE MOSTRAR
LOS CRDITOS DEL AUTOR Y ESTO DEBER SER
REFERENCIADO AS:
Infante S. David. Notas del curso programacin en C de los
microcontroladores ATMEL. Instituto Tecnolgico de Morelia.
Versin 8.10
Experiencia profesional
Motivacin
El motivo de este curso es para dar a conocer las nuevas tecnologas en microcontroladores,
ya que es lamentable que en las universidades e institutos de educacin superior de Mxico
y en Latinoamrica en general, se estn haciendo proyectos y programas demasiados
sencillos en las materias de microcontroladores y peor an que estn usando los
microcontroladores PIC, ya que universidades europeas y de EUA no los usen desde hace
aos por su pobre desempeo, adems de que son microcontroladores que no tiene ninguna
aplicacin industrial o comercial, sino slo para efectos didcticos.
Desde que cursaba la carrera de ingeniera electrnica a la fecha he usado los siguientes
microprocesadores, microcontroladores y DSPs:
de latinoamrica. Estos procesadores nicamente los us por un ao y los dej de usar hace
una dcada por ser procesadores obsoletos y de mal desempeo.
Los Microcontroladores AVR de Atmel tiene 4 veces ms instrucciones que los PICs, tiene
32 registros de trabajo, el pic slo 1, el ADC es ms potente, el TIMER es mucho ms
complejo que el del PIC, y son ms econmicos. Los AVR de Atmel se usan en telfonos
celulares, en receptores satelitales, en robtica, etc. Son microcontroladores muy rpidos y
de alto desempeo y son de bajo costo, existen muchos proyectos, tutoriales y herramientas
gratuitas en la red.
A manera de conclusin dira que en orden de desempeo y calidad colocara los
procesadores as: AVR de Atmel, MSP de Texas Instruments, los 08 de Motorola el 8051
de Intel, COP de Nacional Semiconductor. Un procesador AVR o MSP puede tener un
desempeo de entre 10 y 50 veces al de un PIC con el mismo cristal externo, o en otras
palabras un PIC es entre 10 y 50 veces ms lento que un AVR o que un MSP.
CAPTULO I. PROGRAMACIN EN C
1.1 Tipos de Variables
En esta parte nicamente se ver como se manejan las instrucciones de C, quizs al
terminar este captulo algunas instrucciones no las entienda del todo bien, sin embargo
cuando programemos el microcontrolador usaremos estas instrucciones y las ir
comprendiendo de una mejor manera.
En un programa en C puede colocar comentarios usando //
unsigned char x; // x es una variable
O puede utilizar /*
Tamao en bits
1
8
8
8
16
16
16
16
32
32
32
32
32
Rango
0o1
-128 a 127
0 a 255
-128 a 127
-32768 a 32767
-32768 a 32767
0 a 65535
-32768 a 32767
-2147483648 a 2147483647
0 a 4294967295
-2147483648 a 2147483647
1.75 e -38 a 3.402 e 38
1.75 e -38 a 3.402 e 38
Formato
Nmero
0x nmero hexadecimal
0b nmero binario
0 nmero octal
Ejemplos:
x=20;
x=0x14;
x=0b00010100;
x=024;
// x es 20 decimal
//x es 14 hexadecimal que convertido a decimal es 20 decimal
//x se manejado en binario que es equivalente a 20 decimal
//x se maneja en octal que es 20 decimal
Las constantes deben ser guardadas en FLASH o memoria de programa, ya que stas no
van a ser modificadas, para ello se inicia colocando la palabra const o flash ejemplo:
const int k1=60000;
Que es equivalente a:
flash int k1=60000;
Con lo anterior la constante K1 es inicializada a 60000 y se guarda en flash.
Se puede guardar un carcter en flash para ello ponemos el carcter entre comillas simples (
)
const char x=a
1.4 Arreglos
Un arreglo es un conjunto de datos que pueden ser accesado a travs de un ndice. Su
declaracin se hace as:
flash o const nombre del arreglo [nmero de elementos]={elemento1, elemento2,..
elemento n }
Ejemplo
flash char arreglo1 [3]={0x0a,0x38,0x23};
Es equivalente a la siguiente declaracin:
const char arreglo1 [3]={0x0a,0x38,0x23};
flash y const son lo mismo ya que guardan los datos en flash, pero por compatibilidad con
el lenguaje C usar dentro de este manual la palabra const.
Se guardan de manera individual esos bits en los registros R2 al R14 del procesador del
AVR. Recuerde que el microcontrolador AVR tiene 32 registros desde R0 hasta R31.
Operacin
Suma
Resta
Multiplicacin
Divisin
Divisin Mdulo, y el resultado es el
residuo
Var1=Var2/12;
Var1=Var2%12;
Descripcin
And Bit a Bit
OR bit a Bit
Or exclusivo Bit a Bit
Corrimiento a la Izquierda
Corrimiento a la derecha
Complemento
a
unos
(inversin de bits)
Ejemplos:
Var3=Var1&Var2;
Var3=Var1<<(2);
Var3=Var1<<(Var2);
Var3=~Var1;
Descripcin
Mayor que
Mayor o igual que
Menor que
Menor Igual que
Igual que
Distinto de
Y tambin si
O si
Ejemplos
if (Var2==1)
{
Var1--;
}
b6
0
0
0
b5
0
0
0
b4
0
0
0
b3
0
1
1
b2
1
0
1
b1
1
0
1
b0
1
0
1
b7
1
1
1
b6
1
1
1
b5
0
1
0
b4
0
1
0
b3
1
1
1
b2
0
1
0
b1
1
1
1
b0
1
0
0
Vemos en el ejemplo anterior que apaga el b0 de la variable y los dems bits no los
modifica.
funcin que haga la multiplicacin y cada vez que se vaya a utilizar se manda
llamar la funcin, as de esta manera ahorramos cdigo.
Las funciones pueden o no enviar parmetros y puede o no haber retorno de parmetros.
Cuando se va a utilizar una funcin hay que declararla en la parte superior del programa
(esto se conoce como prototype definition o definicin prototipo) para que la reconozca el
compilador y sepa que vamos a utilizar dichas funciones.
Ejemplos de declaracin de funciones:
//prototype definition
void ejemplofuncion1 (void)
void ejemplofuncion2 (char, char)
int ejemplofuncion3 (void)
char ejemplofuncion4 (int)
En la parte anterior se definieron 4 funciones, el nombre que les di son: ejemplofuncion1,...,
ejemplofuncion4 aunque el nombre puede ser cualquiera. La palabra void significa que no
recibe nada, por ejemplo void ejemplofuncion (void) significa que la funcin no recibe nada
y que tampoco se le enva ningn parmetro. La segundo funcin void ejemplofuncion2
(char, char) indica que no retorna ningn valor la funcin y que se le envan dos
parmetros tipo char. La tercera funcin int ejemplofuncion3 (void) indica que retorna un
valor tipo int y que no se le enva ningn parmetro. La ltima funcin no retorna ningn
valor y se le enva un parmetro tipo int.
La parte anterior slo es la definicin de las funciones que utilizar el programa. El llamado
de las funciones dentro del programa se hace as:
ejemplofuncion1 ();
ejemplofuncion2 (variable1,variable2);
En el llamado de la funcin1 no se coloc nada entre los parntesis porque la funcin
dentro de la definicin le indicamos que no se le iba a enviar ningn parmetro.
En el llamado de la funcin 2 le colocamos entre parntesis dos variables que llamamos
variable1 y 2, que previamente debimos definir. Estas dos variables las recibir la funcin
para que realice operaciones entre ellas.
variablex=ejemplofuncion3 ();
En el llamado de esta funcin colocamos variablex=funcin porque en la definicin del
prototipo le indicamos que iba a retornar la funcin una variable tipo int, entre los
parntesis no se le coloca nada porque se indic que no iba a enviar ningn parmetro.
En la funcin 4 se retorna un valor tipo char y se enva un parmetro tipo int, y su llamado
se hara as:
variabley=elemplofuncion4(variable1);
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
Hasta este punto se ha visto cmo se declaran las funciones y cmo se llaman, falta
nicamente cmo se estructura la funcin.
En el caso de la primer funcin:
void ejemplofuncion1(void)
{
//Cdigo de usuario
}
La funcin lleva void al inicio y entre parntesis porque esa funcin no recibe parmetros
ni retorna ningn parmetro o valor.
La segunda funcin debera colocarse as:
void ejemplofuncion2(char a, char b)
{
//Cdigo de usuario
}
Aqu lleva void al inicio indicando que no retorna parmetro y entre parntesis se coloca a
y b que indica que son los parmetros que se reciben, cuando se hizo el llamado se hizo as:
ejemplofuncion2 (variable1,variable2); entonces la funcin enva dos parmetros variable1
y variable2, que recibe la funcin en a y b, entonces a=variable1 y b=variable2; Se
asignan segn su posicin.
La tercera funcin debe escribirse as:
int ejemplofuncion3(void)
{
//Cdigo de usuario
return variable
}
Cuando se hizo el llamado de la funcin se coloc: variablex=ejemplofuncion3 (); entonces
cuando se ejecute la funcin se retorna un valor a travs de return variable si
variable=0x30 por ejemplo, entonces variablex=0x30.
La funcin 4 debe escribirse as:
char ejemplofuncion4(int a)
{
//Cdigo de usuario
return variable
}
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
Aqu se indica que la funcin regresar un char y que recibe un parmetro int en a, ya que
en el llamado de la funcin se escribi: variabley=elemplofuncion4(variable1);
Entonces a recibir el valor de variable1 y variabley tomar el valor de variable por el
return variable.
Hemos visto slo el envo de parmetros que son variables, pero pueden enviarse tambin
arreglos, o punteros.
Resumen de las funciones
Declaracin de la funcin
void ejemplofuncion1 (void)
Llamado de la funcin
ejemplofuncion1 ();
ejemplofuncion2 (variable1,variable2);
variablex=ejemplofuncion3 ();
variabley=elemplofuncion4(variable1);
Estructura de la funcin
void ejemplofuncion1(void)
{
//Cdigo de usuario
}
void ejemplofuncion2(char a, char b)
{
//Cdigo de usuario
}
int ejemplofuncion3(void)
{
//Cdigo de usuario
return variable
}
char ejemplofuncion4(int a)
{
//Cdigo de usuario
return variable
}
En los ejemplos que coloqu enve como parmetros variables, pero tambin pueden
ser constantes. ejemplofuncion2(char a, 200); En este ejemplo se enva el valor de
la variable a y se enva la constante 200.
El retorno del valor de la funcin que puse como ejemplo fue el retorno de una
variable, pero tambin puede retornarse una constante como return 100;
Vea el video_p1 que se anexa en este CD para que aprecie cmo se inicializa el
microcontrolador y su simulacin.
El siguiente listado es lo que gener el codewizard, inicializando el microcontrolador y lo
que est en azul es lo que ud deber agregar al programa generado para que funcione de
acuerdo a las especificaciones del programa 1.
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7a Evaluation
Automatic Program Generator
Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 13/09/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type
: ATmega48
Clock frequency : 1,000000 MHz
Memory model
: Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Crystal Oscillator division factor: 8
#pragma optsizeCLKPR=0x80;
CLKPR=0x03;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P
PORTB=0xFF;
DDRB=0x00;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00;
DDRD=0xFF;
// Timer/Counter 0 initialization
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
while (1)
{
PORTD=PINB;
//Se lee el valor del Puerto A y se escribe en PORTB
//El Puerto B es de entrada por lo que se accesa usando el registro PINB
//El puerto D es de salida por lo que se accesa usando el registro PORTD
// Place your code here
};
}
Vea el video_p2 para que vea la forma en que se hace este programa y vea tambin su
simulacin.
El siguiente listado lo generar el codewizard para inicializar el microcontrolador y lo que
est en azul es lo que ud deber escribir en el programa para que ejecute lo que se pide en el
programa 2.
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7a Evaluation
Automatic Program Generator
Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 14/09/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type
: ATmega48
Clock frequency : 1,000000 MHz
Memory model
: Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
#include <delay.h> //Esta libreria hay que colocarla para poder utilizar las funciones de retardo
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Crystal Oscillator division factor: 8
#pragma optsizeCLKPR=0x80;
CLKPR=0x03;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
ACSR=0x80;
ADCSRB=0x00;
while (1)
{
PORTB++;
// Incrementa en una unidad el valor del Puerto B
delay_ms(1000); //Se hace un retardo de 1 segundo
// Place your code here
};
}
if (PINC==0)
PORTB=0x06;
Etc...
if (PINC==9)
PORTB=0x6f;
La forma que se puede hacer es a travs de una tabla, por ejemplo se define una tabla en
flash donde estarn todas las combinaciones anteriores:
const char tabla7segmentos [10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x6f};
y dentro del programa principal colocar lo siguiente:
PORTB=tabla7segmentos[PINC];
Y con esa nica instruccin ya tenemos un convertidor de BCD a 7 segmentos, si el puerto
C que leemos con PINC es igual a 0 sacar de la tabla el elemento 0 que es el que dibuja el
0 en el display, si vale 9 sacar de la tabla el elemento 9 que es el que dibuja el 9 en el
display y lo mandar al Puerto B.
De la manera anterior logramos que el programa quede ms compacto, y mucho ms rpido
que usando instrucciones de if.
Vea el video_p3 donde se muestra la configuracin del microcontrolador y su simulacin.
La parte en azul es la que deber agregar al programa generado por el codewizard.
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7a Evaluation
Automatic Program Generator
Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 14/09/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type
: ATmega48
Clock frequency : 1,000000 MHz
Memory model
: Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
unsigned char variable;
const char tabla7segmentos [10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x6f};
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Crystal Oscillator division factor: 8
#pragma optsizeCLKPR=0x80;
CLKPR=0x03;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
while (1)
{
variable=PINC&0x0f;
if (variable<10)
PORTB=tabla7segmentos[variable];
if (variable>=10)
PORTB=0x3f;
// Place your code here
};
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
while (1)
{
if (boton==0)
var1++;
if (var1==10)
var1=0;
PORTB=tabla7segmentos [var1];
// Place your code here
};
}
var++;
//Se incrementa la variable en 1
Pero es ms fcil escribir, interpretar un programa con nombres ms claros, por ejemplo el
C0 es donde est conectado el botn as que en se defini en la parte superior una etiqueta
donde iguala boton a PINC.0, para que sea ms fcil interpretar el programa.
#define boton PINC.0
Con lo anterior boton=PINC.0 as que si utilizo en el programa PINC.0 o boton el
compilador lo interpreta igual, y es ms fcil ubicar la palabra boton que PINC.0. Suponga
que tenga conectados leds, botones, etc. podra hacer esa definicin de
#define led_rojo PORTB.1
#define led_verde PORTB.2
#define borrado PINC.1
etc.
Cuando el botn se presiona, es decir que vale 0, ya que cuando no est presionado lee 1
lgico debido a la resistencia de pull-up, incrementa en 1 la variable var1
if (boton==0)
var1++;
Se utiliza una variable que se nombr var1, aunque puede ser cualquier nombre. Como se
est utilizando la tabla que convierte a 7segmentos el nmero, slo se pueden desplegar
nmeros de 0 hasta 9, as que si la var1 es igual a 10 se regresa a 0, porque nmeros
superiores al 10 desplegaran basura ya que no existen en la tabla accesando localidades no
inicializadas.
if (var1==10)
var1=0;
Y finalmente el valor de var1 que va desde 0 hasta 9 va indexando la tabla con la
instruccin PORTB=tabla7segmentos [var1];
Cuando programe el microcontrolador y arme el circuito ver que cuando presione el botn
se incrementar muy rpidamente el display y la razn de eso es porque el programa
detecta el nivel de 0, es decir, cuando valga 0 el pin se incrementar el valor a mostrar en el
display; aunque nosotros presionemos y soltemos el botn muy rpido el programa leer en
es pequeo lapso de tiempo miles de veces un nivel lgico de 0.
Si deseramos que se modificara el valor slo una vez cuando se presione el botn deber
hacerse que funcione por flancos, es decir cuando cambie el pin de 1 a 0. Vea el diagrama
de la figura 2.8.
Project :
Version :
Date : 14/09/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type
: ATmega48
Clock frequency : 1,000000 MHz
Memory model
: Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
// Declare your global variables here
#define boton PINC.0
bit botonp;
bit botona;
unsigned char var;
const char tabla7segmentos [10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x6f};
void main(void)
{
// Declare your local variables here
// Crystal Oscillator division factor: 8
#pragma optsizeCLKPR=0x80;
CLKPR=0x03;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=P
PORTC=0x01;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
PORTB=tabla7segmentos [var];
botonp=botona;
};
}
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
retardo de 40mS para que se quede ah ciclado el programa y cuando salga de ah, ya los
rebotes no existirn porque ya pasaron 40 mS.
Teclado Matricial
Si deseara manejar digamos 16 botones y lo hiciera poniendo un botn en cada pin gastara
16 pines del microcontrolador, en vez de esto se puede hacer un teclado matricial, el cual
ahorra pines. Por ejemplo una matriz de 4*4 puede manejar 16 teclas, una matriz de 5*5
puede manejar 25 teclas. En el primer caso se ocuparan 4 pines de salida y 4 de entrada, en
el segundo se ocupan 5 pines de salida y 5 de entrada. Aqu vemos el ahorro, para 16 teclas
se ocupan 8 pines en lugar de 16 pines si se hiciera el teclado conectando cada pin a un
botn, y el ahorro es mayor cuando se ocupan 25 teclas, ya que se ocupan 10 pines en total
en lugar de 25 pines si se conecta cada botn con cada pin.
Diagrama de un teclado matricial
el pin, que recordando cuando un pin queda flotado comienza a oscilar leyendo 0 y 1 de
manera aleatoria debido al ruido.
Las resistencias de 100 ohms a la salida de los pines que son los que envan el cdigo son
para proteger contra corto circuitos, por ejemplo si se enviara en la primera columna un 0 y
en la segunda un 1 y se presionar el botn 1 y 4 habra un corto ya que en una lnea hay 5
volts y en el otro 0, as que al tener la resistencia de 100 Ohms la corriente se ve limitada y
no sucede nada al presionar dos teclas al mismo tiempo.
Como son botones los que estn conmutando a tierra hay que quitarle los rebotes, tal y
como lo hicimos en el programa 6. Aunque en este programa que se har no se quitarn los
rebotes.
Este ejemplo de 3*3 se puede usar como base para disear cualquier teclado matricial 5*5,
6*6, etc.
Programa 7. Diseo de un teclado matricial de 3*3, con despliegue a display a 7
segmentos. Los pines C0, C1 y C2 sern los pines de salida por donde se enviarn los
cdigos de saceneo, los pines C3, C4 y C5 sern los pines de entrada donde se leern
los botones presionados.
Configuracin: C0, C1 y C2 de salida, C3, C4 y C5 de entrada con resistencia de pull-up
interna activada. B0 a B7 de salida que es donde se conectar el display.
Project :
Version :
Date : 14/09/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type
: ATmega48
Clock frequency : 1,000000 MHz
Memory model
: Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
// Declare your global variables here
unsigned char tecla,lectura;
const char tabla7segmentos [10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x6f};
void main(void)
{
// Declare your local variables here
// Crystal Oscillator division factor: 8
#pragma optsizeCLKPR=0x80;
CLKPR=0x03;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=Out
// State6=T State5=P State4=P State3=P State2=1 State1=1 State0=1
PORTC=0x3F;
DDRC=0x07;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.7a Evaluation
Automatic Program Generator
Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 14/09/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type
: ATmega48
Clock frequency : 1,000000 MHz
Memory model
: Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
#include <delay.h>
#define boton PINC.0
#define boton_guarda PINC.1
bit botonp;
bit botona;
unsigned char var; //Ahora la variable se guarda en eeprom
const char tabla7segmentos [10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x6f};
eeprom char datoaguardar;
void checa_boton (void); // Aqu se declaran todas las funciones que se van usar
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Crystal Oscillator division factor: 8
#pragma optsizeCLKPR=0x80;
CLKPR=0x03;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=P State0=P
PORTC=0x03;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
ADCSRB=0x00;
if (datoaguardar>10)
datoaguardar=0;
var=datoaguardar;
while (1)
{
checa_boton();
PORTB=tabla7segmentos [var];
if (boton_guarda==0) //Si se presiona el botn de guardar
datoaguardar=var; //se grabara la eeprom con el valor de var
// Place your code here
};
}
void checa_boton (void)
{
if (boton==0)
botona=0;
else
botona=1;
if ((botonp==1)&&(botona==0))
//hubo cambio de flanco de 1 a 0
{
var++;
//Se incrementa la variable
if (var>=10)
var=0;
delay_ms(40); //Se coloca retardo de 40mS para eliminar rebotes
}
if ((botonp==0)&&(botona==1))
//hubo cambio de flanco de 0 a 1
delay_ms(40); //Se coloca retardo de 40mS para eliminar rebotes
botonp=botona;
}
datoaguardar=0;
La razn de ello es que si el datoaguardar que es una variable eeprom tiene un valor inicial
mayor a 10 la hacemos 0, y esto sucedera una sola vez, ya que cuando se guarde un dato el
dato estar entre 0 y 9. Pero un microcontrolador nuevo tiene en la memoria eeprom puros
0xff en todas las localidades, entonces la primera vez har que ese dato de 0xff se haga 0.
Importante. Si dentro de un programa utiliza una variable eeprom como una variable RAM
puede suceder que dae esa localidad de memoria eeprom, ya que una eeprom tiene una
vida til de 100,000 ciclos de escritura y lectura, pero si usa esa variable eeprom como una
variable RAM puede suceder que en cuestin de segundos sucedan esos 100,000 ciclos de
escritura y lectura porque un programa en el microcontrolador ejecuta el cdigo miles de
veces en un segundo, entonces al reescribir esa variable en el programa miles de veces en
un segundo se va a cabar la vida til de la localidad de memoria. En el programa vemos que
la eeprom slo se escribe cuando se presiona un botn.
conversin=(Vin*1024)/Vref .....................................................................................ec(2.1)
Donde Vin es el voltaje que se aplica, vref es el voltaje de referencia y conversin es el
valor digital.
Por ejemplo si Vref=5 y el vin que va a medir es de 2.5 dar como salida 512 segn la
ecuacin 2.1; si ahora el vin es de 1 volt la conversin que dar ser de 204.
En el caso de que se seleccione una conversin de 8 bits, la frmula a utilizar es:
conversin=(Vin*256)/Vref ......................................................................................ec(2.2)
Sustituyendo en la ec 2.2 los valores de vin=2.5 el resultado de la conversin es 128, si el
vin=1el resultado de la conversin ser 51
cuenta que si los va alimentar por separado el voltaje del perifrico del ADC no debe ser
mayor al del microcontrolador, por ejemplo si el microcontrolador lo va alimentar con dos
pilas y el voltaje es de 3 Volts, el ADC debe ser alimentado con 3 volts como mximo
tambin.
El vref que se encuentra en las ecuaciones 2.1 y 2.2 puede ser de tres tipos:
1. Vref=Vcc del microcontrolador, en este caso Aref no se conecta (pin 21), vea la
figura 2.14 el circuito de en medio.
2. Vref=Aref (pin 21). En este caso se tiene una referencia externa y puede ser
cualquier voltaje, siempre y cuando no sea superior al Vcc del microcontrolador.
Este se ejemplifica en el primer diagrama de la figura 2.14.
3. Vref=1.1 Volts interno, se debe conectar un capacitor externo de 0.1uf del tipo gota
de tantalo y se muestra en el tercer circuito de la figura 2.14.
Figura 2.14 conexin de las terminales del ADC segn la seleccin del Vref
Todos los casos anteriores se configuran con el codevision con clicks.
En las ecuaciones 2.1 y 2.2 se tiene un trmino llamado Vin que es el voltaje de entrada, es
decir, el voltaje que ser convertido a una combinacin digital, segn su proporcin con
Vref. Este Vin se aplica en los canales del ADC que se numeran desde ADC0 hasta ADC5
(pines del 23 al 28), entonces tenemos que esos pines tienen varias funciones ya sean como
pines de entrada o salida, o como entradas del ADC. Entonces si el pin se configura como
entrada del ADC ya no puede funcionar como entrada/salida digital, esto es que las
funciones son excluyentes.
El programa 9 hace una conversin sobre el canal 0, pero el resultado que da, no es en
voltaje sino en un cdigo binario. Si Vin=0 volts la conversin da 0b0000,0000; si vin=2.5
volts la conversin da 0b1000,0000 (128 decimal); si es 5 Volts=0b1111,1111 (255
decimal). Es decir nos convierte a una proporcin binaria que luego debemos interpretar,
pero ese resultado lo podemos convertir a voltaje a travs de una regla de 3.
Si Vin=5 da como resultado 0xff, es decir 255, Pero deseamos que muestre un cdigo
nuevo que sea 50 (que sera 5.0 Volts). Entonces se resuleve as:
Cdigo nuevo=Conversin*50/conversin mxima
Note, si Vin=5 Volts, la conversin dar 0b1111,1111 que es 255, que sustituyendo en la ec
1.3 da:
Cdigo nuevo=255*50/255=50 que podemos interpretar como 5.0 Volts.
Si vin=2.5 Volts, la conversin dar 0b1000,0000 que es 128
Cdigo nuevo=128*50/255 =25 que podemos interpretar como 2.5 Volts.
Entonces la ecuacin 1.3 queda:
cdigo nuevo=conversin del ADC * cdigo que deseamos.....................................ec(2.3)
conversin_Mxima.
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com
Ejemplo suponga que conectamos un sensor de temperatura que da 5 volts cuando hay
100C, entonces ahora deseamos mostrar el resultado en grados centgrados, no en voltaje,
as que sustituyendo en la ecuacin 1.3 queda:
Cdigo nuevo=Conversin del ADC*100/Conversin Mxima (255 para 8 bits)
Si conversin=255, el cdigo nuevo=100C
Si la conversin del ADC=128, el cdigo nuevo ser 128*100/255=50, el cdigo
nuevo=50C.
Pero ese cdigo nuevo debemos separarlo en digitos para poderlo desplegar en el display de
7 segmentos o en una LCD. Esto se realiza en el programa 10.
Programa 10. Haga una conversin de 8 bits en el canal 1 y muestre el resultado del
volatje en dos displays que se conectarn al Puerto B. El Vref=Vcc=5 volts. El pin Co
controlar el display de unidades y el C1 el de decenas. Se usar el canal 2 del ADC2
por donde se aplicar un voltaje variable de entre 0 y 5 volts, el cual ser desplegado
en los dos displays desde 0.0 hasta 5.0
Usando la ecuacin 2.3 tenemos que la conversin mxima =255, el cdigo que deseamos
con esa conversin mxima=50 para mostrar 5.0 Volts.
cdigo nuevo= conversin del ADC * cdigo que deseamos
Conversin Mxima
Debemos hacer lo siguiente en el programa:
Leer la conversin del canal
x=read_adc(1);
codigonuevo=x*50/255;
Importante. x es tipo char, se multiplica por 50 pero ese resultado temporal ocupa ms de 8
bits. Para evitar esto se hace el casting, es decir, se le dice al compilador el resultado de
x*50/255 da como resultado un char, ya que no sobrepasa a 255, pero lo obliga a que en las
operaciones intermedias (sobre todo en la multiplicacin) se guarde el resultado en algn
lugar ya que ocupa ms de 8 bits. El casting se hace codigonuevo=(char)x*50/255
El siguiente listado es el programa que gener el codewizard y lo que est en azul es lo que
deber agregar al programa que usted haga.
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.6 Evaluation
Automatic Program Generator
Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 05/10/2008
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type
: ATmega48
Clock frequency : 1,000000 MHz
Memory model
: Small
External RAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
#include <delay.h>
unsigned char var,codigonuevo,unidades,decenas;
const char tabla7segmentos [10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x6f};
void despliega(void); //Se va a utilizar una funcin que se llama despliega sin parmetros
#define ADC_VREF_TYPE 0x60
#define tru PINC.0
#define trd PINC.1
despliega();
Hasta este punto ya sabe como manejar puertos, desplegar datos en displays de 7 segmentos
y LCds, guardar datos en eeprom y adems sabe utilizar el ADC. Con este conocimiento
Programacin en C de los microcontroladores ATMEL
e-mail: dinfante29@hotmail.com