0% encontró este documento útil (0 votos)
546 vistas42 páginas

I2c STM32

El documento describe el módulo i2c y la interfaz i2c. El módulo i2c permite la comunicación con otros microcontroladores y periféricos. La interfaz i2c es un bus de comunicación síncrono de dos hilos desarrollado por Philips que se utiliza comúnmente para comunicar circuitos integrados. La interfaz i2c define las líneas de reloj y datos, los roles de maestro y esclavo, y los protocolos para iniciar y finalizar la transferencia de datos.

Cargado por

Matheus
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
546 vistas42 páginas

I2c STM32

El documento describe el módulo i2c y la interfaz i2c. El módulo i2c permite la comunicación con otros microcontroladores y periféricos. La interfaz i2c es un bus de comunicación síncrono de dos hilos desarrollado por Philips que se utiliza comúnmente para comunicar circuitos integrados. La interfaz i2c define las líneas de reloj y datos, los roles de maestro y esclavo, y los protocolos para iniciar y finalizar la transferencia de datos.

Cargado por

Matheus
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 42

MÓDULO i2c

• Pensado para comunicación con otros Microcontroladores o Periféricos:


EEPROM serie (almacenamiento de datos no volátiles)
Registros de Desplazamiento (expansión de entradas y/o salidas)
Drivers de Displays (reducción de conexiones)
Conversores A/D (digitalización externa de señales)
Interface I2C
• Es un interface síncrono a 2 hilos pensado para la comunicación entre C.I. y
desarrollado por Philips Corporation. Es un bus estándar para muchos equipos de
consumo y telecomunicaciones

• Las dos líneas de comunicación corresponden a reloj (SCL) y datos (SDA). Las
transferencias son por tanto semi-dúplex.

• En el bus debe existir al menos un dispositivo Maestro que genera la señal de reloj
y uno o varios Esclavos que reciben tal señal SCL.

• El dispositivo Maestro es el único que tiene capacidad de iniciar la transferencia,


decidir con quién se realiza, el sentido de la misma (envío o recepción del Maestro)
y cuándo se finaliza

• Cada dispositivo esclavo conectado al bus tiene asignada una dirección única
codificada en 7 (ó en 10 bits de manera opcional)

• Se admite la presencia de varios Maestros en el bus (sistema multi-Maestro) con


un arbitraje que asegura que en cada instante sólo hay uno dominante
Interface I2C
Ventajas del BUS I2C

• Definido inicialmente a mediados de los 80 para trabajar a 100kbit/s y en 1995


se definió un modo rápido de funcionamiento que permitía transferencias de hasta
400kbit/s (algunos dispositivos gráficos llegan a 3,4MHz).

• Es útil y se emplea en muchas aplicaciones en las que la velocidad de transferencia


es mucho mayor de lo que el caso requiere (p.e. Medida de temperaturas con
constantes de tiempo de segundos)

• Su principal ventaja, es que una vez disponible el microcontrolador con sus


funciones de interface con bus I2C, la inclusión de un dispositivo I2C adicional sólo
necesitaría su conexión a las dos líneas del bus (SDA y SCL que son las mismas para
todos) y asignarle una dirección. Los intercambios se realizarían utilizando los mismos
subprogramas para todos

• La tensión de funcionamiento va de 2,5V a 5,5V y no es necesaria la presencia de


“drivers” de adaptación de tensión externos (integración en los propios dispositivos)
Interface I2C
Interface I2C
ESTADOS EN EL BUS I2C: Inicio y Final de transferencia

• En el ESTADO INACTIVO, las líneas SDA y SCL se encuentran a “1”: los


transistores de las etapas de salida de todos los dispositivos se encuentran en
corte
• El INICIO de transferencia se produce cuando aparece una transición de “1” a “0”
en la línea SDA manteniéndose la línea de reloj SCL a “1”

• El FIN de transferencia es por transición de “0” a “1” en SDA cuando SCL está a
“1”
Interface I2C

START y STOP sólo


