Помогите решить проблему с DS18b20
Модератор: boogyman
Помогите решить проблему с DS18b20
Здравствуйте. Сам я далек от программирования, но возникшая проблема вынуждает обратиться к вам за помощью.
Имеется: линия с 8 DS18B20 - cхемка на двух транзисторах(внизу) - адаптер RS232-USB "Z-Tek" - компьютер - программа TempKeeper. Система отлично работала несколько дней и вдруг:
1 - На одном датчике стала плавать(произвольно меняться в процессе измерения) битность с 9 до 12. В свойствах датчика битность - 12
2 - На другом датчике стала плавать(произвольно меняться в процессе измерения) битность с 9 до 11. В свойствах битность - 11
3 - На остальных битность 9, в свойствах - пробел. Программой задана на все датч битность 12
Первым делом отключил линию, подключил новый DS прямо на плату, результ - см выше п.1 . Пробовал поменять комп и ставил другие программы Т-мониторинга - все то же самое. Еще пробовал время изм 750мс менять.
Для меня важна не столько точность, сколь высокое разрешение.
Очень надеюсь на вашу помощь.
Имеется: линия с 8 DS18B20 - cхемка на двух транзисторах(внизу) - адаптер RS232-USB "Z-Tek" - компьютер - программа TempKeeper. Система отлично работала несколько дней и вдруг:
1 - На одном датчике стала плавать(произвольно меняться в процессе измерения) битность с 9 до 12. В свойствах датчика битность - 12
2 - На другом датчике стала плавать(произвольно меняться в процессе измерения) битность с 9 до 11. В свойствах битность - 11
3 - На остальных битность 9, в свойствах - пробел. Программой задана на все датч битность 12
Первым делом отключил линию, подключил новый DS прямо на плату, результ - см выше п.1 . Пробовал поменять комп и ставил другие программы Т-мониторинга - все то же самое. Еще пробовал время изм 750мс менять.
Для меня важна не столько точность, сколь высокое разрешение.
Очень надеюсь на вашу помощь.
Re: Помогите решить проблему с DS18b20
Здравствуйте. Запустил в протеусе термометр по этой статье https://radioparty.ru/programming/avr/c ... n2-ds18b20 На Atmega 8, всё работает. Хотел переделать под Atmega328p, заменил в настройках таймера регистры TIMSK и TCCR2 на TIMSK2 и TCCR2B, всё остральное не трогал. В итоге экран показывает одни прочерки (. Подскажите пожалуйста, может я забыл ещё что-то изменить ? Вот на всякий случай код
Код: Выделить всё
// Подключение цифровых датчиков температуры DS18B20 к AVR
#define F_CPU 8000000UL // Устанавливаем рабочую частоту контроллера
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
// Массив значениий для семисегментного индикатора
char SEGMENTE[] =
{
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F, // 9
0x40, // "минус"
0x00 // "пусто"
};
unsigned char segcounter = 0;
volatile unsigned char display_1, display_2, display_3, display_4;
// Прерывание по переполнению T2, динамическая индикация
ISR (TIMER2_OVF_vect)
{
PORTD = 0xFF;
PORTB = (1 << segcounter);
switch (segcounter)
{
case 0:
PORTD = ~(SEGMENTE[display_1]);
break;
case 1:
PORTD = ~(SEGMENTE[display_2]);
break;
case 2:
PORTD = ~((SEGMENTE[display_3])|0x80); // добавляем точку
break;
case 3:
PORTD = ~(SEGMENTE[display_4]);
break;
}
if ((segcounter++) > 2) segcounter = 0;
}
unsigned char Temp_H, Temp_L, OK_Flag, temp_flag;
// Инициализация DS18B20
unsigned char DS18B20_init(void)
{
DDRC |= (1 << PC0); // PC0 - выход
PORTC &= ~(1 << PC0); // Устанавливаем низкий уровень
_delay_us(490);
DDRC &= ~(1 << PC0); // PC0 - вход
_delay_us(68);
OK_Flag = (PINC & (1 << PC0)); // Ловим импульс присутствия датчика
// если OK_Flag = 0 датчик подключен, OK_Flag = 1 датчик не подключен
_delay_us(422);
return OK_Flag;
}
// Функция чтения байта из DS18B20
unsigned char read_18b20(void)
{
unsigned char i, data = 0;
for(i = 0; i < 8; i++)
{
DDRC |= (1 << PC0); // PC0 - выход
_delay_us(2);
DDRC &= ~(1 << PC0); // PC0 - вход
_delay_us(4);
data = data >> 1; // Следующий бит
if(PINC & (1 << PC0)) data |= 0x80;
_delay_us(62);
}
return data;
}
// Функция записи байта в DS18B20
void write_18b20(unsigned char data)
{
unsigned char i;
for(i = 0; i < 8; i++)
{
DDRC |= (1 << PC0); // PC0 - выход
_delay_us(2);
if(data & 0x01) DDRC &= ~(1 << PC0);
else DDRC |= (1 << PC0);
data = data >> 1; // Следующий бит
_delay_us(62);
DDRC &= ~(1 << PC0); // PC0 - вход
_delay_us(2);
}
}
// Главная функция
int main(void)
{
// Настройка портов ввода/вывода
DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3); // Разряды
PORTB = 0x00;
DDRD = 0xFF; // Сегменты
PORTD = 0x00;
// Настройка Т2
TIMSK2 |= (1 << TOIE2); // Разрешение прерывания по Т2
TCCR2B |= (1 << CS21); // Предделитель на 8
unsigned int buffer;
unsigned int temp_int_1,temp_int_2,temp_int_3; // Переменные для целого значения температуры
unsigned int temp_point; // Переменная для дробного значения температуры
sei(); // Глобально разрешаем прерывания
while(1)
{
// Если датчик не ответил выводим "минус" во всех разрядах
if(OK_Flag) display_1 = display_2 = display_3 = display_4 = 10;
DS18B20_init(); // Инициализация DS18B20
write_18b20(0xCC); // Проверка кода датчика
write_18b20(0x44); // Запуск температурного преобразования
_delay_ms(1000); // Задержка на опрос датчика
DS18B20_init(); // Инициализация DS18B20
write_18b20(0xCC); // Проверка кода датчика
write_18b20(0xBE); // Считываем содержимое ОЗУ
Temp_L = read_18b20(); // Читаем первые 2 байта блокнота
Temp_H = read_18b20();
temp_flag = 1; // Флаг знака температуры равен 1(плюс)
// Вычисляем отрицательную температуру
if(Temp_H &(1 << 3)) // Проверяем бит знака температуры на равенство единице
{
signed int temp;
temp_flag = 0; // Флаг знака равен 0(минус)
temp = (Temp_H << 8)|Temp_L;
temp = -temp; // Переводим дополнительный код в прямой
Temp_L = temp;
Temp_H = temp >> 8;
}
// Вычисляем целое значение температуры
buffer = ((Temp_H << 4) & 0x70)|(Temp_L >> 4);
temp_int_1 = buffer % 1000 / 100;
temp_int_2 = buffer % 100 / 10;
temp_int_3 = buffer % 10;
// Вычисляем дробное значение температуры
if(temp_flag == 0) buffer = (Temp_L & 0x0F) + 1;
else buffer = (Temp_L & 0x0F);
temp_point = buffer * 625 / 1000; // Точность темпер.преобразования(0.0625)
// Если флаг знака температуры равен 0, в первом разряде ставим минус
if(temp_flag == 0) temp_int_1 = 10; // "минус"
// Если первая цифра значения температуры меньше 1, то гасим 1-й разряд индикатора
if(temp_int_1 < 1) temp_int_1 = 11; // "пусто"
// Если первая цифра погашена и вторая цифра значения температуры меньше 1, то гасим 2-й разряд индикатора
if(temp_int_1 == 11 && temp_int_2 < 1) temp_int_2 = 11; // "пусто"
// Если вторая цифра значения температуры меньше 1 и знак равен "минус", то гасим 2-й разряд индикатора
if(temp_int_2 < 1 && temp_flag == 0) temp_int_2 = 11; // "пусто"
// Выводим значения на дисплей
display_1 = temp_int_1;
display_2 = temp_int_2;
display_3 = temp_int_3;
display_4 = temp_point;
}
}
- AntonChip
- Администратор
- Сообщения: 265
- Зарегистрирован: 24 дек 2011, 22:11
- Откуда: Киров
- Контактная информация:
Re: Помогите решить проблему с DS18b20
Здравствуйте. Возможно неправильно установлена частота микроконтроллера, установлен бит CLKDIV8
- microsystems
- Любитель
- Сообщения: 12
- Зарегистрирован: 11 дек 2019, 19:40
Re: Помогите решить проблему с DS18b20
прочерки - значит датчик не читается, так вроде бы?
Re: Помогите решить проблему с DS18b20
А atmel studio и протеусе стоит 8 Мгц
А где его проверить ?CLKDIV8
Re: Помогите решить проблему с DS18b20
Нашёл, в протеусе поставил CLKDIV8 в (1) Unprogrammed, было (0) Programmed и всё заработало. А как в железе нормально будет работать ?
- AntonChip
- Администратор
- Сообщения: 265
- Зарегистрирован: 24 дек 2011, 22:11
- Откуда: Киров
- Контактная информация:
Re: Помогите решить проблему с DS18b20
В железе работает, проверено
Re: Помогите решить проблему с DS18b20
У меня не получилось( Правда у меня другой дисплей (SSD1306). Пробую выводить на него переменные temp_int_1,temp_int_2,temp_int_3.
Вместо них экран показывает :;01 При нагревании датчика нечего не меняется. Может при прошивке в avrdude попробывать убрать галочку с фьюза CKDIV8 ?
Re: Помогите решить проблему с DS18b20
Ура заработало. Пришлось убрать галочку CKDIV8 в avrdude. Спасибо за помощь.