Перейти к содержанию

Простейший (!) Термостат На Меги (Си)


shev377

Рекомендуемые сообщения

Знаний в создании прошивок на мк -> 0, Асамблёр вообще дрова, а вот си ещё более менее понятно....

Вобщем возникла задача, создать термореле с цифровой индикацией, для переносного холодильника

есть мк от Atmel, Mega32в корпусе Dip,

термодатчик цифровой DS18B20 с точностью 0.5 C

4 семисегментных индикатора с общим плюсом

есть ещё реле и оптрон.

Нужно всё это объединить,

В чём проблема скажете Вы? На сайте полно схем схем термореле? В том, что половина из них на PIC, и в том что прошивки на АСМе...

Есть схема, запутана и много лишнего для меня

18452698.gif

есть к ней прошивка

код

/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.5 Professional
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 15.10.2008
Author  : Yurik                           
Company : Hardlock                        
Comments: 


Chip type           : ATtiny2313
Clock frequency     : 8,000000 MHz
Memory model        : Tiny
External SRAM size  : 0
Data Stack size     : 32
*****************************************************/

#include <tiny2313.h>
#include <kbd.h>

// 1 Wire Bus functions
#asm
  .equ __w1_port=0x12 ;PORTD
  .equ __w1_bit=6
#endasm
#include <1wire.h>
#include <delay.h>

#define LED_delay 150    

#define Cathode
//#define Anode

#define heat              //точка отображается если T < Tуст.
//#define cold            //точка отображается если T > Tуст.

BYTE byDisplay[4];        // буфер данных, для вывода на экран     

BOOLEAN Updating;  
BOOLEAN Minus;  
BOOLEAN LoadOn; 

BYTE Counter = 0;  
BYTE View = 0; 

WORD Tnew;        
WORD T_LoadOn;
BYTE DeltaT;

eeprom WORD eeT_LoadOn = 1280;   //1280 = +28°C 1140 = +14°C 
eeprom BYTE eeDeltaT = 10;       //1°C

//температура для удобства представлена так:
// - до 1000 = отрицательная
// - 1000 = 0
// - больше 1000 = положительная
// - 0,1°С = 1
//---------------------------------
//-55°C = 450
//-25°C = 750
//-10.1°C = 899
//0°C = 1000
//10.1°C = 1101
//25°C = 1250
//85°C = 1850
//125°C = 2250       


BYTE byCharacter[15] = {0xFA,     //0
               0x82,   //1
	        0xB9,   //2
        0xAB,	//3 
        0xC3,     //4 
        0x6B,     //5 
        0x7B,     //6
               0xA2,    //7 
               0xFB,      //8
               0xEB,      //9 
               0x00,      //blank   
               0x01,     //-
               0x70,     //t
               0x9B,     //d
               0x58      //L
               }; 



/************************************************************************\
\************************************************************************/
void PrepareData(unsigned int Data)
{
   BYTE i;
   unsigned int D, D1;        
   D = Data;                           

   if (D >= 1000) //если Температура больше нуля
   {
     D = D - 1000;  
     Minus = 0;
   }
   else
   {
     D = 1000 - D; 
     Minus = 1;
   }          
   D1 = D;

   //Преобразуем в десятичное представление
   for(i=0; i<4; i++)
   {
      byDisplay[3-i] = D % 10;
      D /= 10;
   }

   if (D1 < 100)
   {
     byDisplay[0] = 10;
     byDisplay[1] = 10;

     goto exit;
   }   
   if ((D1 >= 100) & (D1 <1000))
   {
     byDisplay[0] = 10;
     goto exit;
   }

exit:  
 if (View == 2)
 {
   byDisplay[0] = 13;     
 }

}

