Practicas para iniciar con el atmega32 utilizando el avrstudio 4 y el lenjuage C

Inicio este tema, debido a que varios habían expresado su interes en los microcontroladores de atmel, y debido a mi asesor de tesis, el cual me sugirio que utilizara el microcontrolador atmega32 de la compañia atmel, inicio estas series de prácticas mientras veo futurama.

Lo siguiente que utilizaré para las prácticas es lo siguiente.

Software:

AVRStudio 4 - version 4.13.528
WINAVR20080402

Hardware:

avrispmkII
microcontrolador atmega32
componentes varios.
 
Primero pondre el código fuente, despues los pasos para llevar este programa hasta el microcontrolador y ejecutarlo.

Código:
#include <avr/io.h>
#include <avr/delay.h>

int main(void)
{
   //Set PORTD for output
   DDRD = 0xFF;
   int i;
      while(1) {
            for (i = 1; i <=128; i = i*2)
            {
               PORTD = i;
               _delay_loop_2(30000);
            }

            for (i = 128; i > 1; i -= i/2)
            {
               PORTD = i;
               _delay_loop_2(30000);
            }
      }
}

1) Abrir el AVRStudio 4.
2) Seleccionar el menú Project, después seleccionar el submenu Project Wizard.
3) En la ventana de dialogo llamada "Welcome to AVR Studio 4" presionamos el boton "New Project".
4) Seleccionamos en "Project type" AVR GCC
5) En "Location" indicamos la ruta en mi caso es C:\atmel.
6) En "Project name:" indicamos el nombre del projecto que será el mismo que el archivo principal en este caso Blinky.
7) Después presionamos "Next>>"
Opcional porque podemos utilizar el proteus. Por lo general con ver los registros me basta pero como todavía no conozco mucho el atmel utilizare el proteus.
8) En "Debug plataform" seleccionamos AVR Simulator.
9) Y en "Device" ATMEGA32
8) Hacemos clic en Finalizar

*Por cierto ya acabo futurama.

1) Creamos el archivo Blinky.c tal y como lo puse arriba.
2) Seleccionamos el menu "Project" y luego el submenu "Configuration Options".
3) En "General" seleccionamos 1000000 en "Frequency", la optimización de "-Os" y Aceptamos la configuración.
Nota: aparecerá un warning pero para eliminarlo hay que elegir la carpeta donde esta ubicada la librería y con compilar de nuevo se elimina ya que la librería automaticamente incluye la libreria correcta.

Ahora procederemos a programar el microcontrolador.
1) Seleccionamos el menu "Tools" y luego el submenu "Program AVR", despues "connect".
2) aparece un dialogo llamado "Select AVR Programmer" en este caso "AVRISP mkII" y en "Port" USB. Y presionamos el boton "CONNECT".

1) En la pestaña "Program" presionamos el boton "Erase Device" y despues en el cuadro "Flash" presionamos el boton program.

Después de esto tendremos nuestro programa ejecutandose en el microcontrolador atmel atmega32.

si conocen algun programa para subir fotos a internet, con mucho gusto subo los menus y submenus y como se ven ejecutandose esta practica y las futuras.

Ah y tambien donde subir archivos para colocar los archivos de proteus y los futuros archivos comprimidos listo para probar y simular.
 
Hola:

Un par de detalles tontos. Creo que hace falta explicar que son los fuses, y que hay que configurarlos antes de programar el micro.

Mas que nada, para asegurarnos que el micro está corriendo con el reloj interno por defecto de 1 MHz, (el que hemos configurado), y que todo está correcto, no sea que alguien haya tocado esos valores.

Hay que recordar que no conviene ni habilitar el uso de relojes externos (o si no no podremos volver a configurar el micro hasta tener un reloj externo conectado), ni poner la frecuencia del ISP a un valor demasiado alto. Parece ser que habitualmente el AVRISP MkII viene configurado como frecuenca de programación de 1MHz, lo cual es un problema, ya que debe ser como mucho un cuarto de la frecuencia de reloj de sistema.

He 'inutilizado' varios AVR's por no hacer eso. Suerte que he podido recuperarlos con un reloj externo.
 
Por lo que he estado viendo depende de la serie del microcontrolador.

En mi caso expongo los que aparecen para mi microcontrolador atmega32-16PU.







Que corresponden con los dos bytes de fusibles, los cuales se dividen en registro de fusibles alto y registro de fusibles bajo.

En el registro de fusibles alto se configuran los siguientes:

OCDEN :Habilita el OCD, habilita algunos osciladores apesar de estar en modo sleep.
JTAGEN :Habilita el JTAG, interfaz que cumple con el estandard 1149.1 de la IEEE.
SPIEN :Desahabilitado con mi programador, ya que habilita o deshabilita el uso del ISP. jejeje
CKOPT :su funcionalidad depende de los bit de CKSEL
EESAVE : Indica si se borra la memoria eeprom o no durante el ciclo de borrado.
BOOTSZ1 :Configura el tamaño del arrancador
BOOTSZ0 :cargador por lo general no usado en mis practicas
BOOTRST :Selecciona donde comienza el vector del reset


imagen del mapa de memoria con boot

En el registro de fusibles bajo se configuran los siguientes:

BODLEVEL :Indica el nivel en el que se detecta el nivel de bajo voltaje
BODEN :habilita el detector de nivel de bajo voltaje
SUT1 :Indica el tiempo que debe de esperar antes iniciar
SUT0 :el programa dentro del microcontrolador
CKSEL3 :Se utiliza para seleccionar los tipos de reloj a utilizar
CKSEL2 :desde el oscilador interno de 1 mhz hasta 8 mhz internos
CKSEL1 :para mi caso, o los osciladores externos que alcanzan hasta
CKSEL0 :los 16mhz

Pero todo esto depende del microcontrolador y por lo general las opciones por default son buenas. Hasta arriba estan las opciones con las que programo el atmega32.

No he subido enviado más practicas porque estoy peleandome con el display LCD para utilizarlo con mi titulación. Espero subir más, pero me ha quitado mucho tiempo el mugre LCD. Pero espero subir más, ya que las que tengo en C las estoy pasando tambien a ensamblador, muy divertido por cierto el ensamblador de los atmel.
 
Confirmo que los fuses dependen del micro, pero hay unos pocos que son comunes en significado, que no en posición.

El del reloj, que por defecto viene programado como interno a 1MHz es fundamental. Es el primero que hay que mirar, y es muy importante estar seguro de lo que se pone, no sea que se programe para funcionar con uno externo, y no haya ningún cristal puesto. Este suele ser la principal causa de los micros que se 'mueren' al programarlos. Por suerte, con un reloj externo se pueden 'resucitar'.

