Температуру стандартная функция CVAVR'а возвращает типа float, т.е. с плавающей запятой. Если тебе не нужна дробная часть температуры то в твоем примере:
temp может быть типа int, т.е. integer - целое. При присвоении дробная часть значения температуры отбросится и останется только нужная тебе целая часть.
По поводу получения цифр для вывода на индикаторы. Я делаю так:
//therm - значение тепературы, тип int, пусть будет 28 градусов
//led_out - функция вывода на индикаторы.
led_out(0, therm/10)); //После деления 28 на 10 остается только целая часть от деления(потому что аргумент функции типа int) - 2, ее выводим на первый индикатор
led_out(1, fmod(therm, 10)); //fmod возвращает остаток от деления therm на 10, т.е. 8, выводим ее на второй индикатор
В конец измучился с этим термометром. Не работает. С выводом на индикатор разобрался. Выводит любые 2-х значные числа правильно.
Подключил датчик - постоянно "1" и быстро мерцает. В протэусе всё работает. В железе нет. Было замечено несколько раз в протеусе при изменении температуры на экран на некоторое время выводилась "1", потом опять нормальная температура. Я уже вообще ничего теперь не понимаю.
честно говоря, я уже потерял нить вашей пробелмы... но если хотите - скачайте исходник к моему проекту мини-термостата и поглядите, как организовано все - от работы с датчиком до вывода на индикатор. ну а потом сделаете свой, улучшенный вариант.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
.......
#asm
.equ __w1_port=0x18 ;PORTB
.equ __w1_bit=0
#endasm
char digit_out[2], cur_dig=0; //переменные для работы с LED
int indicator=0, temp; //переменные для вывода
......
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTC=0x00;
PORTD=0xFF;
if (cur_dig==0) {PORTC.2=1; PORTC.1=0; PORTD=digits[digit_out[cur_dig]];}
// для отображения только одной цифры если t<10 (без 0 слева)
else {PORTC.1=1; PORTC.2=0; if (indicator<10) {PORTD=0b11111111;} else {PORTD=digits[digit_out[cur_dig]];};}
cur_dig++;
if(cur_dig==2) {cur_dig=0;}
}
void cifri_v_massiv (void) { // функция для перекодировки
digit_out[0]=indicator%10;
digit_out[1]=indicator/10;
}
.......
w1_init();
ds18b20_init(0,-5,100,DS18B20_9BIT_RES);
// Global enable interrupts
#asm("sei")
while (1)
{
// Place your code here
delay_ms(1000);
temp=ds18b20_temperature(0); //измеряем
indicator=temp;
cifri_v_massiv();
};
В итоге всё работает (температура показывается), НО периодически на дисплей выводится какая то абракадабра. Причем через разные промежутки времени. Начинается примерно через 30 сек. работы в протеусе. Абракадабра одна и та же. И в протеусе и в железе. Почему?
То так, то так:
И в железе (простите, телефоном фотографировал):
Если просто написать indicator=25; то всё нормально.
Я так понимаю датчик просто какую то ошибку выдает, но почему так часто??? И почему в протеусе тоже???
Исходники прилагаются. Видео тоже (правда это я уже немного поправил код, но смысл тот же)
Я понимаю что тема термометров уже затерта до дыр. Практически везде LCD.
Я никак не пойму что в моём то коде не так???
Почему и в протеусе и в железе датчик глючит???
Если запрещать прерывания на время запроса температуры - индикация начинает "моргать". Так как же тогда датчик опрашивать???
Вывести то не сложно, как значение то получить правильно?????
Я уже месяц над этим бьюсь - все меня нахер посылают.
Goodefine писал(а):Индикацию легко на семисегментники переделать...
// maximum number of DS18B20 connected to the 1 Wire bus
#define MAX_DEVICES 8
// DS18B20 devices ROM code storage area
unsigned char rom_code[MAX_DEVICES][9];
// 1 Wire Bus initialization
w1_init();
// определить устройства (опросить датчики)
devices=w1_search(0xf0,rom_code);
if (devices >= 1) {
temperature=ds18b20_temperature(&rom_code[i][0]);
if (temperature!=-9999) view_term();
...
}
Для нормальной работы при динамической индикации в CVAVR нужно подправить ds18b20.lib
mr_smit писал(а):Я уже месяц над этим бьюсь - все меня нахер посылают.
вы читали мои посты? почему ни разу не ответили, что посмотрели, разобрались и т.п.? если не поступаете так, как советуют - вас скоро и бить начнут. не только посылать... проблема не стоит выеденного яйца
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
У вас 3 поста в этой теме и всё касательно индикации. Я с ней разобрался. Я не понимаю почему у меня датчик с различной периодичностью выдает какую то ерунду. Видео и код я прикреплял. Разве это нормально когда периодически ошибка??? Да ещё так часто??? Тем более и в протеусе тоже.??? Наверное я как то не правильно температуру запрашиваю или ещё что.
Последний раз редактировалось mr_smit Пн июн 15, 2009 16:12:33, всего редактировалось 1 раз.
mr_smit писал(а):...Разве это нормально когда периодически ошибка??? Да ещё так часто??? Тем более и в протеусе тоже.???
Выбросите датчик и купите новый, а также выбросите Протеус и купите новый, а чтобы наверняка выбросите и компьютер на котором установлен Протеус и купите новый и я на 100 процентов уверен что у Вас все наладится и все получится.
последний раз пытаюсь вам помочь.
1. в моем исходнике есть все: работа с датчиком, индикация, преобразование чисел для вывода на индикатор, работа с кнопками... если поймете, как сделал я - наверняка поймете, что у вас не так.
2. протеус - это не просто "лабораторный стол": это в первую очередь отладчик. исполняйте свою программу по шагам, контролируйте содержимое своих переменных и найдите место, где происходит искажение данных
3. если у вас белиберда на индикации - вы считаете, это датчик вам выдает не то?! не поверю!!! это у вас с выводом на дисплей не все в порядке!
4. раз у вас нет вопросов по моему исходнику, зато есть проблемы со своей программой, я делаю вывод, что вы ждете, пока кто-то сделает все за вас, а мои программы даже не пытались понять. вам надо решить проблему, но лень разбирать работающий код? мне лень вникать в ваш код - но у меня нет проблем вряд ли я смогу при таком подходе вам помочь. да и другим скоро надоест.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
mr_smit писал(а):
...100% где то код не правильный.
Тут я с вами полностью согласен. Потратив 15 минут, причесал код до минимума - отображает температуру в пределах 0-99 градусов. Если нужен знак и десятые доли градуса, можете обратится к вышеуказанным мною ссылкам.
Обратите внимание на измененную частоту тактирования таймера Т0...
Итак, код:
/*****************************************************
CodeWizardAVR V2.03.4 Standard
Project : DEMO_TERMOMETRE
Date : 14.06.2009
Author : Goodefine
Chip type : ATmega8
Program type : Application
Clock frequency : 4,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega8>
#include <delay>
#asm
.equ __w1_port=0x18 ;PORTB
.equ __w1_bit=0
#endasm
#include <1wire> //библиотека для работы с 1Wire
#include <ds18b20> //библиотека для работы с датчиком температуры
#define MAX_DS18B20 8
unsigned char ds18b20_devices;
unsigned char ds18b20_rom_codes[MAX_DS18B20][9];
//-------------------------------------------------------------------------
#define PIN_DIGIT_1 PINC.1
#define PIN_DIGIT_2 PINC.2
#define OUT_DIGIT_1 PORTC.1
#define OUT_DIGIT_2 PORTC.2
#define BUF_SIZE 2
unsigned char buffer[BUF_SIZE]; //буфер для разложения числа
unsigned int temp; //температура
//-------------------------------------------------------------------------
flash char digits[]={// массив для отображения на индикаторе
0b10000001,0b11110011,0b01001001,0b01100001,0b00110011,0b00100101,
0b00000101,0b11110001,0b00000001,0b00100001};
//-------------------Функция преобразования числа в строку------------//
void decbin_ds (unsigned int const* x, unsigned char* buffer)
{ unsigned char i;
for (i=0; i<BUF_SIZE>=10; i-=10) {buffer[0]++;}
for (i=*x-10*buffer[0]; i>=1; i-=1) {buffer[1]++;}
}
//==================//
//-------------------- 0 overflow interrupt service routine------------//
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
//динамическая индикация, выводит поочередно числа из buffer
(PIN_DIGIT_1)? (OUT_DIGIT_1=0,PORTD=digits[buffer[1]],OUT_DIGIT_2=1):
(OUT_DIGIT_2=0,PORTD=digits[buffer[0]],OUT_DIGIT_1=1);
}
//====================//
void main(void)
{
PORTB=0x00;
DDRB=0xFF;
PORTC=0xFF;
DDRC=0xFF;
PORTD=0x00;
DDRD=0xFF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
TCCR0=0x04;
TCNT0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
w1_init();
ds18b20_devices=w1_search(0xf0,ds18b20_rom_codes);
ds18b20_init(&ds18b20_rom_codes[0][0],-55,125,DS18B20_9BIT_RES);
// Global enable interrupts
#asm("sei")
for (;;)//---------------------MAIN_LOOP----------------------------------
{
#asm("wdr") //для Протеуса
//получаем температуру
temp=ds18b20_temperature(&ds18b20_rom_codes[0][0]);
//преобразуем значение температуры в строку и ложим в буфер buffer
decbin_ds(&temp, buffer);
//пауза
delay_ms(100);
} //end MAIN_LOOP----------------------------------------------------
}
Рабочий проект:
P.S. На самом деле функция decbin_ds выглядит так:
см. рисунок, иначе не получилось! Первый раз вижу такой глюк...
Но ее почему преобразует с потерей строк ....