pueden ser
generados
por el Maestro
Interface I2C
• Cuando un Maestro decide iniciar una transferencia, envía primero la dirección
del dispositivo con el que quiere “hablar”.

• Todos los dispositivos “escuchan” para determinar si la dirección colocada en


el bus es la suya. Acompañando a la dirección aparece un bit R/W que indica al
esclavo destinatario si el Maestro quiere “leer” (recibir si R/W=1) del Esclavo o
si el Maestro quiere “escribir” (enviar si R/W=0) en el Esclavo.

•El Maestro y el Esclavo direccionado se deben encontrarse siempre en estados


opuestos:
Maestro emite / Esclavo recibe
Maestro recibe / Esclavo emite

• En cualquiera de los casos, el Maestro será el que genere la señal de reloj en SCL

• Si hay más de un Maestro en el bus, se debe producir un arbitraje cuando SCL=1:


el Maestro que envía un “1” y detecta un “0” en la línea SDA “pierde” en el
arbitraje y desactiva su salida de datos (aunque podría seguir generando flancos
en la línea SCL hasta que finalizara el envío del byte donde “perdió” el control del
bus)
Interface I2C
Interface I2C
Reconocimiento de Transferencia (ACK)

• Los datos se transmiten en paquetes de 8 bits (bytes), no hay límite en cuanto


a número de bytes, pero después de cada byte se debe intercalar un bit de
reconocimiento (ACK) por parte del dispositivo receptor

• Si es el Esclavo el receptor y no genera el bit de reconocimiento después de cada


byte, el Maestro debe abortar la transferencia generando un bit de fin (STOP)

• Si el dispositivo Maestro es el receptor, genera un ACK tras cada byte recibido,


permitiendo al Esclavo que continúe enviando bytes. Si el Maestro decide finalizar
la transferencia, genera un bit de STOP en lugar de colocar un bit de
reconocimiento

• Si el Esclavo necesita retardar el envío del siguiente byte (porque no lo tiene


todavía disponible, p.e.), puede situar la línea SCL en estado bajo y forzar al
Maestro a situarse en un estado de “Espera” puesto que no se podrían generar
flancos en SCL
Interface I2C
Interface I2C
Repetición de START (Sr)

Si un dispositivo Maestro no desea abandonar el bus tras una transferencia, en


lugar de generar un bit de STOP y volver a generar el nuevo START, puede
generar una Repetición de START (Sr)

La Repetición de START es idéntica a la condición de START (SDA pasa de 1 a 0


con SCL en estado alto) pero se produce tras un pulso de reconocimiento de bus
(ACK) y no desde un estado inactivo
I2C ESCLAVO: Transmisión

• Se da si hay una coincidencia con la dirección en el bus y además el bit R/W es 1


(el adjunto a la dirección). En ese caso se generael pulso de reconocimiento en SDA.

•Se retiene la generación de reloj del Maestro porque el Esclavo mantiene SCL
a 0 mientras prepara el envío.
I2C ESCLAVO: Transmisión (II)

• Si al finalizar el envío de un byte por parte del Esclavo, el Maestro no sitúa el


pulso de reconocimiento en la línea SDA (no hay ACK), se interpreta que se acabó
la transferencia de datos, se resetea la lógica del Esclavo y queda a la espera
de un nuevo START

Si por el contrario, se recibe un ACK del Maestro, el Esclavo debe continuar enviando
bytes, para lo cual debe cargar el nuevo dato y liberar la línea SCL con CKP=1
I2C en el bus ESCLAVO: “Llamada general” I2C

•La “llamada general” en el interface I2C es un envío con una dirección válida para
todos los esclavos que se encuentren presentes en el bus. La dirección que coloca el
Maestro consiste en 7 ceros seguido de R/W = 0. En este caso, todos los Esclavos
deberían responder con el pulso de reconocimiento ACK.
Interface I2C
Interface I2C

La estructura principal de configuración del periférico i2c es:

Especifica la velocidad de la interface i2c

Typedef struct Especifica la diferencia entre el tiempo en estado bajo y en