/************************************************************************\
 Вывод экранного буфера на дисплей.
     Вход:  -
     Выход: -
\************************************************************************/
void ShowDisplayData(void)
{                      
#ifdef Cathode                     

 PORTB = byCharacter[byDisplay[0]];
 if (Minus)
 {
   PORTB = PINB | 0b00000001;
 }                           
 #ifdef heat
 if (LoadOn)
 #endif

 #ifdef cold
 if (!LoadOn)
 #endif
 {
   PORTB = PINB | 0b00000100;
 }           
 if (View == 1)
 {
   PORTB = PINB | 0b00001000;
 }
 PORTD.5 = 0;
 delay_us(LED_delay);
 PORTD.5 = 1;    

 PORTB = byCharacter[byDisplay[1]];
 PORTD.1 = 0;
 delay_us(LED_delay);
 PORTD.1 = 1;

 PORTB = byCharacter[byDisplay[2]] | 0b00000100;
 PORTD.0 = 0;
 delay_us(LED_delay);
 PORTD.0 = 1;

 PORTB = byCharacter[byDisplay[3]];
 PORTD.4 = 0;
 delay_us(LED_delay);
 PORTD.4 = 1;
#endif

#ifdef Anode
 PORTB = ~byCharacter[byDisplay[0]];  
 if (Minus)
 {
   PORTB = PINB & 0b11111110;
 }                           
 #ifdef heat
 if (LoadOn)
 #endif

 #ifdef cold
 if (!LoadOn)
 #endif
 {
   PORTB = PINB & 0b11111011;
 }           
 if (View == 1)
 {
   PORTB = PINB & 0b11110111;
 } 
 PORTD.5 = 1;
 delay_us(LED_delay);
 PORTD.5 = 0;    

 PORTB = ~byCharacter[byDisplay[1]];
 PORTD.1 = 1;
 delay_us(LED_delay);
 PORTD.1 = 0;

 PORTB = ~byCharacter[byDisplay[2]] & 0b11111011;
 PORTD.0 = 1;
 delay_us(LED_delay);
 PORTD.0 = 0;

 PORTB = ~byCharacter[byDisplay[3]];
 PORTD.4 = 1;
 delay_us(LED_delay);
 PORTD.4 = 0;
#endif


 }


/************************************************************************\
 Обновление дисплея.
     Вход:  -
     Выход: -
\************************************************************************/
void RefreshDisplay(void)
{                                
 WORD Data; 
 switch (View)
 {
   case 0:
     Data = Tnew; 
     if (T_LoadOn != eeT_LoadOn)
       eeT_LoadOn = T_LoadOn;
     if (DeltaT != eeDeltaT)
       eeDeltaT = DeltaT;
   break;
   case 1:
     Data = T_LoadOn;
   break;

   case 2:
     Data = DeltaT + 1000; 
   break;
 }

 PrepareData(Data);      
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{                
// Reinitialize Timer 0 value
TCNT0=0xBF;

ScanKbd();
}

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
 BYTE t1;
 BYTE t2;
 BYTE i; 
 WORD Temp;
 WORD T;
 BYTE Ff;
// Reinitialize Timer 1 value
TCNT1H=0x8F;
TCNT1L=0xD1;
// Place your code here 
w1_init();   
for (i=0; i<11; i++)
 {
   ShowDisplayData();
 }
w1_write(0xCC);               
for (i=0; i<11; i++)
 {
   ShowDisplayData();
 }
Updating = !Updating;
if (Updating)
{
 w1_write(0xBE);  
 for (i=0; i<11; i++)
 {
   ShowDisplayData();
 }
 t1=w1_read();   //LSB 
 for (i=0; i<11; i++)
 {
   ShowDisplayData();
 }
 t2=w1_read();   //MSB      

 // значения из даташита (для проверки раскоментировать нужное значение)

 //+125°C
 //t2 = 0b00000111; //MSB
 //t1 = 0b11010000; //LSB

 //+85°C
 //t2 = 0b00000101; //MSB
 //t1 = 0b01010000; //LSB

 //+25.0625°C
 //t2 = 0b00000001; //MSB
 //t1 = 0b10010001; //LSB

 //+10.125°C
 //t2 = 0b00000000; //MSB
 //t1 = 0b10100010; //LSB

 //+0.5°C
 //t2 = 0b00000000; //MSB
 //t1 = 0b00001000; //LSB

 //0°C
 //t2 = 0b00000000; //MSB
 //t1 = 0b00000000; //LSB

 //-0.5°C
 //t2 = 0b11111111; //MSB
 //t1 = 0b11111000; //LSB

 //-10.125°C
 //t2 = 0b11111111; //MSB
 //t1 = 0b01011110; //LSB

 //-25.0625°C
 //t2 = 0b11111110; //MSB
 //t1 = 0b01101111; //LSB

 //-55°C
 //t2 = 0b11111100; //MSB
 //t1 = 0b10010000; //LSB




 Ff = (t1 & 0x0F);
 t2 = t2 << 4; 
 t1 = t1 >> 4;
 T = (t2 & 0xF0) | (t1 & 0x0F);    

 if (T & 0b10000000) //если отрицательная температура
 { 
   Ff = ~Ff + 1;
   Ff = Ff & 0b00001111; 

   if (!Ff)
   {
     T--;
   }   

   Tnew = 1000 - (((~T & 0xFF) * 10) + (Ff * 10 / 16));
 }
 else
 { 
   Tnew = 1000 + (T * 10) + ((Ff * 10) / 16);
 }     
}
else
{
 w1_write(0x44);  
} 


Temp = T_LoadOn + DeltaT;  

if ((Tnew >= Temp) & (LoadOn)) //Off
{
 PORTD.3 = 1;
 PORTD.2 = 0;              
 LoadOn = 0;
}             

Temp = T_LoadOn;             

if ((Tnew <= Temp) & (!LoadOn)) //On
{
 PORTD.3 = 0;
 PORTD.2 = 1;
 LoadOn = 1;  
} 

if (Counter > 0)
{
 Counter --;
}  
else
{
 View = 0;
}
RefreshDisplay();

}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

       //Разряд DDRx - определяет направление передачи данных (0 - вход, 1 - выход).
       //Разряд PORTx - если вывод определен выходом (DDRx = 1), то:
       //         если установлена 1 - то на выводе устанавливается лог. 1
       //         если установлена 0 - то на выводе устанавливается лог. 0
       //    если вывод определен входом (DDRx = 0), то PORTx - определяет состояние подтягивающего резистора (при PORTx = 1 резистор подключен)
       //Разряд PINx - доступен только для чтения и содержит физическое значение вывода порта

       PORTA=0b00000011;
       DDRA= 0b00000000;

       PORTB=0b00000000;
       DDRB= 0b11111111;


       #ifdef Cathode  
         PORTD=0b01110111;
         DDRD= 0b00111111;
       #endif

       #ifdef Anode  
         PORTD=0b01000100;
         DDRD= 0b00111111;
       #endif


