Тема: Термометр на DS18B20 с большими цифрами
Основная статья - http://rcl-radio.ru/?p=112955
#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 TEMP PB0
#define BUTTON PB2
#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)
bool minus;
uint8_t buffer[8];
int main(void) {
PORTB |=(1 << BUTTON);
OLED_init();
OLED_clear();
while(1) {
if(((PINB >> BUTTON) & 1) == 0){
int temp = read_temp();
if(temp<0){minus=1;temp=-temp;}else{minus=0;}
byte a0 = temp/100;
byte a1 = temp/10%10;
byte a2 = temp%10;
if(minus==0){uint8_t buffer0[8] = {19, a0, a1, 16, a2, 19, 12, 19};OLED_printB(buffer0);}
else{uint8_t buffer1[8] = {18, a0, a1, 16, a2, 19, 12, 19};OLED_printB(buffer1); }
_delay_ms(10000);}
OLED_clear();
}}
///// 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 15
// OLED init settings
const uint8_t OLED_INIT_CMD[] PROGMEM = {
0xA8, 0x1F,
0x22, 0x00, 0x03,
0x20, 0x01,
0xDA, 0x02,
0x8D, 0x14,
0xAF,
0x00, 0x10, 0xB0,
0xA1, 0xC8
};
// Simple reduced 3x8 font
const uint8_t OLED_FONT[] PROGMEM = {
0x7F, 0x41, 0x7F, // 0 0
0x00, 0x00, 0x7F, // 1 1
0x79, 0x49, 0x4F, // 2 2
0x41, 0x49, 0x7F, // 3 3
0x0F, 0x08, 0x7E, // 4 4
0x4F, 0x49, 0x79, // 5 5
0x7F, 0x49, 0x79, // 6 6
0x03, 0x01, 0x7F, // 7 7
0x7F, 0x49, 0x7F, // 8 8
0x4F, 0x49, 0x7F, // 9 9
0x7F, 0x09, 0x7F, // A 10
0x7F, 0x48, 0x78, // b 11
0x7F, 0x41, 0x63, // C 12
0x78, 0x48, 0x7F, // d 13
0x7F, 0x49, 0x41, // E 14
0x7F, 0x09, 0x01, // F 15
0x00, 0x60, 0x00, // . 16
0x00, 0x36, 0x00, // : 17
0x08, 0x08, 0x08, // - 18
0x00, 0x00, 0x00 // 19
};
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_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();
}
uint8_t OLED_stretch(uint8_t b){b=((b & 2)<<3)|(b&1);b|=b<<1;b|=b<<2;return b;}
void OLED_printD(uint8_t ch) {
uint8_t i, j, k, b;
uint8_t sb[4];
ch += ch << 1;
for(i=8; i; i--) I2C_write(0x00);
for(i=3; i; i--) {
b = pgm_read_byte(&OLED_FONT[ch++]);
for(j=0; j<4; j++, b >>= 2) sb[j] = OLED_stretch(b);
j=4; if(i==2) j=6;
while(j--) {
for(k=0; k<4; k++) I2C_write(sb[k]);
}}}
void OLED_printB(uint8_t *buffer) {
I2C_start(OLED_ADDR);
I2C_write(OLED_DAT_MODE);
for(uint8_t i=0; i<8; i++) OLED_printD(buffer[i]);
I2C_stop();
}
//// DS18B20 //////////////////////////////////////
uint8_t therm_reset(){
uint8_t i;
PORTB &= ~(1 << TEMP);
DDRB |= (1 << TEMP);
_delay_us(480);
DDRB &= ~(1 << TEMP);
_delay_us(60);
i=((PINB >> TEMP) & 1);
_delay_us(420);
return i;
}
void therm_write_bit(uint8_t bit){
DDRB |= (1 << TEMP);
if(bit) DDRB &= ~(1 << TEMP);
_delay_us(60);
DDRB &= ~(1 << TEMP);
}
uint8_t therm_read_bit(void){
uint8_t bit=0;
DDRB |= (1 << TEMP);
DDRB &= ~(1 << TEMP);
_delay_us(14);
if(PINB & (1 << TEMP)) bit=1;
_delay_us(45);
return bit;
}
uint8_t therm_read_byte(void){
uint8_t i=8, n=0;
while(i--){n>>=1;n|=(therm_read_bit()<<7);}
return n;
}
void therm_write_byte(uint8_t byte){
uint8_t i=8;
while(i--){therm_write_bit(byte&1);byte >>= 1;
}}
int read_temp(){
uint8_t temperature[2];
int 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();
return temper = (temperature[1] << 8 | temperature[0])*10/16;
}