El de SPI enable es importande dejarlo habilitado (por defecto), y es que si uno lo deshabilita, adiós volver a programarlo. Por suerte, hoy en día el AVRStudio pide confirmación de esto.

El del JTAG y OCD dependen de si el micro tiene esta interfaz. Permite programar por el JTAG por defecto, pero eso ocupa algunos pines que quedan inutilizados para ser usados en el programa. Eso sí, el OCD es muy bueno a la hora de depurar los programas (y barato), hasta el punto en que nunca uso el ISP excepto para productos 'acabados'.

Así que estos fuses son los primeros que hay que comprobar y mirar cuando uno programa el micro.
 
Ya solucione el problema del display LCD, un error de alambrado :rolleyes: jojojojojo. Pero ya funciona.

En el caso de la opción para habilitar el ISP en la imagen se ve que el propio menú bloquea esa opción, para evitar cometer ese error.

Sería bueno que mencionaran los nombres de los programas que utilizan para programar los micros, eso permitiría facilitar que errores se pueden presentar al momento de programar. Por ejemplo: cuando selecciono la pestaña de los "fuses" coloca los valores ideales o por default para el microcontrolador que se va a programar, cuando se programa por primera vez, pero cuando abro el proyecto de nuevo y voy a volver a programar, me pone los valores que contiene el microcontrolador.
 
A continuación pongo la practica número 1 - blinky- pero en ensamblador. Utilizando el atmega32.

Código:
#pragma AVRPART ADMIN PART_NAME ATmega32        ; Use el ATmega32

#pragma AVRPART MEMORY PROG_FLASH 32768         ; 32KB de memoria ram

#pragma AVRPART MEMORY EEPROM 1024              ; 1024 bytes de EEPROM

#pragma AVRPART MEMORY INT_SRAM SIZE 2048       ; 2048 bytes de SRAM

#pragma AVRPART MEMORY INT_SRAM START_ADDR 0x60 ; Inicio de la memoria sram

.include "m32def.inc"

.CSEG

        rjmp    RESET

RESET:  ldi	r16,HIGH(RAMEND) ;Configura la pila 
	out	SPH,r16	         ;para utilizar subrutinas
	ldi	r16,LOW(RAMEND)	 
	out	SPL,r16

        ldi     r16,0xFF         ;Configura el PUERTO A como
        out     DDRA,r16         ;salidas

WHILE:  nop

        ldi     r16,0x01         ;Prende un led en el bit 0
        out     PORTA,r16        ;del puerto A 
INCREMENTA:                
        call    retardo4         ;Retardo para apreciar la posición
                                 ;del led encendido      
        in      r16,PORTA        ;Envia la salida del PUERTOA al registro 16
        sbrc    r16,7            ;Es 128 el valor del PUERTOA
        rjmp    DECREMENTA       ;SI->TERMINA RUTINA INCREMENTA
        rol     r16              ;NO->RECORRE UN BIT A LA IZQUIERDA
        out     PORTA,r16        ;Visualiza el nuevo dato en el PUERTOA
        rjmp    INCREMENTA       ;REPETIMOS OPERACION HASTA QUE SEA IGUAL A 128

DECREMENTA:    
        call    retardo4         ;Retardo para apreciar la posición
                                 ;del led encendido
        in      r16,PORTA        ;Envia la salida del PUERTOA al regitro 16
        sbrc    r16,0            ;Es 1 el valor del PUERTOA
        rjmp    INCREMENTA       ;SI->TERMINA RUTINA DECREMENTA
        ror     r16              ;NO->RECORRE UN BIT A LA DERECHA
        out     PORTA,r16        ;Visualiza el nuevo dato en el PUERTOA
        rjmp    DECREMENTA       ;REPETIMOS OPERACION HASTA QUE SEA IGUAL A 1

;*************************************************************************
;* INICIA SUBRUTINA retardo4
;*************************************************************************
retardo4:
        ldi     r20,8
ret2000:
        ldi     r21,150
ret1000:
        ldi     r22,150
ret0000:
        dec     r22
        brne    ret0000
        dec     r21
        brne    ret1000
        dec     r20
        brne    ret2000
        ret
;*************************************************************************
;* INICIA SUBRUTINA retardo4
;*************************************************************************

Utilizo la directiva #pragma, ya que utilizo el AVR Assembler 2, esta directiva se utiliza en lugar de su predecesora .device del AVR Assembler 1. Esta y demás opciones se muestran haciendo clic en el menú "Project", luego haciendo clic en el subMenú "Assembler option". Con lo cúal aparecerá el dialogo "Assembler option".


Dialogo "Assembler Option"

En el dialogo aparece un "combo box" llamado "Hex Output Format", en el podemos seleccionar 3 formatos:

1) Intel
2) mototola ("jejejeje")
3) generic

Yo utilice las opciones que vienen por default y son las que se muestran en la imagen.

Abajo del combo box Hex Output Format, hay 3 "check box".

1) Create Map File
2) Create File List
3) Wrap Relative Jumps

Al centro arriba hay un "group box" llamado "Output File" que contiene 3 "radio buttons" y un "line edit", que nos permite indicar como se llamará el archivo de salida. Si queremos que tenga el nombre del projecto ó si queremos que se llame como el archivo principal que contiene las directivas pragma ó device, por ultimo podemos nombrarlo como deseemos introduciendo el nombre en el "line edit"

1) Project name :
2) Entry file
3) User
I) "_____".obj

Abajo del "group box" llamado "Output File" esta otro "group box" llamado "Unsupported Instructions" que contiene dos "radio buttons".

1) Warning
2) Error

Aquí indicamos como queremos que sean tratadas las instrucciones que no son reconocidas por el microcontrolador a utilizar, es decir el atmega32 tiene 131 instrucciones y el at90s8515 tiene 118 instrucciones, con pragma podemos indicar que instrucciones no son reconocidas. Cuando escribamos alguna instrucción que no esté soportada por nuestro microcontrolador se nos informaciónrmará. Y no estaremos buscando porque no funciona el programa cuando utilizemos instrucciones que no tiene nuestro microcontrolador empleado. ("Para volverse loco cuando sucede esto, juar juar juar").

Más información viene en el menú "Help" del AVRStudio 4 seleccionando el submenú "Avr Studio User Guide", después en la nueva ventana que aparece seleccionamos "Project" y despues "Assembler project" y por último seleccionamos "Assembler Options".

Con este programa obtenemos los mismos resultados pero en ensamblador en lugar de C.

