I2C teploměr DS1624

V minulém díle o programování AVR jsme se zaměřili na práci se sběrnicí I2C. Zkusili jsme si uložit do paměti EEPROM text a poté ho přečíst zobrazit na LCD. Dnes si ukážeme další využití - měření teploty. Jako periferii jsem zvolil integrovaný obvod firmy Maxim a to DS1624.

DS1624 je obvod kombinující 13ti bitový teploměr a EEPROM o velikosti 256 bajtů. Ke všem funkcím, jako už tradičně u Maxima, se přistupuje pomocí příkazů:
  • 0x17 - přístup do paměti EEPROM
  • 0xAC - přístup ke konfiguračnímu registru
  • 0xAA - čtení teploty
  • 0xEE - start konverze teploty
  • 0x22 - stop konverze teploty

Postup jak přistupovat k periferii je pěkně popsán v datasheetu výrobce, proto myslím není třeba ho uvádět znovu. Následující program ukazuje jakým postupem lze měřit teplotu za pomoci obvodu, myslím, že není třeba ho nijak zvlášť komentovat.

#define F_CPU 14745600UL

#include <avr/io.h>
#include <string.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd_lib.h"
#include "twi_lib.h"


#define DevDS1624  0x90

int main(void)
{   
    unsigned int i=0;
       
    LCD_Init();   
    i2c_init();
    LCD_Position(0,0);
    LCD_WriteCString("TEST DS1624");
   
    // nejprve nastavime, do konfiguracniho
    // registru, ze chceme rezim ONE-SHOT

    i2c_start_wait(DevDS1624+I2C_WRITE);    
    i2c_write(0xAC);
    i2c_write(0x01);
    i2c_stop();
                               
    // cekame, aby se stacila konf. zapsat
    for (i=0; i<1000; i++);

    while(1)
    {
        // spustime konverzi teploty
        i2c_start_wait(DevDS1624+I2C_WRITE);        
        i2c_write(0xEE);
        i2c_stop();

        // cekame dokud konverze neprobehne
        for (i=0; i<1000; i++);

        LCD_Position(1,0);

        // precteme 2 byty z pameti (teplota)
        i2c_start_wait(DevDS1624+I2C_WRITE);    
        i2c_write(0xAA);                       
        i2c_rep_start(DevDS1624+I2C_READ); 
    
        i =(int)i2c_readAck();
        i = i<<8;
        i = i | (int) i2c_readNak();
        i2c_stop();
        i = i>>3;
        i = (float)i*3.125;                 

   
        LCD_PrDec(i/100);
        LCD_WriteData(',');
        LCD_PrDec(i % 100);
        LCD_WriteCString("°C");

        for (i=0; i<50000; i++);
    }
   
    while(1);
}

V první části programu je neprve nutné nastavit v jakém režimu bude teploměr pracovat. Umožňuje totiž tzv. kontinuální převod teploty. To znamená, že pokud jednou odstartujeme převod, bude se provádět automaticky a nemusíme ho spouštět znovu. To ovšem samozřejmě zvyšuje spotřebu. My nepotřebujeme zpracovat další data, takže si klidně budeme spouštět konverzi před každým čtením teploty. Nastavení se provádí v konfiguračním registru, bit 0, do něhož přistoupíme prostřednictvím příkazu "0xAC". Zapsáním jedničky na bit nula, přepneme teploměr do módu ONE-SHOT.

    // nejprve nastavime, do konfiguracniho
    // registru, ze chceme rezim ONE-SHOT

    i2c_start_wait(DevDS1624+I2C_WRITE);    
    i2c_write(0xAC);
    i2c_write(0x01);
    i2c_stop();

 

Samotnou konvezi poté spustíme následujícím kódem:

        // spustime konverzi teploty
        i2c_start_wait(DevDS1624+I2C_WRITE);        
        i2c_write(0xEE);
        i2c_stop();

Máme dvě monosti,  můžeme čekat 10ms, což je doba, po kterou je konverze bezpečně provedena, nebo můžeme testovat bit DONE (bit 7) konfiguračního registru. To dělat nebudeme a zvolíme první možnost.

Přečtení teploty probíhá pomocí příkazu "0xAA" (Read Temp):

        // precteme 2 byty z pameti (teplota)
        i2c_start_wait(DevDS1624+I2C_WRITE);    
        i2c_write(0xAA);                       
        i2c_rep_start(DevDS1624+I2C_READ); 
    
        i =(int)i2c_readAck();
        i = i<<8;
        i = i | (int) i2c_readNak();
        i2c_stop();
        i = i>>3;
        i = (float)i*3.125;

2 bajty přicházející ze sběrnice I2C přesunu do proměnné typu INT. Tu následně rotuji o 3 bity doprava, protože teplota je v 13 bitovém formátu a já jsem vytvořil 16 bitovou proměnnou. Pro přepočet na teplotu by stačilo číslo násobit konstantou 0.03125, já ji však násobím 100x větším číslem, abych mohl jednoduše vypsat na LCD celou část teploty a 2 desetinná místa....

        LCD_PrDec(i/100);
        LCD_WriteData(',');
        LCD_PrDec(i % 100);
        LCD_WriteCString("°C");



Komentovat článek

Jméno:  
Zpráva:

Komentáře k článku

článek zatím nikdo nekomentoval