Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

22/06/2008 #21


Beamspot
Se agradece la felicitación por el Jtag y muy interesante la descripción de los fuses.
Cuando mencionas que es fácil resucitar el micro lo haces con el procedimiento que explicaste de inyectar una señal con el generador de frecuencia por el pin X...
Buen fin de semana a todos.
22/06/2008 #22


Calculadora de Fuses
Encontré en mi disco una hoja de calculo que calcula los fuses, no recuerdo de donde la descargué, pero creo que puede servir.
Sería importante que las personas que han trabajado configurando los fuses le echen una mirada para saber si es confiable o le encuentran alguna pega.
Excel por defecto tiene las macros desabilitadas, para ejecutar las macros hay que bajar la seguridad en Excel.
Cuando presionamos en el boton RUN, aparece un cuadro de diálogo para seleccionar los parámetros.
25/06/2008 #23


Interrupciones en c
Perdón por la tardanza, pero por el rancho no he tenido mucho tiempo ni siquiera para mi proyecto de titulación, se supone que ahorita debo estar con el proyecto de titulación.

El metodo que utiliza el C de GNU y c++, es por medio de la llamada ISR, todo lo que expongo viene en el archivo de encabezado del programa winavr llamado interrupt.h. El metodo anterior es signal.h

Se utiliza, bueno yo utilizo el formato(porque es el que recomindan, ya que signal pronto será eliminado a favor de ISR y luego no tengamos sorpresa de ¿porque no se compilan nuestros codigos?):

Código:
ISR()
{
}
entre parentesis va el nombre del vector de interrupción, es decir en el archivo de definiciones de nuestros micros en particular vienen los nombres de los vectores.

a continuación solo expongo la parte correspondiente a interrupciones para el atmega32 que viene en el archivo iom32.h

Código:
/* 0x3F SREG */

/* Interrupt vectors */

/* External Interrupt Request 0 */
#define INT0_vect			_VECTOR(1)
#define SIG_INTERRUPT0			_VECTOR(1)

/* External Interrupt Request 1 */
#define INT1_vect			_VECTOR(2)
#define SIG_INTERRUPT1			_VECTOR(2)

/* External Interrupt Request 2 */
#define INT2_vect			_VECTOR(3)
#define SIG_INTERRUPT2			_VECTOR(3)

/* Timer/Counter2 Compare Match */
#define TIMER2_COMP_vect		_VECTOR(4)
#define SIG_OUTPUT_COMPARE2		_VECTOR(4)

/* Timer/Counter2 Overflow */
#define TIMER2_OVF_vect			_VECTOR(5)
#define SIG_OVERFLOW2			_VECTOR(5)

/* Timer/Counter1 Capture Event */
#define TIMER1_CAPT_vect		_VECTOR(6)
#define SIG_INPUT_CAPTURE1		_VECTOR(6)

/* Timer/Counter1 Compare Match A */
#define TIMER1_COMPA_vect		_VECTOR(7)
#define SIG_OUTPUT_COMPARE1A		_VECTOR(7)

/* Timer/Counter1 Compare Match B */
#define TIMER1_COMPB_vect		_VECTOR(8)
#define SIG_OUTPUT_COMPARE1B		_VECTOR(8)

/* Timer/Counter1 Overflow */
#define TIMER1_OVF_vect			_VECTOR(9)
#define SIG_OVERFLOW1			_VECTOR(9)

/* Timer/Counter0 Compare Match */
#define TIMER0_COMP_vect		_VECTOR(10)
#define SIG_OUTPUT_COMPARE0		_VECTOR(10)

/* Timer/Counter0 Overflow */
#define TIMER0_OVF_vect			_VECTOR(11)
#define SIG_OVERFLOW0			_VECTOR(11)

/* Serial Transfer Complete */
#define SPI_STC_vect			_VECTOR(12)
#define SIG_SPI				_VECTOR(12)

