Академический Документы
Профессиональный Документы
Культура Документы
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
5 aos de experiencia profesional en el desarrollo de proyectos de automatizacin para empresas embotelladoras y de la transformacin, basados en la integracin y programacin de PLCs, redes industriales, paneles de operador, instrumentacin y control de procesos. Amplia experiencia en programacin de PLCs de Siemens en lenguaje escalera, FBDs, y Grafcet. Programacin de paneles de operador para diseo de interfaces hombre-mquina (HMI), experiencia en el campo de la termografa para anlisis de fallas en sistemas elctricos, mecnicos y estructurales basados en el anlisis de las imgenes trmicas, conocimiento de robots PUMA y saturno y programacin de mquinas de control numrico. Participacin en el diseo de cajeros automticos para bancos nacionales. Diseo electrnico de sistemas empotrados con microcontroladores
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: 6802, HC11 y HC08 de Motorola PICs de Microchip MSP30 de Texas Instruments COP de National Semiconductors AVR y ATMEGA de Atmel 8051 de INTEL DSPs de Texas Instruments y Motorola
Con el conocimiento de estos microcontroladores puedo aportar mi experiencia en el uso de estos dispositivos y que resumiendo puedo sealar que Motorola es un fabricante con dispositivos buenos y de amplio uso industrial como PLCs que basan su CPU en sus microcontroladores. Son usados en ambientes de mucho ruido como el automotriz y el industrial, sin embargo a ltimas fechas ha realizado muchos cambios en el core, en las herramientas de programacin, haciendo ms difcil conseguirlos y elevndose su costo. Los COP son muy poco usados en el ambiente industrial, y resultan caros, adems de que no cuentan con novedades en su diseo, los 8051 de Intel estn en plena desaparicin y los que hay son nicamente para reemplazo. Los microcontroladores MSP de Texas Instrumentes son econmicos, son potentes y tiene herramientas gratuitas, sin embargo son dispositivos para uso porttil por lo que su voltaje es de 3.3 V y son de montaje superficial lo que dificulta el diseo de prototipos. Los microcontroladores PIC son los peores microcontroladores que existen, son muy lentos que trabajan a baja velocidad, tiene un set de instrucciones muy pequeo que obliga a programas muy extensos y lentos, tiene nicamente un work register cuando un procesador RISC debe tener al menos 16 registros, de todos los microcontroladores que existen en el mercado son los peores en el desempeo, algunas empresas comenzaron a hacer sus equipos con estos procesadores y despus al detectrseles fallas como bloqueos o reinicializacin por ruido sacaron del mercado sus productos. En pases desarrollados no se usan ya que no tienen aplicacin industrial o comercial, nicamente en escuelas de pases
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 /* */ para poner varias lneas como comentarios
/* Aqu estamos usando estos smbolos para ilustrar como podemos poner comentarios en varas lneas */ Tipos de datos Nuestras variables pueden ser del siguiente tipo: Tipo Bit Char Unsigned char signed char Int short int Unsigned int signed int long int Unsigned long int signed long int Float Double 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
Importante. Si no se inicializan las variables dentro del programa o en la declaracin de las variables stas son inicializadas a cero. El manejo de nmeros los puede hacer en decimal, binario, hexadecimal u octal. Variable o constante Decimal Hexadecimal Binario 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 Formato Nmero 0x nmero hexadecimal 0b nmero binario 0 nmero octal
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.
Tambin se puede hacer de la declaracin del arreglo como se muestra a continuacin donde omitimos el tamao del arreglo que es 3 ya que al compilarse el programa ver que son de tres elementos el arreglo. flash char arreglo1 []={0x0a,0x38,0x23}; //Note que no se coloc el tamao del arreglo Si no se coloca la palabra flash o const se guardar el arreglo en RAM por ejemplo int arreglo2 [4]={100,200}; Es un arreglo de 4 elementos enteros, el primero vale 100, el segundo 200 y el tercero y cuarto 0 ya que no fueron inicializados. Como fue un arreglo guardado en RAM se pueden modificar. En el caso de que se guarden en FLASH no podrn ser modificados ya que sern considerados como constantes. Tambin podemos guardar caracteres para posteriormente mandarlos a una pantalla de cristal lquido (LCD) ejemplo: flash char arreglostring []=Ejemplo de caracteres;
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.
Var1=Var2/12; Var1=Var2%12;
//Si Var2=40, Var1 ser 3; //Si Var2=40, Var1=4 que es el residuo. til para convertir // nmeros a BCD
Recuerde que variable++ significa incrementar en 1 la variable y que variable-- significa decrementar en 1 la variable. Si lleva slo una instruccin debajo del if no es necesario las llaves: {} If (Var2!=1) Var1++; //Se incrementa Var1 si Var2 es distinto de 1
If (((Var2>12)&&(Var3>=-125)) ||(Var4!=0)) //Var1 se multiplica por -1 si se cumple la Var1=-Var1; //Parte de (Var2 y Var3) o (Var4) o ambas
En la siguiente tabla vemos el resultado de variable|=0x08 que se utiliza para poner en 1 el bit 3; notamos en la tabla que los otros bits de la variable no se modifican y que slo se afecta el bit3 (columna azul), si ste estaba en 0 lo pone en 1 y si estaba ya en 1 lo deja en 1. B7 Variable 1 0x08 0 Resultado 1 De la Or 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
Entonces para prender bits se debe hacer lo siguiente: variable|=0x01 para prender el bit0. variable|=0x02 para prender el bit1. variable|=0x04 para prender el bit2, etc, Si deseara prender el bit0 y el bit6 al mismo tiempo sin afectar los otros bits tendra que escribir: variable|=0x01|0x40 para prender el bit 0 y el bit 6. Para apagar bits se usa la expresin: variable&=~0x01 esta expresin apaga el bit 0 y no modifica los otros bits. variable&=~(0x02|0x08|0x40);esta expresin apaga el bit 1, el bit 3 y el bit6 y no modifica el estado de los otros bits. La expresin variable&=~0x01 es equivalente variable=variable&(~0x01) recordemos que el smbolo ~ saca el compelemento a 1 que es inversin de bits. Si suponemos que variable=0b11001011 Variable ~0x01 Resultado De la AND 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 Autor: David Infante Snchez www.comunidadatmel.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 Autor: David Infante Snchez www.comunidadatmel.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) void ejemplofuncion2 (char, char) int ejemplofuncion3 (void) char ejemplofuncion4 (int) 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 } Estos fueron ejemplos de funciones, el nombre se le puede cambiar, se usaron variables con determinados nombres pero stos pueden cambiar. Cuando no se enva parmetros se coloca la palabra void, cuando no hay retorno de valor de la funcin se coloca la palabra void.
Autor: David Infante Snchez www.comunidadatmel.com
Cuando se envan parmetros se reciben en las funciones en otras variables segn su posicin. El valor que regresar la funcin se hace con return nombre_de_variable. En la definicin del prototipo se le indica al compilador si la funcin va o no a enviar parmetros, y si va o no a retornar algn valor la funcin, en el caso de que en el prototipo se le indique que va a enviar parmetros y no se enve parmetros en el llamado de la funcin se va a marcar error a la hora de la compilacin porque no concuerda la definicin con la forma en que se est manejando la funcin. Entonces el manejo de la funcin debe hacerse como se declar en la definicin del prototipo. 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;
Importante. Dentro de la funcin cuando se colocaron las variables a y b, stas NO se declaran ya que son consideradas variables locales, es decir, que slo tienen validez dentro de la funcin, cuando el programa sale de la funcin desaparecen. O en otras palabras esas variables slo existen dentro de la funcin. Le puse el nombre de a y b, pero puede ponerle el nombre que quiera. Importante. Los PICs y los HC08 slo tienen un slo registro de trabajo, el PIC le llama Work Register y el HC08 le llama acumulador y recomiendan que no use variables locales en los programas, ya que las variables locales se guardan en la pila a travs de instrucciones de PUSH y PULL, haciendo el manejo de variables locales muy lentas, en cambio los AVR tienen 32 registros de trabajo, y es ah donde se guardan las variables locales hacindose ms rpido el manejo de este tipo de variables. En los programas que haga con estos microcontroladores AVR trate de usar siempre variables locales en lugar de variables globales, por las siguientes razones: el programa se ejecuta ms rpido, es ms compacto y no usa la RAM. El manejo de variables locales es de 4 a 8 veces ms rpido el manejo en los AVR que en los PICs o que en los HC08.
Un ATMEL y un PIC trabajando a la misma frecuencia de operacin y con el mismo programa tendra un mejor desempeo el ATMEL pudiendo ocupar entre 6 y 15 veces menos memoria el ATMEL por el conjunto de instrucciones ms amplio, y ejecutando el programa entre 20 y 60 veces ms rpido. Operaciones de punto flotante en el PIC de la serie 16fxx no se pueden realizar ya que por lo pobre de las instrucciones que tiene no es posible, adems de que no tiene capacidad de memoria para poder realizar este tipo de operaciones. Los modos de direccionamiento del AVR es ms amplio, pudiendo inclusive manejar direccionamientos con post y pre incrementos, lo cual eficienta el manejo de tablas y programas. De los microcontroladores AVR y ATMEGA de ATMEL existen muchas familias, pero nosotros nos enfocaremos al ATMEGA48 pero si desea programar cualquier otro AVR o ATMEGA puede hacerlo con los conocimientos que adquiera con este manual. Primero veamos en la figura 2.1 cmo est fsicamente el microcontrolador ATMEGA48.
Figura 2.2 Programas a Instalar En el tema 1.7 se explic que el lenguaje C no tiene instrucciones para manejar timers, ADC, puertos de entrada-salida, etc, es decir, los perifricos del microcontrolador, entonces para poder manejarlos se usan las libreras donde se incluyen las declaraciones de estos registros y su manejo. Es precisamente el programa Code Vision AVR quien tiene esas libreras. El primer programa instala el AVR Studio que es el simulador, el segundo (WinAVR-20071221 ) instala el programador y el tercer SET-UP instala el compilador. Importante. Use slo estas versiones, ya que estn probadas, versiones ms nuevas o viejas pueden tener problemas con el programador, compilador y/o simulador. En el caso de que tenga probados versiones ms nuevas colocar el link para su descarga en mi pgina www.comunidadatmel.com
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
Importante. Si ha manejado otros microcontroladores habr notado que nicamente tienen asociados un slo registro al puerto de entrada/salida, pero en este microcontrolador tiene asociados dos registros al puerto de entrada/salida, si quiere escribir al puerto B deber hacerlo as PORTB=dato; pero si desea leer el estado de los pines de ese puerto deber hacer dato=PINB; es decir deber usar PORTB, PORTC o PORTD para escribir al puerto, y deber usar variable=PINB, variable=PINC o variable=PIND para leer el valor del puerto de entrada. Cualquier otro microcontrolador de otros fabricante slo tienen un slo registro para leer o escribir al puerto, pero en elcaso de ATMEL se tienen dos dando la ventaja de que de esa forma el acceso a puertos es ms rpido cuando se va usar como entrada un determinado pin y posteriormente se va usar como salida, es otra ventaja que tenemos con este tipo de arquitectura. Importante. Limitantes Fsicas de los pines: Mximo pueden dar 40 mA por pin, pero el Circuito Integrado mximo debe manejar 200mA, es decir que sumando la corriente de los pines y la que consume el microcontrolador no deben exceder ms de 200mA. Importante. El pin 1, que es la terminal PC6 tiene a la vez la funcin de RESET, esta terminal no la podemos utilizar como pin de entrada/salida, ya que a travs de ella se hace la programacin del microcontrolador. En otras palabras NO HAGA PROGRAMAS DONDE UTILICE ESA TERMINAL, YA QUE NO LA PODEMOS USAR. Es posible deshabilitarle la funcin de reset y que quede como pin de entrada/salida digital, pero ya no podremos programar al microcontrolador nuevamente. Programa 1. Leer el puerto B y escribirlo al puerto D, activando las resistencias de pull-up en las entradas del puerto B.
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 Autor: David Infante Snchez www.comunidadatmel.com
// 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; ADCSRB=0x00;
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 }; }
Programa 2. Haga un contador binario en el puerto B, el cual deber contar desde 0 hasta 255 y regresar a cero. Para ello coloque un retardo de 1 segundo entre cada cuenta, ya que de no colocar ningn retardo el conteo sera muy rpido no pudiendo apreciarse el conteo en el puerto por la velocidad.
Figura 2.5 Conexin del programa 2 Importante. Hay funciones de retardo llamadas delay_us(dato); y delay_ms(dato); que son funciones en microsegundos y en milisegundos, y el dato es un nmero o una variable de hasta 16 bits. Pero para poder utilizar estas funciones deber colocar la librera #include<delay.h>, ya que de no hacerlo no reconocer las funciones el compilador marcando error. Importante. El oscilador interno es del tipo RC y su valor aproximado es de 8 MHz/8=1 MHz pero este no es un valor exacto de frecuencia por el tipo de oscilador que tiene. Cuando se desean frecuencias exactas o ms altas es necesario un cristal externo. El Valor de oscilacin con el oscilador interno es dependiente del voltaje de alimentacin y de la temperatura, aunque es cercano a 1 MHz.
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 Autor: David Infante Snchez www.comunidadatmel.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 Autor: David Infante Snchez www.comunidadatmel.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 }; }
Programa 3. Hacer un convertidor de BCD a 7 segmentos. En este programa se desea que cuando se introduzca un 0 en el puerto B se dibuje un 0 en el display de 7 segmentos que se conectar en el puerto B, si se introduce un 1 se deber dibujar en el display de 7 segmentos ese nmero, etc. El diagrama de este programa se muestra en la figura 2.6
Figura 2.6 Conexin del programa 3 convertidor de BCD a 7 segmentos Consideraremos tambin que el B0 va conectado al segmento a, el B1 a b, B2 a c, B3 a d, B4 a e, B5 a f y B6 a g. En la tabla 2.1 se aprecia la combinacin que deber ponerse para dibujarse en el display los nmeros, por ejemplo para el 1 debe encenderse el segmento b y c. Estas combinaciones son si se trata de un display de ctodo comn, en el caso de que sea de nodo comn slo deberan invertirse los 1 y los 0.
Tabla 2.1 Conexin del convertidor de BCD a 7 Segmentos Nmero Combinacin digital Combinacin g f e d c b a Hexadecimal B7 B6 B5 B4 B3 B2 B1 B0 0 0 0 1 1 1 1 1 1 0x3f 1 0 0 0 0 0 1 1 0 0x06 2 0 1 0 1 1 0 1 1 0x5b 3 0 1 0 0 1 1 1 1 0x4f 4 0 1 1 0 0 1 1 0 0x66 5 0 1 1 0 1 1 0 1 0x6d 6 0 1 1 1 1 1 0 0 0x7c 7 0 0 0 0 0 1 1 1 0x07 8 0 1 1 1 1 1 1 1 0x7f 9 0 1 1 0 1 1 1 1 0x6f Para este programa deberemos configurar todo el Puerto B como salida, y los pines C0, C1, C2 y C3 como entradas con sus resistencias de pull-up, ya que cuando no se cierre el interruptor quedar a 1 lgico el pin por la resistencia de pull-up interna, y cuando se cierre el interruptor leer 0 el pin. En los cursos que he dado normalmente los participantes dicen que una forma de hacer el programa es con if para probar todas las combinaciones y quizs es la forma que se le ha ocurrido para hacerlo. Es decir algo de esta forma: if (PINC==0) PORTB=0x3f; if (PINC==0) PORTB=0x06; Etc... if (PINC==9) PORTB=0x6f; //Si el puerto C=9 entonces imprime el 9 en el port B //Si el puerto C=0 entonces imprime el 0 en el port B //Si el puerto C=1 entonces imprime el 1 en el port B
//As se haran las 8 pruebas restantes La forma descrita no es incorrecta, pero tiene los siguientes puntos en contra: ocupa demasiadas instrucciones ya que se deben probar todas las posibilidades que es que el puerto C valga 0 hasta que valga 9, ocupando mucha memoria y haciendo lento el programa.
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 Autor: David Infante Snchez www.comunidadatmel.com
// 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=P State2=P State1=P State0=P PORTC=0x0F; 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 Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.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;
//Enmascaramos los 4 bits menos significativos //del puerto A ya que los dems no interesan.
if (variable<10) PORTB=tabla7segmentos[variable]; if (variable>=10) PORTB=0x3f; // Place your code here }; } //Si lo que leemos es mayor o igual de 10 que dibuje en el display un 0
Explicacin del Programa Explicacin de la instruccin variable=PINC&0x0f; suponga que en el puerto C (que es de 7 bits) existen estos datos C=110,0110 pero a nosostros nos interesan solo los 4 menos significativos, esto es el 0110 y los otros no, por lo que debemos quitarlos as que con el and de 110,0110 & 0000,1111 nos da el resultado de 0000,0110, es decir ya slo nos asign a la variable el valor de los 4 bits que nos interesan. Entonces donde se desea que haya un 0 como es el caso de los bits superiores hacemos el and colocando 0 en esas posiciones, y donde queremos que no se modifiquen los bits como en los 4 bits menos significativos hacemos el and con 1 lgico en esa posicin para que nos d como resultado un 1 donde haba un 1 y un 0 donde haba un 0, es decir, lo mismo que haba se queda sin alterarse. Se agreg una instruccin que prueba si el Puerto C tiene un nmero mayor o igual a 10 y en caso de que as sea va a dibujar un 0 en el display. Ya que con 4 bits se pueden representar nmeros desde 0 hasta 15, pero solamente nos interesan los nmeros del 0 al 9 ya que es el tamao de la tabla, en caso de no haberse puesto esas instrucciones, entonces mostrara basura cuando variable>9, ya que esos elementos no estn definidos en la tabla.
Programa 4 Cuando se presione el botn conectado al pin C0 se incrementar el nmero mostrado en el display que ser conectado al puerto B.
Figura 2.7 Conexiones para los programas 4, 5 y 6 Configuracin: C0 como entrada con resistencia de pull-up activada, los pines B0 a B7 como salida que es donde se conectar el display.
/***************************************************** 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> #define boton PINC.0 const char tabla7segmentos [10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x6f}; Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
unsigned char var1; // 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=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 // 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; ADCSRB=0x00; while (1) { if (boton==0) var1++; if (var1==10) var1=0; PORTB=tabla7segmentos [var1]; // Place your code here }; }
Explicacin del programa: Un solo bit de un registro se puede accesar nombre_de_registro.nmero_de_bit El registro del Puerto C es PINC y el bit que deseamos accesar es el 0, entonces PINC.0 es accesar el bit 0 del PINC, que es la terminal C0 Se desea que cuando se presione el botn conectado al pin C0 se incremente el contador, entonces podramos escribir as: if (PINC.0==0) //Cuando se presiona vale 0
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
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.
Figura 2.8 Deteccin de flancos Para poder trabajar por flancos es necesario tener el valor del botn anterior y del botn actual, por ejemplo en 1 y 2 el botn pasado vale 1 y el botn actual vale 1, con eso sabemos que no ha sido presionado el botn; ahora en el punto 2 y 3 el punto 2 es botn pasado y el 3 es botn actual y ambos valen 1, as que no ha sido presionado el botn; en el punto 3 y 4 el botn pasado vale 1 y el botn actual vale 0 eso significa que se presion el botn y que hubo un flanco de bajada de 1 a 0 ese cambio nos sirve, por ejemplo, para incrementar la variable. Despus el punto 4 vale 0 y el punto 5 vale 0 que son botn pasado y actual respectivamente eso significa que no hay cambio de flanco, cuando est en los puntos 7 y 8 tanto botn pasado como actual valen 0 por lo que no hay cambio, en el punto 8 y 9 el botn pasado y actual valen 0 y 1 ese es un cambio de flanco de subida; en el punto 9 y 10 los valores de botn pasado y actual valen 1 por lo que no hay cambio de flanco. Ahora en el programa se har que el valor en el display se incremente solamente en 1 sin importar cunto dure presionado el botn, es decir, que funcionar por flanco, y lo haremos que se incremente en 1 cuando cambia de 1 a 0 el valor del pin, es por ello que debemos tener dos valores: botona y botonp que guardarn los valores que tuvo el botn actual y el botn pasado. Programa 5. Programa que incrementa el valor del contador BCD conectado al puerto B cada vez que se presiona el interruptor conectado al pin C0. Este funcionar por nivel de bajada, es decir, solo cuando se presione el interruptor se incrementar el conteo. Configuracin. Puerto B de salidas, pin C0 de entrada con resistencia de pull-up activada. El circuito a aramar es el mismo de la figura 2.7. La inicializacin se har igual que el programa anterior, vea el video_p5 donde est cmo se inicializa el microcontrolador.
/***************************************************** 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 Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.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> // 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 Autor: David Infante Snchez www.comunidadatmel.com
// 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; ADCSRB=0x00; while (1) { // Place your code here if (boton==0) botona=0; else botona=1; if ((botona==0)&&(botonp==1)) //hubo cambio de flanco de 1 a 0 var++; //Se incrementa la variable if (var==10) var=0; Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
Explicacin del Programa. Cuando el boton (que es el pin C0 por el define) sea 0 se har la variable tipo bit botona=0, si boton es 1 entonces botona=1. Es decir slo copia el valor del pin y se asigna a esa variable tipo bit if (boton==0) botona=0; else botona=1; En la parte ms baja del programa se tiene botonp=botona; Esto es porque el valor del botona (botn actual) se convierte en el valor del botonp (botn pasado), cuando regrese a la parte de arriba del programa se leer el valor del botona (boton actual) entonces de esta manera tenemos el valor actual (botona), as como el valor pasado inmediato (botonp). Cuando llegue a la parte de abajo el botona (botn actual) ser el valor pasado, porque despus se leer el valor del botn actual, y as consecutivamente. Ya que se tiene el valor actual y pasado del botn se tienen las instrucciones de y con el primer if se prueba si hubo cambio de flanco de 1 a 0 ya que se prueba si botonp==1 y que botona==0, con estas dos pruebas sabemos que hubo cambio de flanco de 1 a 0, y si lo hubo se incrementa la variable, entonces solo cuando se presiona el botn se incrementar la variable, sin importar cunto dure en 0, ya que funciona el programa por flanco de bajada y no de subida. if ((botona==0)&&(botonp==1)) //hubo cambio de flanco de 1 a 0 var++; //Se incrementa la variable if (var==10) var=0; Cuando programe el microcontrolador y arme el circuito ver que en ocasiones cuando presiona el interruptor o cuando lo suelta se incrementa en varias unidades el display, y es porque el interruptor genera rebotes, ya que el cerrado y la apertura de interruptores mecnicos no es instantneo generndose rebotes (vea la figura 2.9). A continuacin explicar como eliminar los rebotes.
Eliminacin de rebotes en un interruptor vea el siguiente diagrama donde se aprecia que cuando se presiona un interruptor, ste se abre y cierra varias veces por que el cerrado no es instntaneo; de la misma forma cuando se abre el interruptor se generan rebotes y stos se pueden generar durante periodos de 40 mS.
Figura 2.9 Rebotes en un interruptor mecnico Si hiciramos un programa que cada vez que se presiona una tecla incrementara un valor y no quitramos los rebotes y se generar los rebotes del diagrama anterior veramos que se incrementara la variable 5 veces en lugar de 1 vez debido a que los rebotes generan varios cambios de nivel de 1 a 0 y de 0 a 1 tanto al presionar el interruptor como al soltarlo. En ocasiones los diseadores y programadores inexpertos colocan circuitos externos (filtros pasabajas o circuitos integrados) para eliminar los rebotes, pero esto no es necesario ya que se puede hacer por software. La forma de eliminar los rebotes es detectar cuando hubo cambio de flanco tanto de bajada como de subida y poner un retardo de 40 mS para evitar que detecte los otros flancos.
Programa 6. Cada vez que se presione el botn conectado al pin C0 deber incrementarse el valor que se muestra en el display que se conectar en el Puerto B, eliminndose los rebotes que se generan en el cierre y en la apertura del interruptor. Configuracin: Pin C0 de entrada y con resistencia de pull-up activada, B0 a B6 de salidas. Vea el video_p6 donde se muestra la configuracin del microcontrolador. A continuacin est el listado del programa completo, lo que est en azul es el cdigo que deber agregar al cdigo generado con 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> #include <delay.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; Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
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 Autor: David Infante Snchez www.comunidadatmel.com
// 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) 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 PORTB=tabla7segmentos [var]; botonp=botona; }; }
Explicacin del programa La diferencia con respecto al programa 5 es que en las instrucciones donde detecta el flanco de 1 a 0 se coloc la instruccin de delay_ms(40); esa instruccin dura 40 mS y ah se queda ese tiempo el programa, entonces cuando vuelva a checar el valor del botn ya los rebotes ya no existen porque ya pasaron 40mS 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 } Tambin se agreg las siguientes instrucciones: if ((botonp==0)&&(botona==1)) //hubo cambio de flanco de 0 a 1 delay_ms(40); //Se coloca retardo de 40mS para eliminar rebotes Recuerde que cuando se abre el interruptor (en el flanco de 0 a 1) tambin se pueden generar rebotes, por lo tanto cuando se detecta que se abri el interruptor se coloca un
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.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
Figura 2.10 Diagrama de un teclado matricial de 3*3 En la figura 2.10 se muestra un teclado matricial de 9 teclas, aqu se ocupan 3 pines de salida que son los 3 pines superiores, los 3 pines inferiores se ocupan como entradas, es importante sealar que a los pines de entrada SE LES CONFIGURA LA RESISTENCIA DE PULL-UP INTERNA. Si no se presiona ningn botn marcado de B1 a B9 los 3 pines de entrada leern 111 ya que leen el 1 por la Resistencia de pull-up interna. El funcionamiento del teclado matricial se basa en escaneos, es decir, se va probando columna por columa. Por ejemplo si en los 3 pines de salida se enva 011 se va a probar la primera columna donde estn B1,B2 y B3, si se presiona B1 en los pines de entrada se leer 011, si se presiona B3 se leer 110, si no se presiona ningn botn se leer 111. Note
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
que si en los pines de salida se enva 011 y se presiona un botn de B4 a B9 no se va a leer ningn cero en los 3 pines de entrada porque se est probando la columna 1. Para probar la segunda columna se enva en los pines de salida 101 y si no se presiona ninguna tecla se leer en la entrada 111, pero si se presiona el boton 5 se leer 101, si se presiona el botn 6 se leer 110. Si se presiona los botones B1 a B3 o B7 a B9 se leern en los 3 pines de entrada 111 debido a que se est probando la segunda columna. Las resistencias de 100 ohms que se ponen a la salida de los 3 pines es para prevenir cortos circuitos y daar el puerto del microcontrolador, suponga que no se pusiera esas resistencias y que se enva el dato 101 y se presiona al mismo tiempo el botn B1 y B4 vemos que en B1 hay 1 (5 volts) y en B4 hay 0 (0 Volts) entonces se generara un corto circuito. Pero al poner esa resistencia de 100 ohms no sucede el corto ya que se limita la corriente por ese resistor. Resumen del teclado matricial: Para probar la primera columna (botones B1 a B3) se enva en los pines de salida 011 Para probar la segunda columna (botones B4 a B6) se enva en los pines de salida 101 Para probar la tercera columna (botones B7 a B9) se enva en los pines de salida 110 Si se envi el cdigo 011 y se lee en los pines de entrada 011 entonces se presion el botn B1. Si se envi el cdigo 011 y se lee en los pines de entrada 101 entonces se presion el botn B2. Si se envi el cdigo 011 y se lee en los pines de entrada 110 entonces se presion el botn B3. Si se envi el cdigo 101 y se lee en los pines de entrada 011 entonces se presion el botn B4. Si se envi el cdigo 101 y se lee en los pines de entrada 101 entonces se presion el botn B5. Si se envi el cdigo 101 y se lee en los pines de entrada 110 entonces se presion el botn B6. Si se envi el cdigo 110 y se lee en los pines de entrada 011 entonces se presion el botn B7. Si se envi el cdigo 110 y se lee en los pines de entrada 101 entonces se presion el botn B8. Si se envi el cdigo 110 y se lee en los pines de entrada 110 entonces se presion el botn B9. Si cuando se envan los cdigos 011, 101 y 110 no se presiona ningn botn se leer en los pines de entrada 111 En el teclado matricial a los pines de entrada hay que activarles la resistencia de pull-up para que cuando no se presione ningn botn se lea 1 lgico en cada pin y no quede flotado
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
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 Autor: David Infante Snchez www.comunidadatmel.com
// 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; ADCSRB=0x00; while (1) { //C0 A C2 son de salida y son para //Probar las 3 columnas //Se prueba la primera columna se enva 110 PORTC=0b00111110; //C3, C4 y C5 son las entradas del teclado //Por eso se enmascaran con 00111000 lectura=PINC&0b00111000; if (lectura==0b00110000) tecla=7; if (lectura==0b00101000) tecla=8; if (lectura==0b00011000) tecla=9; Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
//se prueba segunda columna se enva 101 PORTC=0b00111101; //C3, C4 y C5 son las entradas del teclado //Por eso se enmascaran con 00111000 lectura=PINC&0b00111000; if (lectura==0b00110000) tecla=4; if (lectura==0b00101000) tecla=5; if (lectura==0b00011000) tecla=6; //se prueba tercera columna se enva 011 PORTC=0b00111011; //C3, C4 y C5 son las entradas del teclado //Por eso se enmascaran con 00111000 lectura=PINC&0b00111000; if (lectura==0b00110000) tecla=1; if (lectura==0b00101000) tecla=2; if (lectura==0b00011000) tecla=3; PORTB=tabla7segmentos [tecla]; // Place your code here }; }
Importante. Un puerto tiene asociado 2 registros el PINX y el PORTX donde X es el puerto A, B, C, etc segn sea el caso del microcontrolador que se est usando, y adems de de ser los registros para escribir y leer datos al puerto, sirven para ACTIVAR y DESACTIVAR LAS RESISTENCIAS DE PULL-UP. Ejemplo suponga que configura los primeros 4 bits del puerto B como entrada y los 4 bits siguientes como salidas. Cuando desee escribir informacin al Puerto B (vemoslo en binario) puede hacer lo siguiente: 1. PORTB=0b11001111; 2. PORTB=0b11001100; 3. PORTB=0b11000011; En los 3 casos al puerto B le escribira 1100 en la parte alta, la parta baja aparentemente no se modificara porque estn configurados como entradas, pero sucede lo siguiente: Cuando un pin es configurado como entrada y se le escribe a travs del PORTX un 1 en ese bit le activar la resistencia de pull-up. Cuando un pin es configurado como entrada y se le escribe a travs del PORTX un 0 en ese bit le desactivar la resistencia de pull-up. Entonces en el caso 1: le est activando la resistencia de pull-up interna a los 4 bits menos significativos. En el caso 2 le est desactivando la resistencia de pull-up a los 2 bits menos significativos y le est activando la resistencia de pull-up interna a los 2 pines siguientes.
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
En el caso 3 le est activando la resistencia de pull-up a los 2 primeros pines y se la est desactivando a los 2 pines siguientes. Por ello en el programa cuando se deseaba que C2,C1 y C0 fuera 110 se escribi PORTC=0b00111110; para no desactivar las resistencia de pull-up en los pines C3,C4 y C5. Entonces recuerde que si un puerto lo tiene configurado unos pines como salida y otros como entrada, y adems a los de entrada a unos pines les activ la resistencia de pull-up y a otro no, deber escribir a travs del PORTX un 1 en la posicin de los pines que les activ la resistencia de pull-up, ya que si se le pone 0 la va deshabilitar, ahora en el caso de que esos pines sean configurados como entrada y no les activ la resistencia de pull-up deber escribir en PORTX un 0 en los pines que no estn activadas las resistencia de pull-up, ya que de escribirles un 1 las activar. Ejemplo: B3, B2, B1 y B0 como salidas, B4 y B5 como entradas con resistencia de pull-up interna y B6 y B7 tambin de entrada pero sin resistencia interna de pull-up activada. Y desea escribir de B3 a B0 1101 deber usar PORTB as: PORTB=0b00111101; //B7 y B6 0 para no habilitar la R de pull-up, B5 y B4 1 para mantener la R de pull-up y en B3 a B0 1101 que es el dato que desea escribir.
Figura 2.12 Conexiones para el programa 8 Configuracin: C0 y C1 de entrada con resistencia de pull-up activada y es donde se conectarn los botones; B0 a B6 de salida para conectar el display.
/***************************************************** 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 Autor: David Infante Snchez www.comunidadatmel.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 Autor: David Infante Snchez www.comunidadatmel.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; }
Explicacin del Programa En este programa se est utilizando una funcin que llam checa_boton, pero esta funcin se debe declarar en la parte de arriba, esta funcin no regresa, ni enva parmetros por lo que se coloca void checa_boton(void); Para entender mejor esto regrese a la seccin del primer captulo donde se explica las funciones. void checa_boton (void); // Aqu se declaran todas las funciones que se van usar Despus en el programa se llama la funcin y se coloca: checa_boton(); Cuando la funcin se ejecuta, regresa a la instruccin que est debajo de checa_boton(); que es PORTB=tabla7segmentos [var]; En una parte del programa se tiene: if (datoaguardar>10)
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
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.
2.6.1 Funcionamiento de un ADC Un ADC convierte una seal analgica a un dato digital de manera lineal, para ello es necesario identificar tres aspectos importantes y stos son: el voltaje de referencia (Vref), el nmero de bits y si es unipolar o bipolar el ADC. 2.6.1.1 Conversin unipolar En la conversin unipolar el voltaje que se introduce a los canales del convertidor es solamente positivo, y pudiendo ser la conversin del ADC de 10 bits o de 8 bits, si es de 10 bits significa que identifica hasta 210 combinaciones que son 1024; si es de 8 bits tiene 28 combinaciones esto es 256 combinaciones. Obviamente entre ms bits sean es mejor el ADC aunque en ocasiones no es necesario una resolucin tan elevada. El voltaje de referencia es el valor con el que se comparar el voltaje de entrada analgico y con base en ello se determina la combinacin de salida. La forma de obtener la combinacin digital si est configurado el ADC en 10 bits es:
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
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
Figura 2.13 Pines del microcontrolador ATMEGA48 En la figura 2.13 vemos que en las terminales 22 y 20 dicen GND y AVCC, ests son las trminales de tierra y alimentacin del perifrico del convertidor de analgico a digital. Normalmente los microcontroladores de otros fabricantes el ADC se alimenta con el mismo voltaje del microcontrolador, pero en los de ATMEL son alimentados por separado para disminuir los efectos del ruido. Aunque en nuestro caso y para los programas que vamos a realizar el AVCC y VCC los conectaremos juntos y los GND tambin sern conectados juntos. Pero recuerde que si en su aplicacin requiere de una conversin ms exacta puede alimentar el microcontrolador y el perifrico del ADC por separado. Solamente tenga en
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
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.
Resumen del ADC En este perifrico podemos tener: Conversin unipolar donde se aplica a la entrada analgica un valor de voltaje positivo que puede ir desde 0 hasta Vref. o Puede ser la conversin de 8 bits donde el resultado est dado por: conversin=(Vin*256)/Vref o Puede ser la conversin de 10 bits donde el resultado est dado por: conversin=(Vin*1024)/Vref El Vref puede ser el voltaje del microcontrolador, pueder ser uno externo conectado a la terminal Aref o uno interno de 1.1 Volts. El Vin es el voltaje analgico que ser convertido a un combinacin digital, y ese vin se aplica en cualquiera de los canales ADC0 hasta ADC5 El perifrcio del ADC se alimenta por separado, pero no puede ser mayor al Vcc del microcontrolador. Aunque para estos ejemplos conecatremos las terminales de GND y el Vcc lo conectaremos al Avcc. Las configuraciones descritas anteriormente se realizan con clicks en el codevision, por lo que no es necesario aprender ningn registro o bit de stos para su configuracin.
Importante. Si va a utilizar un canal para hacer la conversin tenga la precaucin de configurar ese pin como entrada. Ya que en ese canal va aplicar voltaje y no puede estar configurado el pin como salida, ya que de ser as se podra daar el pin. Por ejemplo si va utilizar el canal 0 del adc que es el pin A0 deber configurar ese pin como entrada. Importante El Avcc no puede ser mayor al Vcc, por eso conctelos juntos Importante El Aref no puede ser mayor al Vcc del microcontrolador. Importante No aplique Vin mayores a Aref o a Vcc para evitar daos en el pin del ADC. Programa 9. Haga una conversin en 8 bits sobre el canal 0 del ADC y muestre el resultado en leds que se conectarn en el Puerto B. Configure como Vref el AVcc del microcontrolador. Tabla 2.1 Canal y pin del ADC Canal Pin 0 ADC0 23 C0 1 ADC1 24 C1 2 ADC2 25 C2 3 ADC3 26 C3 4 ADC4 27 C4 5 ADC5 28 C5
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
Figura 2.15 Conexin para el programa 9 Con el codewizard se hace la configuracin del ADC a travs de simples clicks, lo nico que debemos hacer en el programa es leer el valor de la conversin del canal que estemos usando a travs de la siguiente funcin: variable=read_adc (nmero_de_canal); Por ejemplo si desear utilizar el canal 3, que es el pin 26 deber colocar : variable=read_adc(3); Recuerde tambin que el ADC puede entregar la conversin en 8 o 10 bits, si selecciona conversin en 8 bits, entonces la variable deber definirse como unsigned char variable; es decir tipo char de 8 bits, pero si se selecciona una conversin en 10 bits deber declarar la variable como unsigned int variable, ya que el valor de la conversin ocupa 10 bits. El nombre que le di a la variable donde se guardar el resultado fue variable, pero puede darle cualquier nombre. Importante. La funcin read_adc() slo puede utilizarse si dentro del codevision se habilit el ADC, ya que si lo usa en cualquiera de los otros programas que se han realizado y que no han unicializado el ADC marcar error.
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00; // Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 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; Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
// 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; // ADC initialization // ADC Clock frequency: 500,000 kHz // ADC Voltage Reference: AVCC pin // ADC Auto Trigger Source: None // Only the 8 most significant bits of // the AD conversion result are used // Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On // ADC4: On, ADC5: On DIDR0=0x00; ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0x81; while (1) { x=read_adc(0); //Se hace la conversin sobre el canal 0 del ADC PORTB=x; //Se despliega en el puerto B el valor digital // Place your code here }; }
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 Autor: David Infante Snchez www.comunidadatmel.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 USO DEL CASTING Ejemplo 1. Suponga que tiene x=y+w+z; y todas son tipo char, en ese caso no existe problema ya que si y+w+z da como resultado un nmero menor a 255 se podr guardar en x. Ejemplo 2. x es tipo int; y,w y z son tipo char. Y se escribe x=y+w+z; Pero se sabe que y+w+z van a dar mas de 255, y que caben en x ya que esta es tipo int. Pero lo de la derecha y+w+z est declarado como char, entonces cuando la suma d ms de 255 dnde quedan esas operaciones? Entonces aqu si va existir un problema porque x=int y y+w+z son tipo char cuya suma da mas de 8 bits y que cabe en x, pero en las sumas parciales las variables son char y estas no pueden guardar mas de 8 bits, entonces hay que hacer un casting, obligando al compilador a decirle todas son tipo char, pero el resultado es tipo int para que lo guarde temporalmente en algn lugar para despus asignarlo a x. x=(int) y+w+z; //Esto ya da un resultado correcto x=y+w+z //Dara un resultado errneo ya que y+w+z da mas de 8 bits y estas variables no pueden manejar ms de 8 bits Importante. Podemos evitar hacer clculos de las operaciones intermedias para ver si hacemos o no el casting, y esto dejarlo al compilador. Esta opcin se selecciona en el codevision en project-configure-C Compiler y finalmente dando click en promote char to int como se muestra en la figura 2.15. Con la seleccin de la casilla promote char to int le estamos indicando al compilador que cuando ocupe hacer que la variable la haga ms grande lo haga l mismo para evitarnos problemas de casting.
Con lo anterior le estamos indicando al compilador si la operacin intermedia ocupa el char un espacio de un int que lo genere para evitar errores y as ya nos olvidamos del casting. Con las dos instrucciones anteriores ya tenemos representado en voltaje la conversin, pero debemos separarlo en dos digitos, esto es calcularle la cantidad de decenas y las unidades. Continuando con la explicacin del programa, si ya se calcul el cdigo nuevo, ahora debemos obtener los dos digitos a desplegar ya que el 50 no se puede desplegar en un display, debemos obtener los dos digitos, as que: decenas=codigonuevo/10; unidades=codigonuevo%10; Recuerde que % es la operacin mdulo y que da como resultado el residuo. Suponga que el cdigonuevo=48, es decir 4.8 Volts Entonces decenas=48/10=4 Y unidades=48%10=8 (que es el residuo) Y las decenas y unidades los mandamos desplegar en dos displays de 7 segmentos. Importante. En cada proyecto nuevo que hagamos debemos seleccionar la casilla de promote char to int. Configuracin: PORTB de salidas para conectar los displays. C0 y C1 salidas que sern usados para manejar los dos transistores: el que controla el display de unidades, y el que controla el display de decenas. El pin C2 como entrada que es tambin el canal 2 del ADC (ADC2). Vea el video_p10 donde se muestra la inicializacin del microcontrolador junto con el ADC.
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
// Read the 8 most significant bits // of the AD conversion result unsigned char read_adc(unsigned char adc_input) { ADMUX=adc_input | (ADC_VREF_TYPE & 0xff); // Delay needed for the stabilization of the ADC input voltage delay_us(10); // Start the AD conversion ADCSRA|=0x40; // Wait for the AD conversion to complete while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCH; } // 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=Out Func0=Out // State6=T State5=T State4=T State3=T State2=T State1=0 State0=0 PORTC=0x00; DDRC=0x03; // 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 Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
// 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; ADCSRB=0x00; // ADC initialization // ADC Clock frequency: 500,000 kHz // ADC Voltage Reference: AVCC pin // ADC Auto Trigger Source: None // Only the 8 most significant bits of // the AD conversion result are used // Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On // ADC4: On, ADC5: On DIDR0=0x00; ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0x81; while (1) { var=read_adc(2); //Se lee el valor del Canal 2 del ADC (PIN C2) codigonuevo=50*255/var; //Convierte el valor del ADC a un cdigo nuevo en voltaje decenas=codigonuevo/10; //Calcula las decenas unidades=codigonuevo%10; //Calcula las unidades Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
despliega();
// Place your code here }; } void despliega(void) { PORTB=tabla7segmentos [unidades]; tru=1; //Prende display de unidades delay_ms(4); //Deja prendido display de unidades 4mS tru=0; //Apaga display de unidades PORTB=tabla7segmentos[decenas]; trd=1; //Prende display de decenas delay_ms(4); //Deja prendido display de decenas 4mS trd=0; //Apaga display de decenas }
Explicacin del programa: Se inicializ el valor de la tabla que nos dibuja los nmeros en los 7 segmentos del display y declaramos una funcin que nombr despliega y que utilizar en el programa y que no enva, ni recibe parmetros. 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 Despus se agreg las siguientes igualdades #define tru PINC.0 #define trd PINC.1 El tru es transistor de unidades y el trd es el transistor de decenas, es ms fcil escribir el programa haciendo por ejemplo tru=1; con ello estamos haciendo que el PINC.0=1; ya que es una igualdad, pero tru resulta ms fcil recordar y sabiendo que es donde est conectado el transistor del displya de unidades Recuerde que la funcin para leer el valor de conversin del ADC es read_adc(canal); que es la primera lnea y dicho valor de la conversin se guarda en una variable llamada var que es de 8 bits, ya que la conversin que escojimos a la hora de inicializar el ADC fue de 8 bits. Si el voltaje que se le aplica al canal 2 es de 2.5 Volts, el valor de la conversin ser de 127, pero nosotros queremos representarlo en voltaje, as que con la frmula de 50*255/var y sustituyendo var=127 nos dar como resultado 25, que ahora si podemos representar como 2.5 Volts. Pero el 25 hay que convertirlo a dos digitos para desplegarlos en el display, por lo que 25/10=2, y 25%10=5 (recuerde que % es la funcim mdulo hace la divisin pero el
Programacin en C de los microcontroladores ATMEL e-mail: dinfante29@hotmail.com Autor: David Infante Snchez www.comunidadatmel.com
resultado es el residuo) y esos valores se guardan en decenas y unidades para desplegarlos en la funcin despliega(); Todo lo anterior es el siguiente cdigo agregado al programa: var=read_adc(2); //Se lee el valor del Canal 2 del ADC (PIN C2) codigonuevo=50*255/var; //Convierte el valor del ADC a un cdigo nuevo en voltaje decenas=codigonuevo/10; //Calcula las decenas unidades=codigonuevo%10; //Calcula las unidades Posteriormente se manda llamar una funcin para desplegar los dos digitos del voltaje: despliega(); //Manda desplegar los dos digitos
La funcin de despliega manda imprimir en el puerto B el digito correspondiente de unidades, despus activa el transistor de unidades, lo deja prendido 4mS y lo apaga y despus manda imprimir el digito de decenas lo prende y apaga, pero lo hace tan rpido que aparenta que estn los dos digitos al mismo tiempo. void despliega(void) { PORTB=tabla7segmentos [unidades]; tru=1; //Prende display de unidades delay_ms(4); //Deja prendido display de unidades 4mS tru=0; //Apaga display de unidades PORTB=tabla7segmentos[decenas]; trd=1; //Prende display de decenas delay_ms(4); //Deja prendido display de decenas 4mS trd=0; //Apaga display de decenas }
Importante. La funcin read_adc(canal) funciona nicamente si a la hora de inicializar el microcontrolador con el codewizard inicializa el ADC, as que si utiliza esta funcin en los programas anteriores no funcionar e inclusive marcar erros porque no est inicializado el perifrico del ADC.
idntica sin importar la marca de la LCD. La nica diferencia es en la velocidad, ya que algunas responden ms rpidamente a los comandos que se le mandan. El asistente que tiene el codevision solicita que se le indique de cuntos caracteres es cada lnea de la LCD. As mismo se indica en el mismo asistente cmo conectar la LCD y a que pines. Las pantallas se pueden conectar en un bus de datos de 8 bits o de 4, el asistente lo coloca en un bus de 4 bits para ahorrar pines. El asistente del codevision genera todo el cdigo necesario para inicializar la LCD y el programador slo debe preocuparse por manejar las siguientes funciones: Los comandos que acepta la LCD son: lcd_clear(); Se utiliza para borrar todos los carcteres en la LCD lcd_gotoxy(unsigned char x,unsigned char y); Coloca el cursor en la columna x y fila y, puede ser o una variable x y y o una constante. Cuando se posiciona el cursor en algn punto determinado y se manda escribir una letra el cursor se mueve haca la derecha un lugar. lcd_putchar(char c); Coloca un carcter en la posicin donde haya quedado el cursor, de acuerdo a la funcin anterior. _lcd_write_data(); _lcd_write_byte(direccion,dato); Lo primero que debe hacerse es ubicar la posicin del cursor, es decirle en cul fila y en cual columna. Por ejemplo las LCDs de 2x16 son 2 filas por 16 caracteres. Entonces su se desea escribir en la segunda fi _lcd_ready();
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 Autor: David Infante Snchez www.comunidadatmel.com
que ha adquirido est en la posibilidad de hacer controles, sistemas de adquisicin y monitoreo de datos y su procesamiento. Con esta parte se concluye la programacin bsica-intermedia del microcontrolador. En el siguiente capitulo veremos tems avanzados del microcontrolador como interrupciones, protocolos de comunicacin seriales y timers.