Тема: Часы на адресной светодиодной ленте WS2812B (ATtiny2313)
// ATtiny2313 20MHz
#include <avr/io.h>
#include <util/delay.h>
#define L_BIT PORTB &= ~(1<<PB0)
#define H_BIT PORTB |= (1<<PB0)
#define SDA PD2 // PIN6
#define SCL PD3 // PIN7
#define SQW PD4 // PIN8
#define LED_MAX 88
byte brig=1;
bool r,g,b;
bool rr[LED_MAX];
byte hh,mm,hour,min;
byte r_led=0,g_led=1,b_led=0;
byte mode;
bool sett,w,w1;
int main(void){
DDRB |= (1<<PB0); // PIN12 WS2812B
DDRB &= ~(1<<PB1);// PIN13 BUTTON MODE
DDRB &= ~(1<<PB2);// PIN14 BUTTON UP
DDRB &= ~(1<<PB3);// PIN15 BUTTON DOWN
DDRB &= ~(1<<PB4);// PIN16 BUTTON SET
PORTB |= (1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4);
_delay_ms(100);
if(EEPROM_read(100)!=1){for(int i1=0;i1<101;i1++){EEPROM_write(i1,1);}}// очистка памяти при первом включении
mode = EEPROM_read(0);brig = EEPROM_read(1);
// set_time(21,3,3,9,21,52,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59
while(1){
min = (ds_read(1) & 0x0F) + (((ds_read(1) & 0x70) >> 4) * 10);
hour = ((ds_read(2) & 0x0F) + ((ds_read(2) & 0x70) >> 4) * 10);
/////// BUTTON ///////////////////////////////////////////////
if(((PINB >> PB1) & 1) == 0){mode++;if(mode>6){mode=0;}_delay_ms(300);w=1;}
switch(mode){
case 0: r_led=1,g_led=1,b_led=1; break;
case 1: r_led=1,g_led=0,b_led=0; break;
case 2: r_led=0,g_led=1,b_led=0; break;
case 3: r_led=0,g_led=0,b_led=1; break;
case 4: r_led=1,g_led=1,b_led=0; break;
case 5: r_led=1,g_led=0,b_led=1; break;
case 6: r_led=0,g_led=1,b_led=1; break;
}
if(((PINB >> PB2) & 1) == 0 && sett==0){brig++;if(brig>250){brig=250;}w=1;}
if(((PINB >> PB3) & 1) == 0 && sett==0){brig--;if(brig<1){brig=1;}w=1;}
if(((PINB >> PB4) & 1) == 0 && sett==0){sett=1;_delay_ms(300);}
if(((PINB >> PB4) & 1) == 0 && sett==1){sett=0;_delay_ms(300);}
////////// RGB ////////////////////////////////////////////////
indd(hour / 10, 0);
indd(hour % 10, 21);
if(((PIND >> SQW) & 1) == 0 && sett==0){data_led(42, 1);data_led(43, 1);data_led(44, 1);data_led(45, 1);}
else{data_led(42, 0);data_led(43,0);data_led(44, 0);data_led(45, 0);}
if(sett==1){data_led(42, 1);data_led(43, 1);data_led(44, 1);data_led(45, 1);}
indd(min / 10, 46);
indd(min % 10, 67);
led_rgb();res();
_delay_ms(100);
//////////// SET TIME //////////////////////////////////////////////////////////////////////
if(sett==1){
hh=hour;
mm=min;
if(((PINB >> PB2) & 1) == 0){hh++;if(hh>23){hh=0;}_delay_ms(100);w1=1;}
if(((PINB >> PB3) & 1) == 0){mm++;if(mm>59){mm=1;}_delay_ms(100);w1=1;}
if(w1==1){w1=0;set_time(21,1,12,26,hh,mm,0);}
}
////// EEPROM ///////////////////
if(w==1){w=0;EEPROM_write(0,mode);EEPROM_write(1,brig);}
}} // end loop
void indd(byte t, byte sdv){
switch(t){
case 0: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,0);ws(12+sdv,1);ws(15+sdv,1);ws(18+sdv,1);break;
case 1: ws(0+sdv,0);ws(3+sdv,0);ws(6+sdv,1);ws(9+sdv,0);ws(12+sdv,0);ws(15+sdv,0);ws(18+sdv,1);break;
case 2: ws(0+sdv,0);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,1);ws(15+sdv,1);ws(18+sdv,0);break;
case 3: ws(0+sdv,0);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,0);ws(15+sdv,1);ws(18+sdv,1);break;
case 4: ws(0+sdv,1);ws(3+sdv,0);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,0);ws(15+sdv,0);ws(18+sdv,1);break;
case 5: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,0);ws(9+sdv,1);ws(12+sdv,0);ws(15+sdv,1);ws(18+sdv,1);break;
case 6: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,0);ws(9+sdv,1);ws(12+sdv,1);ws(15+sdv,1);ws(18+sdv,1);break;
case 7: ws(0+sdv,0);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,0);ws(12+sdv,0);ws(15+sdv,0);ws(18+sdv,1);break;
case 8: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,1);ws(15+sdv,1);ws(18+sdv,1);break;
case 9: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,0);ws(15+sdv,1);ws(18+sdv,1);break;
}
}
void ws(byte ind, bool datt){
if(datt==1){data_led(ind, 1);data_led(ind+1, 1);data_led(ind+2, 1);}
else{data_led(ind, 0);data_led(ind+1, 0);data_led(ind+2, 0);}}
void bit_0(){H_BIT;asm("nop");asm("nop"); L_BIT;asm("nop");asm("nop");asm("nop"); asm("nop");}
void bit_1(){H_BIT;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); L_BIT;}
void bit_w(bool x){if(x) bit_1(); else bit_0();}
void res(){_delay_us(100);}
void data_led(byte num, bool rrr){rr[num]=rrr;}
void led_rgb(){
for(byte num_i=0;num_i<LED_MAX;num_i++){
cli();
for(int ii=7;ii>=0;ii--){bit_w((rr[num_i]*brig*r_led & (1<<ii))>>ii);}
for(int ii=7;ii>=0;ii--){bit_w((rr[num_i]*brig*g_led & (1<<ii))>>ii);}
for(int ii=7;ii>=0;ii--){bit_w((rr[num_i]*brig*b_led & (1<<ii))>>ii);}
sei();
}}
bool i2c_read_bit() {
bool i2c_bit = 1;
DDRD &= ~(1 << SDA);
_delay_us(10);
DDRD &= ~(1 << SCL);
if((PIND >> SDA) & 1) i2c_bit=0;
_delay_us(10);
DDRD |= (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 data=0;
for(byte 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(5);
if(b){DDRD |= (1 << SDA);}else{DDRD &= ~(1 << SDA);}
_delay_us(5);
DDRD &= ~(1 << SCL);
_delay_us(10);
DDRD |= (1 << SCL);
}
void i2c_start(){
_delay_us(10);
DDRD &= ~(1 << SDA); DDRD &= ~(1 << SCL);
_delay_us(10);
DDRD |= (1 << SDA); PORTD &= ~(1 << SDA);
_delay_us(10);
DDRD |= (1 << SCL); PORTD &= ~(1 << SCL);
_delay_us(10);
}
void i2c_stop() {
DDRD |= (1 << SDA);
_delay_us(10);
DDRD &= ~(1 << SCL);
_delay_us(10);
DDRD &= ~(1 << SDA);
}
byte ds_read(byte reg){
byte data = 0;
i2c_start();
i2c_write_byte(0b11010000);
i2c_write_byte(reg);
i2c_start();
i2c_write_byte(0b11010001);
data = i2c_read_byte(0);
i2c_stop();
return data;
}
void ds_write(byte reg, byte data){
i2c_start();
i2c_write_byte(0b11010000);
i2c_write_byte(reg);
i2c_write_byte(data);
i2c_stop();
}
void set_time(byte years, byte days, byte monts, byte datas, byte hours ,byte minute, byte second){
if(second < 255){ds_write(0x00,(second/10<<4)+second%10);}
if(minute < 255){ds_write(0x01,(minute/10<<4)+minute%10);}
if(hours < 255){ds_write(0x02,(hours/10<<4)+hours%10);}
if(days < 255){ds_write(0x03,days);}
if(datas < 255){ds_write(0x04,(datas/10<<4)+datas%10);}
if(monts < 255){ds_write(0x05,(monts/10<<4)+monts%10);}
if(years < 255)ds_write(0x06,(years/10<<4)+years%10);
}
unsigned char EEPROM_read(unsigned int uiAddress){
while(EECR & (1<<EEPE)); // проверка готовности EEPROM
EEAR = uiAddress; // регистр адреса
EECR |= (1<<EERE);// чтение EEPROM
return EEDR; // вывод значения
}
void EEPROM_write(unsigned int uiAddress, unsigned char ucData){
while(EECR & (1<<EEPE)); // проверка готовности EEPROM
EEAR = uiAddress; // регистр адреса
EEDR = ucData; // регистр данных
EECR |= (1<<EEMPE);// Разрешение записи в EEPROM
EECR |= (1<<EEPE); // Запись в EEPROM
}
Скетч использует 1926 байт (94%) памяти устройства. Всего доступно 2048 байт.
Глобальные переменные используют 100 байт (78%) динамической памяти, оставляя 28 байт для локальных переменных. Максимум: 128 байт.