/* USART, Rx Complete */
#define USART_RXC_vect			_VECTOR(13)
#define SIG_USART_RECV			_VECTOR(13)
#define SIG_UART_RECV			_VECTOR(13)

/* USART Data Register Empty */
#define USART_UDRE_vect			_VECTOR(14)
#define SIG_USART_DATA			_VECTOR(14)
#define SIG_UART_DATA			_VECTOR(14)

/* USART, Tx Complete */
#define USART_TXC_vect			_VECTOR(15)
#define SIG_USART_TRANS			_VECTOR(15)
#define SIG_UART_TRANS			_VECTOR(15)

/* ADC Conversion Complete */
#define ADC_vect			_VECTOR(16)
#define SIG_ADC				_VECTOR(16)

/* EEPROM Ready */
#define EE_RDY_vect			_VECTOR(17)
#define SIG_EEPROM_READY		_VECTOR(17)

/* Analog Comparator */
#define ANA_COMP_vect			_VECTOR(18)
#define SIG_COMPARATOR			_VECTOR(18)

/* 2-wire Serial Interface */
#define TWI_vect			_VECTOR(19)
#define SIG_2WIRE_SERIAL		_VECTOR(19)

/* Store Program Memory Ready */
#define SPM_RDY_vect			_VECTOR(20)
#define SIG_SPM_READY			_VECTOR(20)

#define _VECTORS_SIZE 84
Por cada interrupción viene dos #define:
el primero que termina con _vect
y el segundo que comienza con SIG_

El primer es el que viene sustituyendo al antigüo método que es por medio de señales. "paradigmas en todo caso" aunque todo tiene una forma y ser.

Por ejemplo para que en el micro se programe que en el vector de interrupción que corresponde al convertidor analógico a digital se realize algo en específico se escribe lo siguiente:

Código:
ISR(ADC_vect)
{
}
Nota:
se puede utilizar SIG_ADC pero ya no es lo recomendable por los propios autores de winavr.

El archivo include io.h se encarga de seleccionar el archivo de encabezado correcto, en mi caso yo utilizo el atmega32, para lo cual se apoya del menu de selección del micro.



con esto el preprocesador sabe que archivo incluir. Esto es así para que resulte transparente a los usuarios el que no tengan que buscar el archivo de encabezado para cada micro. Trampa para los nuevos como yo, al fin y al cabo tengo que buscar el archivo para verificar las definiciones para usarlas jajaja. O se pueden crear sus propios archivos como más gusteis.

En el bloque de código (lo que esta entre llaves{}) ahí podemos poner nuestro código, yo lo que hago es colocar una función que se encarga de guardar el dato del convertidor analógico a digital en un apuntador para su posterior uso. Ustedes pueden hacer lo que gusten.

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

Y esto es lo que hace la función

void readADC(uint16_t *radc);

void readADC(uint16_t *radc)
{
*radc = ADCW;
}
[/code]

Así cualquier operación que realize con el dato obtenido de la conversión analógica a digital no afecta el resultado original, ya que luego lo utilizo para visualizar el dato en la pantalla de cristal liquido al convertir este dato binario a bcd y solo sumarle 30 para que represente el número adecuado, pero eso es aparte.

Me falta poner los parametros utilizados con ISR que son BLOCK y etc. Pero me despido para avanzar con mi proyecto de titulación.
16/07/2008 #24


Me decanto por utilizar ensamblador con C.

Pasas un apuntador a una función y luego ese apuntador a una instrucción condicional y valio el apuntador. A menos que utilizen volatile en la declaración de su apuntador.

Por lo anterior no escribí nada durante este tiempo. Y me preguntaba, ¿Porque no funciona esta .....?. Señores aprendan de todo. Ese es el mejor aporte que les puedo dar.
17/07/2008 #25


Por término general, todas las variables que se modifican en una rutina de servicio a la interrupción (ISR), debe ser declaradas volatile. Eso evita que el compilador las optimice y las haga desaparecer.