PORTD.3 = 1;
PORTD.2 = 0;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x05;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x04;
TCNT1H=0x03;
TCNT1L=0xD1;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x82;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;

// 1 Wire Bus initialization
Tnew = 1000;  

if (eeT_LoadOn == 0xFFFF)
 eeT_LoadOn = 1280;
if (DeltaT == 0xFF)
 DeltaT = 10; 

T_LoadOn = eeT_LoadOn;
DeltaT = eeDeltaT;   

RefreshDisplay();

w1_init();
w1_write(0xCC);
w1_write(0x44);  

KbdInit();

// Global enable interrupts
#asm("sei")

while (1)
     {
     // Place your code here
     #asm("cli");
     ShowDisplayData();
     #asm("sei"); 
     };  

}

Это мне всё слишком сложно, мне не нужны обработчики кнопок, и код для водонагревателя мне тоже не нужен.

Есть нужная мне схема,

post-116162-1276183704,17_thumb.png

Но нет прошивки,

Т,Е. помогите мне упростить Тамашнюю прошивку под мою схему,

Конкретные изменения в схеме,

1)Индикатор подключен по другому:

а. Индикатор с общим анодом (плюсом)

б. Другие порты

анод1индикатора PA0

анод2индикатора PA1

анод3индикатора PA2

анод4индикатора PA3

катодAиндикаторов PC0

катодBиндикаторов PC1

катодCиндикаторов PC2

катодDиндикаторов PC3

катодEиндикаторов PC4

катодFиндикаторов PC5

катодGиндикаторов PC6

катодHиндикаторов PC7

2) реле подключено к порту PD7, чтобы оно замкнулось, на PD7 должно оказаться +5v

3)убраны элементы управления, нет необходимости менять режимы, теперь алгоритм постоянен в прошивке,

Если t<2 снять с PD7 +5v

Если t>6 подать на PD7 +5V

Те будет поддерживаться температура от 2 до 6

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

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

в данном случае могу посоветовать лишь собрать то что уже готово и кем то сделанное.

чем шире кругозор, тем тупее угол обозрения

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

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Особенности хранения литиевых аккумуляторов и батареек

Потеря емкости аккумулятора напрямую зависит от условий хранения и эксплуатации. При неправильном хранении даже самый лучший литиевый источник тока с превосходными характеристиками может не оправдать ожиданий. Технология, основанная на рекомендациях таких известных производителей литиевых источников тока, как компании FANSO и EVE Energy, поможет организовать правильный процесс хранения батареек и аккумуляторов. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

схема с ОК и с ОА програмно отличается лишь инверсией уровней которые подаются на элементы. Можно и аппаратно сделать, хотя не за чем. Что касается меги 8 и 32 то разници тоже сильной не вижу. Разбираться в чужой проге это неблагодарный труд. Пиши сам на основе этого примера.

чем шире кругозор, тем тупее угол обозрения

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

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

темболее

Решил писать с нуля, помогите с функцией получения данных с датчика в переменную, и преобразованием в систему СИ (градусы цельсия) (на СИ)

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

