1

Тема: ATTINY45

https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json

http://forum.rcl-radio.ru/uploads/images/2022/10/954150d071a865594bd456b2c328d8ad.png

http://forum.rcl-radio.ru/uploads/images/2022/10/c39833e0592d3a99288594413fc95b4b.png

http://forum.rcl-radio.ru/uploads/images/2022/10/f3cc35cfccc69c353316df3126cb7d54.png


http://forum.rcl-radio.ru/uploads/images/2022/10/eb6a8e25f195d23c08f5073d9e899083.jpg

2

Re: ATTINY45

BLINK

void setup() {
  pinMode(4, OUTPUT);
}

void loop() {
  digitalWrite(4, HIGH);  
  delay(1000);                     
  digitalWrite(4, LOW);   
  delay(1000);                    
}

3

Re: ATTINY45

LCD1602

http://forum.rcl-radio.ru/uploads/images/2022/10/11828ab7d5331382a715d9094e6cd79f.png

http://forum.rcl-radio.ru/uploads/images/2022/10/84a7ca23cae505dc3affb08e53461e3e.png


#define ADDR    0x27
#define SDA 3 // PB3
#define SCL 4 // PB4
#define RS      0
#define E       2
#define LED     3
 
byte led_b,h[8];
 
void setup() {
    i2c_write(led_b |= (1<<LED));// включаем подсветку
    lcdInit();
}
 
void loop() {
   lcdCurs(0,3);
   lcdString("ATtiny_45");
   lcdCurs(1,3);
   lcdLong(1234567890);  
}
 
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(){ 
    del();
    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(){delayMicroseconds(1000);}
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, то выводить ноль
  }  
 
bool i2c_read_bit() {
    bool i2c_bit = 1;        
    DDRB &= ~(1 << SDA);            
    delayMicroseconds(10); 
    DDRB &= ~(1 << SCL);                
    if((PINB >> SDA) & 1) i2c_bit=0;                            
    delayMicroseconds(10);  
    DDRB |= (1 << SCL);              
    return i2c_bit;  
}
 
byte i2c_write_byte(byte data){
    for (byte i=0; i<8; i++){i2c_write_bit((data&0x80)==0);data<<=1;}    
    return i2c_read_bit(); 
}
 
void i2c_write_bit(byte b){
    delayMicroseconds(5);
    if(b){DDRB |= (1 << SDA);}else{DDRB &= ~(1 << SDA);}
    delayMicroseconds(5);
    DDRB &= ~(1 << SCL);       
    delayMicroseconds(10);
    DDRB |= (1 << SCL);
}
 
void i2c_start(){
     delayMicroseconds(10);  
     DDRB &= ~(1 << SDA); DDRB &= ~(1 << SCL); 
     delayMicroseconds(10); 
     DDRB |= (1 << SDA);  PORTB &= ~(1 << SDA);
     delayMicroseconds(10); 
     DDRB |= (1 << SCL);  PORTB &= ~(1 << SCL);   
     delayMicroseconds(10);
}
 
void i2c_stop()  {
     DDRB |= (1 << SDA);            
     delayMicroseconds(10);
     DDRB &= ~(1 << SCL);               
     delayMicroseconds(10); 
     DDRB &= ~(1 << SDA);             
}
 
void i2c_write(byte lcd){
     i2c_start();
     i2c_write_byte(ADDR<<1);
     i2c_write_byte(lcd);
     i2c_stop();
  }

Скетч использует 1040 байт (25%) памяти устройства. Всего доступно 4096 байт.
Глобальные переменные используют 20 байт (7%) динамической памяти, оставляя 236 байт для локальных переменных. Максимум: 256 байт.

4

Re: ATTINY45

ЧАСЫ ATTINY45+DS3231 С КНОПКАМИ КОРРЕКЦИИ ВРЕМЕНИ
http://forum.rcl-radio.ru/uploads/images/2022/10/3b72447988168ce8a584588e29f88711.png


#define ADDR    0x27
#define ADDR_T  0x68
#define SDA 3 // PB3
#define SCL 4 // PB4
#define SET 0 // PB0
#define UP  1 // PB1
#define DW  2 // PB2
#define RS      0
#define E       2
#define LED     3

byte led_b,init_t;
int seting,tic;
int hh,mm,ss,dd,mon,yy;



void setup() {
    lcdInit();
    i2c_write(led_b |= (1<<LED));// включаем подсветку
    /// set_time(22,3,9,4,9,54,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59
    PORTB |= (1 << UP) | (1 << DW) | (1 << SET);
    delay(500);
}

void loop() {
   byte sec =  (ds_read(0) & 0x0F) + (((ds_read(0) & 0x70) >> 4) * 10);
   byte min =  (ds_read(1) & 0x0F) + (((ds_read(1) & 0x70) >> 4) * 10);
   byte hour = ((ds_read(2) & 0x0F) + ((ds_read(2) & 0x70) >> 4) * 10);
   byte datat = ((ds_read(4) & 0x0F) + ((ds_read(4) & 0x70) >> 4) * 10);
   byte mont = ((ds_read(5) & 0x0F) + ((ds_read(5) & 0x70) >> 4) * 10);
   byte year = ((ds_read(6) & 0x0F) + ((ds_read(6) & 0x70) >> 4) * 10);
   hh=hour;mm=min;ss=sec;dd=datat;mon=mont;yy=year;
   if(((PINB >> SET) & 1) == 0){seting++;if(seting>6){seting=0;}}   

   if(seting>0){tic++;if(tic>1){tic=0;}}

   if(seting>0){
    if(((PINB >> UP) & 1) == 0){
     switch(seting){
      case 1:  hh++;if(hh>23){hh=23;}break;
      case 2:  mm++;if(mm>59){mm=59;}break;
      case 3:  ss=0;break;
      case 4:  dd++;if(dd>31){dd=31;}break;
      case 5:  mon++;if(mon>12){mon=12;}break;
      case 6:  yy++;if(yy>50){yy=50;}break;
      }
    set_time(yy,0,mon,dd,hh,mm,ss);  
    }
    if(((PINB >> DW) & 1) == 0){
     switch(seting){
      case 1:  hh--;if(hh<0){hh=0;}break;
      case 2:  mm--;if(mm<0){mm=0;}break;
      case 3:  ss=0;break;
      case 4:  dd--;if(dd<1){dd=1;}break;
      case 5:  mon--;if(mon<1){mon=1;}break;
      case 6:  yy--;if(yy<22){yy=22;}break;
      }
    set_time(yy,0,mon,dd,hh,mm,ss);  
    }  
    }
   
   lcdCurs(0,4);
   lcdChar(hour/10+'0');lcdChar(hour%10+'0');
   if(seting==1&&tic==1){lcdCurs(0,4);lcdChar(160);lcdChar(160);}lcdChar(58);
   lcdChar(min/10+'0');lcdChar(min%10+'0');
   if(seting==2&&tic==1){lcdCurs(0,7);lcdChar(160);lcdChar(160);}lcdChar(58);
   lcdChar(sec/10+'0');lcdChar(sec%10+'0');
   if(seting==3&&tic==1){lcdCurs(0,10);lcdChar(160);lcdChar(160);}
   lcdCurs(1,4); 
   lcdChar(datat/10+'0');lcdChar(datat%10+'0');
   if(seting==4&&tic==1){lcdCurs(1,4);lcdChar(160);lcdChar(160);}lcdChar(45);
   lcdChar(mont/10+'0');lcdChar(mont%10+'0');
   if(seting==5&&tic==1){lcdCurs(1,7);lcdChar(160);lcdChar(160);}lcdChar(45);
   lcdChar(year/10+'0');lcdChar(year%10+'0');
   if(seting==6&&tic==1){lcdCurs(1,10);lcdChar(160);lcdChar(160);}
   delay(200);
}