Comentaré las partes más interesantes a continuación:

Código:
#pragma AVRPART ADMIN PART_NAME ATmega32        ; Use el ATmega32

#pragma AVRPART MEMORY PROG_FLASH 32768         ; 32KB de memoria ram

#pragma AVRPART MEMORY EEPROM 1024              ; 1024 bytes de EEPROM

#pragma AVRPART MEMORY INT_SRAM SIZE 2048       ; 2048 bytes de SRAM

#pragma AVRPART MEMORY INT_SRAM START_ADDR 0x60 ; Inicio de la memoria sram

Esta es la directiva "#pragma" que sustituye a ".device", la directiva "#pragma" se utiliza a partir de la version 2 del AVR Assembler, lo importante de esta directiva es que nos permite indicar que tipo de procesador estamos utilizando, la cantidad de memoria de programa tiene, la cantidad de memoria eeprom y la cantidad de memoria ram, así como el inicio de la memoria ram. También nos permite indicar las instrucciones soportadas como las no soportadas, entre otras cosas. En lugar de seleccionar el dispositivo en un combo box como se hace con los projectos en C, en los projectos en ensamblador se utiliza la directiva "#pragma" para el mismo proposito que en C.

Código:
.include "m32def.inc"

esta es la forma de incluir las definiciones del atmega32, es decir gracias a esto podemos escribir PORTA, etc.

Código:
        rjmp    RESET

RESET:  ldi	r16,HIGH(RAMEND) ;Configura la pila 
       	out	SPH,r16	         ;para utilizar subrutinas
	ldi	r16,LOW(RAMEND)	 
	out	SPL,r16

Cuando ocurre un reset o inicia por primera vez el programa va a la posición indicada por la etiqueta reset, esto es para saltarse los vectores de interrupcion. En este programa sencillo pude haber quitado esta instrucción de salto, pero por costumbre y por posibles ampliaciónes la utilizo.

Las instrucciones siguientes nos permiten definir la pila para utilizar llamadas a subrutinas y pasar parametros a funciones, etc.

Otra apecto importante son los saltos, pero por ser un programa muy pequeño, utilize rjmp, ya que jmp permite saltar a cualquier parte de la memoria y la instrucción rjmp solo 2000 instrucciones arriba y abajo de donde se localiza.

El programa ensamblador utiliza 0.2% de memoria de programa y el programa en c ocupa 0.2% de memoria de programa .


asmblinky.asm


blinky.c

La próxima práctica será un convertidor binario a bcd en c y luego en ensamblador.
 
1) No puse como configurar el AVR Studio 4 para los programas en ensamblador.

En project wizard se elije Atmel AVR Assembler en lugar de AVR GCC. De ahí en fuera es igual todo lo demás. Hasta en la forma de programar el microcontrolador.

2) Puse un while por ahí. Lo pueden eliminar sin problemas, iba a poner los nombres similares al programa en C de blinky.c, pero me distraje con unos compañeros y se me olvido continuar con la nomenclatura tipo c, indicando donde se inicia el for, como se inicializa la variable, donde se compara y donde se incrementa, todo en ensamblador. Perdonen.
 
Ya funciona bien la pantalla de cristal líquido con el atmega32, me costo trabajo y errores de descuido.

Pronto pondre una practica con la pantalla, pero primero sería en ensamblador y luego en C.

Saludos a todos.

Por cierto los modelos de las pantallas de cristal líquido son:

1) JHD162A
2) TM162AD

Los dos tienen el chip de control KS0066U y funcionan bien.

 

Adjuntos

  • jhd126a475_509.jpg
    jhd126a475_509.jpg
    23.6 KB · Visitas: 2,748
A continuación el codigo fuente, solo necesitamos incluir <avr/io.h> ya que solo vamos a manipular los puertos del microcontrolador.

Código:
/*
BINBCD.C : LEE UN NÚMERO BINARIO DE UN PUERTO Y LO
	   CONVIERTE A BCD, EL NUEVO NUMERO BCD SE
	   EXHIBE POR OTRO PUERTO.
*/

#include <avr/io.h>

int main(void)
{
 unsigned char binario;
 unsigned char bcdUnidades;
 unsigned char bcdDecimas;
 unsigned char bcdCentecimas;
 
 //CONFIGURA EL PUERTO DE ENTRADA PARA DATOS BINARIOS
 //SIN RESISTENCIAS PULLUP
 DDRD = 0x00;
 PORTD = 0xFF;

 //CONFIGURA PUERTOS PARA SALIDA DE DATOS BCD
 DDRA = 0xFF;
 DDRC = 0xFF;

 //INICIA PROGRAMA DE LECTURA DE DATOS Y CONVERSIÓN DE
 //BINARIO A BCD
 while(1)
 {
 binario = PIND;           //DIP SWITCH
 bcdUnidades = 0x00;       //REGISTRO UNIDADES
 bcdDecimas = 0x00;        //REGISTRO DECIMAS
 bcdCentecimas = 0x00;     //REGISTRO CENTESIMAS
 while (binario > 9)            //Si es mayor de nueve restamos 10
 {
	binario -= 10;
	bcdDecimas++;         
	if (bcdDecimas > 9)   
	{                                
	 bcdDecimas = 0x00;
	 bcdCentecimas++;
	}
 }                                      
 if (binario <= 9)               
 {
  //Las unidades están en el registro unidades
  //Las decenas están en decenas
  //las centenas están en centenas
	bcdUnidades = binario;
 }

 bcdDecimas <<= 4;      //Corremos bcdDecimas para 
                        //dejar espacio a las unidades
 PORTC = bcdCentecimas;
 PORTA = bcdDecimas | bcdUnidades;
 }
 return 0;
}
 
un virus entro en mi computadora gracias a un compañero, y me modifico todo lo que tenía de las practicas y lo de mi titulación así que voy a estar un rato fuera de línea, por cierto mi librería de la pantalla de cristal líquido de 16x2 que tanto me costo también se la paso a mejor vida. En este momento estoy tratando de instalar las toolschain, kontrollerlab, y avr32 en linux, les contaré como me fué.
 
hola fitocondria, he comprado un modulo con un atmega128 y creo que me he equivocado en la configuracón de los fuses porque puedo programar el micro pero no hace nada.
¿como es el esquematico del oscilador externo y como se hace para revivir el micro?
Te escribo pq eres el único que ha explicado otros conceptos de forma muy transparente.
gracias.
 
Hola:

Si puedes programar el micro, dudo que tengas problemas con el tema de los fuses del reloj. Sin embargo, si no el AVRStudio no te identifica la 'signature', o el micro no contesta, lo más probable es que hayas seleccionado el fuse de 'Oscilador externo'.