Según muchos, esta es la práctica estándar, y la 'filosofía' detrás de la palabra volatile.

De esta manera con:

volatile unsigned int radc;

ISR(ADC_vect)
{
radc=ADCW;
}

debería funcionar.
20/07/2008 #26


El apuntador fantasma
El apuntador al que hago referencia es del código de mi titulación y no lo he escrito aqui en el foro todavía hasta que este completo.

El código de arriba sino me equivoco es de un ejemplo que puse sobre el uso del convertidor analógico a digital y ese funciona, por eso me desconcerto mi apuntador de mi programa, puesto que el apuntador funciona bien, en el caso del apuntador que me causo problemas es el que paso a una función y dentro de esa función lo utilizo en una función while para verificar cuando se lleno el tanque de agua. Pero ya quedo resuelto el problema.

Ahora estoy realizando otra parte del proyecto. Pero como estoy mucho tiempo en el rancho no he tenido tiempo de poner los programas que les he mencionado antes, el del temporizador en tiempo real, para generar un calendario con reloj, etc.

Estaba pensando subir solo el codigo, pero creo que sería mejor explicar lo que hice para referenci a y aclaraciones y sirva a todos.

De hecho estaba pensando pedir que pidan programas sencillos para ir conociendo poco a poco las caracteristicas de los micros avr, al menos utilizando el atmega8 por que es el unico que tengo jejeje, pero que se pueden utilizar como ejemplo para los demás micros, y hacerlo tanto en ensamblador como en c. Así yo tambien practico. E incluso estaba pensando utilizar los ejemplos del libro que tiene meta sobre pic y pasarlos a los avr, tanto en ensamblador como a lenjuage C, así podría servir de referencia para los que pueden comprar el libro, y comparar los micros de atmel y de microchip.

¿Que les parece la idea? En el proteus no me gusta mucho simular, porque luego me ha engañado jajaja, sobre todo con el lcd. jajajaj pero nada grave. Así que si pueden conseguir los programadores mucho mejor.
24/07/2008 #27


Reinicio del Tutorial -espero que con un poco de más orden por mi parte-
jajaja, se me perdió el libro de pic16f84, así que queda descartada esa opción. Voy a subir nuevas practicas, yo creo que será para la proxima semana. Y comenzaré desde cero con explicaciones de cada paso dado, principalmente una hojeada a la arquitectura, para entender mejor porque se usan más los registros en lugar de la ram y cosas así.

Nos vemos las próxima semana.
08/08/2008 #28


Uso de las palabras reservadas volatile y static
Al instalar las herramientas para trabajar los microcontroladores avr en Debian GNU/Linux 4.1.1-21 encontre algunos ejemplos. Me siento más comodo trabajando en Debian que en Vista, en fin.

Ahí encontre 2 cosas necesarias para mi proyecto, especificamente para la programación en C para los microcontroladores atmel. Las cuales fueron las siguiente palabras reservadas.

volatile :
Todas las variables que son usadas para comunicar valores entre una rutina de servicio de interrupción y la aplicación principal (main function), son declaradas volatile.

static :
El especificador de clase de almacenamiento static, cuando se aplica a una variable global o a una función, evita que la utilice alguna función que no está definida en el mismo archivo. A esto se le conoce como vinculación interna. Las variables y las funciones globales que no son precedidas por static en sus definiciones tienen una vinculación externa; se puede acceder a ellas desde otros archivos, si dichos archivos contienen las declaraciones apropiadas y/o los prototipos de las funciones.
Por lo general, el especificador static se utiliza con las funciones de utilidad que son llamadas por las funciones de un archivo en particular. Si no se requiere una función fuera de un archivo en particular, debe reforzarse el principio del menor privilegio por medio de static. Si una función se define antes de que se utilice en un archivo, static debe aplicarse en la definición de la función; de lo contrario, debe aplicarse al prototipo de la función.
Las variables locales que se declaran con la palabra reservada static sólo se reconocen en la función en la que se definen, pero a diferencia de las variables automáticas, las variables locales static retienen su valor, incluso cuando se sale de la función. La siguiente vez que se invoca a la función, la variable local static contiene el valor que tenía cuando la función terminó por última vez.


