Столкнулся с непонятной проблемой.
Подключил DS1621 к 90s2313.
Процедуры эмуляции i2c взял с одного немецкого сайта. Контроллер вытягивает температуру с датчика, но значение температуры чередуется с 03h значением через один опрос. Пока соорудил затычку в виде двукратного опроса датчика.
Привожу код для i2c и опроса устройства.
[
Диаграммы сигналов для ds1621 смотреть здесь
Прочтите ВНИМАТЕЛЬНО Правила форума: подобные вещи надо оформлять ПРИЛОЖЕНИЕМ к вопросу. Сэр Мурр
Сопряжение 2313 и DS1621
Сопряжение 2313 и DS1621
- Вложения
-
- приложение.txt
- (4.08 КБ) 638 скачиваний
- MiD
- Первый раз сказал Мяу!
- Сообщения: 35
- Зарегистрирован: Ср май 02, 2007 15:20:43
- Контактная информация:
http://www.radiokot.ru/lab/controller/23/
такая же связка: может поможет
такая же связка: может поможет
- Илья79
- Мучитель микросхем
- Сообщения: 429
- Зарегистрирован: Вс июн 29, 2008 13:53:03
- Контактная информация:
У меня тоже проблема такая же случилось, собираю схему термометра на DS1621 при включении выдает -60 градусов, причем если даже подогревать паяльником
схему эмулировал в Proteus 7 Professional все отлично работает
в чем проблема и в какую сторону копать затрудняюсь
прилагаю протокол I2C
схему эмулировал в Proteus 7 Professional все отлично работает
в чем проблема и в какую сторону копать затрудняюсь
прилагаю протокол I2C
- Вложения
-
- I2C.C
- (4.91 КБ) 906 скачиваний
К слову говоря DS1624 вообще непригоден для измерения минусовых температур.. Ниже нуля он всякую чепуху меряет из которой даже путем усреднения сложно полезную температуру выделить - на двух датчиках пробовал.. а вот где-то от 1 до +40 (больше не пробовал, но по даташиту должен до +70) меряет хорошо - колебания показаний у меня составляют+-0,03125 градуса. Единственный ньюанс - датчик надо помещать вдали от сквозняков.
Вложенный файл - снятие показаний измерений. Сначала датчик лежал в комнате, а затем выкинул его за окно, как раз вечер и температура постепенно начала опускаться.
Вообще по наблюдениям при постепенном снижении температуры датчик на каком-то определенном пороге "клинит" и он начинает выдавать большой разброс до тех пор, пока этот порог не будет пройден (см. вложенный файл). Выдаваемое значение TTT нужно множить на 0,03125, значение TXTTEMP - среднее арифметическое). В файле видно что такой порог возникал на значениях -87 и -97. Чем ниже температура - тем больше идет разброс от измерения к измерению. То -120 выдаст (-3,75 градуса), через две секунды -85 (-2,65).. Пробовал перезагрузить - не помогает..
Поскольку задача мониторинг температуры на телекоммуникационных объектах - забил на это. Если минус - это уже плохо, а сколько там минус неважно. Думаю заказать себе датчик LM92 от National Semiconductor - у него точность +-1 от минус 10 и +-1,5 от -25.. но поэкспериментировать уже наверное не получится - пока дойдет до меня уже температуры в плюс уйдут ))
Вложенный файл - снятие показаний измерений. Сначала датчик лежал в комнате, а затем выкинул его за окно, как раз вечер и температура постепенно начала опускаться.
Вообще по наблюдениям при постепенном снижении температуры датчик на каком-то определенном пороге "клинит" и он начинает выдавать большой разброс до тех пор, пока этот порог не будет пройден (см. вложенный файл). Выдаваемое значение TTT нужно множить на 0,03125, значение TXTTEMP - среднее арифметическое). В файле видно что такой порог возникал на значениях -87 и -97. Чем ниже температура - тем больше идет разброс от измерения к измерению. То -120 выдаст (-3,75 градуса), через две секунды -85 (-2,65).. Пробовал перезагрузить - не помогает..
Поскольку задача мониторинг температуры на телекоммуникационных объектах - забил на это. Если минус - это уже плохо, а сколько там минус неважно. Думаю заказать себе датчик LM92 от National Semiconductor - у него точность +-1 от минус 10 и +-1,5 от -25.. но поэкспериментировать уже наверное не получится - пока дойдет до меня уже температуры в плюс уйдут ))
- Вложения
-
- ds1624.txt
- Показания DS1624 при снижении температуры от 18,75 до -3,5 градусов
- (82.81 КБ) 339 скачиваний
Re: Сопряжение 2313 и DS1621
Илья79, очень требуется помощь. В протоколе вроде я разобрался, но только понять одно не могу равна переменная freq в вашей программе( у меня тактовая частота равна 4 мгц).
это ваш код!
#include <io51.h> /*Подключение системной библиотеки= 2*/
#define SDA P1.0 /*Информационный сигнал шины i2c= 3*/
#define SCL P1.1 /*Тактовый сигнал шины i2c= 4*/
extern unsigned char freq; /*Частота ZQ1, МГц= 5*/
/*---------- задержки времени------------= 6*/
void pause(void) /*Задержка в зависимости от частоты= 7*/
{ unsigned char p; /*Счетчик циклов= 8*/
/*Строка-разделитель= 9*/
for (p = freq; p > 0; p--); /*Цикл задержки=10*/
return; /*Возврат после выполнения функции=11*/
} /*Окончание функции <pause>=12*/
/*---------- старта для шины i2c------------=13*/
void i2start(void) /*Команда START шины i2c=14*/
{ SDA = 1; pause(); /*Установка логических уровней=15*/
SCL = 1; pause(); /*с паузами между ними=16*/
SDA = 0; pause(); /*=17*/
SCL = 0; pause(); /*=18*/
return; /*Возврат после выполнения функции=19*/
} /*Окончание функции <i2start>=20*/
/*-------Функция записи байта через шину i2c--------=21*/
void i2write(unsigned char byt) /*Команда WRITE i2c=22*/
{ unsigned char k, m; /*Вспомогательные счетчики=23*/
/*Строка-разделитель=24*/
for (k = 0; k < 8; k++) /*Смена 8 битов в байте=25*/
{ m = 0x01 & (byt >> (7 - k)); /*Значение бита=26*/
SDA = m; pause(); /*Занесение бита в линию SDA=27*/
SCL = 1; pause(); /*Формирование одного=28*/
SCL = 0; pause(); /*тактового импульса SCL=29*/
} /*Окончание цикла передачи 8 битов=30*/
return; /*Возврат после выполнения функции=31*/
} /*Окончание функции <i2write>=32*/
/*-------Функция завершения работы с шиной i2c------=33*/
void i2stop(void) /*Команда STOP шины i2c=34*/
{ SDA = 0; pause(); /*Установка логических уровней=35*/
SCL = 1; pause(); /*с паузами между ними=36*/
SDA = 1; pause(); /*=37*/
return; /*Возврат после выполнения функции=38*/
} /*Окончание функции <i2stop>=39*/
/*--------Функция проверки бита подтверждения-------=40*/
unsigned char i2ack(void) /*Команда ACK шины i2c=41*/
{ unsigned char check, y; /*Данные и счетчик=42*/
/*Строка-разделитель=43*/
SDA = 1; pause(); /*Установка единичных уровней=44*/
SCL = 1; /*с паузой между ними=45*/
for (y = 10; y > 0; y--) /*10 попыток чтения=46*/
{ pause(); /*Задержка времени=47*/
if ((check = SDA) == 0) break; /*Досрочный выход=48*/
} /*Если за 10 чтений нет подтверждения, то ошибка=49*/
SCL = 0; pause(); /*Исходная установка линии SCL=50*/
return (check); /*Возврат (при CHECK=0 норма)=51*/
} /*Окончание функции <i2ack>=52*/
/*-------Функция выдачи бита подтверждения----------=53*/
void i2mack(void) /*Команда MASTER ACK шины i2c=54*/
{ SDA = 0; pause(); /*Установка бита подтверждения=55*/
SCL = 1; pause(); pause(); /*Генерация тактового=56*/
SCL = 0; pause(); /*импульса на линии SCL=57*/
return; /*Возврат после выполнения функции=58*/
} /*Окончание функции <i2mask>=59*/
/*-------Функция отсутствия бита подтверждения------=60*/
void i2nack(void) /*Команда NO ACK шины i2c=61*/
{ unsigned char y; /*Счетчик попыток=62*/
/*Строка-разделитель=63*/
SDA = 1; pause(); /*Режим чтения на линии SDA=64*/
SCL = 1; /*Начало единичного тактового импульса=65*/
for (y = 10; y > 0; y--) /*10 попыток чтения=66*/
{ pause(); /*Формирование полки тактового импульса=67*/
if (SDA != 0) break; /*Досрочный выход при норме=68*/
} /*Если за 10 чтений есть подтверждение - ошибка=69*/
SCL = 0; pause(); /*Исходная установка линии SCL=70*/
return; /*Возврат после выполнения функции=71*/
} /*Окончание функции <i2nack>=72*/
/*-------Функция чтения байта через шину i2c--------=73*/
unsigned char i2read(void) /*Команда READ шины i2c=74*/
{ unsigned char k, s, d=0; /*Счетчики и данные=75*/
/*Строка-разделитель=76*/
SDA = 1; /*Перевод линии SDA в режим чтения=77*/
for (s = k = 0; k < 8; k++) /*Цикл чтения 8 бит=78*/
{ SCL = 1; pause(); pause(); /*Начало такта=79*/
s = SDA << (7 - k); /*Чтение данных с линии SDA=80*/
d = d | s; pause(); pause(); /*Сборка байта=81*/
SCL = 0; pause(); pause(); /*Окончание такта=82*/
} /*Окончание цикла чтения 8 бит=83*/
return (d); /*Передача байта <d> в программу=84*/
} /*Окончание функции <i2read>=85*/
вот мой код.
/*************************************************************
Project name: "Thermo Controller" v.0.2
developed by: Coder Salyahov (e-mail: kukry@list.ru)
MC: ATtiny2313, PID controller, two 7digit, 2 buttons, I2C protocol
**************************************************************/
typedef unsigned char uint8;
typedef char int8;
#define TIME_DELAY_BUTT 1000 //time delay before increasing
#define TIME_DELAY_SHOW 1200 //time delay for showing control temper after pressed button
#define delta 1 //delta temperature for changing
#define Temp_max 99 //maximum temperature
#define Temp_min -60 //minimum temperature
#define READ 0
#define WRITE 1
#include <avr/interrupt.h>
#include <avr/iotn2313.h>
// Defines controlling timing limits
// ports for attiny2313
#define DDR_USI DDRB
#define PORT_USI PORTB
#define PIN_USI PINB
#define PORT_USI_SDA PORTB5
#define PORT_USI_SCL PORTB7
#define PIN_USI_SDA PINB5
#define PIN_USI_SCL PINB7
// General defines
#define TRUE 1
#define FALSE 0
int8_t contr_temp = 00; //Controlling temperature
unsigned char temperature; //temperature from sensor
char show_number[] = {0xff, 0xff};
// void pause(void)
// { unsigned char p;
//
// for (p = 40; p > 0; p--);
// return;
// }
/*Набор внешних функций i2c*/
extern unsigned char freq=13; /*Частота BQ1, МГц*/
/*---------- задержки времени------------*/
void pause(void) /*Задержка в зависимости от частоты*/
{ unsigned char p; /*Счетчик циклов*/
/*Строка-разделитель*/
for (p = freq; p > 0; p--); /*Цикл задержки*/
return; /*Возврат после выполнения функции*/
} /*Окончание функции <pause>*/
// //---------- старта для шины i2c------------*/
void i2start(void) /*Команда START шины i2c*/
{ PORT_USI|= (1<<PORT_USI_SDA); pause(); /*Установка логических уровней*/
PORT_USI|= (1<<PORT_USI_SCL); pause(); /*с паузами между ними*/
PORT_USI&=~(1<<PORT_USI_SDA); pause(); /**/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); /**/
return; /*Возврат после выполнения функции*/
} /*Окончание функции <i2start>*/
/*-------Функция записи байта через шину i2c--------*/
void i2write(unsigned char byt) /*Команда WRITE i2c*/
{ unsigned char k, m; /*Вспомогательные счетчики*/
/*Строка-разделитель*/
for (k = 0; k < 8; k++) /*Смена 8 битов в байте*/
{ m = 0x01 & (byt >> (7 - k)); /*Значение бита*/
if(m){
PORT_USI|= (1<<PORT_USI_SDA); pause();
} /*Занесение бита в линию SDA*/
else {PORT_USI&=~(1<<PORT_USI_SDA);pause();}
PORT_USI|= (1<<PORT_USI_SCL); pause(); /*Формирование одного*/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); /*тактового импульса SCL=29*/
} /*Окончание цикла передачи 8 битов=*/
return; /*Возврат после выполнения функции=*/
} /*Окончание функции <i2write>=*/
/*-------Функция завершения работы с шиной i2c------=*/
void i2stop(void) /*Команда STOP шины i2c=*/
{ PORT_USI&=~(1<<PORT_USI_SDA); pause(); /*Установка логических уровней=*/
PORT_USI|= (1<<PORT_USI_SCL); pause(); /*с паузами между ними=*/
PORT_USI|= (1<<PORT_USI_SDA); pause(); /*=*/
return; /*Возврат после выполнения функции=*/
} /*Окончание функции <i2stop>=*/
/*--------Функция проверки бита подтверждения-------=*/
unsigned char i2ack(void) /*Команда ACK шины i2c=*/
{ unsigned char check=0, y; /*Данные и счетчик=*/
/*Строка-разделитель=*/
PORT_USI|= (1<<PORT_USI_SDA);
DDR_USI&=~(1<<PORT_USI_SDA); pause(); /*Установка единичных уровней= настройка порта на вход*/
PORT_USI|= (1<<PORT_USI_SCL); /*с паузой между ними=*/
for (y = 10; y > 0; y--) /*10 попыток чтения=*/
{ pause(); /*Задержка времени=*/
if (((PIN_USI&(1<<PORT_USI_SDA))==0)) {check=96; return(33);} /*Досрочный выход=*/
} /*Если за 10 чтений нет подтверждения, то ошибка=*/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); /*Исходная установка линии SCL=*/
DDR_USI|= (1<<PORT_USI_SDA);
return (check); /*Возврат (при CHECK=0 норма)=*/
} /*Окончание функции <i2ack>=*/
/*-------Функция выдачи бита подтверждения----------=*/
void i2mack(void) /*Команда MASTER ACK шины i2c=*/
{ PORT_USI&=~(1<<PORT_USI_SDA); pause(); /*Установка бита подтверждения=*/
PORT_USI|= (1<<PORT_USI_SCL); pause(); /*Генерация тактового=*/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); /*импульса на линии SCL=*/
return; /*Возврат после выполнения функции=*/
} /*Окончание функции <i2mask>=*/
/*-------Функция отсутствия бита подтверждения------=*/
void i2nack(void) /*Команда NO ACK шины i2c=*/
{ unsigned char y; /*Счетчик попыток=*/
/*Строка-разделитель=*/
PORT_USI|= (1<<PORT_USI_SDA); pause(); /*Режим чтения на линии SDA=*/
PORT_USI|= (1<<PORT_USI_SCL); /*Начало единичного тактового импульса=*/
for (y = 10; y > 0; y--) /*10 попыток чтения=*/
{ pause(); /*Формирование полки тактового импульса=*/
if (((PORT_USI|(1<<PORT_USI_SDA))>>PORT_USI_SDA) != 0) break; /*Досрочный выход при норме=*/
} /*Если за 10 чтений есть подтверждение - ошибка=*/
PORT_USI&= ~(1<<PORT_USI_SCL); pause(); /*Исходная установка линии SCL=70*/
return; /*Возврат после выполнения функции=*/
} /*Окончание функции <i2nack>=*/
/*-------Функция чтения байта через шину i2c--------=*/
unsigned char i2read(void) /*Команда READ шины i2c=*/
{ unsigned char k, s, d=0; /*Счетчики и данные=*/
/*Строка-разделитель=*/
DDR_USI&=~(1<<PORT_USI_SDA); /*Перевод линии SDA в режим чтения=*/
for (s = k = 0; k < 8; k++) /*Цикл чтения 8 бит=*/
{ PORT_USI|= (1<<PORT_USI_SDA); pause(); pause(); /*Начало такта=*/
s = (PIN_USI&(1<<PORT_USI_SDA)) << (7 - k); /*Чтение данных с линии SDA=*/
d = d | s; pause(); pause(); /*Сборка байта=81*/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); pause(); /*Окончание такта=*/
} /*Окончание цикла чтения 8 бит=*/
return (d); /*Передача байта <d> в программу=*/
} //Окончание функции <i2read>=
void solve_digit (int number) //subscription to showing temperature on display
{
uint8_t segments[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f};
uint8_t k;
if ((number < Temp_max) && (number > Temp_min)) //verify number for showing on display
{
if (number < 0) //if number is negative
{
show_number[0] = 1 << 7;
show_number[1] = 1 << 7;
number = 0 - number; //change sign
}
if (number >= 0)
{
k = 0;
while (number >= k * 10) k++; //k - tens of
show_number[0] = segments[--k];
show_number[1] = segments[number - k * 10];
}
}
else //invalid mean of the temperature show "Er"
{
show_number [0] = 0x79; //"E"
show_number[1] = 0x50; //"r"
}
}
void butt_and_display ()
{
/* show 2 digits on display */
//solve_digit (contr_temp);
int time;
int time_show;
int butt;
char temp;
uint8_t term;
if (time_show > 0) {solve_digit(contr_temp);term=0;} //show temperature of the control
time_show--;
if (time_show == 0) {solve_digit(temperature);term=1;} //show env (real) temperature on display
if (time & 1) temp = ~show_number[1]; //show first digit
else temp = ~show_number[0]; //show second digit
if((time_show > 0 && contr_temp<0)||(term==1 && temperature<0))
{
PORTD = (PORTD & (~(1 << PD2)));
}
PORTD = (PORTD & (~(1 << PD4)))| ((time & 1) << PD4);
PORTB = (PORTB & 0xE0)|(temp & 0x1f); //вывод на семисегментные инд
PORTD = (PORTD & 0xF8)|((temp >> 5) & 0x07);
// Negativ Temperature
//PORTD = ((~PORTD) & (1 << PD4)) | (PORTD & (~(1 << PD4))); //show other digit
/* buttons */
time++;
if ((!(PIND & (1 << PD3)))||(!(PINB & (1 << PB6))))
{
time_show = TIME_DELAY_SHOW;
if ((butt > TIME_DELAY_BUTT) || (butt == 0))
{
if ((butt & 0b00001111) == 0)
{
if (!(PIND & (1 << PD3))) contr_temp -= delta; //если нажата кнопка '>'
if (!(PINB & (1 << PB6))) contr_temp += delta; //если нажата кнопка '<'
if (contr_temp > 99) contr_temp = Temp_max; //max
if (contr_temp < -60) contr_temp = Temp_min; //min
}
}
butt++;
}
else butt = 0;
//if (time == 255) time =0;
PORTB |=0x1F;
PORTD |=0x07;
/* если возник перенос разряда, то сохранить значение в EEPROM*/
//eeprom_update_byte(&contr_temp_eeprom, &contr_temp); //update e2prom meaning
/* pwm for fan */
//PORTD = (((~PORTD) & (1 << PD5)) | (PORTD & ~(1 << PD5)));
}
ISR (TIMER0_OVF_vect) //timer0 interrupt for twi 100kHz
{
butt_and_display ();//show on 7seg digit
}
// ISR (TIMER1_OVF_vect) //timer1 interrupt
// {
// i2c_start();// command for read temperature
// temperature = i2c_write(0xA0 | (1 << 1) | READ);
// i2c_write(0xAA);
// i2c_stop();// command for read temperature
// i2c_start();
// i2c_write(0xA0 | (1 << 1) | WRITE);
// uint8_t temp = i2c_read();
// uint8_t temp2 = i2c_read();
// i2c_stop();
// temperature=(temp);
// }
int main (void)
{
//asm("cli");
unsigned char tem2;
PORTB = 0b01000000;
DDRB = 0b00011111;
PORTD = 0b00011000;
DDRD = 0b11110111;
GIMSK = 0x00; //---
TCCR0B = (1<<CS00); //без делителя тактовой частоты
TIMSK |= (1 << TOIE0);
//TIMSK |= (1 << TOIE1);
asm("sei"); //разрешить прерывания
//PORTB = 0xff & 0x1f;
temperature=20;
solve_digit(contr_temp);//вывод на семисегментные индикаторы
//начать конвертирование температуры
i2start();
i2write(0b10010010);
temperature=i2ack();
i2mack();
i2write(0xEE);
i2ack();
i2mack();
i2stop();
//start convert
//чтение температуры
//чтение температуры
while (1) //зацикливание
{
//asm("sleep"); //sleep
//temperature = read_temp (1); //read temperature from DS1624
//solve_digit (temperature);
i2start();
i2write(0b10010010);
i2ack();
i2mack();
i2write(0xAA);
i2ack();
i2mack();
i2start();
i2write(0b10010011);
i2ack();
i2mack();
temperature=i2read();
i2ack();
i2mack();
tem2=i2read();
i2nack();
i2stop();
if (temperature - contr_temp > 0) PORTD |= 1 << PD6; // начать нагрев
else PORTD &= ~(1 << PD6) ; // остановить нагрев
}
return 1;
}
это ваш код!
#include <io51.h> /*Подключение системной библиотеки= 2*/
#define SDA P1.0 /*Информационный сигнал шины i2c= 3*/
#define SCL P1.1 /*Тактовый сигнал шины i2c= 4*/
extern unsigned char freq; /*Частота ZQ1, МГц= 5*/
/*---------- задержки времени------------= 6*/
void pause(void) /*Задержка в зависимости от частоты= 7*/
{ unsigned char p; /*Счетчик циклов= 8*/
/*Строка-разделитель= 9*/
for (p = freq; p > 0; p--); /*Цикл задержки=10*/
return; /*Возврат после выполнения функции=11*/
} /*Окончание функции <pause>=12*/
/*---------- старта для шины i2c------------=13*/
void i2start(void) /*Команда START шины i2c=14*/
{ SDA = 1; pause(); /*Установка логических уровней=15*/
SCL = 1; pause(); /*с паузами между ними=16*/
SDA = 0; pause(); /*=17*/
SCL = 0; pause(); /*=18*/
return; /*Возврат после выполнения функции=19*/
} /*Окончание функции <i2start>=20*/
/*-------Функция записи байта через шину i2c--------=21*/
void i2write(unsigned char byt) /*Команда WRITE i2c=22*/
{ unsigned char k, m; /*Вспомогательные счетчики=23*/
/*Строка-разделитель=24*/
for (k = 0; k < 8; k++) /*Смена 8 битов в байте=25*/
{ m = 0x01 & (byt >> (7 - k)); /*Значение бита=26*/
SDA = m; pause(); /*Занесение бита в линию SDA=27*/
SCL = 1; pause(); /*Формирование одного=28*/
SCL = 0; pause(); /*тактового импульса SCL=29*/
} /*Окончание цикла передачи 8 битов=30*/
return; /*Возврат после выполнения функции=31*/
} /*Окончание функции <i2write>=32*/
/*-------Функция завершения работы с шиной i2c------=33*/
void i2stop(void) /*Команда STOP шины i2c=34*/
{ SDA = 0; pause(); /*Установка логических уровней=35*/
SCL = 1; pause(); /*с паузами между ними=36*/
SDA = 1; pause(); /*=37*/
return; /*Возврат после выполнения функции=38*/
} /*Окончание функции <i2stop>=39*/
/*--------Функция проверки бита подтверждения-------=40*/
unsigned char i2ack(void) /*Команда ACK шины i2c=41*/
{ unsigned char check, y; /*Данные и счетчик=42*/
/*Строка-разделитель=43*/
SDA = 1; pause(); /*Установка единичных уровней=44*/
SCL = 1; /*с паузой между ними=45*/
for (y = 10; y > 0; y--) /*10 попыток чтения=46*/
{ pause(); /*Задержка времени=47*/
if ((check = SDA) == 0) break; /*Досрочный выход=48*/
} /*Если за 10 чтений нет подтверждения, то ошибка=49*/
SCL = 0; pause(); /*Исходная установка линии SCL=50*/
return (check); /*Возврат (при CHECK=0 норма)=51*/
} /*Окончание функции <i2ack>=52*/
/*-------Функция выдачи бита подтверждения----------=53*/
void i2mack(void) /*Команда MASTER ACK шины i2c=54*/
{ SDA = 0; pause(); /*Установка бита подтверждения=55*/
SCL = 1; pause(); pause(); /*Генерация тактового=56*/
SCL = 0; pause(); /*импульса на линии SCL=57*/
return; /*Возврат после выполнения функции=58*/
} /*Окончание функции <i2mask>=59*/
/*-------Функция отсутствия бита подтверждения------=60*/
void i2nack(void) /*Команда NO ACK шины i2c=61*/
{ unsigned char y; /*Счетчик попыток=62*/
/*Строка-разделитель=63*/
SDA = 1; pause(); /*Режим чтения на линии SDA=64*/
SCL = 1; /*Начало единичного тактового импульса=65*/
for (y = 10; y > 0; y--) /*10 попыток чтения=66*/
{ pause(); /*Формирование полки тактового импульса=67*/
if (SDA != 0) break; /*Досрочный выход при норме=68*/
} /*Если за 10 чтений есть подтверждение - ошибка=69*/
SCL = 0; pause(); /*Исходная установка линии SCL=70*/
return; /*Возврат после выполнения функции=71*/
} /*Окончание функции <i2nack>=72*/
/*-------Функция чтения байта через шину i2c--------=73*/
unsigned char i2read(void) /*Команда READ шины i2c=74*/
{ unsigned char k, s, d=0; /*Счетчики и данные=75*/
/*Строка-разделитель=76*/
SDA = 1; /*Перевод линии SDA в режим чтения=77*/
for (s = k = 0; k < 8; k++) /*Цикл чтения 8 бит=78*/
{ SCL = 1; pause(); pause(); /*Начало такта=79*/
s = SDA << (7 - k); /*Чтение данных с линии SDA=80*/
d = d | s; pause(); pause(); /*Сборка байта=81*/
SCL = 0; pause(); pause(); /*Окончание такта=82*/
} /*Окончание цикла чтения 8 бит=83*/
return (d); /*Передача байта <d> в программу=84*/
} /*Окончание функции <i2read>=85*/
вот мой код.
/*************************************************************
Project name: "Thermo Controller" v.0.2
developed by: Coder Salyahov (e-mail: kukry@list.ru)
MC: ATtiny2313, PID controller, two 7digit, 2 buttons, I2C protocol
**************************************************************/
typedef unsigned char uint8;
typedef char int8;
#define TIME_DELAY_BUTT 1000 //time delay before increasing
#define TIME_DELAY_SHOW 1200 //time delay for showing control temper after pressed button
#define delta 1 //delta temperature for changing
#define Temp_max 99 //maximum temperature
#define Temp_min -60 //minimum temperature
#define READ 0
#define WRITE 1
#include <avr/interrupt.h>
#include <avr/iotn2313.h>
// Defines controlling timing limits
// ports for attiny2313
#define DDR_USI DDRB
#define PORT_USI PORTB
#define PIN_USI PINB
#define PORT_USI_SDA PORTB5
#define PORT_USI_SCL PORTB7
#define PIN_USI_SDA PINB5
#define PIN_USI_SCL PINB7
// General defines
#define TRUE 1
#define FALSE 0
int8_t contr_temp = 00; //Controlling temperature
unsigned char temperature; //temperature from sensor
char show_number[] = {0xff, 0xff};
// void pause(void)
// { unsigned char p;
//
// for (p = 40; p > 0; p--);
// return;
// }
/*Набор внешних функций i2c*/
extern unsigned char freq=13; /*Частота BQ1, МГц*/
/*---------- задержки времени------------*/
void pause(void) /*Задержка в зависимости от частоты*/
{ unsigned char p; /*Счетчик циклов*/
/*Строка-разделитель*/
for (p = freq; p > 0; p--); /*Цикл задержки*/
return; /*Возврат после выполнения функции*/
} /*Окончание функции <pause>*/
// //---------- старта для шины i2c------------*/
void i2start(void) /*Команда START шины i2c*/
{ PORT_USI|= (1<<PORT_USI_SDA); pause(); /*Установка логических уровней*/
PORT_USI|= (1<<PORT_USI_SCL); pause(); /*с паузами между ними*/
PORT_USI&=~(1<<PORT_USI_SDA); pause(); /**/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); /**/
return; /*Возврат после выполнения функции*/
} /*Окончание функции <i2start>*/
/*-------Функция записи байта через шину i2c--------*/
void i2write(unsigned char byt) /*Команда WRITE i2c*/
{ unsigned char k, m; /*Вспомогательные счетчики*/
/*Строка-разделитель*/
for (k = 0; k < 8; k++) /*Смена 8 битов в байте*/
{ m = 0x01 & (byt >> (7 - k)); /*Значение бита*/
if(m){
PORT_USI|= (1<<PORT_USI_SDA); pause();
} /*Занесение бита в линию SDA*/
else {PORT_USI&=~(1<<PORT_USI_SDA);pause();}
PORT_USI|= (1<<PORT_USI_SCL); pause(); /*Формирование одного*/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); /*тактового импульса SCL=29*/
} /*Окончание цикла передачи 8 битов=*/
return; /*Возврат после выполнения функции=*/
} /*Окончание функции <i2write>=*/
/*-------Функция завершения работы с шиной i2c------=*/
void i2stop(void) /*Команда STOP шины i2c=*/
{ PORT_USI&=~(1<<PORT_USI_SDA); pause(); /*Установка логических уровней=*/
PORT_USI|= (1<<PORT_USI_SCL); pause(); /*с паузами между ними=*/
PORT_USI|= (1<<PORT_USI_SDA); pause(); /*=*/
return; /*Возврат после выполнения функции=*/
} /*Окончание функции <i2stop>=*/
/*--------Функция проверки бита подтверждения-------=*/
unsigned char i2ack(void) /*Команда ACK шины i2c=*/
{ unsigned char check=0, y; /*Данные и счетчик=*/
/*Строка-разделитель=*/
PORT_USI|= (1<<PORT_USI_SDA);
DDR_USI&=~(1<<PORT_USI_SDA); pause(); /*Установка единичных уровней= настройка порта на вход*/
PORT_USI|= (1<<PORT_USI_SCL); /*с паузой между ними=*/
for (y = 10; y > 0; y--) /*10 попыток чтения=*/
{ pause(); /*Задержка времени=*/
if (((PIN_USI&(1<<PORT_USI_SDA))==0)) {check=96; return(33);} /*Досрочный выход=*/
} /*Если за 10 чтений нет подтверждения, то ошибка=*/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); /*Исходная установка линии SCL=*/
DDR_USI|= (1<<PORT_USI_SDA);
return (check); /*Возврат (при CHECK=0 норма)=*/
} /*Окончание функции <i2ack>=*/
/*-------Функция выдачи бита подтверждения----------=*/
void i2mack(void) /*Команда MASTER ACK шины i2c=*/
{ PORT_USI&=~(1<<PORT_USI_SDA); pause(); /*Установка бита подтверждения=*/
PORT_USI|= (1<<PORT_USI_SCL); pause(); /*Генерация тактового=*/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); /*импульса на линии SCL=*/
return; /*Возврат после выполнения функции=*/
} /*Окончание функции <i2mask>=*/
/*-------Функция отсутствия бита подтверждения------=*/
void i2nack(void) /*Команда NO ACK шины i2c=*/
{ unsigned char y; /*Счетчик попыток=*/
/*Строка-разделитель=*/
PORT_USI|= (1<<PORT_USI_SDA); pause(); /*Режим чтения на линии SDA=*/
PORT_USI|= (1<<PORT_USI_SCL); /*Начало единичного тактового импульса=*/
for (y = 10; y > 0; y--) /*10 попыток чтения=*/
{ pause(); /*Формирование полки тактового импульса=*/
if (((PORT_USI|(1<<PORT_USI_SDA))>>PORT_USI_SDA) != 0) break; /*Досрочный выход при норме=*/
} /*Если за 10 чтений есть подтверждение - ошибка=*/
PORT_USI&= ~(1<<PORT_USI_SCL); pause(); /*Исходная установка линии SCL=70*/
return; /*Возврат после выполнения функции=*/
} /*Окончание функции <i2nack>=*/
/*-------Функция чтения байта через шину i2c--------=*/
unsigned char i2read(void) /*Команда READ шины i2c=*/
{ unsigned char k, s, d=0; /*Счетчики и данные=*/
/*Строка-разделитель=*/
DDR_USI&=~(1<<PORT_USI_SDA); /*Перевод линии SDA в режим чтения=*/
for (s = k = 0; k < 8; k++) /*Цикл чтения 8 бит=*/
{ PORT_USI|= (1<<PORT_USI_SDA); pause(); pause(); /*Начало такта=*/
s = (PIN_USI&(1<<PORT_USI_SDA)) << (7 - k); /*Чтение данных с линии SDA=*/
d = d | s; pause(); pause(); /*Сборка байта=81*/
PORT_USI&=~(1<<PORT_USI_SCL); pause(); pause(); /*Окончание такта=*/
} /*Окончание цикла чтения 8 бит=*/
return (d); /*Передача байта <d> в программу=*/
} //Окончание функции <i2read>=
void solve_digit (int number) //subscription to showing temperature on display
{
uint8_t segments[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f};
uint8_t k;
if ((number < Temp_max) && (number > Temp_min)) //verify number for showing on display
{
if (number < 0) //if number is negative
{
show_number[0] = 1 << 7;
show_number[1] = 1 << 7;
number = 0 - number; //change sign
}
if (number >= 0)
{
k = 0;
while (number >= k * 10) k++; //k - tens of
show_number[0] = segments[--k];
show_number[1] = segments[number - k * 10];
}
}
else //invalid mean of the temperature show "Er"
{
show_number [0] = 0x79; //"E"
show_number[1] = 0x50; //"r"
}
}
void butt_and_display ()
{
/* show 2 digits on display */
//solve_digit (contr_temp);
int time;
int time_show;
int butt;
char temp;
uint8_t term;
if (time_show > 0) {solve_digit(contr_temp);term=0;} //show temperature of the control
time_show--;
if (time_show == 0) {solve_digit(temperature);term=1;} //show env (real) temperature on display
if (time & 1) temp = ~show_number[1]; //show first digit
else temp = ~show_number[0]; //show second digit
if((time_show > 0 && contr_temp<0)||(term==1 && temperature<0))
{
PORTD = (PORTD & (~(1 << PD2)));
}
PORTD = (PORTD & (~(1 << PD4)))| ((time & 1) << PD4);
PORTB = (PORTB & 0xE0)|(temp & 0x1f); //вывод на семисегментные инд
PORTD = (PORTD & 0xF8)|((temp >> 5) & 0x07);
// Negativ Temperature
//PORTD = ((~PORTD) & (1 << PD4)) | (PORTD & (~(1 << PD4))); //show other digit
/* buttons */
time++;
if ((!(PIND & (1 << PD3)))||(!(PINB & (1 << PB6))))
{
time_show = TIME_DELAY_SHOW;
if ((butt > TIME_DELAY_BUTT) || (butt == 0))
{
if ((butt & 0b00001111) == 0)
{
if (!(PIND & (1 << PD3))) contr_temp -= delta; //если нажата кнопка '>'
if (!(PINB & (1 << PB6))) contr_temp += delta; //если нажата кнопка '<'
if (contr_temp > 99) contr_temp = Temp_max; //max
if (contr_temp < -60) contr_temp = Temp_min; //min
}
}
butt++;
}
else butt = 0;
//if (time == 255) time =0;
PORTB |=0x1F;
PORTD |=0x07;
/* если возник перенос разряда, то сохранить значение в EEPROM*/
//eeprom_update_byte(&contr_temp_eeprom, &contr_temp); //update e2prom meaning
/* pwm for fan */
//PORTD = (((~PORTD) & (1 << PD5)) | (PORTD & ~(1 << PD5)));
}
ISR (TIMER0_OVF_vect) //timer0 interrupt for twi 100kHz
{
butt_and_display ();//show on 7seg digit
}
// ISR (TIMER1_OVF_vect) //timer1 interrupt
// {
// i2c_start();// command for read temperature
// temperature = i2c_write(0xA0 | (1 << 1) | READ);
// i2c_write(0xAA);
// i2c_stop();// command for read temperature
// i2c_start();
// i2c_write(0xA0 | (1 << 1) | WRITE);
// uint8_t temp = i2c_read();
// uint8_t temp2 = i2c_read();
// i2c_stop();
// temperature=(temp);
// }
int main (void)
{
//asm("cli");
unsigned char tem2;
PORTB = 0b01000000;
DDRB = 0b00011111;
PORTD = 0b00011000;
DDRD = 0b11110111;
GIMSK = 0x00; //---
TCCR0B = (1<<CS00); //без делителя тактовой частоты
TIMSK |= (1 << TOIE0);
//TIMSK |= (1 << TOIE1);
asm("sei"); //разрешить прерывания
//PORTB = 0xff & 0x1f;
temperature=20;
solve_digit(contr_temp);//вывод на семисегментные индикаторы
//начать конвертирование температуры
i2start();
i2write(0b10010010);
temperature=i2ack();
i2mack();
i2write(0xEE);
i2ack();
i2mack();
i2stop();
//start convert
//чтение температуры
//чтение температуры
while (1) //зацикливание
{
//asm("sleep"); //sleep
//temperature = read_temp (1); //read temperature from DS1624
//solve_digit (temperature);
i2start();
i2write(0b10010010);
i2ack();
i2mack();
i2write(0xAA);
i2ack();
i2mack();
i2start();
i2write(0b10010011);
i2ack();
i2mack();
temperature=i2read();
i2ack();
i2mack();
tem2=i2read();
i2nack();
i2stop();
if (temperature - contr_temp > 0) PORTD |= 1 << PD6; // начать нагрев
else PORTD &= ~(1 << PD6) ; // остановить нагрев
}
return 1;
}