в кодевижине есть встроенный генератор кода, в котором уже есть обработка дс18б20, и в хелпе все примеры есть. надо только почитать :)

чем шире кругозор, тем тупее угол обозрения

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

проще терморезистор вместо датчика использовать и потом ADC контроллера. и дешевле обошлось бы.

я когда в камнях не очень шарил, начал контролер цифровой електродуховки делать (несколько реле, терморезистор, вивод температури в цифрах). два года делал). это при том, что я С знал хорошо и ассемблер более-менее.

здесь проще проектик, но все равно времени уйдет много, если не уметь программировать. если хочешь сэкономить время и деньги, то лучше обратись к специалисту. другое дело если хочешь сам научиться. но самому учиться - это не значит писать на форуме: напишите мне функцию для чтения датичика. ;)

и еще совет по теме. не используй чисел с запятой. если нужно вычислить формулу типа x * 0.25 - лучше эту формулу записать x * 25/100. таким образом размер прошивки значительно уменьшится.

для такого проекта будет достаточно Attiny на 2кбайт (только они не все с ADC), может даже в 1кбайт.

мега сделана не для таких задач :)

Изменено пользователем Siquel
Ссылка на комментарий
Поделиться на другие сайты

А контроллер точно нужен? Не проще ли на К572ПВ2/ПВ5 + любой ОУ + терморезистор из медной проволоки? Там никакую прошивку писать точно не надо) Хотя конечно на 2313-й в плане схемотехники, размеров и цены будет чуть лучше

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

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

если писать самому, то не факт что выйдет работоспособно, тк я не очень понимаю что происходит при записи в порт 255, если весь порт назначен на вывод, и если весь порт назначен на ввод...

я так понимаю что если порт на вывод и в порте 255 то на всех ножках будет ~+5V, это так? (книжки читать некогда)

а вот мне зажжется что есть библиотека для CVavr специально для семисегментиков, в неё посылаются настройки и данные и всё

