I2Cn_Init_Advanced(unsigned long : I2C_ClockSpeed, const Module_Struct *module);
I2Cn_Start();
I2Cn_Write(unsigned char slave_address, unsigned char *buf, unsigned long count, unsigned long END_mode);
I2Cn_Read(char slave_address, char *ptrdata, unsigned long count, unsigned long END_mode);
#define PCF8574A_ADDR 0x3F //c PCF8574 void I2C_PCF8574_WriteReg(unsigned char wData) { I2C1_Start(); // START I2C1_Write(PCF8574A_ADDR,&wData, 1, END_MODE_STOP); // 1 STOP } char PCF8574A_reg; // PCF8574 void main () { I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // I2C delay_ms(25); // PCF8574A_reg.b0 = 0; // PCF8574A_reg.b1 = 1; // while (1) { delay_ms(500); PCF8574A_reg.b0 = ~PCF8574A_reg.b0; PCF8574A_reg.b1 = ~PCF8574A_reg.b1; // I2C_PCF8574_WriteReg (PCF8574A_reg); // PCF8574 } }
#define PCF8574A_ADDR 0x3F //c PCF8574 void I2C_PCF8574_WriteReg(unsigned char wData) { I2C1_Start(); // START I2C1_Write(PCF8574A_ADDR, &wData, 1, END_MODE_STOP); // 1 STOP } void I2C_PCF8574_ReadReg(unsigned char rData) { I2C1_Start(); // START I2C1_Read(PCF8574A_ADDR, &rData, 1, END_MODE_STOP); // 1 STOP } char PCF8574A_reg; // PCF8574 char PCF8574A_out; // PCF8574 char lad_state; // void main () { I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // I2C delay_ms(25); // PCF8574A_reg.b0 = 0; // PCF8574A_reg.b1 = 1; // PCF8574A_reg.b6 = 1; // 6 7 . PCF8574A_reg.b7 = 1; while (1) { delay_ms(100); I2C_PCF8574_WriteReg (PCF8574A_reg); // CF8574 I2C_PCF8574_ReadReg (PCF8574A_out); // CF8574 if (~PCF8574A_out.b6) PCF8574A_reg.b0 = ~PCF8574A_reg.b0; // 1 (6 CF8574 0, / ) if (~PCF8574A_out.b7) PCF8574A_reg.b1 = ~PCF8574A_reg.b1; // 2 2 } }
The datashit on it and the HD44780 controller can be easily found on the Internet. We connect our display to the RCF8574, and its, respectively, to our STM32.
HD44780 uses a parallel gated interface. Data is transmitted over 8 (in one clock) or 4 (in 2 clock cycles) of the strobe pulse at pin E. (read by the display controller on the descending front, the transition from 1 to 0). The RS output indicates whether we send data to our display ( RS = 1 ) (the characters it should display, in fact, from ASCII codes) or commands ( RS = 0 ). RW indicates the direction of data transfer, write or read. Usually we write data to the display, therefore ( RW = 0 ). Resistor R6 controls the display contrast. Just connect the input contrast adjustment to the ground or power can not, otherwise you will not see anything. . VT1 is used to turn on and off the backlight display commands MK. MicroC has a library for working with such displays on a parallel interface, but usually it’s expensive to spend 8 feet on a display, so I almost always use the F8574 to work with such small screens. (If someone is interested, I will write an article about working with HD44780-based displays built into MicroC via a parallel interface.) The exchange protocol is not particularly complicated (we will use 4 data lines and transmit information in 2 cycles), the following shows it timing chart:
Before transferring data to our display, it must be initialized by passing service commands. (Described in the datasheet, here we give only the most used)
#define PCF8574A_ADDR 0x3F //c PCF8574 #define DB4 b4 // PCF8574 #define DB5 b5 #define DB6 b6 #define DB7 b7 #define EN b3 #define RW b2 #define RS b1 #define BL b0 // #define displenth 20 // static unsigned char BL_status; // (/) void lcd_I2C_Init(void); // PCF8574 void lcd_I2C_txt(char *pnt); // , - void lcd_I2C_int(int pnt); // , - void lcd_I2C_Goto(unsigned short row, unsigned short col); // , row - ( 1 2 4 ) col - ( 1 displenth)) void lcd_I2C_cls(); // void lcd_I2C_backlight (unsigned short int state); // ( 1 - 0 )
#include "i2c_lcd.h" // - char lcd_reg; // PCF8574 void I2C_PCF8574_WriteReg(unsigned char wData) // i2c PCF8574 { I2C1_Start(); I2C1_Write(PCF8574A_ADDR,&wData, 1, END_MODE_STOP); } void LCD_COMMAND (char com) // { lcd_reg = 0; // 0 lcd_reg.BL = BL_status.b0; // , lcd_reg.DB4 = com.b4; // 4 lcd_reg.DB5 = com.b5; lcd_reg.DB6 = com.b6; lcd_reg.DB7 = com.b7; lcd_reg.EN = 1; // . 1 I2C_PCF8574_WriteReg (lcd_reg); // PCF8574, delay_us (300); // lcd_reg.EN = 0; // 0, I2C_PCF8574_WriteReg (lcd_reg); delay_us (300); lcd_reg = 0; lcd_reg.BL = BL_status.b0; lcd_reg.DB4 = com.b0; // 4 lcd_reg.DB5 = com.b1; lcd_reg.DB6 = com.b2; lcd_reg.DB7 = com.b3; lcd_reg.EN = 1; I2C_PCF8574_WriteReg (lcd_reg); delay_us (300); lcd_reg.EN = 0; I2C_PCF8574_WriteReg (lcd_reg); delay_us (300); } void LCD_CHAR (unsigned char com) // (ASCII ) { lcd_reg = 0; lcd_reg.BL = BL_status.b0; lcd_reg.EN = 1; lcd_reg.RS = 1; // 1 RS lcd_reg.DB4 = com.b4; // 4 lcd_reg.DB5 = com.b5; lcd_reg.DB6 = com.b6; lcd_reg.DB7 = com.b7; I2C_PCF8574_WriteReg (lcd_reg); delay_us (300); lcd_reg.EN = 0; // . 0, I2C_PCF8574_WriteReg (lcd_reg); delay_us (300); lcd_reg = 0; lcd_reg.BL = BL_status.b0; lcd_reg.EN = 1; lcd_reg.RS = 1; lcd_reg.DB4 = com.b0; // 4 lcd_reg.DB5 = com.b1; lcd_reg.DB6 = com.b2; lcd_reg.DB7 = com.b3; I2C_PCF8574_WriteReg (lcd_reg); delay_us (300); lcd_reg.EN = 0; I2C_PCF8574_WriteReg (lcd_reg); delay_us (300); } void lcd_I2C_Init(void) { I2C1_Init_Advanced(400000, &_GPIO_MODULE_I2C1_PB67); // I2c delay_ms(200); lcd_Command(0x28); // 4 delay_ms (5); lcd_Command(0x08); // delay_ms (5); lcd_Command(0x01); // delay_ms (5); lcd_Command(0x06); // delay_ms (5); lcd_Command(0x0C); // delay_ms (25); } void lcd_I2C_txt(char *pnt) // { unsigned short int i; // char tmp_str[displenth + 1]; // , 1 , v NULL ASCII 0x00 strncpy(tmp_str, pnt, displenth); // displenth for (i=0; i<displenth; i++) { if (tmp_str[i] == 0) break; // NULL , і LCD_CHAR(tmp_str[i]); // } } void lcd_I2C_int(int pnt) // { char tmp_str[8]; // unsigned short i, j; IntToStr(pnt,tmp_str); // , 6 + NULL while (tmp_str[0]==32) { for (i=0; i<7; i++) { tmp_str[i]=tmp_str[i+1]; // (ASCII 32) tmp_str[6-j]=0; } j++; } lcd_I2C_txt (tmp_str); // } void lcd_I2C_Goto(unsigned short row, unsigned short col) // { col--; // 0, 1 switch (row) { case 1: lcd_Command(0x80 + col); // break; case 2: lcd_Command(0x80 + col + 0x40); break; case 3: lcd_Command(0x80 + col + 0x14); break; case 4: lcd_Command(0x80 + col + 0x54); break; } } void lcd_I2C_cls() // { lcd_Command(0x01); delay_ms (5); } void lcd_I2C_backlight (unsigned short int state) // { lcd_reg = 0; BL_status.b0 = state.b0; // , lcd_reg.BL = state.b0; I2C_PCF8574_WriteReg (lcd_reg); delay_ms (1); }
#include "i2c_lcd.h" // - unsigned int i; // void main() { lcd_I2C_Init(); // lcd_I2C_backlight (1); // lcd_I2C_txt ("Hellow habrahabr"); // while (1) { delay_ms(1000); lcd_I2C_Goto (2,1); // 1 2 lcd_i2c_int (i); // i++; // } }
In the next article, we will continue to deal with the i2c protocol and devices working with it. Consider working with EEPROM 24XX memory and MPU6050 accelerometer / gyroscope.
Source: https://habr.com/ru/post/322184/
All Articles