#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include «i2cmaster.h»
//#define F_CPU 3686400L
// Порт XCLR Датчика
#define XCLR_DDR DDRD
#define XCLR_PORT PORTD
#define XCLR PIND0
// Порт Тактирования АЦП Датчика
#define MCLK_DDR DDRD
#define MCLK_PORT PORTD
#define MCLK PIND1
// Калибровочные коэффициенты
long int c1, c2, c3, c4, c5, c6, c7, a, b, c, d;
// Значение АЦП
long int d1, d2;
// Температура
long int t;
// Давление
long int Pressure;
//#############################################################################
// Возведение двойки в степень
//
long int pow2(uint8_t i)
{
long int uiData;
uiData=2;
i=i-1;
while(i) {
uiData *= 2;
i–;
}
return uiData;
}
#define fospEEPROM_ADR 0xA0 // Адрес EEPROM
#define fospADC_ADR 0xEE // Адрес ADC
#define PRESSURE 0xF0
#define TEMPERATURE 0xE8
#define mm_rt_st 0.7500638 // мм. рт. ст. (@ 0 гр. C)
//#############################################################################
// Инициализация HP03
//
void HP03Init(void)
{
// Сброс HP03
XCLR_PORT &= ~(1<<XCLR);
_delay_ms(200);
XCLR_PORT |= (1<<XCLR);
_delay_ms(200);
XCLR_PORT &= ~(1<<XCLR);
_delay_ms(200);
}
//#############################################################################
// Считывает два байта
//
unsigned int HP03_Get2Bytes()
{
unsigned int HiTemp, LowTemp;
HiTemp=i2c_readAck();
LowTemp=i2c_readAck();
return (((int)HiTemp) << 8) + LowTemp;
}
//#############################################################################
// Чтение калибровочных коэффициентов из EEPROM (HP03)
//
void HP03ReadCoeff(void)
{
unsigned int ret;
ret = i2c_start(fospEEPROM_ADR); // Адрес
EEPROM
if(ret)
{
// датчик не обнаружен
i2c_stop();
}
else
{
i2c_write(0×10); // Адрес коэффициентов в EEPROM
i2c_start(0xA1);
c1=HP03_Get2Bytes();
c2=HP03_Get2Bytes();
c3=HP03_Get2Bytes();
c4=HP03_Get2Bytes();
c5=HP03_Get2Bytes();
c6=HP03_Get2Bytes();
c7=HP03_Get2Bytes();
a = i2c_readAck();
b = i2c_readAck();
c = i2c_readAck();
d = i2c_readNak();
i2c_stop();
}
}
//#############################################################################
// Чтение данных АЦП (HP03)
//
unsigned int HP03ReadValue(unsigned char n)
{
unsigned int ret;
unsigned int temp;
temp = 0;
ret=i2c_start(fospADC_ADR); // Адрес ADC
if(ret)
{
// датчик не обнаружен
i2c_stop();
}
else
{
i2c_write(0xff);
i2c_write(n); // Pressure(0xF0), Temperature(0xE8)
i2c_stop();
_delay_ms(50);
i2c_start(fospADC_ADR); // Адрес ADC
i2c_write(0xfd);
i2c_rep_start(0XEF); // Адрес ADC
temp = HP03_Get2Bytes();
i2c_stop();
}
return temp;
}
//#############################################################################
// Вычисление температуры и атмосферного давления
// с учетом калибровочных коэффициентов
//
void PressureTemperatureMeasure(void)
{
long int dUT;
long int off, sens, x;
XCLR_PORT |= (1<<XCLR);
d1 = HP03ReadValue(PRESSURE);
d2 = HP03ReadValue(TEMPERATURE);
XCLR_PORT &= ~(1<<XCLR);
//if(d2 >= c5) { dUT = (d2-c5) –
(((d2-c5)/pow2(7))*((d2-c5)/pow2(7))*a)/pow2(c); }
//else { dUT = (d2-c5) –
(((d2-c5)/pow2(7))*((d2-c5)/pow2(7))*b)/pow2(c); }
if(d2 >= c5) { t = a; }
else { t = b; }
dUT = (d2-c5) – (((d2-c5)/pow2(7))*((d2-c5)/pow2(7))*t)/pow2(c);
t = (250 + ((dUT*c6)/pow2(16)) –
dUT/pow2(d));///10; // Вычисляем температуру в градусах по шкале Цельсия
off = (c2+(c4-1024)*dUT/pow2(14))*4;
sens = c1+(c3*dUT)/pow2(10);
x = (sens*(d1-7168))/pow2(14)-off;
//Pressure = (x*100/pow2(5)+c7*10);
Pressure = ((x*100/pow2(5)+c7*10)/100)*mm_rt_st; // Вычисляем
давление в миллиметрах ртутного столба
}
//=============================================================================
//#############################################################################
// Тактирование АЦП Датчика
// Тактовая частота процессора 3.6864 МГц
//
ISR(TIMER0_OVF_vect) {
if ((MCLK_PORT & (1<<MCLK)) == 0) {
MCLK_PORT |= (1<<MCLK);
}
else {
MCLK_PORT &= ~(1<<MCLK);
}
}
//#############################################################################
//#############################################################################
int main(void){
// Настраиваем порт для Сброса и Синхронизации датчика
XCLR_DDR |= (1<<XCLR);
MCLK_DDR |= (1<<MCLK);
// Настраиваем таймер для тактирования АЦП
TCCR0 = (1<<CS00);
// Разрешаем прерывания
TIMSK = (1<<TOIE0);
// Запускаем таймера
TCNT0 = 0;
sei();
i2c_init();
// TWI PULL UP Включаем внутренние подтягивающие резисторы, поэтому
наружные резисторы можно не устанавливать.
PORTC |= ((1<<PINC4) | (1<<PINC5));
HP03Init();
HP03ReadCoeff();
while(1) {
PressureTemperatureMeasure();
// Выводим переменные
// t – температура
// Pressure – давление
}
}
|