Преобразование числа в строку и обратно (DS18B20 + 7 сегм.)

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Аватара пользователя
Forest_CAt
Встал на лапы
Сообщения: 126
Зарегистрирован: Вт дек 18, 2007 12:53:58
Откуда: Сибирь. Омск
Контактная информация:

Сообщение Forest_CAt »

Температуру стандартная функция CVAVR'а возвращает типа float, т.е. с плавающей запятой. Если тебе не нужна дробная часть температуры то в твоем примере:

Код: Выделить всё

temp=ds18b20_temperature(0);
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, выводим ее на второй индикатор

Удачи! :)
Everyone has his own way in his own life.
Реклама
Аватара пользователя
OBIVAN
Встал на лапы
Сообщения: 84
Зарегистрирован: Вт ноя 25, 2008 18:56:41

Сообщение OBIVAN »

Можно еще и так

decod((minut/10)%10);десятки
decod(minut%10); единицы
Реклама
Аватара пользователя
Forest_CAt
Встал на лапы
Сообщения: 126
Зарегистрирован: Вт дек 18, 2007 12:53:58
Откуда: Сибирь. Омск
Контактная информация:

Сообщение Forest_CAt »

Кстати, да... Чего мне этот fmod() дался... Так ведь короче :) Спасибо :)
Everyone has his own way in his own life.
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

В конец измучился с этим термометром. Не работает. С выводом на индикатор разобрался. Выводит любые 2-х значные числа правильно.
Подключил датчик - постоянно "1" и быстро мерцает. В протэусе всё работает. В железе нет. Было замечено несколько раз в протеусе при изменении температуры на экран на некоторое время выводилась "1", потом опять нормальная температура. Я уже вообще ничего теперь не понимаю.
Нельзя всё знать, достаточно понимать.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Не работает и всё тут. Прям издевательство какое то. :cry:

Немного переделал. В протеусе идет с огромными тормозами. В железе вообще не работает.

Изображение
Нельзя всё знать, достаточно понимать.
Реклама
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Поменял местами порты, сделал прерывание по кнопке. Т.е. нажал - значение на 1 увеличилось. Всё работает. А с датчиком никак.

Изображение
Нельзя всё знать, достаточно понимать.
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

честно говоря, я уже потерял нить вашей пробелмы... но если хотите - скачайте исходник к моему проекту мини-термостата и поглядите, как организовано все - от работы с датчиком до вывода на индикатор. ну а потом сделаете свой, улучшенный вариант.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Вот до чего дошел:

Код: Выделить всё

.......

#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; то всё нормально.
Я так понимаю датчик просто какую то ошибку выдает, но почему так часто??? И почему в протеусе тоже???

Исходники прилагаются. Видео тоже (правда это я уже немного поправил код, но смысл тот же)
Нельзя всё знать, достаточно понимать.
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Задолбал меня этот датчик, не знаю что ему ещё надо. Порт для него на выход настроен.
Нельзя всё знать, достаточно понимать.
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

Вот, почти то, что доктор прописал. Индикацию легко на семисегментники переделать... Цифры в буфере разложенные лежат. Будет примерно так...
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Я понимаю что тема термометров уже затерта до дыр. Практически везде LCD.
Я никак не пойму что в моём то коде не так???
Почему и в протеусе и в железе датчик глючит???
Если запрещать прерывания на время запроса температуры - индикация начинает "моргать". Так как же тогда датчик опрашивать???
Вывести то не сложно, как значение то получить правильно?????
Я уже месяц над этим бьюсь - все меня нахер посылают.
Goodefine писал(а):Индикацию легко на семисегментники переделать...
ну вот опять...
Нельзя всё знать, достаточно понимать.
Аватара пользователя
Danko
Сверлит текстолит когтями
Сообщения: 1287
Зарегистрирован: Пн окт 13, 2008 11:45:54
Откуда: РФ, Крым, г.Бахчисарай
Контактная информация:

Сообщение Danko »

mr_smit писал(а):Задолбал меня этот датчик, не знаю что ему ещё надо. Порт для него на выход настроен.
Вот такой пример кода:

Код: Выделить всё

// 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

было:

Код: Выделить всё

w1_write(0x55);
стало:

Код: Выделить всё

#asm("cli")
w1_write(0x55);
#asm("sei")
во всех строках соответственно.

Да я еще отказался от float у меня ds18b20_temperature() возвращает signed int.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

mr_smit писал(а):Я уже месяц над этим бьюсь - все меня нахер посылают.
вы читали мои посты? почему ни разу не ответили, что посмотрели, разобрались и т.п.? если не поступаете так, как советуют - вас скоро и бить начнут. не только посылать... проблема не стоит выеденного яйца
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

У вас 3 поста в этой теме и всё касательно индикации. Я с ней разобрался. Я не понимаю почему у меня датчик с различной периодичностью выдает какую то ерунду. Видео и код я прикреплял. Разве это нормально когда периодически ошибка??? Да ещё так часто??? Тем более и в протеусе тоже.??? Наверное я как то не правильно температуру запрашиваю или ещё что.
Последний раз редактировалось mr_smit Пн июн 15, 2009 16:12:33, всего редактировалось 1 раз.
Нельзя всё знать, достаточно понимать.
Аватара пользователя
Danko
Сверлит текстолит когтями
Сообщения: 1287
Зарегистрирован: Пн окт 13, 2008 11:45:54
Откуда: РФ, Крым, г.Бахчисарай
Контактная информация:

Сообщение Danko »

mr_smit писал(а):...Разве это нормально когда периодически ошибка??? Да ещё так часто??? Тем более и в протеусе тоже.???
Выбросите датчик и купите новый, а также выбросите Протеус и купите новый, а чтобы наверняка выбросите и компьютер на котором установлен Протеус и купите новый и я на 100 процентов уверен что у Вас все наладится и все получится. :)
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Больше ничего не остается
Нельзя всё знать, достаточно понимать.
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

ds18b20.lib исправил.

Код: Выделить всё

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")

while (1)
      {
      temp=ds18b20_temperature(&ds18b20_rom_codes[0][0]);
      indicator=temp;
      cifri_v_massiv();
      };
Скачет, то так то так:

Изображение Изображение

100% где то код не правильный.
Нельзя всё знать, достаточно понимать.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

последний раз пытаюсь вам помочь.
1. в моем исходнике есть все: работа с датчиком, индикация, преобразование чисел для вывода на индикатор, работа с кнопками... если поймете, как сделал я - наверняка поймете, что у вас не так.
2. протеус - это не просто "лабораторный стол": это в первую очередь отладчик. исполняйте свою программу по шагам, контролируйте содержимое своих переменных и найдите место, где происходит искажение данных
3. если у вас белиберда на индикации - вы считаете, это датчик вам выдает не то?! не поверю!!! это у вас с выводом на дисплей не все в порядке!
4. раз у вас нет вопросов по моему исходнику, зато есть проблемы со своей программой, я делаю вывод, что вы ждете, пока кто-то сделает все за вас, а мои программы даже не пытались понять. вам надо решить проблему, но лень разбирать работающий код? мне лень вникать в ваш код - но у меня нет проблем :))) вряд ли я смогу при таком подходе вам помочь. да и другим скоро надоест.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

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 выглядит так:
см. рисунок, иначе не получилось! Первый раз вижу такой глюк...
Но ее почему преобразует с потерей строк :shock: ....
Вложения
decbin.jpg
(76.23 КБ) 582 скачивания
ds1820_demo.rar
(16.63 КБ) 273 скачивания
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

ARV писал(а):последний раз пытаюсь вам помочь.
1. в моем исходнике есть все
В каком вашем исходнике??? вы ничего не выкладывали.
Нельзя всё знать, достаточно понимать.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»