{ estado alto de la linea SCL, se configura mediante ratios de
uint32_t ClockSpeed; diferencia representado por:
uint32_t DutyCycle; I2C_DUTYCYCLE_2 ratio de 2:1
uint32_t OwnAddress1; I2C_DUTYCYCLE_16_9 ratio de 16:9
uint32_t AddressingMode;
Especifica la primera dirección del esclavo. Este parámetro
uint32_t DualAddressMode;
puede ser de 7 o 10 bits.
uint32_t OwnAddress2;
uint32_t GeneralCallMode; Especifica si la dirección será de 10 o 7 bits, este parámetro
uint32_t NoStretchMode; puede tomar los siguientes valores:
I2C_ADDRESSINGMODE_7BIT
}I2C_InitTypeDef; I2C_ADDRESSINGMODE_10BIT
Interface I2C

La estructura principal de configuración del periférico i2c es:

Especifica si se ha seleccionado la dirección dual. Este


parámetro puede tomar los siguientes valores:
Typedef struct I2C_DUALADDRESS_DISABLE
{ I2C_DUALADDRESS_ENABLE
uint32_t ClockSpeed;
uint32_t DutyCycle; Si se habilito la dirección dual. Este campo especifica la
uint32_t OwnAddress1; segunda dirección del esclavo. Este parámetro puede ser de
uint32_t AddressingMode; solo de 7 bits.
uint32_t DualAddressMode;
Especifica si se habilita o no la llamada general. Este
uint32_t OwnAddress2;
parámetro puede tomar los siguientes valores:
uint32_t GeneralCallMode;
I2C_GENERALCALL_DISABLE
uint32_t NoStretchMode;
I2C_GENERALCALL_ENABLE
}I2C_InitTypeDef; Especifica si no se selecciona el modo de estiramiento. Este
parámetro puede ser un valor de:
I2C_NOSTRETCH_DISABLE
I2C_NOSTRETCH_ENABLE
Interface I2C

Para inicializar la configuración del periférico se ejecuta la función:

HAL_I2C_Init (I2C_HandleTypeDef * hi2c);

Para el Envío y Recepción de bytes de datos se usan la funciones provistas dentro de la librería HAL.

FUNCIONES POR SONDEO PARA LA CONFIGURACION MAESTRO Y ESCLAVO


• HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
• HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
• HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
• HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);

FUNCIONES POR INTERRUPCION PARA LA CONFIGURACION MAESTRO Y ESCLAVO
• HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
• HAL_I2C_Master_Receive _IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size,);
• HAL_I2C_Slave_Transmit _IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
• HAL_I2C_Slave_Receive _IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
Interface I2C
• FUNCIONES POR SONDEO PARA LA LECTURA Y ESCRITURA SOBRE MEMORIA PARA MAESTRO
• HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t
*pData, uint16_t Size, uint32_t Timeout);
• HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t
*pData, uint16_t Size, uint32_t Timeout);

• FUNCIONES POR INTERRUPCION PARA LA LECTURA Y ESCRITURA SOBRE MEMORIA PARA MAESTRO
• HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize,
uint8_t *pData, uint16_t Size);
• HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize,
uint8_t *pData, uint16_t Size);

FUNCIONES PARA VERIFICAR SI EL DISPOSITIVO OBJETO YA ESTA LISTO PARA LA COMUNICACION


HAL_I2C_IsDeviceReady(I2C_HandleTypeDef * hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)
Interface I2C

Parámetros de las funciones


• hi2c: Puntero a la estructura I2C_HandleTypeDef que contiene la información de la configuración
i2c específica.
• DevAddress: Dirección del dispositivo: Target device address: la dirección de 7 bits debe
desplazarse a la izquierda antes de llamar a la interface
• pData: Puntero al buffer de datos. Especifica los bytes a enviar si es transmisor o los bytes a
recibir si es receptor.
• Size: Cantidad de datos a enviar
• Timeout: Tiempo de espera.
• MemAddress: Dirección de la memoria interna
o I2C_MEMADD_SIZE_8BIT
o I2C_MEMADD_SIZE_16BIT
• MemAddSize: Tamaño de la dirección de memória interna
• Trials: Número de intentos
Interface I2C