Para eso, el ATmega128 tiene dos pines (XTAL1 y XTAL2, 23 y 24) donde poner un cristal de cuarzo para que funcione a la frecuencia del cristal. Si es temporal, no hace falta que añadas ningún condensador. Te recomiendo un cristal de 8 MHz o similar frecuencia. Si aún así no te comunica, entonces seguramente tendrás que 'inyectarle' una senñal cuadrada de la frecuencia que puedas (aquí es donde le generador de funciones va estupendo) con las tensiones adecuadas, pero no se por qué pin (habrá que mirar el Datasheet).

Según como lo programes, debes asegurarte que la velocidad de programación esté por debajo de 1/4 de la velocidad del micro. Es decir, si está con el reloj interno de 1MHz (valor por defecto), debes programarlo como mucho a 250KHz. De lo contrario, puedes tener problemas.
 
Me gustaría saber algunas cosas antes. Como cual es el estado de los fuses que se leen con tu programador. Que programa utilizas para grabar el micro para conocer su interfaz. Yo no he tenido ningun problemas de ese tipo con los osciladores de cristal, pero si de equivocarme al momento de seleccionar 1mhz como frecuencia de trabajo del microcontrolador y lo tengo programado como 4mhz. Lo primero es que leas el estado de los fuses para saber como estan configurados y compararlos con lo que tu esperas recibir y apartir de ahí ya puedes solucionar tu situación.

Por cierto voy a regresar con unos programas para manipular el RTC del atmega 32 y el convertidor analógico a digital. Tanto en ensamblador como en C. Que por cierto utilizando librerias de terceros el programa de mi titulación ocupo 16 k de memoria y con librerias personalizadas llego a 6k.

Espero vernos pronto por aquí. Ya le pondre como llenar un canal de agua con un atmel 32, aunque me gustaría conseguir un atiny pero lo tengo que pedir a México. Nos vemos
 
Hola Beamspot, efectivamente, el problema que he tenido ha sido que no configuré bien los fuses, cambiando las características del cristal me ha funcionado.
Hace poco que programo los micros de Atmel por eso me hago mucho lío con los fuses.
Por lo que me has explicado la configuración del oscilador con los capacitores es la que utilizo siempre.
Entiendo que cuando pregunte me he explicado mal y la solución en caso de que me equivocara en la configuración de los fuses es la que comentaste de inyectar una onda cuadrada en el sitio adecuado. Muy buen consejo el de utilizar el generador de funciones.
 
Hola fitocondria, en verdad los osciladores externos no dan problemas, el programa que usaba para programar los micros es el Avr Studio 4.14 y un programador Jtag Ice, que me he cargado hace dos días atrás, ahora uso el ponyprog que me va lentísimo. Hasta que pueda hacerme otro Jtag saldré de apuros con el programador de puerto paralelo de la Simmstick DT006 que usa solamente tres resistencia en serie el cual es muy veloz.
No se decirte en estos momentos el estados de los fuses ya que el AVR Studio tiene muchas más opciones de configuración que el ponyprog, de todos modos mi configuración actual es la siguiente:
Oceden, Jtagen,Spien,Ckopt,Bodlevel,Sut1.
Estoy usando un cristal de 14.7456Mhz con capacitores de 22pf.
En estos momentos está funcionando a pesar de todo lo que le hago al micro. :)
Es una muy buena noticia el anuncio del tuorial de C y ensamblador, esperamos contar con ellos en breve. Te agradezco el tiempo y el esfuerzo que dedicas en compartir tus conocimientos.
 
Dos cosas: primero, enhorabuena por usar un JTAG. Cuando empiezes a depurar programas con el verás las ventajas que ofrece. Cúidalo.
Segundo: intento explicar los fuses que has puesto:
OCDEnable: habilita el debug en el chip con el JTAG.
JTAGEnable: habilita el JTAG, para programar, y para depurar si el fuse anterior está habilitado (los dos están habilitados por defecto de fábrica).
SPIEn: habilita la programación por el ISP/SPI. Habilitado de fábrica, para poder programar el micro.
CKOpt: es un fusible que permite tener una salida 'amplificada' del oscilador del reloj, para poder suministrar el mismo a otros micros o sistemas.
BODLevel: el BOD es un detector de caidas de tensión que resetea el micro. En algunos AVR se puede ajustar a diferentes tensiones (para trabajar a 5V o a 3V3).
SUT: tiempo de arranque después de un HW reset. Hay diferentes opciones, para dar tiempo a estabilizarse tanto la tensión como el oscilador/reloj.
Y quedan los fusibles de selección de reloj interno/externo y velocidad del interno (si se usa). Estos últimos son bastante 'delicados', y generalmente la causa de la 'muerte' de la mayoría de AVR's por novatos (aunque yo mismo, sin ser novato, también tuve este problema). Por suerte, 'resucitar' a estos micros es sencillo.

Y para acabar, quiero felicitar a Fitocondria por tu magnífico trabajo con este tutorial. Me parece muy bueno, y me gustaría poner un Link en www.webdearde.com, pero antes quisiera contar con tu permiso, porsupuesto.
 
Ya tengo tiempo que no aporto nada, así que comparto este convertidor analógico a digital, el cual es la base para medir el nivel de agua en mi tanque de agua. Lo que pongo no es el que utilizo para mi tesis pero es el que hice para verificar que el microcontrolador hiciera su trabajo.

Expongo el código a continuación.

Código:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <compat/ina90.h>
#include <inttypes.h>
#include <lcd.h>

unsigned int datoadc = 0;

void LCDyear(unsigned int binario);

void readADC(uint16_t *radc);

ISR(ADC_vect)
{
   readADC(&datoadc);
}

