Микросхема AD7416 от компании Analog Devices - достаточно простой в применении датчик температуры с интерфейсом I2C обладает следующими характеристиками:
Напряжение питания: 2.7 V ... 5.5V;
Разрешение: 0,25°C;
Корпус: SOIC-8;
Максимальная погрешность измерения: не более 2°C;
Рабочий диапазон температур: – 40°C ... +125°C;
Приём десятиразрядного значения измеренной температуры осуществляется после оправки по интерфейсу I2C адреса датчика с признаком чтения. Для установки семибитного адреса чипа на шине предназначены выводы A0, A1 и A2 микросхемы, которые задают состояние младших битов, при этом значения старших четырёх всегда равно 1001b.
Таким образом содержимое I2C-пакета ADR+R/W:
bit 0 = 1 (признак чтения);
bit 1 = A0;
bit 2 = A1;
bit 3 = A2;
bit 4 = 1; bit 5 = 0; bit 6 = 0; bit 7 = 1.
Для управления обменом по шине введём признак состояния обмена I2C_STT, меняющий своё значение по ходу действия. Тогда запуск опроса датчика можно начинать установкой I2C_STT=0 через определённые интервалы времени.
Пример кода для обмена с датчиком, AVR в режиме ведущего приёмника.
(компилятор-IAR):
signed char TempVal; // Знаковое значение температуры.
unsigned char TempAbs; // Абсолютное значение температуры.
unsigned char I2C_STT; // Статус обмена с датчиком температуры.
unsigned char minus; // Признак отрицательного значения температуры.
union {unsigned int TM0; unsigned char TM1[2];} TM; // Объединение двух байтов температуры
void main (void)
{
while (1)
{
if (I2C_STT==0) // Установить состояние START на шине.
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); I2C_STT=1;
}
if ((I2C_STT==1)&&(TWCR&(1<<TWINT))) // Проверка флага и статуса после установки старта.
{
if ((TWSR&0xF8)==8) I2C_STT=2; // Если успешно сгенерирован START...
else {I2C_STT=12;} // Если сбой по отправке старта...
}
if (I2C_STT==2) // Отправка пакета ADR+R.
{
TWDR =((0x4F<<1)|1); // Адрес ведомого 0x4F=1001111b (A0=A1=A2=1).
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); I2C_STT=3;
}
if ((I2C_STT==3)&&(TWCR&(1<<TWINT))) // Ожидание ACK подтверждения на ADR+R.
{
if ((TWSR&0xF8)==64) I2C_STT=4; // Если ведомый подтвердил свой адрес...
else {I2C_STT=14;} // Если сбой по подтверждению адреса...
}
if (I2C_STT==4) // Принять первый байт и отправить ACK.
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); I2C_STT=5;
}
if ((I2C_STT==5)&&(TWCR&(1<<TWINT)))
{
TM.TM1[1]=TWDR; I2C_STT=6; // Сохранить принятый байт.
}
if (I2C_STT==6) // Принять второй байт и отправить NO_ACK.
{
TWCR = (1<<TWINT)|(1<<TWEN); I2C_STT=7;
}
if ((I2C_STT==7)&&(TWCR&(1<<TWINT)))
{
TM.TM1[0]=TWDR; I2C_STT=8; // Сохранить принятый байт.
}
if (I2C_STT==8)
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); I2C_STT=10;
}
if (I2C_STT==10) // Если опрос успешный.
{
TempVal=(TM.TM0>>8); // Сдвинуть на 8 бит (отбросить 2 младших бита весом 0,25°C).
if (TempVal<0) {minus=1; TempAbs=0-TempVal;}
else {minus=0; TempAbs=TempVal;} // Выделяем знак и абсолютное значение для отображения.
}
}
}
Выделив лимит времени на обмен с датчиком, по его окончанию можно проверять значение признака I2C_STT на равенство 10 (успешный обмен). Это позволит вовремя отследить зависания, установить соотвествующий признак и предпринять все необходимые меры к оживлению датчика.