void lcd_write_char(unsigned char data)
{
RS = 1; //se enviara data
lcd_write_4bit(cmd & 0xF0); //envia Nibble alto
lcd_write_4bit((cmd << 4) & 0xF0); //envia Nibble bajo
}void lcd_write_char(unsigned char data)
{
RS = 1; //se enviara data
lcd_write_4bit(data & 0xF0); //envia Nibble alto
lcd_write_4bit((data << 4) & 0xF0); //envia Nibble bajo
}
¿Qué lenguaje C estás usando?
Esta pregunta me delata, pero los lenguajes de alto nivel son parecidos a la hora de trabajar.
En otros lenguajes no se hace tantas cosas para trabajar con un LCD y estoy sospechando que no sabes usar las librerías.
Para adelantar, normalmente, se parte de un código. Se inicializan las cosas, luego se va al main o al bucle infinito y se comienza enviar datos; la espera de datos, procesar datos, ect.
A la hora de inicializar el LCD, se incluye la librería, se configura la librería con una función dedicada a ello y luego se le envía los datos.
Por ejemplo. Para configurar la librería, dicha librería tiene una función de configuración; donde se le indica en qué puerto está conectado el LCD, si los datos se envían por los 8 bit o en 4 bit, y algunas cosillas más. Luego, se inicializa el LCD para luego enviarle los datos.
Código: [Seleccionar]void lcd_write_char(unsigned char data)
{
RS = 1; //se enviara data
lcd_write_4bit(cmd & 0xF0); //envia Nibble alto
lcd_write_4bit((cmd << 4) & 0xF0); //envia Nibble bajo
}
Raro que te lo haya compilado pues cmd no está definido.
Debe serCódigo: [Seleccionar]void lcd_write_char(unsigned char data)
{
RS = 1; //se enviara data
lcd_write_4bit(data & 0xF0); //envia Nibble alto
lcd_write_4bit((data << 4) & 0xF0); //envia Nibble bajo
}
tienes razón, apenas se usar las librerías.
hola, mira si andas en eso de entender finamente el funcionamiento de los lcd hitachi 44780 genéricos, te recomiendo que con la hoja de datos en mano veas los videos del U2, donde muestran como los manejan manualmente a fuerza de mini interruptores dip.
Luego te bajas y estudias las librerias de Donald Weiman, donde hace funcionar esos lcd, muy didacticamente.
http://web.alfredstate.edu/faculty/weimandn/index.html
Ahira de todo ésto y sabiendo como funcionan los integrados i2c pcf8574, podrás entender como hacer tu propia librería versión i2c, o mejor usar una ya lista, como es el caso del greco Vassilis Serasidis, donde muestra hasta con video como controla varias cosas i2c...
https://www.serasidis.gr/circuits/i2c_sensors/I2C_sensors.htm
Hice todo lo que digo y llegue a buen puerto, y logre que me funcionen esas librerias i2c, que en realidad las escribio un tal Davide Gironi, y con el WinAvr, con el Studio 7, te ira mejor.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "i2c_lib.h"
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define LCD_FIRST_ROW 0x80
#define LCD_SECOND_ROW 0xC0
#define LCD_THIRD_ROW 0x94
#define LCD_FOURTH_ROW 0xD4
#define LCD_CLEAR 0x01
#define LCD_RETURN_HOME 0x02
#define LCD_ENTRY_MODE_SET 0x04
#define LCD_CURSOR_OFF 0x0C
#define LCD_UNDERLINE_ON 0x0E
#define LCD_BLINK_CURSOR_ON 0x0F
#define LCD_MOVE_CURSOR_LEFT 0x10
#define LCD_MOVE_CURSOR_RIGHT 0x14
#define LCD_TURN_ON 0x0C
#define LCD_TURN_OFF 0x08
#define LCD_SHIFT_LEFT 0x18
#define LCD_SHIFT_RIGHT 0x1E
#define LCD_TYPE 2 // 0 -> 5x7 | 1 -> 5x10 | 2 -> 2 lines
void LCD_Init();
void i2c_escribe(unsigned char Data);
void LCD_Write_4Bit(unsigned char Nibble);
void LCD_CMD(unsigned char CMD);
void LCD_Set_Cursor(unsigned char ROW, unsigned char COL);
void LCD_Write_Char(char);
void LCD_Write_String(char*);
void Backlight();
void noBacklight();
void LCD_SR();
void LCD_SL();
void LCD_Clear();
unsigned char RS, BackLight_State = LCD_BACKLIGHT;
unsigned char i2c_add;
void LCD_Init()
{
//i2c_add = I2C_Add;
sei();
i2c_iniciar();
i2c_escribe(0x00);
_delay_ms(30);
LCD_CMD(0x03);
_delay_ms(5);
LCD_CMD(0x03);
_delay_ms(5);
LCD_CMD(0x03);
_delay_ms(5);
LCD_CMD(LCD_RETURN_HOME);
_delay_ms(5);
LCD_CMD(0x20 | (LCD_TYPE << 2));
_delay_ms(50);
LCD_CMD(LCD_TURN_ON);
_delay_ms(50);
LCD_CMD(LCD_CLEAR);
_delay_ms(50);
LCD_CMD(LCD_ENTRY_MODE_SET | LCD_RETURN_HOME);
_delay_ms(50);
}
void i2c_escribe(unsigned char Data)
{
i2c_inicia_com();
i2c_envia_dato(0b01001110); //0b01110000 01001110
_delay_us(80);
i2c_envia_dato(Data | BackLight_State);
_delay_us(80);
i2c_detener();
}
/*
void IO_Expander_Write(unsigned char Data)
{
I2C_Master_Start();
I2C_Master_Write(i2c_add);
I2C_Master_Write(Data | BackLight_State);
I2C_Master_Stop();
}*/
void LCD_Write_4Bit(unsigned char Nibble)
{
// Get The RS Value To LSB OF Data
Nibble |= RS;
i2c_escribe(Nibble | 0x04);
i2c_escribe(Nibble & 0xFB);
_delay_us(50);
}
void LCD_CMD(unsigned char CMD)
{
RS = 0; // Command Register Select
LCD_Write_4Bit(CMD & 0xF0);
LCD_Write_4Bit((CMD << 4) & 0xF0);
}
void LCD_Write_Char(char Data)
{
RS = 1; // Data Register Select
LCD_Write_4Bit(Data & 0xF0);
LCD_Write_4Bit((Data << 4) & 0xF0);
}
void LCD_Write_String(char* Str)
{
for(int i=0; Str[i]!='\0'; i++)
LCD_Write_Char(Str[i]);
}
void LCD_Set_Cursor(unsigned char ROW, unsigned char COL)
{
switch(ROW)
{
case 2:
LCD_CMD(0xC0 + COL-1);
break;
case 3:
LCD_CMD(0x94 + COL-1);
break;
case 4:
LCD_CMD(0xD4 + COL-1);
break;
// Case 1
default:
LCD_CMD(0x80 + COL-1);
}
}
void LCD_SL()
{
LCD_CMD(0x18);
_delay_us(40);
}
void LCD_SR()
{
LCD_CMD(0x1C);
_delay_us(40);
}
void LCD_Clear()
{
LCD_CMD(0x01);
_delay_us(40);
}#include <avr/io.h>
void i2c_iniciar(); //función para iniciar el módulo TWI I2C AVR
void i2c_espera(); //función de espera
void i2c_inicia_com(); //función que inicia la comunicación I2C AVR
void i2c_detener(); //función que detiene la comunicación I2C AVR
void i2c_envia_dato(unsigned char ); //función para enviar o escribir
//datos en el esclavo
unsigned char i2c_recibe_dato_ack(); //función para recibir o leer datos del esclavo
//enviando el bit ACK si se quiere leer mas datos
//después del último leído
unsigned char i2c_recibe_dato_nack(); //función para recibir o leer datos del esclavo
//sin enviar el bit ACK si no se quiere leer mas datos
//después del último leido
uint8_t i2c_estado_com(); //función para averiguar el estado de la comunicación I2C AVR
//útil para detectar errores
//void i2c_escribe(unsigned char data); //funcion general para escribir
void i2c_iniciar()
{
//PORTC = (1<<4) | (1<<5); //Activa las resistencias pull up de los pines de scl y sda
//TWBR = 17; //velocidad 400Khz, Fosc 8Mhz, prescaler de 1
//TWSR &=~ (1<<TWPS0);
//TWSR &=~ (1<<TWPS1);
TWBR = 17;
TWCR |= (1<<TWEN); //módulo TWI iniciado
PRR &=~ (1<<PRTWI);
}
void i2c_espera()
{
while ((TWCR & (1<<TWINT)) == 0);
}
void i2c_inicia_com()
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);//bandera de interrupción a 1, start, habilita I2C AVR
i2c_espera(); //espera mientras el bit TWINT sea 0
}
void i2c_detener()
{
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);//bandera de interrupción a 1, detener, habilita I2C AVR
}
void i2c_envia_dato(unsigned char dato) {
TWDR = dato;
TWCR = (1<<TWINT)|(1<<TWEN);//para empezar a enviar el dato
i2c_espera();//cuando TWINT se ponga a 1 se habrá terminado de enviar el dato
}
unsigned char i2c_recibe_dato_ack(){//maestro envia ack para seguir recibiendo
//mas datos
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
i2c_espera();
return TWDR;
}
unsigned char i2c_recibe_dato_nack(){//maestro no envia ack para no seguir recibiendo
//mas datos
TWCR = (1<<TWINT)|(1<<TWEN);
i2c_espera();
return TWDR;
}
uint8_t i2c_estado_com(){
uint8_t estado; //variable donde se almacena el estado de la comunicación
//I2C AVR
estado = TWSR & 0xf8; //en la variable estado se guarda el valor de los 5 bits de
//mas peso del registro TWSR seguidos de 3 ceros,
//el número obtenido indica
//el estado en que se encuentra la comunicación I2C AVR
return estado; //la función retorna el estado de la comunicación
}#include <avr/io.h>
#include <util/delay.h>
#include "lcd_i2c.h"
int main(void)
{
LCD_Clear();
LCD_Set_Cursor(1, 1);
LCD_Write_String("hola");
}