int main(void)
{
	// turn on and initialize A/D converter
   LCDinit();
   LCDclr();
   LCDhome();
	
	// configure a2d port (PORTA) as input
	// so we can receive analog signals
	DDRA &= ~(1<<DDA0);
	// make sure pull-up resistors are turned off
	PORTA = 0x00;

   //ADMUX = REFS1,REFS0,ADLAR,MUX4,MUX3,MUX2,MUX1,MUX0
   //ADMUX =   0  ,  1  ,  0  ,  0 ,  0 ,  0 ,  0 ,  0
   ADMUX = 0x40;

   //ADCSR = ADEN,ADSC,ADATE,ADIF,ADIE,ADPS2,ADPS1,ADPS0
   //ACDSR =   1 , 0  ,  0  ,  0 ,  1 ,  1  ,  1  ,  1  
   ADCSRA =   0x8F;

   //ADCL = REGISTRO BAJO DEL RESULTADO DEL CONVERTIDOR
   //ADCH = REGISTRO ALTO DEL RESULTADO DEL CONVERTIDOR

   //SFIOR = ADTS2, ADTS1, ADTS0
   //SFIOR = NO UTILIZADO

   sei();
   while(1)
   {
      LCDhome();
      LCDGotoXY(0, 0);
      uint8_t mensaje0[] = {'E','l',' ','r','e','s','u','l','t','a','d','o',' ','e','s',':'};
      LCDstring(mensaje0, 16);

      ADCSRA |= (1<<ADSC);

      while (ADIF == 1)
      {
         _NOP();
      }
      
      LCDGotoXY(6, 1);
      LCDyear(datoadc);
           
      _delay_ms(250);
      _delay_ms(250);
      _delay_ms(250);
      _delay_ms(250);
   }
	return 0;
}

void LCDyear(unsigned int binario)
{
   uint8_t dato[4];
   uint8_t bcdDecenas = 0x00;
   uint8_t bcdCentenas = 0x00;
   uint8_t bcdMillar = 0x00;

 while (binario > 9) //INICIA PROGRAMA DE LECTURA DE DATOS Y CONVERSIÓN DE BINARIO A BCD
 {
	binario -= 10;
	bcdDecenas++;
	if (bcdDecenas > 9)
	{
	   bcdDecenas = 0x00;
	   bcdCentenas++;
      if (bcdCentenas > 9)
      {
         bcdCentenas = 0x00;
         bcdMillar++;
      }
	}
 } //Guarda la conversión en el arreglo
 	dato[0] = bcdMillar + 0x30;
   dato[1] = bcdCentenas + 0x30;
   dato[2] = bcdDecenas + 0x30;
   dato[3] = binario + 0x30;
   
   LCDstring(dato, 4);
}

void readADC(uint16_t *radc)
{
   *radc = ADCW;   
}

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <compat/ina90.h>
#include <inttypes.h>
#include <lcd.h>

Explico a continuación el uso de cada librería.

io.h : Empleada para la definición de los registros de mi microcontrolador, en realidad este archivo incluye el archivo correcto para el microcontrolador seleccionado en la ventana de depuracion.


interrupt.h : Empleada para utilizar las interrupciones del microcontrolador.

delay.h : Famosa en Insituto Tecnológico de Veracruz, por aparecer mensajes de advertencia, porque no poniamos la dirección correcta de la libraría que es la que puse en este documento. Y utilizada para generar retardos por registro. si se utiliza _delay_ms(), el máximo valor es 255 por supuesto milisegundos. Si se utiliza _delay_us(), el máximo valor es 768 me parece. Para que funcione bien y no nos marque errores o advertencia de f_cpu no definido, hay que definirlo en la siguiente ventana:



Este ventana sale del menu Project y luego seleccionamos el submenu Configuration Options y de la nueva ventana que aparece seleccionamos el menu general como se aprecia en la imagen tengo configurado el reloj a 4MHz y la optimización a -0s ya que lo pide la libreria <util/delay.h>

ina90.h : Utilizada para habilitar y deshabilitar las interrupciones mediante las llamadas _CLI() y _SEI().

inttypes.h : Empleada para la definición de los tipos empleadas en las librerias de winavr tales como uint8_t y uint16_t.

lcd.h : en realidad es una modificación, bueno en realidad solo pegue las definiciones dentro de los encabezado. el cual expongo hasta el final.

A continuación imagenes de como se ve el circuito.





unsigned int datoadc = 0;
Es la variable donde guardo la señal convertida a digital de la conversión analógica a digital.

void LCDyear(unsigned int binario);
Es una función que cree para mi proyecto de titulacion, la cual visualiza el año y como el año y el valor de la conversión analógica a digital tienen el mismo tamaño es decir 4 digitos la utilice para mostrar el valor de la conversión analógica a digital en la pantalla de cristal liquido.

void readADC(uint16_t *radc);
Es la función que se encarga de guardar el dato de la conversión analógica a digital en la variable que mencione arriba.

ISR(ADC_vect)
{
readADC(&datoadc);
}
Es la forma en que el c de gnu llama a las subrutinas se pone esta función y como parametro se
pone el vector de interrupción el cual viene en el archivo de definiciones de cada microcontrolador en mi caso en el archivo de encabezado iom32.h, y ya solo llaman a la función que realizara el grueso del trabajo. La explico a profundidad mañana porque ya me voy al rancho. saludos a todos.


Código:
//*****************************************************************************
//
// File Name	: 'lcd_lib.h'
// Title		: 8 and 4 bit LCd interface
// Author		: Scienceprog.com - Copyright (C) 2007
// Created		: 2007-03-29
// Revised		: 2007-08-08
// Version		: 1.0
// Target MCU	: Atmel AVR series
//
// This code is distributed under the GNU Public License
//		which can be found at [url]http://www.gnu.org/licenses/gpl.txt[/url]
//
//*****************************************************************************
#ifndef LCD_LIB
#define LCD_LIB

#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

//Uncomment this if LCD 4 bit interface is used
//******************************************
#define LCD_4bit
//***********************************************

#define LCD_RS	0 	//define MCU pin connected to LCD RS
#define LCD_RW	1 	//define MCU pin connected to LCD R/W
#define LCD_E	2	//define MCU pin connected to LCD E
#define LCD_D0	0	//define MCU pin connected to LCD D0
#define LCD_D1	1	//define MCU pin connected to LCD D1
#define LCD_D2	2	//define MCU pin connected to LCD D1
#define LCD_D3	3	//define MCU pin connected to LCD D2
#define LCD_D4	4	//define MCU pin connected to LCD D3
#define LCD_D5	5	//define MCU pin connected to LCD D4
#define LCD_D6	6	//define MCU pin connected to LCD D5
#define LCD_D7	7	//define MCU pin connected to LCD D6
#define LDP PORTD	//define MCU port connected to LCD data pins
#define LCP PORTD	//define MCU port connected to LCD control pins
#define LDDR DDRD	//define MCU direction register for port connected to LCD data pins
#define LCDR DDRD	//define MCU direction register for port connected to LCD control pins