EJEMPOS DEL USU DE LAS FUNCIONES


Interface I2C
EJEMPLO: Escribir un programa para el STM32F103C8T6 configurado como maestro i2c, el cual
pueda escribir un mensaje en una memoria EEPROM i2c a partir de su dirección 0x1AAA. Así
también, sea capaz de leer de la memoria el mensaje que se envió. Si se recupera el mensaje y es
idéntico al que se envió que invierta el valor de un led. Y envié a una computadora mediante el UART
el mensaje que se transmite y se lee por módulo i2c.

SOLUCIÓN : CÓDIGO
La memoria EEPROM i2c tiene la siguiente dirección: 1010 E2
E1 E0. Las funciones de i2c de la librería HAL necesitan que #include "stm32f1xx_hal.h"
la dirección del dispositivo se recorran a la izquierda una #include <string.h>
posición, por lo cual la dirección seria: 1010 E2 E1 E0 0. #include <stdlib.h>
Los valores de E2 E1 E0 se define mediante hardware ya
GPIO_InitTypeDef GPIO_InitStruct;
que son tres pines del circuito. Si se conectan a tierra como UART_HandleTypeDef huart1;
muestra la figura la dirección sería: 1010 0000 = 0xA0 I2C_HandleTypeDef hi2c1;

La dirección de la celda de memoria a static void GPIO_Init(void);


partir de la cual se quiere escribir static void UART1_Init(void);
será: 1AAA (dirección de 16 bits) void SystemClock_Config(void);
static void I2C1_Init(void);
Interface I2C
int main(void)
{
char wmsg[] ="HOLA MUNDO";
char rmsg[11];
HAL_Init();
SystemClock_Config();
I2C1_Init();
GPIO_Init();
UART1_Init();
HAL_UART_Transmit(&huart1, (uint8_t*)wmsg, strlen(wmsg), 100);
HAL_I2C_Mem_Write(&hi2c1, 0xA0, 0x1AAA, I2C_MEMADD_SIZE_16BIT, (uint8_t*)wmsg, strlen(wmsg)+1,HAL_MAX_DELAY);
while(HAL_I2C_IsDeviceReady(&hi2c1, 0xA0, 1, HAL_MAX_DELAY) != HAL_OK);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_10);
HAL_I2C_Mem_Read(&hi2c1, 0xA0, 0x1AAA, I2C_MEMADD_SIZE_16BIT, (uint8_t*)rmsg, strlen(wmsg)+1, HAL_MAX_DELAY);
HAL_UART_Transmit(&huart1, (uint8_t*)rmsg, strlen(rmsg), 100);

if(strcmp(wmsg, rmsg) == 0)
{
while(1)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_10);
HAL_Delay(100);
}
}
while(1);
}
Interface I2C void GPIO_Init(void)