где-то я её видео, но найти не могу =(

PS рассчитываю через пару недель сделать готовый девайс

Изменено пользователем shev377
Ссылка на комментарий
Поделиться на другие сайты

(книжки читать некогда)

а нам думаете есть когда читать?

а по вопросу: на всех ножках будет логическая единица

Это сообщение поставляется "как есть", без каких либо гарантий. Автор сообщения не несёт какой либо ответственности

за материальный, либо моральный ущерб причиненный данным сообщением напрямую или косвенно.

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

Лучше выводить не в десятичном коде а в шестнадцатеричном или еще лучше в двоичном. Так понятнее разбираться на какие конкретно выводы что подается. Предположим мы используем порт Й (такого точно нигде нет, поэтому для примера самое то). Тогда если написать

ldi r16,0b11110000
out DDRЙ, r16
ldi r16,0b11001100
out PortЙ,r16

то ноги PЙ0,PЙ1 будут на входом с высоким сопротивлением ; ноги PЙ2,PЙ3 - на вход, но подключен внутренний резистор ~20к между ногой и + питания ; ноги PЙ4,PЙ5 - на выход, причем напряжение на них близко к 0 ; ноги PЙ6,PЙ7 - тоже на выход, но на них лог.1, т.е. напряжение близкое к +.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

Тут ссылка и ссылка проекты с описанием для Мега8, можно перекомпилировать под другой АТМЕЛ.

Разбираться в чужой проге это неблагодарный труд. Пиши сам

Почему бы не использовать чужой удачный кусок кода. Кстати на этом сайте на 7сегментную индикацию исходники есть. Изменено пользователем VIT125
Ссылка на комментарий
Поделиться на другие сайты

COKPOWEHEU Спасибо за урок, только что значит r16

VIT125, первый сайт весь поиском прошарил, а вот на втором полазаю, спасибо за ссылку

Изменено пользователем shev377
Ссылка на комментарий
Поделиться на другие сайты

r0-r31 - РОН - Регистры Общего Назначения. Физически располагаются в ОЗУ по адресам 0x0000-0x001F. Чаще всего используются r16-r25 и X(r26,r27), Y(r28,r29), Z(r30,r31), т.к. некоторые операторы (такие как ldi)могут использоваться только с ними (а не с r0-r15). Далее, для удобства есть такие вещи как .def и .equ

.def temp=r16
.equ LDI_TEMP=0b01010101
...
ldi temp,LDI_TEMP

первое (.def) - аналог переменных в языках высокого уровня. Но стоит помнить что это не переменная а регистр, т.е. их число ограничено (те самые 32) зато скорость обращения к ним всего 1 такт.

Второе (.equ) - аналог константы.

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

.equ VAR_1=0x0100
lds temp,VAR_1
add temp,r30
sts VAR_1,temp

Это процедура прибавления к переменной VAR_1 (которая находится в ОЗУ по адресу 0x0100)значения регистра r30.

Вообще, поскольку первые адреса ОЗУ заняты чем попало (и РОНы и Portы и DDRы и внутренние порты - АЦП, SREG и т.п.)то адреса ОЗУ до 0x0060 (а в крутых типа ATmega128 - 0x00FF)заняты под системные нужды и писать туда свои значения нужно с крайней осторожностью. В относительно мощных контроллерах (кроме, пожалуй, ATTtny, да и то вряд ли всех)проще использовать адреса от 0x0100 и до... сколько память позволяет

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

Всё до чего дописался, так и не написал функцию дробления числа temp на отдельные цифры digit_out1 digit_out2 digit_out3 digit_out4

просьба просмотреть явные ошибки


#include <mega8.h>               //библиотека ввода\вывода
#include <delay.h>               //библиотека задержки


DDRB.0=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?
DDRB.1=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?
DDRB.2=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?
DDRB.3=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?
DDRB.4=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?
DDRB.5=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?
DDRB.6=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?
DDRB.7=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?


DDRD.0=1 //здесь анод 1, порт определён на выход... А точно так нужно?
DDRD.1=1 //здесь анод 2, порт определён на выход... А точно так нужно?
DDRD.2=1 //здесь анод 3, порт определён на выход... А точно так нужно?
DDRD.3=1 //здесь анод 4, порт определён на выход... А точно так нужно?


DDRD.6=0 //здесь датчик, порт на вход

DDRA.0=1 //здесь реле, порт на выход









#asm                             //сообщаем куда подключен датчик, D6 порт
       .equ __w1_port=0x15; PORTD
       .equ __w1_bit=6
#endasm                  

#include <1wire.h>               //библиотека работы с 1Wire
#include <ds18b20.h>             //библиотека для работы с датчиком ds18b20
#include <stdio.h>               //





//Массив с числами для вывода
     unsigned char digits[] = {

//0
0b01010000,
//1
0b11011011,
//2
0b01100010,.
//3
0b01001010,
//4
0b11001001,
//5
0b01001100,
//6
0b01000100, 
//7
0b11011010,
//8
0b01000000, 
//9
0b01001000,
//минус
0b11101111,
//пусто
0b11111111,
//градус
0b11101000
};




void main(void)                  
{
unsigned char devices;         //переменная в которой количество присоеденённых датчиков
int temp;                        //переменная для хранения температуры
devices=w1_init();               //ищим датчики
while(devices>0)                 //бесконечный цикл, если датчик подключон
     {

         temp=ds18b20_temperature(0);  //читаем температуру  
         if (temp>1000){               //если датчик выдаёт больше 1000
            temp=4096-temp;            //отнимаем от данных 4096
            temp=-temp;                //и ставим знак "минус"
         }



//реле

if (temp>6){               //если датчик выдаёт больше 6 градусов подать на реле плюс 5 вольт
PORTA.0=1
}

if (temp<3){               //если датчик выдаёт больше 3 градусов снять с реле плюс 5 вольт
PORTA.0=0
}





//вывод на индикатор temp



//Здесь функция дробления числа temp на digit_out1 digit_out2 digit_out3 digit_out4
//при этом число может быть как и одноразрядным так и трёхразрядным с минусом.



//вывод digit_out1 digit_out2 digit_out3 digit_out4
//Функция обработки прерывания от Таймера 0
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
switch (cursor)
{
case 0:{PORTD=0b0000010;break;};
case 1:{PORTD=0b0010000;break;};
case 2:{PORTD=0b0000100;break;};
case 3:{PORTD=0b0001000;break;};
}
PORTB=digits[digit_out[cursor]];
cursor++;
if (cursor==4) cursor=0;
}







//delay_ms(500);              //ждём 500мс


     };
}


Изменено пользователем shev377
Ссылка на комментарий
Поделиться на другие сайты

просьба просмотреть явные ошибки

delay_ms(500); НИ В КОЕМ СЛУЧАИ НЕ ИСПОЛЬЗУЙТЕ ФУНКЦИИ ЗАДЕРЖКИ В ПРЕРЫВАНИЯХ!!!!

Это сообщение поставляется "как есть", без каких либо гарантий. Автор сообщения не несёт какой либо ответственности

за материальный, либо моральный ущерб причиненный данным сообщением напрямую или косвенно.

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

закомментировал задержку,