¿Qué es lo importate de esto? Si no se utilizan estas palabras reservadas y dependiendo de como se empleen las variables, tendremos problemas en tiempo de ejecución. Es decir nuestro programa se compilara sin ningún problema, el compilador ni el preprocesador nos diran nada. Pero no funcionará de la forma correcta el programa. Por ejemplo no se actualizaban los valores del reloj cuando entraba a una función. En la función main todo funcionaba perfectamente, pero dentro de funciones que necesitan manipular esas variables sus valores no son actualizados. Es algo que ya había expuesto anteriormente, pero ahora con pruebas y recomendaciones de la propria avr-gcc avr-libc. Es decir esto es válido para los que usamos winavr, para otro compilador de alguna otra empresa no se si esto es válido.

La información viene en el manual del avr-libc. Específicamente en el ejemplo largedemo.c. De hecho les recomiendo que vean los ejemplos presentados en la documentación.
10/08/2008 #29

Avatar de microtronic

hola amigos tengo un jtagice mkii me lo gane de una encuesta de atmel noruega ;-)
...estoy aprendiendo la arquitectura atmel... y bueno me gustaria saber para conectar el jtag a un atmega 16 y depurar el codigo necesito conectar reisstencia pull-up a los pines...
PC5 (TDI)
PC4 (TDO)
PC3 (TMS)
PC2 (TCK)...
ah otra pregunta cuando programe el micro via ISP tengo que alimentar el avr o con el vcc y gnd que me proporciona el isp es suficiente..
12/08/2008 #30


Conección isp
Yo tengo el mkIIisp y programo el micro cuando tengo alimentado el micro. El propio programador pone en modo programación el micro y cuando termina de realizar su tarea, regresa al microcontrolador al modo ejecución de su programa grabado.



Si puedes, lee la nota de aplicación avr060 para el jtag y para el isp avr069 y el AVR067: JTAGICE mkII Communication Protocol.

Yo no tengo el JTAG pero quiero uno.
16/11/2008 #31


Hola amigos,soy nuevo en este foro y quiero que alguin me ayude para usar un lcd 16X2. Quiero usar el lcd con un avr,uso winavr, e bajado las librerias del lcd, pero nose que debo de hacer con ellas, tengo que pegarlas en una carpeta especial o que? porque en algunos ejemplos que e visto solo ponen #include "lcd_lib.h" y nada mas,por favor que alguin me instruya.Gracias.
14/01/2009 #32


Display lcd usando microcontroladores de 8 bits de atmel
Si todavìa necesitas una mano avisa. Tenía tiempo que no revisaba el foro. Pero me parece que al principio puse la libreria completa para emplear un display lcd de 16x2 del fabricante JHD. Lee los mensajes anteriores cualquier duda, espero aclarartela.
15/01/2009 #33


hola Fitocondria:

estoy haciendo una aplicación en la que se requiere usar un display de 2*16 y estoy retomando el AVR, un tiempo lo usé progrmándolo con el AVR Studio y en ensamblador, no se si puedas compartir tu diagrama de conexión del display, de cualquier forma buscaré haber si logro dar con él.

gracias por compartir tu conocimiento con nosotros...
30/01/2009 #34


Diagrama de mi lcd
Disculpa la demora. Te debo el diagrama de conexión de mi display lcd de 2 líneas y 16 caracteres. No estoy seguro de la conexión porque cambie varias veces de puerto debido a que conforme iba creciendo mi proyecto lo fuí cambiando de lugar, te paso la librería solo ve que puertos son y ahí conectas tu display.

Mi problema con librerias de 3eras personas fué el tiempo que ellos asignaban a la inicialización del display.