{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE(); //IMPORTANTE!!!!!
__HAL_RCC_GPIOB_CLK_ENABLE();

GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
Interface I2C

void UART1_Init(void) static void I2C1_Init(void)

{ {
__HAL_RCC_USART1_CLK_ENABLE(); hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 400000;
huart1.Instance = USART1; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
huart1.Init.BaudRate = 9600;
hi2c1.Init.OwnAddress1 = 0;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
huart1.Init.Mode = UART_MODE_TX_RX; hi2c1.Init.OwnAddress2 = 0;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

HAL_UART_Init(&huart1); __HAL_AFIO_REMAP_I2C1_ENABLE();
} __HAL_RCC_I2C1_CLK_ENABLE();

__HAL_RCC_I2C1_FORCE_RESET();
__HAL_RCC_I2C1_RELEASE_RESET();

HAL_I2C_Init(&hi2c1);
}
Interface I2C
Hardware del Módulo adaptador LCD a I2C
El Módulo adaptador LCD a I2C que se usará se
basa en el Expansor de Entradas y Salidas
digitales controlado por el PCF8574. Este módulo
se usa para controlar un LCD Alfanumérico.
La dirección I2C, de 7 bits, por defecto del
módulo puede ser 0x3F o en otros casos
0x27. Es importante identificar la dirección I2C
del modulo. Si existe la necesidad de usar más
de un LCD se puede modificar la dirección I2C
del modulo adaptador soldando los puentes A0,
A1 y A2 presentes en el módulo, estos tres
puentes son los bits menos significativos de la
dirección I2C del módulo. La dirección 0x3F en
binario sería: 0|0|1|1|1|A2|A1|A0 y la dirección
0x27: 0|0|1|0|0|A2|A1|A0. Por defecto A0, A2,
A1 valen 1 pero si soldamos los puentes, estos
se conectan a tierra teniendo un valor 0. Por
ejemplo si soldamos los tres puentes la nueva
dirección sería 0|0|1|0|0|0|0|0 (0x20), para un
chip que anteriormente era 0x27.
Interface I2C
Hardware del Módulo adaptador LCD a I2C
El Módulo adaptador LCD a I2C que se usará se
basa en el Expansor de Entradas y Salidas
digitales controlado por el PCF8574. Este módulo
se usa para controlar un LCD Alfanumérico.
La dirección I2C, de 7 bits, por defecto del
módulo puede ser 0x3F o en otros casos
0x27. Es importante identificar la dirección I2C
del modulo. Si existe la necesidad de usar más
de un LCD se puede modificar la dirección I2C
del modulo adaptador soldando los puentes A0,
A1 y A2 presentes en el módulo, estos tres
puentes son los bits menos significativos de la
dirección I2C del módulo. La dirección 0x3F en
binario sería: 0|0|1|1|1|A2|A1|A0 y la dirección
0x27: 0|0|1|0|0|A2|A1|A0. Por defecto A0, A2,
A1 valen 1 pero si soldamos los puentes, estos
se conectan a tierra teniendo un valor 0. Por
ejemplo si soldamos los tres puentes la nueva
dirección sería 0|0|1|0|0|0|0|0 (0x20), para un
chip que anteriormente era 0x27.
Interface I2C
Interface I2C Conexión con el LCD

Vcc

Debido a que el PCF8574 tiene un puerto paralelo de


salida de 8bits, y puesto que se necesita controlar los
pines RS R/W y E del LCD, el control del LCD solo puede
GND
ser por medio del formato de control de 4bits. El nibble
alto será usado para enviar D7, D6, D5 y D4, mientras el
nibble bajo para el control del LCD (RS R/W y E ).
Interface I2C Conexión con el LCD
Interface I2C Funciones de control para el LCD
ENVIO DE COMANDOS

En el modo de 4 bits, hay que enviar los datos y comandos en dos


pasos, primero el Nibble alto y luego el Nibble bajo.

• Para enviar comandos, se establece RS=0 y R/W=0.


• Se coloca el comando en el bus de datos.
• Se generar un pulso en E para cargar el dato.
• Se esperar un tiempo para que se ejecute el
comando.
Interface I2C Funciones de control para el LCD
ENVIO DE COMANDOS En el modo de 4 bits, hay que enviar los datos y comandos en
dos pasos, primero el Nibble alto y luego el Nibble bajo.
bits-> 76543210
Para el análisis sea el comando -> hgf edcba • Para enviar comandos, se
establece RS=0 y R/W=0.
• Se coloca el comando en el
void lcd_enviar_cmd (char cmd) bus de datos.
{ • Se generar un pulso en E
char nibb_h, nibb_l; para cargar el dato.
uint8_t dato_t[4]; A E RW RS
nibb_h = (cmd&0xf0); -> hgfe0000
nibb_l = ((cmd<<4)&0xf0); -> dcba0000
dato_t[0] = nibb_h|0x0C; //E=1,RW=0,RS=0 ->hgfe1100
dato_t[1] = nibb_h|0x08; //E=0,RW=0,RS=0 ->hgfe1000
dato_t[2] = nibb_l|0x0C; //E=1,RW=0,RS=0 ->dcba1100
dato_t[3] = nibb_l|0x08; //E=0,RW=0,RS=0 ->dcba1000
HAL_I2C_Master_Transmit (&hi2c1, DIR_ESCLAVO_LCD,(uint8_t *) dato_t, 4, 100);
}
Interface I2C Funciones de control para el LCD
ENVIO DE DATOS

En el modo de 4 bits, hay que enviar los datos y comandos en dos


pasos, primero el Nibble alto y luego el Nibble bajo.

• Para enviar datos se establece RS=1 y R/W=0.


• Se coloca el dato en el bus de datos.
• Se generar un pulso en E para cargar el dato.
• Se esperar un tiempo para que el dato aparezca
en el LCD (100 us).
Interface I2C Funciones de control para el LCD
ENVIO DE DATOS En el modo de 4 bits, hay que enviar los datos y comandos en
dos pasos, primero el Nibble alto y luego el Nibble bajo.
bits-> 7 6 5 4 3 2 1 0
Para el análisis sea el dato -> h g f e d c b a • Para enviar datos se
establece RS=1 y R/W=0.
• Se coloca el dato en el bus
de datos.
void lcd_enviar_dato (char dato)
• Se generar un pulso en E
{ para cargar el dato.
char nibb_h, nibb_l; • Se esperar un tiempo para
uint8_t dato_t[4]; A E RW RS que el dato aparezca en el
LCD (100 us).
nibb_h = (dato&0xf0); -> hgfe0000
nibb_l = ((dato<<4)&0xf0); -> dcba0000
dato_t[0] = nibb_h|0x0D; //E=1,RW=0,RS=1 ->hgfe1101
dato_t[1] = nibb_h|0x09; //E=0,RW=0,RS=1 ->hgfe1001
dato_t[2] = nibb_l|0x0D; //E=1,RW=0,RS=1 ->dcba1101
dato_t[3] = nibb_l|0x09; //E=0,RW=0,RS=1 ->dcba1001
HAL_I2C_Master_Transmit (&hi2c1, DIR_ESCLAVO_LCD,(uint8_t *) dato_t, 4, 100);
}
Interface I2C Funciones de control para el LCD
INICIALIZACION DEL LCD Para habilitar el modo de 4 bits, el controlador del LCD nos permite la
void lcd_init (void) siguiente secuencia
{
uint8_t i=0;
HAL_Delay(100);
for(i=0;i<3;i++) // enviamos tres veces 3: selección del modo de 4-bit
{
lcd_enviar_cmd(0x03);
}
HAL_Delay(45);
lcd_enviar_cmd (0x02); //configuración de modo de 4 bits
HAL_Delay(100);
lcd_enviar_cmd (0x28); //función Set: 0 0 1 DL N F x x
// 0x28: 0 0 1 0 1 0 0 0
// (4 bits,2 líneas, 5x7)
HAL_Delay(1);
lcd_enviar_cmd (0x0c); //ctrl. del Display: 0 0 0 0 1 D C B
// 0x0c: 0 0 0 0 1 1 0 0
// Dipl. Cursor blink
// On off off
HAL_Delay(1);
lcd_enviar_cmd (0x80); //Dirección DDRAM: cursor en las coordenadas (1,1)
HAL_Delay(1);
}
Interface I2C FUNCIONES DEL LCD i2C

ENVIAR DE STRING

void lcd_enviar_string (char *str)


{
while (*str) lcd_enviar_dato (*str++);
}

ENVIAR DE FLOTANTE
void lcd_enviar_float (float dato, int numerodedigitos)
{
char flotante[12];
sprintf (flotante,"%f", dato);
for (int i=0; i< numerodedigitos; i++)
{
lcd_enviar_dato (flotante[i]);
}
}
Interface I2C FUNCIONES DEL LCD i2C

ENVIAR ENTERO
void lcd_enviar_int (int dato)
{
char numero[12];
sprintf (numero,"%d", dato);
lcd_enviar_string (numero);
}
}