void lcdSend(bool rs, byte data) {
    if(rs==0){led_b |= (1<<RS);} else {led_b &= ~(1<<RS);}//RS
    
    delay(1);
    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(){ 
    lcd(0x03);delay(5);
    lcd(0x03);delay(5);
    lcd(0x03);delayMicroseconds(200);
    lcd(0b00000010);delay(5);
    lcd(0b00001100);delay(5);
    lcdClear();
  } 

void lcdClear(){lcd(0b00000001);} 
void lcd(uint8_t sett) {lcdSend(true, sett);}
void lcdChar(const char chr) {lcdSend(false, (uint8_t)chr);}
void e_pin(){i2c_write(led_b |= (1<<E));delay(1);i2c_write(led_b &= ~(1<<E));}


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

///// i2c /////////////

bool i2c_read_bit() {
    bool i2c_bit = 1;        
    DDRB &= ~(1 << SDA);            
  //  delayMicroseconds(10); 
    DDRB &= ~(1 << SCL);                
    if((PINB >> SDA) & 1) i2c_bit=0;                            
  //  delayMicroseconds(10);  
    DDRB |= (1 << SCL);              
    return i2c_bit;  
}
 
byte i2c_write_byte(byte data){
    for (byte i=0; i<8; i++){i2c_write_bit((data&0x80)==0);data<<=1;}    
    return i2c_read_bit(); 
}

byte i2c_read_byte(byte a){
    byte i, data=0;                
    for(i=0; i<8; i++){if (!i2c_read_bit()) data++;if(i!=7) data<<=1;}        
    i2c_write_bit(a);return data;  
}
 
void i2c_write_bit(byte b){
    delayMicroseconds(5);
    if(b){DDRB |= (1 << SDA);}else{DDRB &= ~(1 << SDA);}
    delayMicroseconds(5);
    DDRB &= ~(1 << SCL);       
    delayMicroseconds(10);
    DDRB |= (1 << SCL);
}
 
void i2c_start(){
     DDRB &= ~(1 << SDA); DDRB &= ~(1 << SCL);
     DDRB |= (1 << SDA);  PORTB &= ~(1 << SDA);
     DDRB |= (1 << SCL);  PORTB &= ~(1 << SCL);
}
 
void i2c_stop()  {
     DDRB |= (1 << SDA);           
     DDRB &= ~(1 << SCL);            
     DDRB &= ~(1 << SDA);           
}
 
void i2c_write(byte lcd){
     i2c_start();
     i2c_write_byte(ADDR<<1);
     i2c_write_byte(lcd);
     i2c_stop();
  }   

void ds_write(byte reg, byte data){
     i2c_start();
     i2c_write_byte(ADDR_T<<1);
     i2c_write_byte(reg);
     i2c_write_byte(data);
     i2c_stop();
  }  
  
byte ds_read(byte reg){
     byte dat=0;
     i2c_start();
     i2c_write_byte(ADDR_T<<1);
     i2c_write_byte(reg);
     i2c_start(); 
     i2c_write_byte((ADDR_T<<1)|1); 
     dat = i2c_read_byte(0);
     i2c_stop();
     return dat;
  }

void set_time(byte years, byte days, byte monts, byte datas, byte hours ,byte minute, byte second){
  if(second>=0){ds_write(0x00,(second/10<<4)+second%10);}
  if(minute>=0){ds_write(0x01,(minute/10<<4)+minute%10);}
  if(hours>=0){ds_write(0x02,(hours/10<<4)+hours%10);}
  if(days>=0){ds_write(0x03,days);}
  if(datas>=0){ds_write(0x04,(datas/10<<4)+datas%10);}
  if(monts>=0){ds_write(0x05,(monts/10<<4)+monts%10);}
  if(years>=0){ds_write(0x06,(years/10<<4)+years%10);}
  }  

5

Re: ATTINY45

ПРОСТОЕ РЕЛЕ ВРЕМЕНИ 0...99 МИН

Кнопками (+/-) можно задавать время от 1 до 99 минут, при установки времени таймера сразу же активируется реле, при обнулении таймера реле отключает нагрузку.

http://forum.rcl-radio.ru/uploads/images/2022/10/263dcdf931f3828793e6b75567ef1139.png


#define CLK  PB1 // TM1637
#define DIO  PB0 // TM1637
#define UP   PB3 // BUTTON +++
#define DOWN PB4 // BUTTON ---
#define OUT  PB2 // RELAY
 
char i,tic;
bool w,w1=0,cl;
unsigned long times;
 
void setup(){
  DDRB |= (1 << OUT);
  PORTB &= ~(1 << OUT);
  PORTB |= (1 << UP) | (1 << DOWN);
}
 
void loop(){
   cl=0;
   if(((PINB >> UP) & 1) == 0){i++;if(i>99){i=99;}cl=1;}
   if(((PINB >> DOWN) & 1) == 0){i--;if(i<0){i=0;tic=0;}cl=1;}
 
   if(i>0 || (i==0 && tic>0)){PORTB |= (1 << OUT);w=1;w1=1;}
    else{PORTB &= ~(1 << OUT);w=0;w1=0;}
 
   if(w==1&&cl==0){
    if(millis()-times>999){times=millis();tic--;}
     if(tic<0){tic=59;i--;}
    }  
   tm_print(i*100+tic,w1,5);      
}// end loop
 
void tm_dec(byte dig){
       for(byte i = 0; i < 8; i++) {
         DDRB |= (1 << CLK);del();
       if (dig & 0x01)
         DDRB &= ~(1 << DIO);
       else
         DDRB |= (1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
         dig = dig >> 1;
  }
         DDRB |= (1 << CLK);
         DDRB &= ~(1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
 
       if (((PINB >> DIO) & 1) == 0)
         DDRB |= (1 << DIO);del();
         DDRB |= (1 << CLK);del();
  }  
 
void tm_stop(){
         DDRB |= (1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
         DDRB &= ~(1 << DIO);del();
  }  
 
void tm_start(){
         DDRB |= (1 << DIO);del();
  }
 
void tm_print(int t, bool pd_t, byte br){
        tm_start();tm_dec(0b10001000 + br);
        tm_dec(0x40);tm_stop();tm_start();
 
        int data0 = t / 1000;
        int data1 = t / 100 % 10;
        int data2 = t / 10 % 10;
        int data3 = t % 10;
 
      for(byte n = 0; n < 4; n++){
        int data;
      switch(n){
        case 0: data = data0;break;
        case 1: data = data1;break;
        case 2: data = data2;break;
        case 3: data = data3;break;
        }  
 
      switch(data){    // XGFEDCBA
        case 0:  data = 0b00111111;break;     // 0
        case 1:  data = 0b00000110;break;     // 1
        case 2:  data = 0b01011011;break;     // 2
        case 3:  data = 0b01001111;break;     // 3
        case 4:  data = 0b01100110;break;     // 4
        case 5:  data = 0b01101101;break;     // 5
        case 6:  data = 0b01111101;break;     // 6
        case 7:  data = 0b00000111;break;     // 7
        case 8:  data = 0b01111111;break;     // 8
        case 9:  data = 0b01101111;break;     // 9
        }
        if(n == 0){data0 = data;}
        if(n == 1){data1 = data;}
        if(n == 2){data2 = data;}
        if(n == 3){data3 = data;}
        }
      if(pd_t==1){data1 = data1+0b10000000;}
      tm_dec(0xC0);tm_dec(data0);tm_dec(data1);tm_dec(data2);tm_dec(data3);tm_stop();
}  
 
void del(){delay(1);}

6

Re: ATTINY45

DHT11 ДАТЧИК ТЕМПЕРАТУРЫ И ВЛАЖНОСТИ

http://forum.rcl-radio.ru/uploads/images/2022/10/7bff58d93fb70cc833fad3547528b550.png
http://forum.rcl-radio.ru/uploads/images/2022/10/cf0779bcd0facbe008b656af16852f1b.png

// DHT11
#define DHT PB2
// TM1637
#define DIO PB1
#define CLK PB0

byte data_dht[5];
 
void setup(){}  
 
void loop() {
  dht_read(); 
  delay(3000);
  print_time(data_dht[2],0,7,1);
  delay(3000);
  print_time(data_dht[0],0,7,0);
}
 
void tm_dec(byte dig){
       for(byte i = 0; i < 8; i++) {
         DDRB |= (1 << CLK);del();
       if (dig & 0x01)
         DDRB &= ~(1 << DIO);
       else
         DDRB |= (1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
         dig = dig >> 1;
  }
         DDRB |= (1 << CLK);
         DDRB &= ~(1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
 
       if (((PINB >> DIO) & 1) == 0)
         DDRB |= (1 << DIO);del();
         DDRB |= (1 << CLK);del();
  }  
 
void tm_stop(){
         DDRB |= (1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
         DDRB &= ~(1 << DIO);del();
  }  
 
void tm_start(){
         DDRB |= (1 << DIO);del();
  }
 
void print_time(int t, byte pd_t, int br, bool mn){
        tm_start();tm_dec(0b10001000 + br);//tm_stop();tm_start();
        tm_dec(0x40);tm_stop();tm_start();
 
        int data0;
        if(mn == 1){data0 = 11;}else{data0 = 12;}
        int data1 = 10;
        int data2 = t / 10 % 10;
        int data3 = t % 10;
 
      for(byte n = 0; n < 4; n++){
        int data;
      switch(n){
        case 0: data = data0;break;
        case 1: data = data1;break;
        case 2: data = data2;break;
        case 3: data = data3;break;
        }
 
      switch(data){    // XGFEDCBA
        case 0:  data = 0b00111111;break;     // 0
        case 1:  data = 0b00000110;break;     // 1
        case 2:  data = 0b01011011;break;     // 2
        case 3:  data = 0b01001111;break;     // 3
        case 4:  data = 0b01100110;break;     // 4
        case 5:  data = 0b01101101;break;     // 5
        case 6:  data = 0b01111101;break;     // 6
        case 7:  data = 0b00000111;break;     // 7
        case 8:  data = 0b01111111;break;     // 8
        case 9:  data = 0b01101111;break;     // 9
        case 10: data = 0b00000000;break;     // пусто
        case 11: data = 0b01111000;break;     // t
        case 12: data = 0b01110110;break;     // H
        }
 
        if(n == 0){data0 = data;}
        if(n == 1){data1 = data;}
        if(n == 2){data2 = data;}
        if(n == 3){data3 = data;}
        }
      switch(pd_t){
        case 1 : data2 = data2+0b10000000;break;
        case 2 : data1 = data1+0b10000000;break;
        case 3 : data0 = data0+0b10000000;break;
        }
      tm_dec(0xC0);tm_dec(data0);tm_dec(data1);tm_dec(data2);tm_dec(data3);tm_stop();
}  
 
void del(){delayMicroseconds(200);}
 
int dht_read(){
        byte i = 0,i1 = 0;  
        for(i = 0;i < 5;i++){data_dht[i] = 0;}                  
        DDRB |=(1 << DHT); 
        PORTB &= ~(1 << DHT); 
        delay(18); 
        PORTB |= (1 << DHT);
        delayMicroseconds(40); 
        DDRB &= ~(1 << DHT); 
        delayMicroseconds(80); 
    while(PINB & (1 << DHT));
      for (i = 0; i < 5; i++){
        data_dht[i]=0;
      for (i1=0; i1<8; i1++){
    while(!(PINB & (1 << DHT)));  
        delayMicroseconds(30);
      if (PINB & (1 << DHT)){data_dht[i] |= 1 << (7-i1);}
    while(PINB & (1 << DHT));  
}}return 1;}

7

Re: ATTINY45

ВОЛЬТМЕТР 0...5В

0V
http://forum.rcl-radio.ru/uploads/images/2022/10/3b0b88ee890193be40d2cfe8651a6c89.png
1.8V
http://forum.rcl-radio.ru/uploads/images/2022/10/012c1d360170534558afbdb8c29255b1.png
3.3V
http://forum.rcl-radio.ru/uploads/images/2022/10/ef5d490b3701f8ed5363cb9e8c23bff6.png

#define VCC 5090.00 // mB
// TM1637
#define DIO PB1
#define CLK PB0

byte data_dht[5];
int u;
 
void setup(){
  pinMode(A3,INPUT);
  }  
 
void loop() {
  u=0;
  for(int n=0;n<10;n++){u += analogRead(A3);delay(100);}
  u=u/10;
  print_time(VCC/1023.00/10*u,2,7);
}
 
void tm_dec(byte dig){
       for(byte i = 0; i < 8; i++) {
         DDRB |= (1 << CLK);del();
       if (dig & 0x01)
         DDRB &= ~(1 << DIO);
       else
         DDRB |= (1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
         dig = dig >> 1;
  }
         DDRB |= (1 << CLK);
         DDRB &= ~(1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
 
       if (((PINB >> DIO) & 1) == 0)
         DDRB |= (1 << DIO);del();
         DDRB |= (1 << CLK);del();
  }  
 
void tm_stop(){
         DDRB |= (1 << DIO);del();
         DDRB &= ~(1 << CLK);del();
         DDRB &= ~(1 << DIO);del();
  }  
 
void tm_start(){
         DDRB |= (1 << DIO);del();
  }
 
void print_time(int t, byte pd_t, int br){
        tm_start();tm_dec(0b10001000 + br);//tm_stop();tm_start();
        tm_dec(0x40);tm_stop();tm_start();
 
        int data0 = 11;
        int data1 = t/100%10;
        int data2 = t/10%10;
        int data3 = t%10;
 
      for(byte n = 0; n < 4; n++){
        int data;
      switch(n){
        case 0: data = data0;break;
        case 1: data = data1;break;
        case 2: data = data2;break;
        case 3: data = data3;break;
        }
 
      switch(data){    // XGFEDCBA
        case 0:  data = 0b00111111;break;     // 0
        case 1:  data = 0b00000110;break;     // 1
        case 2:  data = 0b01011011;break;     // 2
        case 3:  data = 0b01001111;break;     // 3
        case 4:  data = 0b01100110;break;     // 4
        case 5:  data = 0b01101101;break;     // 5
        case 6:  data = 0b01111101;break;     // 6
        case 7:  data = 0b00000111;break;     // 7
        case 8:  data = 0b01111111;break;     // 8
        case 9:  data = 0b01101111;break;     // 9
        case 10: data = 0b00000000;break;     // пусто
        case 11: data = 0b00111110;break;     // u
        }
 
        if(n == 0){data0 = data;}
        if(n == 1){data1 = data;}
        if(n == 2){data2 = data;}
        if(n == 3){data3 = data;}
        }
      switch(pd_t){
        case 1 : data2 = data2+0b10000000;break;
        case 2 : data1 = data1+0b10000000;break;
        case 3 : data0 = data0+0b10000000;break;
        }
      tm_dec(0xC0);tm_dec(data0);tm_dec(data1);tm_dec(data2);tm_dec(data3);tm_stop();
}  
 
void del(){delayMicroseconds(200);}
 

8

Re: ATTINY45

#define I2C_SDA         PB3                  
#define I2C_SCL         PB4    
#define OLED_ADDR       0x78  // OLED write address       

#include <avr/io.h>
#include <util/delay.h>

const char Message1[] PROGMEM = "RCL-RADIO.RU";
const char Message2[] PROGMEM = "OLED 0.96";
const char Message3[] PROGMEM = "SSD1306";
const char Message4[] PROGMEM = "LINE ";
const char Message5[] PROGMEM = "---------------------";
int n;

int main(void) {
  _delay_ms(200);
  OLED_init();
  OLED_clear();                         

  while(1) {                                                  
  //  OLED_clear();                       
    OLED_cursor(0, 0);                
    OLED_printP(Message1);  
    OLED_cursor(0, 1);                
    OLED_printP(Message2);  
    OLED_cursor(0, 2);                
    OLED_printP(Message3);               
    OLED_cursor(0, 3);
    OLED_printP(Message5);
    OLED_cursor(0, 4);
    OLED_printP(Message4);OLED_num(5);
    OLED_cursor(0, 5);
    OLED_printP(Message4);OLED_num(6);
    OLED_cursor(0, 6);
    OLED_printP(Message4);OLED_num(7);
    OLED_cursor(0, 7);
    OLED_printP(Message4);OLED_num(8);
    
    n++;
    if(n>50){n=0;}
    OLED_cursor(70, 7);
    OLED_num(n/10);OLED_num(n%10);
    _delay_ms(100);                      
   
  }
}


#define I2C_SDA_HIGH()  DDRB &= ~(1<<I2C_SDA)
#define I2C_SDA_LOW()   DDRB |=  (1<<I2C_SDA) 
#define I2C_SCL_HIGH()  DDRB &= ~(1<<I2C_SCL) 
#define I2C_SCL_LOW()   DDRB |=  (1<<I2C_SCL) 
#define OLED_CMD_MODE   0x00                  
#define OLED_DAT_MODE   0x40  
const uint8_t OLED_INIT_CMD[] PROGMEM = {0xA8, 0x3F, 0x8D, 0x14, 0xAF, 0xA1, 0xC8};
                
void I2C_init(void) {
  DDRB  &= ~((1<<I2C_SDA)|(1<<I2C_SCL)); 
  PORTB &= ~((1<<I2C_SDA)|(1<<I2C_SCL)); 
}

void I2C_write(uint8_t data) {
  for(uint8_t i = 8; i; i--) {           
    I2C_SDA_LOW();                       
    if (data & 0x80) I2C_SDA_HIGH();   
    I2C_SCL_HIGH();                      
    data<<=1;                             
    I2C_SCL_LOW();                       
  }
  I2C_SDA_HIGH();                        
  I2C_SCL_HIGH();   
  asm("nop");           
  I2C_SCL_LOW();     
}

// I2C start transmission
void I2C_start(uint8_t addr) {
  I2C_SDA_LOW();                          // start condition: SDA goes LOW first
  I2C_SCL_LOW();                          // start condition: SCL goes LOW second
  I2C_write(addr);                        // send slave address
}

// I2C stop transmission
void I2C_stop(void) {
  I2C_SDA_LOW();                          // prepare SDA for LOW to HIGH transition
  I2C_SCL_HIGH();                         // stop condition: SCL goes HIGH first
  I2C_SDA_HIGH();                         // stop condition: SDA goes HIGH second
}


// Standard ASCII 5x8 font (adapted from Neven Boyanov and Stephen Denne)
const uint8_t OLED_FONT[] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, //   0 
  0x00, 0x00, 0x2f, 0x00, 0x00, // ! 1 
  0x00, 0x07, 0x00, 0x07, 0x00, // " 2 
  0x14, 0x7f, 0x14, 0x7f, 0x14, // # 3 
  0x24, 0x2a, 0x7f, 0x2a, 0x12, // $ 4 
  0x62, 0x64, 0x08, 0x13, 0x23, // % 5 
  0x36, 0x49, 0x55, 0x22, 0x50, // & 6 
  0x00, 0x05, 0x03, 0x00, 0x00, // ' 7 
  0x00, 0x1c, 0x22, 0x41, 0x00, // ( 8 
  0x00, 0x41, 0x22, 0x1c, 0x00, // ) 9 
  0x14, 0x08, 0x3E, 0x08, 0x14, // * 10
  0x08, 0x08, 0x3E, 0x08, 0x08, // + 11
  0x00, 0x00, 0xA0, 0x60, 0x00, // , 12
  0x08, 0x08, 0x08, 0x08, 0x08, // - 13
  0x00, 0x60, 0x60, 0x00, 0x00, // . 14
  0x20, 0x10, 0x08, 0x04, 0x02, // / 15
  0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 16
  0x00, 0x42, 0x7F, 0x40, 0x00, // 1 17
  0x42, 0x61, 0x51, 0x49, 0x46, // 2 18
  0x21, 0x41, 0x45, 0x4B, 0x31, // 3 19
  0x18, 0x14, 0x12, 0x7F, 0x10, // 4 20
  0x27, 0x45, 0x45, 0x45, 0x39, // 5 21
  0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 22
  0x01, 0x71, 0x09, 0x05, 0x03, // 7 23
  0x36, 0x49, 0x49, 0x49, 0x36, // 8 24
  0x06, 0x49, 0x49, 0x29, 0x1E, // 9 25
  0x00, 0x36, 0x36, 0x00, 0x00, // : 26
  0x00, 0x56, 0x36, 0x00, 0x00, // ; 27
  0x08, 0x14, 0x22, 0x41, 0x00, // < 28
  0x14, 0x14, 0x14, 0x14, 0x14, // = 29
  0x00, 0x41, 0x22, 0x14, 0x08, // > 30
  0x02, 0x01, 0x51, 0x09, 0x06, // ? 31
  0x32, 0x49, 0x59, 0x51, 0x3E, // @ 32
  0x7C, 0x12, 0x11, 0x12, 0x7C, // A 33
  0x7F, 0x49, 0x49, 0x49, 0x36, // B 34
  0x3E, 0x41, 0x41, 0x41, 0x22, // C 35
  0x7F, 0x41, 0x41, 0x22, 0x1C, // D 36
  0x7F, 0x49, 0x49, 0x49, 0x41, // E 37
  0x7F, 0x09, 0x09, 0x09, 0x01, // F 38
  0x3E, 0x41, 0x49, 0x49, 0x7A, // G 39
  0x7F, 0x08, 0x08, 0x08, 0x7F, // H 40
  0x00, 0x41, 0x7F, 0x41, 0x00, // I 41
  0x20, 0x40, 0x41, 0x3F, 0x01, // J 42
  0x7F, 0x08, 0x14, 0x22, 0x41, // K 43
  0x7F, 0x40, 0x40, 0x40, 0x40, // L 44
  0x7F, 0x02, 0x0C, 0x02, 0x7F, // M 45
  0x7F, 0x04, 0x08, 0x10, 0x7F, // N 46
  0x3E, 0x41, 0x41, 0x41, 0x3E, // O 47
  0x7F, 0x09, 0x09, 0x09, 0x06, // P 48
  0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 49
  0x7F, 0x09, 0x19, 0x29, 0x46, // R 50
  0x46, 0x49, 0x49, 0x49, 0x31, // S 51
  0x01, 0x01, 0x7F, 0x01, 0x01, // T 52
  0x3F, 0x40, 0x40, 0x40, 0x3F, // U 53
  0x1F, 0x20, 0x40, 0x20, 0x1F, // V 54
  0x3F, 0x40, 0x38, 0x40, 0x3F, // W 55
  0x63, 0x14, 0x08, 0x14, 0x63, // X 56
  0x07, 0x08, 0x70, 0x08, 0x07, // Y 57
  0x61, 0x51, 0x49, 0x45, 0x43, // Z 58
  0x00, 0x7F, 0x41, 0x41, 0x00, // [ 59
  0x02, 0x04, 0x08, 0x10, 0x20, // \ 60
  0x00, 0x41, 0x41, 0x7F, 0x00, // ] 61
  0x04, 0x02, 0x01, 0x02, 0x04, // ^ 62
  0x40, 0x40, 0x40, 0x40, 0x40  // _ 63
};

void OLED_init(void) {
  I2C_init();                             
  I2C_start(OLED_ADDR);                   
  I2C_write(OLED_CMD_MODE);               
  for (uint8_t i = 0; i < 7; i++) I2C_write(pgm_read_byte(&OLED_INIT_CMD[i])); 
  I2C_stop();                            
}

void OLED_printC(char ch) {
  uint16_t offset = ch - 32;             
  offset += offset << 2;                
  I2C_write(0x00);        
  for(uint8_t i=5; i; i--) I2C_write(pgm_read_byte(&OLED_FONT[offset++])); 
}

void OLED_printP(const char* p) {
  I2C_start(OLED_ADDR);                  
  I2C_write(OLED_DAT_MODE);               
  char ch = pgm_read_byte(p);             
  while (ch != 0){OLED_printC(ch);ch = pgm_read_byte(++p);}
  I2C_stop();       
}

void OLED_num(byte num){
  I2C_start(OLED_ADDR);                 
  I2C_write(OLED_DAT_MODE);    
  OLED_printC(num+48); 
  I2C_stop();    
  }

void OLED_cursor(uint8_t xpos, uint8_t ypos) {
  I2C_start(OLED_ADDR);                   
  I2C_write(OLED_CMD_MODE);               
  I2C_write(xpos & 0x0F);                 
  I2C_write(0x10 | (xpos >> 4));     
  I2C_write(0xB0 | (ypos & 0x07));    
  I2C_stop();                           
}

void OLED_clear(void) {
  for (uint8_t i = 0; i < 8; i++) {   // clear screen line by line
    OLED_cursor(0, i);
    I2C_start(OLED_ADDR);                   // start transmission to OLED
    I2C_write(OLED_DAT_MODE);               // set data mode
    for(uint8_t i=128; i; i--) I2C_write(0x00);
    I2C_stop();                             // stop transmission
  }
  }

9

Re: ATTINY45

http://forum.rcl-radio.ru/uploads/images/2022/10/9eed620c709e4520dbdc3133fed17854.png


#include <avr/io.h>
#include <util/delay.h>
 
// Project Files (Github):  https://github.com/wagiminator/ATtiny13-TinyOLEDdemo
// License: http://creativecommons.org/licenses/by-sa/3.0/
 
#define I2C_SDA         PB3                   
#define I2C_SCL         PB4                  
 
#define I2C_SDA_HIGH()  DDRB &= ~(1<<I2C_SDA) 
#define I2C_SDA_LOW()   DDRB |=  (1<<I2C_SDA) 
#define I2C_SCL_HIGH()  DDRB &= ~(1<<I2C_SCL) 
#define I2C_SCL_LOW()   DDRB |=  (1<<I2C_SCL) 
 
const char Message1[] PROGMEM = "RCL-RADIO.RU";
const char Message2[] PROGMEM = "OLED 0.91 / 128x32";
const char Message3[] PROGMEM = "SSD1306";
const char Message4[] PROGMEM = "Line 4";
int n;
 
int main(void) {
  OLED_init();
  OLED_brig(150);// 0...255
  OLED_inver(0); // invers                           
  OLED_clear(); 
 
  while(1) { 
OLED_cursor(0, 0);                
    OLED_printP(Message1); 
    OLED_cursor(0, 1);                
    OLED_printP(Message2);  
    OLED_cursor(0, 2);                
    OLED_printP(Message3);               
    OLED_cursor(0, 3);
    OLED_printP(Message4);                   
        n++;
    if(n>50){n=0;}
    OLED_cursor(70, 3);
    OLED_num(n/10);OLED_num(n%10);
    _delay_ms(100);                      
}}
 
///// I2C ///////////////////////////////////////////////////////
void I2C_init(void) {DDRB  &= ~((1<<I2C_SDA)|(1<<I2C_SCL)); PORTB &= ~((1<<I2C_SDA)|(1<<I2C_SCL));}
void I2C_write(uint8_t data) {
  for(uint8_t i = 8; i; i--) {I2C_SDA_LOW();                        
    if (data & 0x80) I2C_SDA_HIGH();I2C_SCL_HIGH();data<<=1;I2C_SCL_LOW();}
  I2C_SDA_HIGH();I2C_SCL_HIGH();asm("nop");I2C_SCL_LOW();                         
}
void I2C_start(uint8_t addr) {I2C_SDA_LOW();I2C_SCL_LOW();I2C_write(addr);}
void I2C_stop(void) {I2C_SDA_LOW();I2C_SCL_HIGH();I2C_SDA_HIGH();}
 
///// OLED ///////////////////////////////////
#define OLED_ADDR       0x78                  
#define OLED_CMD_MODE   0x00                  
#define OLED_DAT_MODE   0x40                  
#define OLED_INIT_LEN   12                 
 
const uint8_t OLED_INIT_CMD[] PROGMEM = {0xA8,0x1F,0x22,0x00,0x03,0x20,0x00,0xDA,0x02,0x8D,0x14,0xAF,0xA1,0xC8};
const uint8_t OLED_FONT[] PROGMEM = {
   0x00, 0x00, 0x00, 0x00, 0x00, // sp
   0x00, 0x00, 0x5F, 0x00, 0x00, // !
   0x00, 0x03, 0x00, 0x03, 0x00, // "
   0x14, 0x3E, 0x14, 0x3E, 0x14, // #
   0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
   0x43, 0x33, 0x08, 0x66, 0x61, // %
   0x36, 0x49, 0x55, 0x22, 0x50, // &
   0x00, 0x05, 0x03, 0x00, 0x00, // '
   0x00, 0x1C, 0x22, 0x41, 0x00, // (
   0x00, 0x41, 0x22, 0x1C, 0x00, // )
   0x14, 0x08, 0x3E, 0x08, 0x14, // *
   0x08, 0x08, 0x3E, 0x08, 0x08, // +
   0x00, 0x50, 0x30, 0x00, 0x00, // ,
   0x08, 0x08, 0x08, 0x08, 0x08, // -
   0x00, 0x60, 0x60, 0x00, 0x00, // .
   0x20, 0x10, 0x08, 0x04, 0x02, // /
   0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
   0x00, 0x04, 0x02, 0x7F, 0x00, // 1
   0x42, 0x61, 0x51, 0x49, 0x46, // 2
   0x22, 0x41, 0x49, 0x49, 0x36, // 3
   0x18, 0x14, 0x12, 0x7F, 0x10, // 4
   0x27, 0x45, 0x45, 0x45, 0x39, // 5
   0x3E, 0x49, 0x49, 0x49, 0x32, // 6
   0x01, 0x01, 0x71, 0x09, 0x07, // 7
   0x36, 0x49, 0x49, 0x49, 0x36, // 8
   0x26, 0x49, 0x49, 0x49, 0x3E, // 9
   0x00, 0x36, 0x36, 0x00, 0x00, // :
   0x00, 0x56, 0x36, 0x00, 0x00, // ;
   0x08, 0x14, 0x22, 0x41, 0x00, // <
   0x14, 0x14, 0x14, 0x14, 0x14, // =
   0x00, 0x41, 0x22, 0x14, 0x08, // >
   0x02, 0x01, 0x51, 0x09, 0x06, // ?
   0x3E, 0x41, 0x59, 0x55, 0x5E, // @
   0x7E, 0x09, 0x09, 0x09, 0x7E, // A
   0x7F, 0x49, 0x49, 0x49, 0x36, // B
   0x3E, 0x41, 0x41, 0x41, 0x22, // C
   0x7F, 0x41, 0x41, 0x41, 0x3E, // D
   0x7F, 0x49, 0x49, 0x49, 0x41, // E
   0x7F, 0x09, 0x09, 0x09, 0x01, // F
   0x3E, 0x41, 0x41, 0x49, 0x3A, // G
   0x7F, 0x08, 0x08, 0x08, 0x7F, // H
   0x00, 0x41, 0x7F, 0x41, 0x00, // I
   0x30, 0x40, 0x40, 0x40, 0x3F, // J
   0x7F, 0x08, 0x14, 0x22, 0x41, // K
   0x7F, 0x40, 0x40, 0x40, 0x40, // L
   0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
   0x7F, 0x02, 0x04, 0x08, 0x7F, // N
   0x3E, 0x41, 0x41, 0x41, 0x3E, // O
   0x7F, 0x09, 0x09, 0x09, 0x06, // P
   0x1E, 0x21, 0x21, 0x21, 0x5E, // Q
   0x7F, 0x09, 0x09, 0x09, 0x76, // R
   0x26, 0x49, 0x49, 0x49, 0x32, // S
   0x01, 0x01, 0x7F, 0x01, 0x01, // T
   0x3F, 0x40, 0x40, 0x40, 0x3F, // U
   0x1F, 0x20, 0x40, 0x20, 0x1F, // V
   0x7F, 0x20, 0x10, 0x20, 0x7F, // W
   0x41, 0x22, 0x1C, 0x22, 0x41, // X
   0x07, 0x08, 0x70, 0x08, 0x07, // Y
   0x61, 0x51, 0x49, 0x45, 0x43, // Z
   0x00, 0x7F, 0x41, 0x00, 0x00, // [
   0x02, 0x04, 0x08, 0x10, 0x20, // "/"
   0x00, 0x00, 0x41, 0x7F, 0x00, // ]
   0x04, 0x02, 0x01, 0x02, 0x04, // ^
   0x40, 0x40, 0x40, 0x40, 0x40, // _
   0x00, 0x01, 0x02, 0x04, 0x00, // `
   0x20, 0x54, 0x54, 0x54, 0x78, // a
   0x7F, 0x44, 0x44, 0x44, 0x38, // b
   0x38, 0x44, 0x44, 0x44, 0x44, // c
   0x38, 0x44, 0x44, 0x44, 0x7F, // d
   0x38, 0x54, 0x54, 0x54, 0x18, // e
   0x04, 0x04, 0x7E, 0x05, 0x05, // f
   0x08, 0x54, 0x54, 0x54, 0x3C, // g
   0x7F, 0x08, 0x04, 0x04, 0x78, // h
   0x00, 0x44, 0x7D, 0x40, 0x00, // i
   0x20, 0x40, 0x44, 0x3D, 0x00, // j
   0x7F, 0x10, 0x28, 0x44, 0x00, // k
   0x00, 0x41, 0x7F, 0x40, 0x00, // l
   0x7C, 0x04, 0x78, 0x04, 0x78, // m
   0x7C, 0x08, 0x04, 0x04, 0x78, // n
   0x38, 0x44, 0x44, 0x44, 0x38, // o
   0x7C, 0x14, 0x14, 0x14, 0x08, // p
   0x08, 0x14, 0x14, 0x14, 0x7C, // q
   0x00, 0x7C, 0x08, 0x04, 0x04, // r
   0x48, 0x54, 0x54, 0x54, 0x20, // s
   0x04, 0x04, 0x3F, 0x44, 0x44, // t
   0x3C, 0x40, 0x40, 0x20, 0x7C, // u
   0x1C, 0x20, 0x40, 0x20, 0x1C, // v
   0x3C, 0x40, 0x30, 0x40, 0x3C, // w
   0x44, 0x28, 0x10, 0x28, 0x44, // x
   0x0C, 0x50, 0x50, 0x50, 0x3C, // y
   0x44, 0x64, 0x54, 0x4C, 0x44, // z
   0x00, 0x08, 0x36, 0x41, 0x41, // {
   0x00, 0x00, 0x7F, 0x00, 0x00, // |
   0x41, 0x41, 0x36, 0x08, 0x00, // }
   0x02, 0x01, 0x02, 0x04, 0x02, // ~
};
 
void OLED_init(void) {
  I2C_init();                             
  I2C_start(OLED_ADDR);                   
  I2C_write(OLED_CMD_MODE);               
  for (uint8_t i = 0; i < OLED_INIT_LEN; i++) I2C_write(pgm_read_byte(&OLED_INIT_CMD[i])); 
  I2C_stop();                            
}
 
void OLED_printC(char ch) {
  uint16_t offset = ch - 32;             
  offset += offset << 2;                
  I2C_write(0x00);        
  for(uint8_t i=5; i; i--) I2C_write(pgm_read_byte(&OLED_FONT[offset++])); 
}
 
void OLED_printP(const char* p) {
  I2C_start(OLED_ADDR);                   
  I2C_write(OLED_DAT_MODE);               
  char ch = pgm_read_byte(p);            
  while (ch != 0){OLED_printC(ch);ch = pgm_read_byte(++p);}
  I2C_stop();                   
}
 
void OLED_cursor(uint8_t xpos, uint8_t ypos) {
  I2C_start(OLED_ADDR);                   
  I2C_write(OLED_CMD_MODE);               
  I2C_write(xpos & 0x0F);                 
  I2C_write(0x10 | (xpos >> 4));     
  I2C_write(0xB0 | (ypos & 0x07));    
  I2C_stop();                           
}
 
void OLED_clear(void) {
  OLED_cursor(0, 0);                      
  I2C_start(OLED_ADDR);                   
  I2C_write(OLED_DAT_MODE);              
  for(uint16_t i=512; i; i--) I2C_write(0x00); 
  I2C_stop();  
}
 
void OLED_num(byte num){
  I2C_start(OLED_ADDR);                 
  I2C_write(OLED_DAT_MODE);    
  OLED_printC(num+48); 
  I2C_stop();    
  }

void OLED_brig(byte br){
  I2C_start(OLED_ADDR);                   
  I2C_write(OLED_CMD_MODE);               
  I2C_write(0x81);                 
  I2C_write(br);        
  I2C_stop();
  }
 
void OLED_inver(bool inv){
  int inv_data;
  if(inv==0) inv_data=0xA6; else inv_data=0xA7;
  I2C_start(OLED_ADDR);                   
  I2C_write(OLED_CMD_MODE);               
  I2C_write(inv_data);                        
  I2C_stop();
  } 
  

10

Re: ATTINY45

ЧАСЫ С БОЛЬШИМИ ЦИФРАМИ И ДАТЧИКОМ ТЕМПЕРАТУРЫ ATTINY45+LCD1602_I2C+DS18B20+DS3231

http://forum.rcl-radio.ru/uploads/images/2022/10/542d45f323ad16329d0045ce29d0150c.png

http://forum.rcl-radio.ru/uploads/images/2022/10/626bb2f149e8d23ffe479721f0565e63.png

http://forum.rcl-radio.ru/uploads/images/2022/10/30fc887ef850a9513f49d6dc2a67ce7d.png


#include <avr/io.h>
#include <util/delay.h>

#define ADDR_DS3231  0b1101000
#define ADDR_1602    0x27
#define SDA          PB4 
#define SCL          PB3 
#define TERM         PB2 
#define HH           PB0
#define MM           PB1 


#define RS      0
#define E       2
#define LED     3


 byte led_b,init_t;
 byte d1,d2,d3,d4,d5,d6,e1,e2,e3;
 int a[6],x;
 int t_dig;
 byte sec,min,hour;
 int hh,mm;
 int w;
 bool k=1;


int main(){
   PORTB |=(1 << HH)|(1 << MM);

  // set_time(22,2,10,24,13,20,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59
   lcdInit();
   i2c_write(led_b |= (1<<LED)); // включаем подсветку
   lcdWrite(0, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07);
   lcdWrite(8, 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00);      
   lcdWrite(16,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F);
   lcdWrite(24,0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F);
   lcdWrite(32,0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C);
   lcdWrite(40,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C);
   lcdWrite(48,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07);
   lcdWrite(56,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00);
   
   while (1) {  
    sec =  (ds_read(0) & 0x0F) + (((ds_read(0) & 0x70) >> 4) * 10);
    min =  (ds_read(1) & 0x0F) + (((ds_read(1) & 0x70) >> 4) * 10);
    hour = ((ds_read(2) & 0x0F) + ((ds_read(2) & 0x70) >> 4) * 10);
    
    hh=hour;mm=min;
    if(((PINB >> HH) & 1) == 0){hh++;if(hh>23){hh=0;}set_time(22,2,10,24,hh,mm,0);_delay_ms(200);}
    if(((PINB >> MM) & 1) == 0){mm++;if(mm>59){mm=0;}set_time(22,2,10,24,hh,mm,0);_delay_ms(200);}
    
  if(sec>=35&&sec<=40||sec>=55){
   if(w==0){ lcdClear();t_dig = read_temp();}w++;  
     a[0]=t_dig/100;
     a[1]=t_dig/10%10;
     a[2]=t_dig%10;
   for(x=0;x<3;x++){
    switch(x){
        case 0: e1=2;e2=3,e3=4;break;
        case 1: e1=5,e2=6,e3=7;break;
        case 2: e1=9,e2=10,e3=11;break;

  }digit();
  lcdCurs(1,8);lcdChar(0x2e);lcdCurs(1,12);lcdChar(0xdf);lcdChar(0x43);}
  }
 else{
     w=0;
     a[0]=hour/10;
     a[1]=hour%10;
     a[2]=min/10;
     a[3]=min%10;
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=7,e2=8,e3=9;break;
        case 3: e1=10,e2=11,e3=12;break;
  }digit();
  lcdCurs(0,6);lcdChar(0x2e);lcdCurs(1,6);lcdChar(0x2e);lcdCurs(1,13);lcdChar(20);lcdCurs(1,14);lcdChar(sec/10+'0');lcdChar(sec%10+'0');}
 }
}}// END


void digit(){
  switch(a[x]){
    case 0: d1=0,d2=7,d3=5,d4=0,d5=2,d6=5;break;
    case 1: d1=32,d2=1,d3=5,d4=32,d5=32,d6=5;break;
    case 2: d1=1,d2=7,d3=5,d4=0,d5=3,d6=4;break;
    case 3: d1=1,d2=3,d3=5,d4=6,d5=2,d6=5;break;
    case 4: d1=0,d2=2,d3=5,d4=32,d5=32,d6=5;break;
    case 5: d1=0,d2=3,d3=4,d4=6,d5=2,d6=5;break;
    case 6: d1=0,d2=3,d3=4,d4=0,d5=2,d6=5;break;
    case 7: d1=0,d2=7,d3=5,d4=32,d5=32,d6=5;break;
    case 8: d1=0,d2=3,d3=5,d4=0,d5=2,d6=5;break;
    case 9: d1=0,d2=3,d3=5,d4=6,d5=2,d6=5;break;
    case 10:d1=150,d2=150,d3=150,d4=150,d5=150,d6=150;break;}
    lcdCurs(0,e1);lcdChar(d1);
    lcdCurs(0,e2);lcdChar(d2);
    lcdCurs(0,e3);lcdChar(d3);
    lcdCurs(1,e1);lcdChar(d4);
    lcdCurs(1,e2);lcdChar(d5);
    lcdCurs(1,e3);lcdChar(d6);
}   


void lcdSend(bool rs, byte data) {
    cli();
    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();
    sei();
}
 
void lcdInit(){ 
    lcd(0x03);_delay_us(4500);
    lcd(0x03);_delay_us(4500);
    lcd(0x03);_delay_us(200);
    lcd(0b00000010);_delay_ms(5);
    lcd(0b00001100);_delay_ms(5);
    lcdClear();
  } 
 
void lcdClear(){lcd(0b00000001);} 
void lcdString(const char* str) {while(*str != '\0') {del();lcdChar(*str);str++;}}
void lcd(uint8_t sett) {lcdSend(true, sett);}
void lcdChar(const char chr) {lcdSend(false, (uint8_t)chr);}
void e_pin(){i2c_write(led_b |= (1<<E));del();i2c_write(led_b &= ~(1<<E));}
void lcdWrite(byte addr_w, byte wr1,byte wr2,byte wr3,byte wr4,byte wr5,byte wr6,byte wr7,byte wr8){
     lcd(0b01000000|addr_w);lcdChar(wr1);lcdChar(wr2);lcdChar(wr3);lcdChar(wr4);lcdChar(wr5);lcdChar(wr6);lcdChar(wr7);lcdChar(wr8);}
void del(){_delay_us(500);}     
 
 
void lcdCurs(byte str, byte mesto){
  if(str==0){lcd(0b10000000+mesto);}
  if(str==1){lcd(0b11000000+mesto);}
  }  


///// i2c /////////////

bool i2c_read_bit() {
    bool i2c_bit = 1;        
    DDRB &= ~(1 << SDA);            
    _delay_us(5); 
    DDRB &= ~(1 << SCL);                
    if((PINB >> SDA) & 1) i2c_bit=0;                            
    _delay_us(5);  
    DDRB |= (1 << SCL);              
    return i2c_bit;  
}
 
byte i2c_write_byte(byte data){
    for (byte i=0; i<8; i++){i2c_write_bit((data&0x80)==0);data<<=1;}    
    return i2c_read_bit(); 
}

byte i2c_read_byte(byte a){
    byte i, data=0;                
    for(i=0; i<8; i++){if (!i2c_read_bit()) data++;if(i!=7) data<<=1;}        
    i2c_write_bit(a);return data;  
}
 
void i2c_write_bit(byte b){
    _delay_us(1);
    if(b){DDRB |= (1 << SDA);}else{DDRB &= ~(1 << SDA);}
    _delay_us(1);
    DDRB &= ~(1 << SCL);       
    _delay_us(1);
    DDRB |= (1 << SCL);
}
 
void i2c_start(){
     DDRB &= ~(1 << SDA); DDRB &= ~(1 << SCL);
     DDRB |= (1 << SDA);  PORTB &= ~(1 << SDA);
     DDRB |= (1 << SCL);  PORTB &= ~(1 << SCL);
}
 
void i2c_stop()  {
     DDRB |= (1 << SDA);           
     DDRB &= ~(1 << SCL);            
     DDRB &= ~(1 << SDA);           
}
 
void i2c_write(byte lcd){
     i2c_start();
     i2c_write_byte(ADDR_1602<<1);
     i2c_write_byte(lcd);
     i2c_stop();
  }   

void ds_write(byte reg, byte data){
     i2c_start();
     i2c_write_byte(ADDR_DS3231<<1);
     i2c_write_byte(reg);
     i2c_write_byte(data);
     i2c_stop();
  }  
  
byte ds_read(byte reg){
     byte dat=0;
     i2c_start();
     i2c_write_byte(ADDR_DS3231<<1);
     i2c_write_byte(reg);
     i2c_start(); 
     i2c_write_byte((ADDR_DS3231<<1)|1); 
     dat = i2c_read_byte(0);
     i2c_stop();
     return dat;
  } 

void set_time(byte years, byte days, byte monts, byte datas, byte hours ,byte minute, byte second){
    ds_write(0x00,(second/10<<4)+second%10);
    ds_write(0x01,(minute/10<<4)+minute%10);
    ds_write(0x02,(hours/10<<4)+hours%10);
    ds_write(0x03,days);
    ds_write(0x04,(datas/10<<4)+datas%10);
    ds_write(0x05,(monts/10<<4)+monts%10);
    ds_write(0x06,(years/10<<4)+years%10);
  }    


// reset
uint8_t therm_reset(){
    uint8_t i;
    PORTB &= ~(1 << TERM);
    DDRB |= (1 << TERM);
    _delay_us(480);  
    DDRB &= ~(1 << TERM);
    _delay_us(60);
    i=((PINB >> TERM) & 1);
    _delay_us(420);
    return i;
}
// write bit
void therm_write_bit(uint8_t bit){
    PORTB &= ~(1 << TERM);
    DDRB |= (1 << TERM);
    _delay_us(1);
    if(bit) DDRB &= ~(1 << TERM);
    _delay_us(60);
    DDRB &= ~(1 << TERM);
}
// read bit
uint8_t therm_read_bit(void){
    uint8_t bit=0;
    PORTB &= ~(1 << TERM);
    DDRB |= (1 << TERM);
    _delay_us(1);
    DDRB &= ~(1 << TERM);
    _delay_us(14);
    if(PINB & (1 << TERM)) bit=1;
    _delay_us(45);
    return bit;
}
 
// read byte
uint8_t therm_read_byte(void){
    uint8_t i=8, n=0;
    while(i--){n>>=1;n|=(therm_read_bit()<<7);}
    return n;
}
 
// write byte
void therm_write_byte(uint8_t byte){
    uint8_t i=8;
    while(i--){therm_write_bit(byte&1);byte >>= 1;
    }
}
// read temp
int read_temp(){
    uint8_t temperature[2];
    float temper;
    therm_reset();
    therm_write_byte(0xCC);
    therm_write_byte(0x44);
    while(!therm_read_bit());
    therm_reset();
    therm_write_byte(0xCC);
    therm_write_byte(0xBE);
    temperature[0]=therm_read_byte();
    temperature[1]=therm_read_byte();
    therm_reset();
    temper = (temperature[1] << 8 | temperature[0])/1.60;
    return (int)temper;
}