Código:
void LCDinit(void)//Initializes LCD
{
#ifdef LCD_4bit	
	//4 bit part
	_delay_ms(50); <-- Cambia el tiempo por lo que tu necesites.
	LDP=0x00;
mi librería en ensamblador no me acuerdo bien cuál es. Pero teniendo la librería de C la puedes transladar a ensamblador. Que fué lo que yo hice. Hasta que encontre la hoja de datos del C.I. que controla mi LCD.

a continuación te muestro el código en C de la libreria del LCD, de hecho todas funcionan solo ajusta los puertos de control y de datos de acuerdo a tus necesidades y tambien los tiempos de inicialización del Display LCD.
Por cierto el siguiente código es la librería:
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 http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#ifndef _LCDLIB_H_
#define _LCDLIB_H_

#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(50);
	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|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);
	//-------four-------------
	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]);
	}
   LCDcursorOFF();
}
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
En la librería del display LCD viene la configuración para 4 u 8 lineas de datos, las 3 de control se mantienen, te lo menciono porque algunas librerias solo manejan 2 lineas de control.

Código:
#ifdef LCD_4bit	
	//4 bit part
	_delay_ms(50);
	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

#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;
Como te muestro a continuación al principio de la libreria se definen donde van a conectarse las lineas de datos y de control del display LCD.

Código:
#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
con los siguientes comandos envias los datos al display y el control sobre esos datos:

Código:
datos enviados:
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;
control aplicado a los datos:
LCDR|=1<<LCD_E|1<<LCD_RW|1<<LCD_RS;
Por lo anterior solo queda decir que tú decides en que puerto o puertos colocas tu Display LCD de acuerdo a tus necesidades.

Y un programa que hice en ensamblador para manejar el display, similar a uno que encontre pero lo ordene y no me acuerdo bien que le agregue, espero te sirva de guía.

Código:
#pragma AVRPART ADMIN PART_NAME ATmega32

#pragma AVRPART MEMORY PROG_FLASH 32768

#pragma AVRPART MEMORY EEPROM 1024

#pragma AVRPART MEMORY INT_SRAM SIZE 2048

#pragma AVRPART MEMORY INT_SRAM START_ADDR 0x60

.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 

   call  UNSEG
   call  INI_LCD
NOMBRE:      
   ldi   r16,0x41
   call  caracterLCD
   ldi   r16,0x44
   call  caracterLCD
   ldi   r16,0x4F
   call  caracterLCD
   ldi   r16,0x4C
   call  caracterLCD
   ldi   r16,0x46
   call  caracterLCD
   ldi   r16,0x4F
   call  caracterLCD
   ldi   r16,0x02
   call  comandoLCD
   call  UNSEG
   rjmp  NOMBRE

/*************************************************************************
* Subrutina
* Nombre    : INI_LCD
* 
* Proposito : Inicializa el LCD por instrucción. 
*             PORTD = DATOS; PORTC,0 = RS; PORTC,1 = E.
*             Basado en la pagina 46 de la hoja de datos del HD44780U.PDF
*************************************************************************/
INI_LCD:
   ser   r16
   out   DDRD,r16       ;Configura puerto de datos como salida
   ldi   r16,0b00000011
   out   DDRC,r16       ;Configura puerto de control como salida
   nop                  ;Actualiza registros
   cbi   PORTC,0        ;0->RS
   cbi   PORTC,1        ;0->E
   call  TREINTAMS
   ldi   r16,0x38       ;Inicializa LCD
   call  comandoLCD
   call  CINCOMS
   ldi   r16,0x38       ;Inicializa LCD
   call  comandoLCD
   call  UNMS
   ldi   r16,0x38       ;Function Set
   call  comandoLCD
   call  UNMS
   ldi   r16,0x0C       ;Display on
   call  comandoLCD
   call  UNMS
   ldi   r16,0x01       ;Display clear
   call  comandoLCD
   call  UNMS
   ldi   r16,0x06       ;Entry Mode Set
   call  comandoLCD
   call  UNMS
   ldi   r16,0x02       ;Return Home
   call  comandoLCD
   call  UNMS
   call  UNMS
   ret