кстати, схема такая-же но порты другие, там в прошивке всё в комментариях!

Буду писать разбивание вручную, но зато 200% будет работать,

( по принципу если число -10 то

digit1 = -

digit2 = 1

digit 3=0

digit 4 =

)

Напишу явасрипт который мне напишет красивый словарик для этих целей, от -30 до +50.

Посмотрите, нет ли ещё ошибок?

и ещё вопрос, как округлить число до целых? так temp=(char)temp ?

Изменено пользователем shev377
Ссылка на комментарий
Поделиться на другие сайты

Для таких целей существуют процедуры перевода в BCD-формат. Языком Си под МК не увлекаюсь, поэтому точно не скажу, где их искать. В свое время (не так давно) писал похожую процедуру в асме. Вроде работала :-)

По поводу кода:

DDRB.0=1
DDRB.1=1
DDRB.2=1
DDRB.3=1
DDRB.4=1 

То что для перевода порта Й на выход нужно установить DDRЙ в 1 это верно, но разве в Си нет функции установки сразу всего порта? Ну чтото типа DDRB=0xFF.

if (temp>1000){
temp=4096-temp;
temp=-temp;  

Как я понял, temp-число знаковое. Тогда зачем такие сложности, пишешь "temp=temp-4096" если 4096 - 0 градусов. Кстати по коду не понятно каким боком там 1000. Кто из них (1000 или 4096) - 0оС?

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
switch (cursor)
{
case 0:{PORTD=0b0000010;break;};
case 1:{PORTD=0b0010000;break;};
case 2:{PORTD=0b0000100;break;};
case 3:{PORTD=0b0001000;break;};
}
PORTB=digits[digit_out[cursor]];
cursor++;
if (cursor==4) cursor=0;
}

Это, как я понимаю, динамическая индикация? Как-то сложно сделан выбор анодов, что, сдвиги или те же маски (как с числами) еще не придумали или памяти жалко?

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

Отдельно порты прописывал для себя, чтобы проще было ориентироваться в коде

Как я понял, temp-число знаковое. Тогда зачем такие сложности, пишешь "temp=temp-4096" если 4096 - 0 градусов. Кстати по коду не понятно каким боком там 1000. Кто из них (1000 или 4096) - 0оС?

Да, но везде, во всех термометрах я видел именно такую запись, что и странно.

0 градусов это 4096, просто какая разница, при минусовых температурах в любом случае значение будет больше 1000

int anod1

int anod2

int anod3

int anod4

anod1=DDRD.0

anod2=DDRD.1

anod3=DDRD.2