MOVER CURSOR
void lcd_a_xy(uint8_t x, uint8_t y)
{
uint8_t direccion[] = {0x80, 0xC0, 0x94, 0xD4};
lcd_enviar_cmd(direccion[y-1] + (x-1));
HAL_Delay(1);
}
Interface I2C Funciones de control para el LCD
Para habilitar el modo de 4 bits, el controlador del LCD también nos
INICIALIZACION DEL LCD
permite la siguiente secuencia
void lcd_init (void)
{
// inicialización de 4 bits
HAL_Delay(50); // espera >40ms
lcd_enviar_cmd (0x30);
HAL_Delay(5); // espera >4.1ms
lcd_enviar_cmd (0x30);
HAL_Delay(1); // espera >100us
lcd_enviar_cmd (0x30);
HAL_Delay(10);
lcd_enviar_cmd (0x20); // modo de 4 bits
HAL_Delay(10);

// inicialización del display


lcd_enviar_cmd (0x28); // Function set --> DL=0 (modo 4 bits), N = 1 (2 líneas de display) F = 0 (formato 5x8)
HAL_Delay(1);
lcd_enviar_cmd (0x08); //Display on/off control --> D=0,C=0, B=0 ---> display apagado
HAL_Delay(1);
lcd_enviar_cmd (0x01); // limpiar display
HAL_Delay(1);
HAL_Delay(1);
lcd_enviar_cmd (0x06); //Entry mode set --> I/D = 1 (incremento del cursor) & S = 0 (sin desplazamiento)
HAL_Delay(1);
lcd_enviar_cmd (0x0C); //Display on/off control --> D = 1, C y B = 0. (Cursor y blink apagados)
}
Interface I2C Ejemplo del uso del LCD con I2C