/*************************************************************************
* Subrutina
* Nombre    : comandoLCD
* 
* Proposito : Envía un dato al bus de datos del LCD para ser procesado
*             como un comando que modifica el comportamiento del LCD
*************************************************************************/
comandoLCD:
   cbi   PORTC,0        ;0->RS
   cbi   PORTC,1        ;0->E
   out   PORTD,r16      ;Envía el dato al bus de datos
   call  habilitaLCD
   ret

/*************************************************************************
* Subrutina
*Nombre     : caracterLCD
*
*Proposito  : Envía un dato al bus de datos del LCD para ser procesado  
*             como un caracter alfanumérico a visualizarse en el LCD
*************************************************************************/
caracterLCD:
   sbi   PORTC,0        ;1->RS
   cbi   PORTC,1        ;0->E
   out   PORTD,r16      ;Envía el dato al bus de datos
   call  habilitaLCD
   ret

/*************************************************************************
* Subrutina
* Nombre    : habilitaLCD
* 
* Proposito : Activa el LCD para procesar las instrucciones ya sean estas
*             Instrucciones de comando ó Instrucciones de datos
*************************************************************************/
habilitaLCD:
   sbi   PORTC,1        ;1->E
   ldi   r16,0xFF
HLCD:
   dec   r16
   brne  HLCD
   cbi   PORTC,1        ;0->E
   ret

/*************************************************************************
*Subrutina
*Nombre     : UNSEG
*
* Propósito : Genera un temporizado de un segundo. realmente 1002897
*************************************************************************/
UNSEG:
   ldi   r16,14
UNSEG2:
   ldi   r17,95
UNSEG1:
   ldi   r18,250
UNSEG0:
   dec   r18
   brne  UNSEG0
   dec   r17
   brne  UNSEG1
   dec   r16
   brne  UNSEG2
   ret

/*************************************************************************
* Subrutina
* Nombre    : TREINTAMS
*
* Propósito : Genera un temporizado de 30 milisegundos. realmente 30.172ms
*************************************************************************/
TREINTAMS:
   ldi   r16,15
TREINTAMS2:
   ldi   r17,59
TREINTAMS1:
   ldi   r18,10
TREINTAMS0:
   dec   r18
   brne  TREINTAMS0
   dec   r17
   brne  TREINTAMS1
   dec   r16
   brne  TREINTAMS2
   ret

/*************************************************************************
* Subrutina
* Nombre    : CINCOMS
*
* Propósito : Genera un temporizado de 5 milisegundos. realmente 5.011ms
*************************************************************************/
CINCOMS:
   ldi   r16,9
CINCOMS2:
   ldi   r17,29
CINCOMS1:
   ldi   r18,5
CINCOMS0:
   dec   r18
   brne  CINCOMS0
   dec   r17
   brne  CINCOMS1
   dec   r16
   brne  CINCOMS2  
   ret
/*************************************************************************
* Subrutina
* Nombre    : UNMS
*
* Propósito : Genera un temporizado de 1 milisegundo. realmente 1ms
*************************************************************************/
UNMS:
   ldi   r16,4
UNMS2:
   ldi   r17,11
UNMS1:
   ldi   r18,6
UNMS0:
   dec   r18
   brne  UNMS0
   dec   r17
   brne  UNMS1
   dec   r16
   brne  UNMS2
   nop
   nop
   nop
   nop
   nop
   ret
Al archivo lo nombre ks0066 porque ese es el controlador de mi display LCD. No esta demás que revises cuál es tu controlador, porque mi problema es que todos mis compañeros manejaban el jhd *** y yo manejaba otro y a todos les funcionaba menos a mi hasta que modifique los tiempos de inicialización de ahí en fuera eran iguales en todo.
30/01/2009 #35


