Zodiac21

Отрицательные температуры ds18b20

6 сообщений в этой теме

Zodiac21    0

Ребята, я вот делаю термометр на atmega8 + ds18b20+ семисегментник, и столкнулся с такой вот проблемкой . Как реализовать вывод отрицательной температуры???

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

#include <mega8.h>
#include <delay.h>


#asm
   .equ __w1_port=0x15 ;PORTC
   .equ __w1_bit=2
#endasm

#include <1wire.h>
#include <ds18b20.h>
#define MAX_DS1820 8


 unsigned char rom_codes[MAX_DS1820][9]; //переменная хранения rom кодов
 unsigned char temp[8]; // переменная для хранения значений температуры
 unsigned char devices; // переменная для устройств
 
 
flash char number[] = 
{
  0x3f, //0
  0x06, //1
  0x5b, //2
  0x4f, //3   
  0x66, //4
  0x6d, //5 
  0x7d, //6
  0x07, //7   
  0x7f, //8
  0x6f,  //9 
  0x00,  //blank
  0x40   // minus
};
   

//числа для вывода на индикатор
volatile unsigned char data1 = 0;
volatile unsigned char data2 = 0;
volatile unsigned char data3 = 0;
volatile unsigned char data4 = 0;
volatile unsigned char data5 = 0;
volatile unsigned char data6 = 0;





void temperature(void)
{
 temp[0]=ds18b20_temperature(&rom_codes[0][0]);
 temp[1]=ds18b20_temperature(&rom_codes[1][0]); 
       
        if (temp>1000){
            temp[0]=4096-temp[0];               
            temp[0]=-temp[0];
            data4 = 11;
               }
            
            if(temp>1000){
            temp[1]=4096-temp[1];
            temp[1]=-temp[1];
            data1 = 11;
              } 
              
    data6 = temp[0]%10;
    data5 = temp[0]/10;
    data4 = 10;
    data3 = temp[1]%10;
    data2 = temp[1]/10;
    data1 = 10;
    }

   
    
    
void main( void )
{

  //порт, к которому подкл. сегменты
  PORTD = 0xff;
  DDRD = 0xff;
  
  PORTC=0xFF;
  DDRC=0x00;

  
  //порт, к которому подкл. катод
  PORTB = 0xff;
  DDRB |= (1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0); 
  
  //инициализация таймера Т0 
  TCCR0 = (1<<CS02)|(0<<CS01)|(1<<CS00);
  TCNT0 =  0xE6;
  
  // Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (1<<TOIE0);

// Оприделение устройств
devices=w1_search(0xf0,rom_codes);
 
  #asm("sei")
  
 
  
  while(1){
   
   temperature();
        
  }  
}

//прерывания таймера Т0 - вывод на индикатор
interrupt [TIM0_OVF] void Timer0Ovf(void)
{
  static unsigned char count = 0;
  TCNT0 = 0xE6;
  
   //гасим все разряды
   PORTB |= (1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0);
   
   //зажигаем следующий разряд
   if (count == 0) {
      PORTD = number[data1];
      PORTB = ~(1<<0);
   }
   if (count == 1) {
      PORTD = number[data2];
      PORTB = ~(1<<1);
   }
   if (count == 2) {
      PORTD = number[data3];
      PORTB = ~(1<<2);
    }  
   if (count == 3) {
      PORTD = number[data4];
      PORTB = ~(1<<3);
      }
   if (count == 4) {
      PORTD = number[data5];
      PORTB = ~(1<<4);
      }
   if (count == 5) {
      PORTD = number[data6];
      PORTB = ~(1<<5);
      }     
    
    count++;
    if (count == 6) count = 0;

}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
o_l_e_g    1 622
29 минут назад, Zodiac21 сказал:

unsigned char temp

А температура с датчика, является знаковой переменной.
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zodiac21    0

Изменил на int temp, результат тот-же..... 

Снимок1.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    214
Только что, o_l_e_g сказал:

А температура с датчика, является знаковой переменной.
 

К тому же 16-битной...

http://arv.radioliga.com/content/view/106/49/ - вот здесь я писал о том, как можно выводить числа на семисегментник, в том числе и с минусом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zodiac21    0

Будьте добры,  подскажите как на примере моего кода это организовать.....

Вот я подключил эту функцию, а как дальше быть?

#include <mega8.h>
#include <delay.h>

 
// DS1307 Real Time Clock functions
#include <ds1307.h>

#asm
   .equ __w1_port=0x15 ;PORTC
   .equ __w1_bit=2
#endasm

#include <1wire.h>
#include <ds18b20.h>
#define MAX_DS1820 8


 unsigned char rom_codes[MAX_DS1820][9]; //переменная хранения rom кодов
 int temp[8]; // переменная для хранения значений температуры
 unsigned char devices; // переменная для устройств
 
  
            #define DIG_BASE  10 /* основание системы считсления для перевода */
			#define MAX_SIZE 6 /* максимальное число выводимых символов */ 
			#define SPACE_CHAR  ' ' /* символ "пустого" места */
			#define NEG_CHAR '-' /* символ "минус" */
 
  unsigned char out[MAX_SIZE]; // выходной массив символов (экранная область)
  
  