#define LCD_CLR             0	//DB0: clear display
#define LCD_HOME            1	//DB1: return to home position
#define LCD_ENTRY_MODE      2	//DB2: set entry mode
#define LCD_ENTRY_INC       1	//DB1: increment
#define LCD_ENTRY_SHIFT     0	//DB2: shift
#define LCD_ON_CTRL         3	//DB3: turn lcd/cursor on
#define LCD_ON_DISPLAY      2	//DB2: turn display on
#define LCD_ON_CURSOR       1	//DB1: turn cursor on
#define LCD_ON_BLINK        0	//DB0: blinking cursor
#define LCD_MOVE            4	//DB4: move cursor/display
#define LCD_MOVE_DISP       3	//DB3: move display (0-> move cursor)
#define LCD_MOVE_RIGHT      2	//DB2: move right (0-> left)
#define LCD_FUNCTION        5	//DB5: function set
#define LCD_FUNCTION_8BIT   4	//DB4: set 8BIT mode (0->4BIT mode)
#define LCD_FUNCTION_2LINES 3	//DB3: two lines (0->one line)
#define LCD_FUNCTION_10DOTS 2	//DB2: 5x10 font (0->5x7 font)
#define LCD_CGRAM           6	//DB6: set CG RAM address
#define LCD_DDRAM           7	//DB7: set DD RAM address
// reading:
#define LCD_BUSY            7	//DB7: LCD is busy
#define LCD_LINES			2	//visible lines
#define LCD_LINE_LENGTH		16	//line length (in characters)
// cursor position to DDRAM mapping
#define LCD_LINE0_DDRAMADDR		0x00
#define LCD_LINE1_DDRAMADDR		0x40
#define LCD_LINE2_DDRAMADDR		0x14
#define LCD_LINE3_DDRAMADDR		0x54
// progress bar defines
#define PROGRESSPIXELS_PER_CHAR	6


void LCDsendChar(uint8_t);		//forms data ready to send to 74HC164
void LCDsendCommand(uint8_t);	//forms data ready to send to 74HC164
void LCDinit(void);			//Initializes LCD
void LCDclr(void);				//Clears LCD
void LCDhome(void);			//LCD cursor home
void LCDstring(uint8_t*, uint8_t);	//Outputs string to LCD
void LCDGotoXY(uint8_t, uint8_t);	//Cursor to X Y position
void CopyStringtoLCD(const uint8_t*, uint8_t, uint8_t);//copies flash string to LCD at x,y
void LCDdefinechar(const uint8_t *,uint8_t);//write char to LCD CGRAM 
void LCDshiftRight(uint8_t);	//shift by n characters Right
void LCDshiftLeft(uint8_t);	//shift by n characters Left
void LCDcursorOn(void);		//Underline cursor ON
void LCDcursorOnBlink(void);	//Underline blinking cursor ON
void LCDcursorOFF(void);		//Cursor OFF
void LCDblank(void);			//LCD blank but not cleared
void LCDvisible(void);			//LCD visible
void LCDcursorLeft(uint8_t);	//Shift cursor left by n
void LCDcursorRight(uint8_t);	//shif cursor right by n
// displays a horizontal progress bar at the current cursor location
// <progress> is the value the bargraph should indicate
// <maxprogress> is the value at the end of the bargraph
// <length> is the number of LCD characters that the bargraph should cover
//adapted from AVRLIB - displays progress only for 8 bit variables
void LCDprogressBar(uint8_t progress, uint8_t maxprogress, uint8_t length);

const uint8_t LcdCustomChar[] PROGMEM=//define 8 custom LCD chars
{
	0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, // 0. 0/5 full progress block
	0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, // 1. 1/5 full progress block
	0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, // 2. 2/5 full progress block
	0x00, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x00, // 3. 3/5 full progress block
	0x00, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x00, // 4. 4/5 full progress block
	0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 5. 5/5 full progress block
	0x03, 0x07, 0x0F, 0x1F, 0x0F, 0x07, 0x03, 0x00, // 6. rewind arrow
	0x18, 0x1C, 0x1E, 0x1F, 0x1E, 0x1C, 0x18, 0x00  // 7. fast-forward arrow
};


void LCDsendChar(uint8_t ch)		//Sends Char to LCD
{

#ifdef LCD_4bit
	//4 bit part
	LDP=(ch&0b11110000);
	LCP|=1<<LCD_RS;
	LCP|=1<<LCD_E;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);	
	LCP&=~(1<<LCD_RS);
	_delay_ms(1);
	LDP=((ch&0b00001111)<<4);
	LCP|=1<<LCD_RS;
	LCP|=1<<LCD_E;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);	
	LCP&=~(1<<LCD_RS);
	_delay_ms(1);
#else
	//8 bit part
	LDP=ch;
	LCP|=1<<LCD_RS;
	LCP|=1<<LCD_E;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);	
	LCP&=~(1<<LCD_RS);
	_delay_ms(1);
#endif
}
void LCDsendCommand(uint8_t cmd)	//Sends Command to LCD
{
#ifdef LCD_4bit	
	//4 bit part
	LDP=(cmd&0b11110000);
	LCP|=1<<LCD_E;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);
	LDP=((cmd&0b00001111)<<4);	
	LCP|=1<<LCD_E;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);
#else
	//8 bit part
	LDP=cmd;
	LCP|=1<<LCD_E;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);	
#endif
}
void LCDinit(void)//Initializes LCD
{
#ifdef LCD_4bit	
	//4 bit part
	_delay_ms(15);
	LDP=0x00;
	LCP=0x00;
	LDDR|=1<<LCD_D7|1<<LCD_D6|1<<LCD_D5|1<<LCD_D4; //Registro de datos
	LCDR|=1<<LCD_E|1<<LCD_RW|1<<LCD_RS;            //Registro de control
   //---------one------
	LDP=0<<LCD_D7|0<<LCD_D6|1<<LCD_D5|1<<LCD_D4; //4 bit mode
	LCP|=1<<LCD_E|0<<LCD_RW|0<<LCD_RS;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(5);
	//-----------two-----------
	LDP=0<<LCD_D7|0<<LCD_D6|1<<LCD_D5|1<<LCD_D4; //4 bit mode
	LCP|=1<<LCD_E|0<<LCD_RW|0<<LCD_RS;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);
	//-------three-------------
	LDP=0<<LCD_D7|0<<LCD_D6|1<<LCD_D5|0<<LCD_D4; //4 bit mode
	LCP|=1<<LCD_E|0<<LCD_RW|0<<LCD_RS;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);
	//--------4 bit--dual line---------------
	LCDsendCommand(0b00101000);
   //-----increment address, invisible cursor shift------
	LCDsendCommand(0b00001100);
		//init 8 custom chars
	uint8_t ch=0, chn=0;
	while(ch<64)
	{
		LCDdefinechar((LcdCustomChar+ch),chn++);
		ch=ch+8;
	}