anod4=DDRD.3

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{

switch (cursor)

{

if (cursor==1) PortB=255 PortB=digits[digit_out1] Anod4=0 Anod1=1;

if (cursor==2) PortB=255 PortB=digits[digit_out2] Anod1=0 Anod2=1;

if (cursor==3) PortB=255 PortB=digits[digit_out3] Anod2=0 Anod3=1;

if (cursor==4) PortB=255 PortB=digits[digit_out4] Anod3=0 Anod4=1;

cursor=cursor+1;

if (cursor==4) cursor=1;

}

как-то так?

Изменено пользователем shev377
Ссылка на комментарий
Поделиться на другие сайты

так и не написал функцию дробления числа temp на отдельные цифры digit_out1 digit_out2 digit_out3 digit_out4

попробуйте так:

unsigned char flag_minus=0; // флаг наличия отрицательной температуры

// процедура разложения на десятки, единицы

void decbin (unsigned int x) {

unsigned int i;

d=0;e=0;i=0;

#asm("cli")

for (i=x; i>=10; i=i-10) {d++;};

for (i=x-10*d; i>=1; i=i-1) {e++;};

#asm("sei")

if (flag_minus) // вывод отрицательной температуры со знаком минус

{digit_out1=10;}

else // вывод положительной температуры

{digit_out1=11;};

if (d==0){digit_out2=e;digit_out3=11;digit_out4=12;}else{digit_out2=d;digit_out3=e;digit_out4=12;}

}

//вывод на индикатор temp

decbin(temp);

........................

в кусок кода измерения температуры вставьте:

while(devices>0) //бесконечный цикл, если датчик подключен

{

temp=ds18b20_temperature(0); //читаем температуру

if (temp>1000){ // при отрицательной температуре

temp=4096-temp; //отнимаем от данных 4096

flag_minus=1; //и ставим знак "минус"

}

else {flag_minus=0;};

.................

DDRB.0=1 //здесь катоды, сегменты дисплея, порт определён на выход... А точно так нужно?

и т.д. замените на

DDRB= 0xFF; // 0b11111111

PORTB= 0x00; // 0b00000000

DDRD.0=1 //здесь анод 1, порт определён на выход... А точно так нужно?

и т.д. замените на

DDRD = 0x4F; // 0b01001111

PORTD = 0x00; // 0b00000000

так как-то красивее...

Изменено пользователем Юрец

не всё золото, что на контактах...

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

я имел в виду чтото вроде

char anods[4]={0b0000010,0b0010000,0b0000100,0b0001000};
...
anod=anods[cursor];
cursor++;
cursor=cursor && 0b00000011; //обнуляем все после 2-го разряда, это быстрее чем if
//или в асме ;;;;
ldi YH,high(ANODS)
ldi YL,low(ANODS)
ldi temp,0b0000010
st Y+,temp
ldi temp,0b0010000
st Y+,temp
ldi temp,0b0000100
st Y+,temp
ldi temp,0b0001000
st Y+,temp           ;сохраняем ANODS в ОЗУ, их оттуда быстрее извлекать
ldi YH,high(ANODS)
ldi YL,low(ANODS)
ldi cursor,0
............
ld cursor,Y+           ;Y-cursor
andi YL,0b00000011
;хоть и выглядит страшно, выполняться будет гораздо быстрее

О динамической индикации я уже писал: смотрите описание BCD формата для Си

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

Делал плату...



#include <mega32.h>               //библиотека ввода\вывода
#include <delay.h>               //библиотека задержки

DDRB= 0xFF; // 0b11111111
PORTB= 0x00; // 0b00000000

DDRD = 0x4F; // 0b01001111
PORTD = 0x00; // 0b00000000






#asm                             //сообщаем куда подключен датчик, D6 порт
       .equ __w1_port=0x15; PORTD
       .equ __w1_bit=6
#endasm                  

#include <1wire.h>               //библиотека работы с 1Wire
#include <ds18b20.h>             //библиотека для работы с датчиком ds18b20
#include <stdio.h>               //





//Массив с числами для вывода
     unsigned char digits[] = {

//0
0b01010000,
//1
0b11011011,
//2
0b01100010,.
//3
0b01001010,
//4
0b11001001,
//5
0b01001100,
//6
0b01000100, 
//7
0b11011010,
//8
0b01000000, 
//9
0b01001000,
//минус
0b11101111,
//пусто
0b11111111,
//градус
0b11101000
};




void main(void)                  
{
unsigned char devices;         //переменная в которой количество присоеденённых датчиков
int temp;                        //переменная для хранения температуры
devices=w1_init();               //ищим датчики



while(devices>0) //бесконечный цикл, если датчик подключен
{
temp=ds18b20_temperature(0); //читаем температуру
if (temp>1000){ // при отрицательной температуре
temp=4096-temp; //отнимаем от данных 4096
flag_minus=1; //и ставим флаг "минус"
PORTA.1=1
}
else {flag_minus=0;};





//реле

if (temp>6){               //если датчик выдаёт больше 6 градусов подать на реле плюс 5 вольт
PORTA.0=1
PORTA.2=1

}
if (temp<3){               //если датчик выдаёт больше 3 градусов снять с реле плюс 5 вольт
PORTA.0=0
PORTA.2=0

}






//Здесь функция дробления числа temp на digit_out1 digit_out2 digit_out3 digit_out4
unsigned char flag_minus=0; // флаг наличия отрицательной температуры
// процедура разложения на десятки, единицы
void decbin (unsigned int x) {
unsigned int i;
d=0;e=0;i=0;
#asm("cli")
for (i=x; i>=10; i=i-10) {d++;};
for (i=x-10*d; i>=1; i=i-1) {e++;};
#asm("sei")
if (flag_minus) // вывод отрицательной температуры со знаком минус
{digit_out1=10;}
else // вывод положительной температуры
{digit_out1=11;};
if (d==0){digit_out2=e;digit_out3=11;digit_out4=12;}else{digit_out2=d;digit_out3=e;digit_out4=12;}
}




//вывод на индикатор temp
char anods[4]={0b0000010,0b0010000,0b0000100,0b0001000};
...
anod=anods[cursor];
cursor++;
cursor=cursor && 0b00000011; //обнуляем все после 2-го разряда, это быстрее чем if
//или в асме ;;;;
ldi YH,high(ANODS)
ldi YL,low(ANODS)
ldi temp,0b0000010
st Y+,temp
ldi temp,0b0010000
st Y+,temp
ldi temp,0b0000100
st Y+,temp
ldi temp,0b0001000
st Y+,temp           ;сохраняем ANODS в ОЗУ, их оттуда быстрее извлекать
ldi YH,high(ANODS)
ldi YL,low(ANODS)
ldi cursor,0
............
ld cursor,Y+           ;Y-cursor
andi YL,0b00000011
;хоть и выглядит страшно, выполняться будет гораздо быстрее



     };
}





Как я понял это конечный и уже работоспособный код, пошёл шить...

post-116162-1276775178,29_thumb.jpg

post-116162-1276775185,79_thumb.jpg

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

CVavr сдох, сейчас переустановил, попытаюсь откомпилить

Нёс всякий бред вроде как w1_init() переменной не существует, хотя это вообще не переменная функция

Изменено пользователем shev377
Ссылка на комментарий
Поделиться на другие сайты

//Массив с числами для вывода

unsigned char chisla[13] = {0b01010000, 0b11011011, 0b01100010, 0b01001010, 0b11001001, 0b01001100, 0b01000100, 0b11011010, 0b01000000, 0b01001000, 0b11101111, 0b11111111, 0b11101000};

//0 1 2 3 4 5 6 7 8 9 Тире подчёркнивание градус

Чем компилятору не нравится массив chisla?

Unferenced global variable chisla

размещён до main

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

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • @dimanaviator где вы тут делитель увидели? Срисуйте правильно.
    • А лучший вариант предложил Огонек:
    • PS Я слепой определенно. Проглядел что было на графике в стартовом посте - температура Но тем не менее, симуляции микрокапа у меня доверия в этом плане ноль. Я про реальные испытания  
    • И в чем же хрень? Вполне соответствует предложенному ТЗ - от насоса поступает постоянное напряжение 10 вольт. Видимо, это не напряжение питания мотора насоса, а от какой-то управляющей схемы. Или это насос от аквариума, маломощный, или еще что-то. "Есть в мире многое такое, друг Горацио, что и не снилось нашим мудрецам!" 
    • @beggar Учитывая, что Вам влом читать статьи, ща я вкратце поясню (но было бы лучше, Вам прочитать учебники). DCA режим мультиметра - это измерение среднего значения тока. в этом режиме, мультиметр измеряет - какой заряд, протёк за одну секунду, через поперечное сечение проводника. ЗЫ имеет значение, какое число электронов, прошло через поперечное сечение, за одну секунду, и не важно: с какой скоростью они двигались, быстро, медленно, толпами или строем,  главное - сколько. Это среднее значение тока. Действующее значение тока - это вовсе не ток, а его мощностной эквивалент. Здесь важна и скорость электронов, чем быстрее движутся электроны, тем больше потери энергии. Когда по проводнику протекает какой-то ток, на проводнике выделяется тепловая энергия, мощностью P=I*I*R. Рассмотрим случай, когда ток в 1 А протекает в течении 1 секунды, через проводник сопротивлением 1 Ом, тогда мощность равна P=I*I*R=1*1*1=1 Вт. Теперь рассмотрим другой случай, когда тот же ток в 1 ампер (среднее значение), протекает импульсом тока величиной 10 А, продолжительностью 0.1 секунды и паузой продолжительностью 0.9 секунды. тогда мощность выделяющаяся в течении 0.1 секунды P=I*I*R=10*10*1=100 Вт, а в течении 0,9 секунды, т.е. ещё 9 раз по 0,1 секунды 0 Вт, таким образом, мощность выделяющаяся в течении секунды 100/10=10 Вт. Получается, что ток, который покажет амперметр среднего значения - одинаковый, а теплота, выделяющаяся на проводнике, во втором случае, в 10 раз больше. Это какой же ток должен протекать через проводник, чтоб выделялась такая же мощность на проводнике? - получается 3.16 А, P=I*I*R=3.16*3.16*1=10 Вт. Вот амперметр среднеквадратичного значения, в первом случае, показал бы 1 А, а во втором 3.16 А. Получается, что заряд таким током (второй вариант - с импульсным током), заряжал бы аккумулятор током 1 А, а: проводники трансформатора, провода, предохранители, шунты амперметров... грелись бы, как будто по ним проходил бы постоянный ток 3.16 А. при этом, амперметр среднего значения, показывал бы ток 1 А, а амперметр действующего значения 3.16 А. ЗЗЫ хочется верить, что Вам не придётся объяснять, чем отличается - емкость конденсатора, от емкости аккумулятора…
    • что нужно изменить и в какую сторону чтобы повысить напряжение? сейчас 12В хочу попробовать сделать 18-20В, что изменить в делителе?  
    • Окончание заряда сигнализируется красочным свето-дымовым шоу )) 
×
×
  • Создать...