1

Тема: ATMEGA328 + LCD1602_I2C

#define ADDR    0x27
#define CPU_F   16000000  // тактовая частота микроконтроллера
#define SCL_F   400000    // частота шины I2C
#define RS      0
#define E       2
#define LED     3

byte led_b;

void setup() {
    TWBR = (((CPU_F)/(SCL_F)-16 )/2); // устанавливаем скорость шины
    TWSR = 0;
    i2c_write(led_b |= (1<<LED));// включаем подсветку
    lcdInit();
}

void loop() {
   
   lcdCurs(0,3);
   lcdString("LCD1602_I2C");
   lcdCurs(1,3);
   lcdLong(1234567890);
   delay(100);
   

}

void lcdSend(bool rs, byte data) {
    if(rs==0){led_b |= (1<<RS);} else {led_b &= ~(1<<RS);}//RS
    
    del();
    if(((data >> 7) & 1) ==1){i2c_write(led_b |= (1<<7));} else {i2c_write(led_b &= ~(1<<7));}
    if(((data >> 6) & 1) ==1){i2c_write(led_b |= (1<<6));} else {i2c_write(led_b &= ~(1<<6));}
    if(((data >> 5) & 1) ==1){i2c_write(led_b |= (1<<5));} else {i2c_write(led_b &= ~(1<<5));}
    if(((data >> 4) & 1) ==1){i2c_write(led_b |= (1<<4));} else {i2c_write(led_b &= ~(1<<4));}
    e_pin();
    if(((data >> 3) & 1) ==1){i2c_write(led_b |= (1<<7));} else {i2c_write(led_b &= ~(1<<7));}
    if(((data >> 2) & 1) ==1){i2c_write(led_b |= (1<<6));} else {i2c_write(led_b &= ~(1<<6));}
    if(((data >> 1) & 1) ==1){i2c_write(led_b |= (1<<5));} else {i2c_write(led_b &= ~(1<<5));}
    if(((data >> 0) & 1) ==1){i2c_write(led_b |= (1<<4));} else {i2c_write(led_b &= ~(1<<4));}
    e_pin();
}

void lcdInit(){ 
    delay(100);
    lcd(0x03);delayMicroseconds(4500);
    lcd(0x03);delayMicroseconds(4500);
    lcd(0x03);delayMicroseconds(200);
    
    lcd(0b00000010);del();
    lcd(0b00001100);del();
    lcdClear();
  } 

void lcdClear(){lcd(0b00000001);} 
void lcd(uint8_t cmd) {lcdSend(true, cmd);}
void lcdChar(const char chr) {lcdSend(false, (uint8_t)chr);}
void lcdString(const char* str) {while(*str != '\0') {del();lcdChar(*str);str++;}}
void del(){delay(1);}
void e_pin(){i2c_write(led_b |= (1<<E));del();i2c_write(led_b &= ~(1<<E));}



void lcdCurs(byte str, byte mesto){
  if(str==0){lcd(0b10000000+mesto);}
  if(str==1){lcd(0b11000000+mesto);}
  }  

void lcdLong(long int_x){
   byte h[8];
   long int_y=int_x;
   int i,i_kol;
  if(int_x<0){int_x=abs(int_x);lcdChar('-');}    // если минус
  for(i_kol=0;int_x>0;i_kol++){int_x=int_x/10;}  // определяем кол-во цифр в long
  for(i=0;i<i_kol;i++){h[i]=int_y%10; int_y=int_y/10;}// разбиваем число на отдельные цифры
  for(i=i_kol-1;i>=0;i--){lcdChar(h[i] +'0');} // преобразуем числа в char
  if(i_kol==0){lcdChar('0');} // если long = 0, то выводить ноль
  }  

void i2c_write(byte lcd){
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);  // START
  while (!(TWCR & (1<<TWINT))); // Ожидание установки флага TWINT. Это покажет, что START был передан.

  TWDR = ADDR << 1; //передаем адрес устройства
  TWCR = (1<<TWINT) | (1<<TWEN); //включим прием данных
  while (!(TWCR & (1<<TWINT))); // Ожидание установки флага TWINT. Это покажет, что SLA+W был передан, и будет принят ACK/NACK.

  TWDR = lcd;
  TWCR = (1<<TWINT) | (1<<TWEN); //включим прием данных
  while (!(TWCR & (1<<TWINT))); // Ожидание установки флага TWINT. Это покажет, что SLA+W был передан, и будет принят ACK/NACK.
  
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // СТОП
  }