#else
	//8 bit part
	_delay_ms(15);
	LDP=0x00;
	LCP=0x00;
	LDDR|=1<<LCD_D7|1<<LCD_D6|1<<LCD_D5|1<<LCD_D4|1<<LCD_D3
			|1<<LCD_D2|1<<LCD_D1|1<<LCD_D0;
	LCDR|=1<<LCD_E|1<<LCD_RW|1<<LCD_RS;
   //---------one------
	LDP=0<<LCD_D7|0<<LCD_D6|1<<LCD_D5|1<<LCD_D4|0<<LCD_D3
			|0<<LCD_D2|0<<LCD_D1|0<<LCD_D0; //8 it mode
	LCP|=1<<LCD_E|0<<LCD_RW|0<<LCD_RS;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);
	//-----------two-----------
	LDP=0<<LCD_D7|0<<LCD_D6|1<<LCD_D5|1<<LCD_D4|0<<LCD_D3
			|0<<LCD_D2|0<<LCD_D1|0<<LCD_D0; //8 it mode
	LCP|=1<<LCD_E|0<<LCD_RW|0<<LCD_RS;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);
	//-------three-------------
	LDP=0<<LCD_D7|0<<LCD_D6|1<<LCD_D5|1<<LCD_D4|0<<LCD_D3
			|0<<LCD_D2|0<<LCD_D1|0<<LCD_D0; //8 it mode
	LCP|=1<<LCD_E|0<<LCD_RW|0<<LCD_RS;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);
	//--------8 bit dual line----------
	LDP=0<<LCD_D7|0<<LCD_D6|1<<LCD_D5|1<<LCD_D4|1<<LCD_D3
			|0<<LCD_D2|0<<LCD_D1|0<<LCD_D0; //8 it mode
	LCP|=1<<LCD_E|0<<LCD_RW|0<<LCD_RS;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(1);
   //-----increment address, invisible cursor shift------
	LDP=0<<LCD_D7|0<<LCD_D6|0<<LCD_D5|0<<LCD_D4|1<<LCD_D3
			|1<<LCD_D2|0<<LCD_D1|0<<LCD_D0; //8 it mode
	LCP|=1<<LCD_E|0<<LCD_RW|0<<LCD_RS;		
	_delay_ms(1);
	LCP&=~(1<<LCD_E);
	_delay_ms(5);
		//init custom chars
	uint8_t ch=0, chn=0;
	while(ch<64)
	{
		LCDdefinechar((LcdCustomChar+ch),chn++);
		ch=ch+8;
	}

#endif
}			
void LCDclr(void)				//Clears LCD
{
	LCDsendCommand(1<<LCD_CLR);
}
void LCDhome(void)			//LCD cursor home
{
	LCDsendCommand(1<<LCD_HOME);
}
void LCDstring(uint8_t* data, uint8_t nBytes)	//Outputs string to LCD
{
register uint8_t i;

	// check to make sure we have a good pointer
	if (!data) return;

	// print data
	for(i=0; i<nBytes; i++)
	{
		LCDsendChar(data[i]);
	}
}
void LCDGotoXY(uint8_t x, uint8_t y)	//Cursor to X Y position
{
	register uint8_t DDRAMAddr;
	// remap lines into proper order
	switch(y)
	{
	case 0: DDRAMAddr = LCD_LINE0_DDRAMADDR+x; break;
	case 1: DDRAMAddr = LCD_LINE1_DDRAMADDR+x; break;
	case 2: DDRAMAddr = LCD_LINE2_DDRAMADDR+x; break;
	case 3: DDRAMAddr = LCD_LINE3_DDRAMADDR+x; break;
	default: DDRAMAddr = LCD_LINE0_DDRAMADDR+x;
	}
	// set data address
	LCDsendCommand(1<<LCD_DDRAM | DDRAMAddr);
	
}
//Copies string from flash memory to LCD at x y position
//const uint8_t welcomeln1[] PROGMEM="AVR LCD DEMO\0";
//CopyStringtoLCD(welcomeln1, 3, 1);	
void CopyStringtoLCD(const uint8_t *FlashLoc, uint8_t x, uint8_t y)
{
	uint8_t i;
	LCDGotoXY(x,y);
	for(i=0;(uint8_t)pgm_read_byte(&FlashLoc[i]);i++)
	{
		LCDsendChar((uint8_t)pgm_read_byte(&FlashLoc[i]));
	}
}
//defines char symbol in CGRAM
/*
const uint8_t backslash[] PROGMEM= 
{
0b00000000,//back slash
0b00010000,
0b00001000,
0b00000100,
0b00000010,
0b00000001,
0b00000000,
0b00000000
};
LCDdefinechar(backslash,0);
*/
void LCDdefinechar(const uint8_t *pc,uint8_t char_code){
	uint8_t a, pcc;
	uint16_t i;
	a=(char_code<<3)|0x40;
	for (i=0; i<8; i++){
		pcc=pgm_read_byte(&pc[i]);
		LCDsendCommand(a++);
		LCDsendChar(pcc);
		}
}

void LCDshiftLeft(uint8_t n)	//Scrol n of characters Right
{
	uint8_t i;
	for (i=0;i<n;i++)
	{
		LCDsendCommand(0x1E);
	}
}
void LCDshiftRight(uint8_t n)	//Scrol n of characters Left
{
	uint8_t i;
	for (i=0;i<n;i++)
	{
		LCDsendCommand(0x18);
	}
}
void LCDcursorOn(void) //displays LCD cursor
{
	LCDsendCommand(0x0E);
}
void LCDcursorOnBlink(void)	//displays LCD blinking cursor
{
	LCDsendCommand(0x0F);
}
void LCDcursorOFF(void)	//turns OFF cursor
{
	LCDsendCommand(0x0C);
}
void LCDblank(void)		//blanks LCD
{
	LCDsendCommand(0x08);
}
void LCDvisible(void)		//Shows LCD
{
	LCDsendCommand(0x0C);
}
void LCDcursorLeft(uint8_t n)	//Moves cursor by n poisitions left
{
	uint8_t i;
	for (i=0;i<n;i++)
	{
		LCDsendCommand(0x10);
	}
}
void LCDcursorRight(uint8_t n)	//Moves cursor by n poisitions left
{
	uint8_t i;
	for (i=0;i<n;i++)
	{
		LCDsendCommand(0x14);
	}
}
//adapted fro mAVRLIB
void LCDprogressBar(uint8_t progress, uint8_t maxprogress, uint8_t length)
{
	uint8_t i;
	uint16_t pixelprogress;
	uint8_t c;

	// draw a progress bar displaying (progress / maxprogress)
	// starting from the current cursor position
	// with a total length of "length" characters
	// ***note, LCD chars 0-5 must be programmed as the bar characters
	// char 0 = empty ... char 5 = full

	// total pixel length of bargraph equals length*PROGRESSPIXELS_PER_CHAR;
	// pixel length of bar itself is
	pixelprogress = ((progress*(length*PROGRESSPIXELS_PER_CHAR))/maxprogress);
	
	// print exactly "length" characters
	for(i=0; i<length; i++)
	{
		// check if this is a full block, or partial or empty
		// (u16) cast is needed to avoid sign comparison warning
		if( ((i*(uint16_t)PROGRESSPIXELS_PER_CHAR)+5) > pixelprogress )
		{
			// this is a partial or empty block
			if( ((i*(uint16_t)PROGRESSPIXELS_PER_CHAR)) > pixelprogress )
			{
				// this is an empty block
				// use space character?
				c = 0;
			}
			else
			{
				// this is a partial block
				c = pixelprogress % PROGRESSPIXELS_PER_CHAR;
			}
		}
		else
		{
			// this is a full block
			c = 5;
		}
		
		// write character to display
		LCDsendChar(c);
	}

}
#endif
 