Programa ejemplo que muestra la utilización de las funciones i2c para el madejo del LCD por medio del
C.I. PCF8574

#include "main.h"

#define DIR_ESCLAVO_LCD 0x4E // 0x4E es la dirección por defecto del LCD i2c

I2C_HandleTypeDef hi2c1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
//Prototipo de las funciones i2c del LCD
void lcd_enviar_cmd (char cmd);
void lcd_enviar_dato (char dato);
void lcd_init (void);
void lcd_enviar_string (char *str);
void lcd_a_xy(uint8_t x, uint8_t y);
void lcd_enviar_int (int dato);
void lcd_enviar_float (float dato, int numerodedigitos);
Interface I2C Ejemplo del uso del LCD con I2C

int main(void)
{
HAL_Init();

SystemClock_Config();

MX_GPIO_Init();
MX_I2C1_Init();
lcd_init ();

lcd_enviar_cmd (0x01); // borrar display


HAL_Delay(2); // retardo de ejecución del comando
lcd_enviar_cmd (0x80); // cursor en la posición (1,1)
lcd_enviar_string ("LCD 2 x 16");
Interface I2C Ejemplo del uso del LCD con I2C

while (1)
{
float numero=99.00;
for (uint8_t i=0;i<10 ;i++ )
{
lcd_a_xy(1,2); // cursor en la posición (1,2)
lcd_enviar_string ("contando: ");
lcd_enviar_int (i); // se imprime el valor del contador i
HAL_Delay(500); // retardo de medio segundo
}
for (uint8_t i=1;i<10 ;i++ ) // primer valor de i=1 por que no se divide entre 0
{
lcd_a_xy(1,2); // cursor en la posición (1,2)
lcd_enviar_string ("contando: ");
numero=numero/i;
lcd_enviar_float (numero,4); // se imprime el numero flotante con 4 caracteres incluyendo el punto
HAL_Delay(500); // retardo de medio segundo
}
lcd_a_xy(1,2); // cursor en la posición (1,2)
lcd_enviar_string (" "); // 16 espacios en blanco para borrar la 2da línea
}
}

También podría gustarte