Gracias
Muchas gracias, lo revisaremos a detalle, y estoy de acuerdo contigo, en que lo delicado son los tiempos y quizá el comportamiento de los puertos del MCU empleados....
30/01/2009 #36


Prueba del lcd
Si no les urge mucho, el lunes les pongo un ejemplo del display lcd, con diagrama y foto funcionando. solo digan si quiere el ejemplo en ensamblador o en c. Digo hasta el lunes porque mañana me voy al rancho y regreso el domingo en la noche.

Saludos y a leer. Aunque creo que puse un ejemplo. Pero de todas formas digan que para eso estamos por aquí. Para tratar de apoyarnos con lo que podemos.
09/02/2009 #37


Me gustaria que pusieras el ejemplo del display lcd pero en C...Gracias de antemano
10/02/2009 #38


mi amigo fitocondria tengo una duda .
al querer simular en el AVR studio el Atmega32
en el menu DEBUG - "AVR SIMUlATOR OPTIONS "
pongo una frecuencia de reloj de 10 Mhz y al simular
me sale un mensaje , que dice la velocidad sobrepaso el limite del dispositivo

no entiendo por que , tal vez sea que el simulador trabaja con el reloj interno
que llega a un maximo de 8Mz. y si es asi como hago para simular
con relojes superiores a los 8 Mhz , por ejemplo 10Mhz .


18/02/2009 #39


Respuestas
Primero lo del reloj. El ATMega32 tiene una frecuencia de funcionamiento de 8MHz máxima sin cristal oscilador externo, para utilizar una frecuencia mayor necesitas emplear un cristal externo.

Para realizar simulaciones el mismo programa de simulación límita de acuerdo a sus funciones implementadas.

Es decir que si en Simulator Options, en la etiqueta de Device selection, tu seleccionas un dispositivo cualquiera el programa solo te deja seleccionar las velocidades que el puede manejar es decir el propio simulador no el dispositivo. Yo he comprobado que para la versión que tengo de AVRStudio, para el ATMega32 solo me permite seleccionar un reloj de frecuencia máxima de 8MHz y en el propio cuadro de información aparece la velocidad Máxima.

Algo curioso de mencionar es lo siguiente en la versión 4.13 de AVRStudio me permite seleccionar una frecuencia máxima de 12MHz y en la versión 4.14 de AVRStudio me permite seleccionar una frecuencia máxima de 8MHz.





Es decir encontraste un Bug o error pero que en la versión siguiente ya fué corregido. En la imagen de arriba se ve que me aparece la misma advertencia. Pero si vemos las siguientes imagenes. Ya no aparece, porque solo me permite seleccionar la frecuencia marcada por el cuadro de información.





Conclusión: Solo puedes emplear la velocidad de reloj que te indique el cuadro de información. Al menos eso me indica lo anterior. por lo cual no te puedo decir como hacerle para que simules con una velocidad superior a 8MHz, sino es que modificando el programa de AVRSimulator 2. Lo mejor es actualizar el software si lo necesitas.
18/02/2009 #40


Respuesta
Para el display LCD quería probar de nuevo los programas que hice pero no encuentro mi cable para el programador. Voy a poner la librería y un pequeño ejemplo sin probar si es que no está en los ejemplos anteriores lo del display.

Revisando. . .

En la página 2 de este tema hay un ejemplo que puse del convertidor analógico a digital en el que empleo el display LCD.

La librería del LCD es la siguiente:

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 http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#ifndef _LCDLIB_H_
#define _LCDLIB_H_

#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(50);
	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|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);
	//-------four-------------
	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]);
	}
   LCDcursorOFF();
}
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
No es mi librería, pero es la que usé y funciona muy bien. Ahora es cuestión de fijarse en como la utilizo en el ejemplo del convertidor analógico a digital. Si algo no esta bien claro, adelante, con confianza pregunta, pero mientras no encuentre mi cable no voy a poder programar y probar los ejemplos.
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.