flash char number[] = 
{
  0x3f, //0
  0x06, //1
  0x5b, //2
  0x4f, //3   
  0x66, //4
  0x6d, //5 
  0x7d, //6
  0x07, //7   
  0x7f, //8
  0x6f,  //9 
  0x00,  //blank
  0x40   // minus
};
   

//числа для вывода на индикатор
volatile unsigned char data1 = 10;
volatile unsigned char data2 = 0;
volatile unsigned char data3 = 0;
volatile unsigned char data4 = 10;
volatile unsigned char data5 = 0;
volatile unsigned char data6 = 0;





void temperature(void)
{
 temp[0]=ds18b20_temperature(&rom_codes[0][0]);
 temp[1]=ds18b20_temperature(&rom_codes[1][0]); 
       
        if (temp>1000){
            temp[0]=4096-temp[0];               
            temp[0]=-temp[0];            
               }
            
            if(temp>1000){
            temp[1]=4096-temp[1];
            temp[1]=-temp[1];
              } 
              
    data6 = temp[0]%10;
    data5 = temp[0]/10;
   
    data3 = temp[1]%10;
    data2 = temp[1]/10;
    
    
    }

  
  void s_trim_convert(int NUM){
			 int i, m, sign = 0;
			 if(NUM <0){
			 // если число отрицательное
			  sign = 1; // установим признак наличия знака
			  NUM *= -1; // а само число возьмем по модулю
			 }
			 // выводим уже положительное число
			 i=MAX_SIZE-1;
			 do{
			  // цикл заполнения выходного массива СПРАВА НАЛЕВО
			  m = NUM % DIG_BASE; // находим остаток от деления числа на основание
			  if((NUM==0)&&(i!=(MAX_SIZE-1)))
			   break; // закончим цикл вывода числа
			  else
			   out[i] = number[m]; // иначе выводим символ нужной ЦИФРЫ
			  NUM /= DIG_BASE;  // уменьшаем число в DIG_BASE раз
			 } while (--i >= 0);
			 // число выведено, проверяем свободное место и выводим при необходимости знак
			 if (i < 0) return; // места не хватает - выход
			 if (sign) out[i--] = NEG_CHAR; // выводим знак, если нужно
			 for(; i>=0;i--) out[i] = SPACE_CHAR; // очищаем незначащие позиции 
			}
 
    
    
void main( void )
{

  //порт, к которому подкл. сегменты
  PORTD = 0xff;
  DDRD = 0xff;
  
  PORTC=0xFF;
  DDRC=0x00;

  
  //порт, к которому подкл. катод
  PORTB = 0xff;
  DDRB |= (1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0); 
  
  //инициализация таймера Т0 
  TCCR0 = (1<<CS02)|(0<<CS01)|(1<<CS00);
  TCNT0 =  0xE6;
  
  // Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (1<<TOIE0);

// Оприделение устройств
devices=w1_search(0xf0,rom_codes);
 
  #asm("sei")
  
 
  
  while(1){
  s_trim_convert(temp[0]); 
   temperature();
        
  }  
}

//прерывания таймера Т0 - вывод на индикатор
interrupt [TIM0_OVF] void Timer0Ovf(void)
{
  static unsigned char count = 0;
  TCNT0 = 0xE6;
  
   //гасим все разряды
   PORTB |= (1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0);
   
   //зажигаем следующий разряд
   if (count == 0) {
      PORTD = number[data1];
      PORTB = ~(1<<0);
   }
   if (count == 1) {
      PORTD = number[data2];
      PORTB = ~(1<<1);
   }
   if (count == 2) {
      PORTD = number[data3];
      PORTB = ~(1<<2);
    }  
   if (count == 3) {
      PORTD = number[data4];
      PORTB = ~(1<<3);
      }
   if (count == 4) {
      PORTD = number[data5];
      PORTB = ~(1<<4);
      }
   if (count == 5) {
      PORTD = number[data6];
      PORTB = ~(1<<5);
      }     
    
    count++;
    if (count == 6) count = 0;

}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Zodiac21    0

Получилось сделать следующим образом: 

void temperature(void)
{
 temp[0]=ds18b20_temperature(&rom_codes[0][0]);
 temp[1]=ds18b20_temperature(&rom_codes[1][0]); 
       
        if (temp[0]<0){               
            temp[0]=~temp[0]+1;
            data4=11;            
               }
            
            if(temp[1]<0){
            temp[1]=~temp[1]+1;
            data1=11;
              } 
              
    data6 = temp[0]%10;
    data5 = temp[0]/10;
   
    data3 = temp[1]%10;
    data2 = temp[1]/10;
    
    
    }

То есть проинвертировав значения переменной temp и прибавив 1.......

Вроде всё работает........ 

Снимок1.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас