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

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


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

Hongfa для различных применений в Компэл. Большой выбор в наличии!

Компания HONGFA - это не только крупнейший в мире производитель электромеханических реле, но также производитель конденсаторов, вакуумных прерывателей, трансформаторов и низковольтного коммутационного оборудования. На складе КОМПЭЛ регулярно поддерживаются около 100 самых популярных позиций электромеханических реле. Реле Hongfa могут заместить многие изделия производства недоступных брендов. Подробнее>>

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

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

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

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

Тренды и лучшие решения для разработки зарядных станций в России

К 2029 году в России прогнозируется увеличение числа зарядных станций до 40 000. При этом отечественный рынок электротранспорта имеет климатические, потребительские и географические особенности. Для успешной разработки и построения инфраструктуры станций заряда в России идеальным вариантом является использование решений и электронных компонентов китайских производителей – лидеров индустрии электротранспорта и возобновляемой энергетики, которые уже представлены в КОМПЭЛ. Подробнее>>

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

Секреты депассивации литиевых батареек FANSO EVE Energy

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

Реклама: АО КОМПЭЛ, ИНН: 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 пользователей онлайн

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

    • Можно начать с холода. Замораживаем воду до льда  потом в пакет и морозим микросхему. Луше конечно специальный охлаждающий спрей им проще. Можно еще спиртом смазывать, он испаряется и охлаждает микросхему. Замораживаем включаем, смотрим изменения. Наша задача поймать любые изменения в поведении: есть ли влияние температуры?
    • а почему судя по графикам самый подъем частот в в районе 35-40 получатся в ФИ в таком огромном ящике?
    • Статика не "щиплет" щиплет, это сетевое где то утекает, я б по внимательней изучил вопрос, относительно вашей конкретной ситуации. PS: ппц, почитал тему, сборище стендаперов просто. По теме, если в квартире есть заземление, то обязательно все заземлять а в ванне сделать систему уравнивания потенциалов (СУП). Если земли в квартире нет, то лучшее что можно сделать это просто поставить в щиток УЗО.
    • Обратите внимание, в модельке выше, я злонамеренно привел пример условно устойчивой системы. Фазовый запас на частоте единичного усиления достаточен, однако ниже этой частоты будет возбуждение, если усиление каких-либо каскадов упадет, например в переходных режимах.  Пмсм, этот пример демонстрирует вполне себе вероятный случай – вроде устойчиваая работа, а потом херак, и наша марахайка почему-то ушла вразнос. Нужно правильно расставить нули и полюса. В сети много помогалок и переводных статей. Ещё мне кажется, очень полезно читать оригиналы именитых авторов. Пусть и с помощью машинного перевода, но зато без лишних фантазий переводчика. Яндекс-браузер неплохо справляется с переводами, в том числе и озвучка роликов с Ютуб. Настройте перевод сайтов, роликов (лучше перевод с субтитрами, так косяки перевода заметнее) и перед вами откроется океан полезнейшей информации. Огромную пользу получите от семинаров и ответов на вопросы от Кристофа Бассо. Крутейший мужик, автор десятка книг. У него потрясающая способность объяснять непростые темы очень доходчиво. В этом плане, пмсм, ему нет равных.  Есть полезный буржуйский сайт вопросов-ответов, вот персональная страничка с милой аватаркой - https://electronics.stackexchange.com/users/141599/verbal-kint - под ней и скрывается персона Криса Бассо. Не поленитесь, настройте перевод и пройдитесь по ссылкам. Сайт удобен тем, что после ответа приводятся топовые посты по близкой тематике. Если в них отметился Крис, значит получите ответы в самом компетентном и доходчивом виде – как грамотно расставлять нули и полюса, про токовое управление, по  методам моделирования контуров управления и многое-многое другое, без которого, оказывается, просто нельзя жить - просто вы этого не знали Вынужден на время покинуть тему, в последний месяц перед отпуском много работы, потом отпуск без ноутбука, потом традиционно – вал работы после отпуска. Успехов.
    • Я думал про тороид на дереве или пластмассе. Дело в том, что в моем случае на первый план выходят омические потери на рабочей частоте. Как это связано с тороидом: если надо меньшая длина провода, катушку придется делать относительно большего диаметра, тогда будет мало витков, из-за этого по внешнему диаметру тороида будут очень большие расстояния между витками, поэтому будет очень большое рассеяние даже при такой конструкции. Вот тут более подробно про этот дроссель:  
    • КЗ экранирование несколько ослабляет магнитное поле дросселя, магнитропровод - усиливает.
    • Кнопок полно, не спорю, но я хотел этот франкенштейн убрать и поставить простую, на подобие как у компьютерных блоков сзади, но не могу найти подходящую по размеру. У меня повреждена не сама кнопка, а выломан рычаг, который эту кнопку нажимает. Итого в корпусе имеем отверстие 15х15 мм, в которое не подходит ничего из ассортимента магазина без танцев с напильником ((
×
×
  • Создать...