четверг, 17 ноября 2011 г.

Оч.умелое изнутри (2)..

Еще кусок: DS75 термометр

Вчера я с ним промудохался :( - работал на макетке в тесовом проекте специально для чтения температуры, воткнул вчера в макетку с часами - а хрен вам

В общем, бубном тарахтел-тарахтел вокруг него, потом зачем-то прошил фьюзы, чтобы контроллер тактовался не от внешнего кварца (14 МГц с копейками, просто какой был в небольшом корпусе), а от внутреннего генератора 8 МГц - и все заработало.. Может кварц плохой или быстрый слишком, хз; поменяю да и все

В общем вот так он (термометр) подключается:

Уж проще некуда - питание, А0-А2 задают адрес, у меня тупо 0х00; линии SDA/SCL подтянуты к Vcc через 5 кОм резисторы. Кода немного:

unsigned char i2c_start(void)
{
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //Send START condition 

    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) == TW_START)   //Check value of TWI Status Register
        return(0);
    else
        return(1);
} 

unsigned char i2c_sendAddress(unsigned char address)
{
    unsigned char STATUS; 

    if((address & 0x01) == 0)
        STATUS = TW_MT_SLA_ACK;
    else
        STATUS = TW_MR_SLA_ACK; 

    TWDR = address;
    TWCR = (1<<TWINT)|(1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) == TW_STATUS)
        return(0);
    else
        return(1);
} 

unsigned char i2c_sendData(unsigned char data)
{
    TWDR = data;
    TWCR = (1<<TWINT) |(1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
        return(1);
    else
        return(0);
} 

unsigned char i2c_receiveData_ACK(void)
{
    unsigned char data; 

    TWCR = (1<<TWEA)|(1<<TWINT)|(1<<TWEN); 

    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != TW_MR_DATA_ACK)
        return(TW_BUS_ERROR); 

    data = TWDR;
    return(data);
} 

unsigned char i2c_receiveData_NACK(void)
{
    unsigned char data; 

    TWCR = (1<<TWINT)|(1<<TWEN); 

    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != TW_MR_DATA_NACK)
        return(TW_BUS_ERROR); 

    data = TWDR;
    return(data);
} 

void i2c_stop(void)
{
    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);    //Transmit STOP condition
}

В конце даташита на DS75 есть последовательности - "что надо сделать, чтобы.." В след. процедуре сначала задается адрес термометра (0х00), а потом читаются данные из него

#include "twi.h"
...
u08 measureTemp () {
    i2c_start();
    i2c_sendAddress(0x90);
    i2c_sendData(0);
    i2c_sendData(0);
    i2c_stop(); 

    i2c_start();
    i2c_sendAddress(0x91);

    u08 ms = i2c_receiveData_ACK();
    i2c_receiveData_NACK();
    i2c_stop();

    return ms;
}

Так не совсем правильно конечно, но в моем конкретном случае сойдет: я использую 9-битную точность (если так можно выражаться), если я правильно все понял, то это означает, что под знак отводится бит, под целые градусы - 7 бит и под десятые доли - 1 бит, т.е. точность в пол-градуса; в младшем байте эти пол-градуса и храняться, а в старшем - или просто положительное значение, или отрицательное, если старший бит установлен в "1"; поск. я не собираюсь (пока) измерять температуру зимой на улице, то значение старшего байта == температуре

Комментариев нет:

Отправить комментарий