saludos, yo agrego un programa que ando haciendo para el atmega32 que es una terminal serial donde monitoreare el llenado de unos contenedores.

todavia me Falta hacer mucho en el, pero ya puedo ejecutar comandos en el desde la hyperterminal
Código:
/*programa de monitoreo de totes via serial*/
/*todavia esta en fabricacion*/

#include <iom32v.h>
#include <stdio.h>

#define MAXCONT 20
#define RAMEND 0X085F


typedef struct
			{
			unsigned int 	contador;
			unsigned char	dia;
			unsigned char	minuto;
			unsigned char	meshr;
			
			
			}campo_datos;

campo_datos memoria[MAXCONT];



//////////////////////////////////////////////////////////////

void delay2(unsigned char n)
{
	unsigned char a, c;

	for (a = 1; a; a++)
		for (c = 1; c<n; c++);
}


int iniciacampos(void) // simulo un guardado de datos
{

int cont;



for (cont=0;cont<MAXCONT;cont++)
	{
	memoria[cont].contador=4000+cont;
	memoria[cont].dia=7;
	memoria[cont].minuto=3;
	}

return 0;
}


void saca_serial(char *cadena)
{
//char dato;
unsigned char i;

for (i=0;cadena[i]!='\0';i++)
	 	{
		saca_caracter_USART(cadena[i]);
		}
saca_caracter_USART(10);
saca_caracter_USART(13);
}


///////////////////////////////////////////////////////////////
void entrega_reporte(void)
{
char cadena [55];
unsigned char dia=7,mes=5,hora=12,minuto=00;
unsigned int piezas=0;
int cont;


PORTB=0x00;
sprintf(cadena,"Reporte de datos dia %d, Mes %d ",dia,mes);
saca_serial(cadena);
for (cont=0;cont<MAXCONT;cont ++)
	{
	piezas	= memoria[cont].contador;
	dia		= memoria[cont].dia;
	minuto	= memoria[cont].minuto;
	hora	= (memoria[cont].meshr) & 0x0F;
	mes		= (memoria[cont].meshr >>4 ) &0X0F;

	sprintf(cadena,"%d->\t%d/%d/08\t%d:%d\t Tote con %d \tPzas  ",cont,dia,mes,hora,minuto,piezas);
	saca_serial(cadena);
    
	}
sprintf(cadena,"Reporte terminado....");
saca_serial(cadena);

}



void USART_Init( unsigned int baud )
{
/* Set baud rate */
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
/* Habilitacion de transmisor */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}


void saca_caracter_USART( unsigned char dato )
{

while ( !( UCSRA & (1<<UDRE)) ); //espera por si hay una transmision
UDR = dato; //envia el dato
return;
}

unsigned char recibe_caracter_USART( void )
{
while ( !(UCSRA & (1<<RXC)) ); // espera por un dato recibido
return UDR;   // regresa el valor recibido
}

///////////////////////////////////////////////////////////////
int main()
{
int i=0;
unsigned char car;
char cad[45];

DDRD = 0x02;  // solo la salida 1 del puerto d es salida
DDRB = 0XFF;  //el puerto b es salida
DDRA = 0X00;  /*//Puerto A es entrada*/


SPH	= (unsigned char) (RAMEND>>8);
SPL = (unsigned char) (RAMEND);


USART_Init(47);  /* ubrr = 47 para 9600 bauds con cristal de  7.3728 Mhz */


PORTB=0xF0;
iniciacampos();
saca_caracter_USART(10);
saca_caracter_USART(13);
sprintf(cad,"- Prueba de terminal -");
saca_serial(cad);
saca_caracter_USART(10);
saca_caracter_USART(13);
saca_caracter_USART('a');
saca_caracter_USART('v');
saca_caracter_USART('r');
saca_caracter_USART('^');
saca_caracter_USART('\\');

while (1)
	{
	car = recibe_caracter_USART();
	
	if (car!=13 )  // si el caracter es diferente de enter
		{
		cad[i] = car;   // se agrega el caracter recibido
		i++;                                              
		saca_caracter_USART(car);	// se muestra de regreso
		}
	
	else   /// en caso de enter....
		{
		cad[i]='\0';

		saca_caracter_USART(10);
		saca_caracter_USART(13);

		if (!strcmp(cad,"reporta"))
			{
			entrega_reporte();
			}
		else if (!strcmp(cad,"borra"))
			{
			sprintf(cad,"borrando...");
			saca_serial(cad);
			delay2(100);

			sprintf(cad,"terminado");
			saca_serial(cad);
			}
		else if (!strcmp(cad,"?"))
			{
			sprintf(cad,"Comandos:");
			saca_serial(cad);
			sprintf(cad,"reporta\t\tborra");
			saca_serial(cad);
			}
		
		else
			{
			saca_caracter_USART('-');
			saca_serial(cad);
			saca_caracter_USART(' ');
			
			sprintf(cad,"comando no reconocido...");
			saca_serial(cad);
			}
		
		saca_caracter_USART(10);
		saca_caracter_USART(13);
		saca_caracter_USART('a');
		saca_caracter_USART('v');
		saca_caracter_USART('r');
		saca_caracter_USART('^');
		saca_caracter_USART('\\');
		i=0;
		car=' ';
		}
	
		
	
	delay2(250);

	delay2(250);

    }
return 0;
}
 
Atrás
Arriba