Форум по микроконтроллерам: Динамическая индикация - Форум по микроконтроллерам

Перейти к содержимому

Страница 1 из 1
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

Динамическая индикация Варианты схем и решений.

#1 Пользователь офлайн   Mizar 

  • Знаток
  • PipPip
  • Группа: Пользователи
  • Сообщений: 161
  • Регистрация: 09 Март 11

Отправлено 18 Февраль 2012 - 11:23

Как с наименьшим количеством выводов контроллера и дополнительных радиодеталей организовать управление 8 разрядным 7 сегментным индикатором?

Как с наименьшими затратами можно легко адаптировать схему под индикаторы с ОК и ОА.

На pic16f876 я собрал такую схему
Прикрепленное изображение: 2_7seg.jpg
Но длинный пик и много транзисторов, работают, но уж как то громоздко получилось

Я хотел бы сделать смд по такой схеме
Прикрепленное изображение: 2_7seg628.jpg

Но есть сомнения, что выход 4094 не потянет все 8 сегментов, упадет яркость.
На сдвиговых регистрах красиво, но не все у нас можно купить.....
Что посоветуете при бюджете схемы = тому что есть в наличии...
Любая сложная задача имеет простое, легкое для понимания неправильное решение...
0

#2 Пользователь офлайн   vintik 

  • Завсегдатай
  • PipPipPip
  • Группа: Пользователи
  • Сообщений: 503
  • Регистрация: 10 Апрель 11
  • ГородУкраина

Отправлено 18 Февраль 2012 - 13:00

Тут есть один момент, я его не проверял, по тому и интересно. Если есть возможность и желание, можно проверить.
Допустим у нас 8ми разрядный индикатор. Если включить его в статическом режиме, то для нормальной яркости через каждый сегмент нужно (ориентировочно) пропустить 5мА тока. Тогда общий ток получится 7х8х5мА= 280мА
В динамическом режиме сегмент включен только часть времени, которая зависит от количества разрядов, если оттолкнуться от приведенной схемы. Т.е. на один разряд получается 7х5мА=35мА (с одного порта). А общая мощность потребления будет в 8 раз меньше. При этом снижение яркости (визуально) будет не значительно, во всяком случае, не в восемь раз. Это связанно со свойствами глаза.
Чтобы небыло видно мерцания, нужно чтобы период обновления не превышал 10-15мс.
Ну и, если пойти дальше, то включение по одному сегменту даст еще большую экономию. Если в первом случае в восемь раз, то во втором в 56 раз. Для поточнее, нужно просто экспериментально проверить.
Ток через один сегмент можно увеличить до 25мА (лиш бы порт выдержал). И больше чем уверен - индикатор будет светить с той же яркостью, как и при статическом питании, если не ярче.
Конечно, ток в 25мА для сегмента может оказаться очень большим, что будет видно по изменению цвета свечения. Тут нужно подобрать оптимальный ток для одного сегмента.

Цитата

Что посоветуете при бюджете схемы = тому что есть в наличии...

0

#3 Пользователь офлайн   Mizar 

  • Знаток
  • PipPip
  • Группа: Пользователи
  • Сообщений: 161
  • Регистрация: 09 Март 11

Отправлено 18 Февраль 2012 - 13:49

Цитата

Ну и, если пойти дальше, то включение по одному сегменту даст еще большую экономию.

Об этом я как то не задумывался...

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

Если диоды подключить к +, каждый через свой резистор, а с контроллера подавать -, то яркость не уменьшится. Проверено...
Многие ТТЛ микросхемы построены аналогично, то есть на общий + много не поцепишь.

А вот если индикацию разбить не только по разрядам, но и по сегментам, в каждом отдельном случае будет подключен только один светодиод. Довольно таки много прорисовывать индикацию, как это интересно отобразиться на общем мерцании. Надо попробовать.
Любая сложная задача имеет простое, легкое для понимания неправильное решение...
0

#4 Пользователь офлайн   vintik 

  • Завсегдатай
  • PipPipPip
  • Группа: Пользователи
  • Сообщений: 503
  • Регистрация: 10 Апрель 11
  • ГородУкраина

Отправлено 18 Февраль 2012 - 14:23

Цитата

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

-один сегмент, об этом и говорю :rolleyes:
и тогда потянет

Цитата

Но есть сомнения, что выход 4094 не потянет все 8 сегментов, упадет яркость.


Цитата

Довольно таки много прорисовывать индикацию, как это интересно отобразиться на общем мерцании.

Когда я писал, что: "Чтобы небыло видно мерцания, нужно чтобы период обновления не превышал 10-15мс",
то имел в виду обновление всего индикатора. Мерцание в динамической индикации только от периода обновления и зависит. Сделаеш большИм, будет мерцать.
0

#5 Пользователь офлайн   utrecker 

  • Прибывший
  • Группа: Пользователи
  • Сообщений: 1
  • Регистрация: 24 Ноябрь 12

Отправлено 24 Ноябрь 2012 - 19:18

Вот динамический индикатор С ОА на 5 проводов, включая землю и питание:
ссылка
Работает на уровнях 3.3 и 5, там и либа
0

#6 Пользователь офлайн   Mizar 

  • Знаток
  • PipPip
  • Группа: Пользователи
  • Сообщений: 161
  • Регистрация: 09 Март 11

Отправлено 16 Февраль 2017 - 00:11

Понимаю, что прошло 5 лет с момента последнего сообщения в этой теме, но что бы новую не начинать...

Помогите советом.
Динамическая индикация 8 разрядов.
Построено по алгоритму:
-погасил все разряды
-вывел код первого разряда
- включил разряд
- далее выполняются другие функции и подпрограммы.
- пришло время смены индикации, цикл повторяется.

Все бы хорошо, не мерцает, стабильное и яркое изображение, но в схеме используется датчик температуры DS18B20.
На его опрос проходит какое-то время, из-за этого пауза между сменой разрядов увеличиваются и в момент опроса датчика экран как бы моргает.
Как победить? Заранее благодарен.
Исходник....
#include <pic.h>
#include <stdio.h>
#include <string.h> 

/*
Используется контроллер Pic16F877 с кварцем на 20МГц
Терморегулятор для управления 3 нагревателями и циркуляционным насосом.
Два дисплея 4 разярдных семисегментных индикаторов.
Кнопки меню, + , -, и включение регулировки.
Выды экранов:
1 - главный экран, показывает текущие показания с датчиков температуры.
2 - выбор режима нагрева по воде или по воздуху
3 - Установка температеры нагрева по воде или воздуху
4 - уставка включения насоса
5 - смещение уставки для нагревателя 1
6 - смещение уставки для нагревателя 2
7 - смещение уставки для нагревателя 3
8 - установка гистерезиса
9 - Установка порога аварийной сигнализации 

Екран меняется кнопкой Меню.
В каждом пункте меняется уставка и сразу принимается к работе.
При бездействии 10 сек, происхоидт возврат на главный экран и запись параметров в память.
По кнопке ОК, сохраняются параметры.

Из главного экрана в меню установки температуры можно перейти кнопками + или -

При достижении уставки включения насоса, подается команда на включение насоса.
Если через 2 сек насос не включился, появляется сообщение о неисправсности, мигает инидкатор работа, и работает пищалка.
Кнопкой вкл. квитируется звук и экран, при аварии инидкатор работа мигает.
При аварии кнопка вкл.  отключает блокировку.

При достижении аварийной уставки по температуре, на экаране сообщение, мигает инидкатор работа, пищит пищалка.
Кнопка вкл. квитирует звук и экран, повторно снимает блокировку.

При включении горят все сегменты и пищит индикатор.
Кнопака вкл. включает режим регулирования. Включаются нагреватели.
2 нагреватель включается с задержкой 3 сек, 3 с задержкой 6 сек.

В каждом пункте меню установлены ограничения ввода параметров.
рабочая уставка по температуре от 10 до аварийной
аварийная уставка не ниже рабочей до 100
Насос не ниже рабочей до аварийной - 10
Гистерезис  0...5
коррекция нагревателей -10...+10

Реализован контроль наличия датчиков на линиях, при условии наличия подтягивающего резистора.
При обрыве датчика на экран выводится ERR  и мигает 0...2
При коротком замыкании выводится ERR и мигает 0...1.
При неисправности датчика по первому каналу (основной), включается насос.
*/



// Обявлениефункция заранее, так как о них незнают другие программы

//=============================================================================
// глобальные переменные
//=============================================================================
volatile unsigned int RTC = 0; 	// счетчик реального времени
unsigned int Dlay; 				// для программы задержки
int Temp;						// временная переменная
int ERRTemp ;
// время, задержки и т.д.	
//int Tsec;						// переменная для внутреннего счета секунд, что бы не орпашивать часто часы реального времени
int TimeMenu;					// задержка перед автовозвратом в главный экран
int buff[15];					// массив данных для датчика температуры
char Disp1[5];					// массив данных для дисплея 1
char Disp2[5];					// массив данных для дисплея 2
bit EnDp; 						// точка
long temp1,temp2; 				// температура от 1 и 2 датчиков
//long T12;						// средняя температура от двух датчиков

char Button;					// код кнопки
char ValButton;					// промежуточная переменная кода кнопки от автоматического повторного нажатия
bit ON,fm;						// признак кнопки сохранения параметров
int ni,bi,ti;					//ni - номер текущего сегмента, bi - счетчик циклов опроса кнопок за один проход экрана
//int i_errD1; i_errD2;			// счетчик активности датсчиков для определения неисправности
//char string[4];				// рабочий буфер пеерд выводом на экран
int ENdisp;						// строб жисплея экран
bit TempEnable;					// флаг разрешения сбора данных и обработки режимов
char mode;						// режим работы. 

int Hyst; 						//  гистерезис
int	TempUst; 					// уставка температуры по воде
int	TempUstIn; 					// уставка температуры в помещении
int	TempTe1;					// смещение уставки для нагревателя 1 
int	TempTe2;					// смещение уставки для нагревателя 2
int	TempTe3;					// смещение уставки для нагревателя 3
int	TempPump;					// уставка температуры для включения насоса
int Alarm;						// уставка тмпературы включения аварийной сигнализации
int FAlarm;						// код неисправности аварии
int TimePump;					// задержка перед аварией
bit AlarmBlok;					// флаг блокировки аварии, квитирование звука
int TimeTen1,TimeTen2,TimeTen3;	// задержки перед включением нагревателей
bit bTen1,bTen2,bTen3;			// флаг включения нагревателя
int TempMode;					//  режим работы 0 по воде, 1 по помещеню.
//bit protect; 					// 
//bit memo; 					//
//===========================================================================
// назначение Выводов микроконтроллера
//===========================================================================
#define TEN1 	RA0				// нагреватель 1
#define TEN2 	RA3				// нагреватель 2
#define TEN3 	RE0				// нагреватель 3
#define PUMP 	RE1				// насос	
#define RezervOUT 	RE2				// ркзкрвное реле
#define BUZZ 	RB6				// звуковой оповещатель (пищалка)
#define	LED 	RB7				// индикатор работа авария

//#define SHIBER 	RA0
// выводы для семисегментного индикатора код символа
#define seg7__a		RC0
#define seg7__b		RC1
#define seg7__c		RC2
#define seg7__d		RC3
#define seg7__e		RD0
#define seg7__f		RD1
#define seg7__g		RB5
//#define seg7__DP	RB4
// выводы для семисегментного индикатора разряды
#define Razr8	RD7
#define Razr7	RD6
#define Razr6	RD5
#define Razr5	RD4
#define Razr1	RD2
#define Razr2	RD3
#define Razr3	RC4
#define Razr4	RC5

//#define KEY		RB3				// вывод для обработки кнопок
#define PUMPOK	RA1				// вход контроль работы насоса
#define IN2 	RA2				// резерв 
#define IN3 	RA4				// резерв
#define KEY1 	RB0				// меню
#define KEY2 	RB3				// +
#define KEY3 	RB4				// -
#define KEY4 	RA5				// ОК


// DS18b20
#define DSIO1 	TRISB1			//	назначение линии для
#define DS1 	RB1				//	температурного датчика №1
#define DSIO2 	TRISB2			//	назначение линии для
#define DS2 	RB2				//	температурного датчика №2

//============================================================================
//Процедуры и функции (подпрограммы)
//============================================================================ 
// процедура задержки. 1 == 160млсек
void Delay (int Td)  	// один вариант задержки
{	Dlay = RTC + Td;
	while (Dlay != RTC);
}
void delay(unsigned int p) // задержка используется при работе с датчиками температуры
{	unsigned int i;
	for(i=0;i<p;i++){asm("NOP");}
}
void delayCount(int t) { while (t--) ; } // задержка используется при работе с датчиками температуры

//============================================================================
//Процедуры и функции (подпрограммы)
//============================================================================ 

//============================================================================
// Функции для работы с индикатором
//============================================================================ 
void seg7ch(CH)			// код для семисегментного индикатора
{//		seg7__DP = 1;
		switch (CH){	
			case '0': seg7__a=0;seg7__b=0;seg7__c=0;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=1; break;	// 0
			case '1': seg7__a=1;seg7__b=0;seg7__c=0;seg7__d=1;seg7__e=1;seg7__f=1;seg7__g=1; break; // 1
			case '2': seg7__a=0;seg7__b=0;seg7__c=1;seg7__d=0;seg7__e=0;seg7__f=1;seg7__g=0; break; // 2
			case '3': seg7__a=0;seg7__b=0;seg7__c=0;seg7__d=0;seg7__e=1;seg7__f=1;seg7__g=0; break; // 3
			case '4': seg7__a=1;seg7__b=0;seg7__c=0;seg7__d=1;seg7__e=1;seg7__f=0;seg7__g=0; break; // 4
			case '5': seg7__a=0;seg7__b=1;seg7__c=0;seg7__d=0;seg7__e=1;seg7__f=0;seg7__g=0; break; // 5
			case '6': seg7__a=0;seg7__b=1;seg7__c=0;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=0; break; // 6
			case '7': seg7__a=0;seg7__b=0;seg7__c=0;seg7__d=1;seg7__e=1;seg7__f=1;seg7__g=1; break; // 7
			case '8': seg7__a=0;seg7__b=0;seg7__c=0;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=0; break; // 8
			case '9': seg7__a=0;seg7__b=0;seg7__c=0;seg7__d=0;seg7__e=1;seg7__f=0;seg7__g=0; break; // 9
			case '-': seg7__a=1;seg7__b=1;seg7__c=1;seg7__d=1;seg7__e=1;seg7__f=1;seg7__g=0; break; // - тире
			case '=': seg7__a=1;seg7__b=1;seg7__c=1;seg7__d=0;seg7__e=1;seg7__f=1;seg7__g=0; break; // = равно
			case ' ': seg7__a=1;seg7__b=1;seg7__c=1;seg7__d=1;seg7__e=1;seg7__f=1;seg7__g=1; break; // пробел
			case 'H': seg7__a=1;seg7__b=0;seg7__c=0;seg7__d=1;seg7__e=0;seg7__f=0;seg7__g=0; break; // H
			case 'P': seg7__a=0;seg7__b=0;seg7__c=1;seg7__d=1;seg7__e=0;seg7__f=0;seg7__g=0; break; // P
			case 'T': seg7__a=1;seg7__b=1;seg7__c=1;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=0; break; // t
			case 'U': seg7__a=1;seg7__b=0;seg7__c=0;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=1; break; // U
			case 'Y': seg7__a=1;seg7__b=0;seg7__c=0;seg7__d=0;seg7__e=1;seg7__f=0;seg7__g=0; break; // Y
			case 'E': seg7__a=0;seg7__b=1;seg7__c=1;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=0; break; // E
			case 'A': seg7__a=0;seg7__b=0;seg7__c=0;seg7__d=1;seg7__e=0;seg7__f=0;seg7__g=0; break; // A
			case '_': seg7__a=1;seg7__b=1;seg7__c=1;seg7__d=0;seg7__e=1;seg7__f=1;seg7__g=1; break; // _ подчеркивание
			case 'S': seg7__a=0;seg7__b=1;seg7__c=0;seg7__d=0;seg7__e=1;seg7__f=0;seg7__g=0; break; // S
			case 'C': seg7__a=0;seg7__b=1;seg7__c=1;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=1; break; // C
			case 'D': seg7__a=1;seg7__b=0;seg7__c=0;seg7__d=0;seg7__e=0;seg7__f=1;seg7__g=0; break; // D
			case 'N': seg7__a=1;seg7__b=1;seg7__c=0;seg7__d=1;seg7__e=0;seg7__f=1;seg7__g=0; break; // n
			case 'R': seg7__a=1;seg7__b=1;seg7__c=1;seg7__d=1;seg7__e=0;seg7__f=1;seg7__g=0; break; // r
			case 'F': seg7__a=0;seg7__b=1;seg7__c=1;seg7__d=1;seg7__e=0;seg7__f=0;seg7__g=0; break; // F
			case 'O': seg7__a=0;seg7__b=0;seg7__c=0;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=1; break;	// O
			case 'L': seg7__a=1;seg7__b=1;seg7__c=1;seg7__d=0;seg7__e=0;seg7__f=0;seg7__g=1; break;	// L
			case 'o': seg7__a=1;seg7__b=1;seg7__c=0;seg7__d=0;seg7__e=0;seg7__f=1;seg7__g=0; break; // o маленькое
		}
}

void disp()						//  развертка для дисплея и сбор нажатых кнопок
{		Razr1 = Razr2 = Razr3 = Razr4 = Razr5= Razr6 = Razr7 = Razr8 = 1; // выключить все сегменты
		if (ni > 7) ni = 0;		// заходим на новый круг
		// 2 экран
		if (ni == 7) {			// 4 разряяд 2 экран
			seg7ch(Disp2[3]);	// выводим в порт код символа из буфера экрана
			Razr8 = 0;			// засвечиваем сегмент
//			if (KEY == 1) {Button = 4; bi=8;}  // OK нажата кнопка, включем счетчик для 
			ni++;				// готовим переход к новому разряду при следующем заходе
		}
		if (ni == 6) {			// 3 разряяд 2 экран
			seg7ch(Disp2[2]);
			Razr7 = 0;
//			if (KEY == 1) {Button = 3;bi=8;} // -
			ni++;
		}
		if (ni == 5) {			// 2 разряяд 2 экран
			seg7ch(Disp2[1]);
			Razr6 = 0;
//			if (KEY == 1) {Button = 2;bi=8;} // +
			ni++;
		}		
		if (ni == 4) {			// 1 разряяд 2 экран
			seg7ch(Disp2[0]); 
			Razr5 = 0;
//			if (KEY == 1) {Button = 1;bi=8;} // Menu
			ni++;
		}
		// 1 экран
		if (ni == 3) {			// 4 разряяд 
			seg7ch(Disp1[3]);
			Razr4 = 0;
			ni++;
		}
		if (ni == 2) {			// 3 разряяд
			seg7ch(Disp1[2]);
			Razr3 = 0;
			ni++;
		}
		if (ni == 1) {			// 2 разряяд
			seg7ch(Disp1[1]);
			Razr2 = 0;
			ni++;
		}		
		if (ni == 0) {			// 1 разряяд
			seg7ch(Disp1[0]);
			Razr1 = 0;
			ni++;
		}

} 

//============================================================================
//функции для работы с внутренней епром
//============================================================================
unsigned char ee_read(unsigned char address){
	GIE = 0; // разрешаем прерывания
	EEADR = address;  	// считываем из памяти   настройки
	RD = 1; 			// считываем значение статус 1 вен
	GIE = 1; // разрешаем прерывания
	return EEDATA;
}
void Param_Read()
{	
	TempUst 	= ee_read(0x00); // уставка температуры
	TempUstIn 	= ee_read(0x01); // уставка температуры
	TempTe1	 	= ee_read(0x02);	
	TempTe2	 	= ee_read(0x03);
	TempTe3 	= ee_read(0x04);
	TempPump 	= ee_read(0x05);
	Hyst 		= ee_read(0x06);
	Alarm 		= ee_read(0x07);
}
void Param_Write()
{	eeprom_write(0x00,TempUst);	// 
	eeprom_write(0x01,TempUstIn);	// 
	eeprom_write(0x02,TempTe1); // 
	eeprom_write(0x03,TempTe2); // 
	eeprom_write(0x04,TempTe3); // 
	eeprom_write(0x05,TempPump); // 
	eeprom_write(0x06,Hyst); 	// 
	eeprom_write(0x07,Alarm); 	//

}
//============================================================================
//функции для работы с датчиком DS18B20
//============================================================================ 
void ds18b20_higt(sensor)
{	if(sensor == 1) DSIO1=1;//high
	if(sensor == 2) DSIO2=1;//high
//	clc = clc ^1;
//	RB1=RB1^1;

}
void ds18b20_low(sensor)
{	if(sensor == 1) {DS1=0; DSIO1=0;} //low
	if(sensor == 2) {DS2=0; DSIO2=0;} //low
}
int ds18b20_init(int sensor)
{ 	int err;
	err = 0;
//	RB7 =  RB7^1;
//	RB6 =0;
	ds18b20_higt(sensor);
	if(sensor == 1) {
		if (DS1 == 0) err = 1;
	} 
	if(sensor == 2) {
		if (DS2 == 0) err = 1;
	} 
	if (err == 0 ){
		ds18b20_low(sensor);
	    delayCount(250);
	    ds18b20_higt(sensor);
		delayCount(18);
	}
	if(sensor == 1) {
		if (DS1 == 1) err = 2;
	} 
	if(sensor == 2) {
		if (DS2 == 1) err = 2;
	} 
    delayCount(250);
	return err;

}
int ds18b20_read_byte(int sensor)
{	int ds=0;
   	int n, i_byte=0;
	for (n=0; n<8; n++){
		ds18b20_low(sensor);
		ds18b20_higt(sensor);
		if (sensor == 1) ds = DS1;	//  проверка вывода на котором подключен датчик
		if (sensor == 2) ds = DS2;
		if (ds==1){					//  если вывод в состоянии 1
        	i_byte=(i_byte>>1) | 0x80;	// least sig bit first
      	}
      	else{						//  если вывод в состоянии 0
        	i_byte=i_byte >> 1;
      	}
      	delayCount(30);	// 
   }
   return(i_byte);
}
void ds18b20_write_byte(int d,int sensor)
{  int n;
	for(n=0; n<8; n++){
		if (d&0x01){
			ds18b20_low(sensor);
			ds18b20_higt(sensor);
	       	delayCount(30);
	    }
	    else{
			ds18b20_low(sensor);
			delayCount(30);
			ds18b20_higt(sensor);
	    }
    d=d>>1;
   }
}

int initemp(int sensor) // чтение температуры датчика
{	long Ttemp;
	int n;
	int b_temp;
	int F;
	F =0;
//	iTemp=0;
	T0IE = 0;
	ERRTemp  = ds18b20_init(sensor);
	if (ERRTemp  == 0 ) {
	    ds18b20_write_byte(0xcc,sensor);  // skip ROM пропускаем адрес,запрашиваем все датчики на шине
	    ds18b20_write_byte(0x44,sensor);  // запускаем конвертацию температуры
		while (F == 0) {// wait for conversion complete
			b_temp = ds18b20_read_byte(sensor);
			if (b_temp == 0xff) F = 0; else F =1;
		}
		ERRTemp = ds18b20_init(sensor);
		ds18b20_write_byte(0xcc,sensor);  // skip ROM	запрашиваем все датчики на шине
		ds18b20_write_byte(0xbe,sensor);  // чтение памяти
		for (n=0; n<9; n++){     // read 9 bytes but, use only one byte
			buff[n]=ds18b20_read_byte(sensor);  // read DS1820
		}
	    Ttemp=(buff[0]>>4)+(buff[1]<<4);
		if(Ttemp>128) {
			Ttemp=4096-Ttemp;
			Ttemp = Ttemp-Ttemp-Ttemp;
		}
	}
	else {
		if (ERRTemp == 1) Ttemp = 901;
		if (ERRTemp == 2) Ttemp = 902;
	} 

														
	T0IE = 1;
	return(Ttemp);
}


// ============================================================================
// обработчики прерываний
// ============================================================================
// обработчик прерывания от таймера
void interrupt tmr_int (void)
{	if (T0IF) { 							// если запрос на прерывание посупил от таймера TMR0
		T0IF = 0;  							// то сбросить флаг прерывания
	 	RTC++;     							//  и выполнить инкремент счетчика реального времени
		
//		if ((RTC % 255) == 0){				// из расчета выполняется каждую пол секунду 300
		ENdisp = 1; 						// активировать дисплей
		
//		}


		if ((RTC % 300) == 0){				// из расчета выполняется каждую пол секунду 300

			TempEnable =1;	
		}

		if ((RTC % 610) == 0){ 				//  из расчета выполняется каждую секунду
	//		Tsec++;							// считаем секунды внутри контроллера
//			clc = clc^1;
	
	//		EnDp = EnDp^1;					// мигание точки
			if (TimeMenu != 0) --TimeMenu;

		}						//  конец условия каждую секунду
		
	} 	// конец условного оператора таймера T_O
} // конец обработчика прерываний
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ============================================================================
// главная прогармма 
// ============================================================================
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void main (void)
{	OPTION = 0b00000100; 	// предделитель 32, jnrk.xtyb gjlnzubdf.ob[ htpbcnjhjd 0b10000100;
	TMR0 = 0; 				// начальное значение счетчика реального времени
	T0IE = 1;				// разрешить прерывания от таймера
	// предустановка портов
	RBPU = 1;				// включениеп одтягивающих резисторов
  	TRISA = 0b00110110;		// настраиваем порт A 
	TRISB = 0b00011111;		// настраиваем порт В 3 и 4 вход 
  	TRISC = 0b11000000;		// настраиваем порт c
  	TRISD = 0b00000000;		// настраиваем порт d
  	TRISE = 0b00000000;		// настраиваем порт e

	PORTA=255;
	PORTB=0;
	PORTC=255;
	PORTD=255;

	// включение и настройка АЦП
//	ADCON0=0b00000000; // включен
	ADCON1=0b00000110; // выключен


	//  выполняем инициализацию переферийных устройств
//	if ((KEY2 == 0) && (KEY3 == 0))  eeprom_write(0xFF,0);
	if(ee_read(0xFF) != 120){		// если запуск первый, набросаем в память настройки по умолчанию
	Delay(100);
		eeprom_write(0x00,45); 	// установка по воде
		eeprom_write(0x01,25); 	// установка  в помещении
		eeprom_write(0x02,0); 	// те1
		eeprom_write(0x03,1); 	// те2
		eeprom_write(0x04,1); 	// те3
		eeprom_write(0x05,30); 	// насос
		eeprom_write(0x06,1); 	// гистерезис
		eeprom_write(0x07,90); 	// тревога
		eeprom_write(0xFF,120); 	// флаг
	Delay(100);
	}

	Param_Read();					// считаем параметры из памяти
	BUZZ = 0;						// включим пищалку при включении
	GIE = 1;				// разрешить обработку прерываний
	for (Temp = 1; Temp<5; Temp++){	// несколько раз считаем температуру, исключит ошибку 85
		temp1=initemp(1);
	Delay(100);

		temp2=initemp(2);
	Delay(100);
	}
//		sprintf (Disp1, "8888");
//		sprintf (Disp2, "8888");
//	RezervOUT = 1;
//=================================================================================
// ОСНОВНАЯ ПРОГРАММА =============================================================
//=================================================================================
	while (1 == 1) { 	// бесконечный цикл
	
	if (TempEnable ==1) { 					// каждую секунду
		Razr1 = Razr2 = Razr3 = Razr4 = Razr5= Razr6 = Razr7 = Razr8 = 1;
		if (ti == 0) temp1=initemp(1);		// считываем датчик температуры 1
		if (ti == 1) temp2=initemp(2);		// считываем датчик температуры 2
		if (ti++ > 1) ti=0;					// обнуляем для работы c начала
		// тут обрабатываются пункты меню
//			Val = Temp;
		if (FAlarm == 0)  AlarmBlok = 0; 		// если неисправности ушли, сбросить блокировку аварии для повторной активации при аварии
		if ((FAlarm > 0) && (AlarmBlok == 0)){ 	// наличие аварии И отсутствие блокировки
			BUZZ = BUZZ^1; 						// пипикать каждую секунду
			if (FAlarm == 1){					// если авария по температуре
				sprintf (Disp1, "H%3d", temp1);	// вывести на дисплей температуру и сообщение ALAr
				sprintf (Disp2, "ALAR");
			}
			if (FAlarm == 2){					// если авария по нерабочему насосу
				sprintf (Disp1, "%4d", temp1);	// вывести на дисплей температуру и сообщение ENAS
				sprintf (Disp2, "ENAS");
			}
			if (FAlarm == 3){					// если авария по температуре
				if (temp1 == 901) sprintf (Disp1, "9999");	//
				if (temp1 == 902) sprintf (Disp1, "----");	//
				sprintf (Disp2, "%4d", temp2);

			}
			if (FAlarm == 4){					// если авария по температуре
				sprintf (Disp1, "%4d", temp1);	// вывести на дисплей температуру и сообщение ALAr
				if (temp2 == 901) sprintf (Disp2, "9999");	//
				if (temp2 == 902) sprintf (Disp2, "----");	//

			}

			ON = 0;								// выключить устройство при аварии (отключает тены)
		}
		else BUZZ = 1;							//  если нет аварии или квитировано, звук отключается

		if (FAlarm > 0)	LED = LED ^1;			// мигаем при аварии
		else			LED = ON^1;				// включаем инидкатор при работе, выключаем при ожидании

		if ((FAlarm == 0) || (AlarmBlok == 1)){	// отсутствие аварии ИЛИ вклчение блокироваки (квитирование)

//			mode = 20;
//		sprintf (Disp1, "%4d", Button);
//		sprintf (Disp2, "%4d", ValButton);

			if (mode == 0){ 					//  главный экран вывод показаний температуры от датчиков
//				sprintf (Disp1, "%0*d", 4, temp1);
//				sprintf (Disp2, "%0*d", 4, temp2);
				sprintf (Disp1, "%4d", temp1);		// температура воды
				sprintf (Disp2, "%4d", temp2);		// температура помещения
			}

			if (mode == 1){ 							// выбор режима по воде или помещению
				if (fm == 0) {Temp = TempMode; fm =1;}	// запоминаем параметр для редактирования и меняем после
				else TempMode = Temp;	
				if (TempMode < 0) Temp=TempMode = 1;			// нижнее ограничение региулировки
				if (TempMode > 1) Temp=TempMode = 0;			// нижнее ограничение региулировки

				if (TempMode == 0) {
					sprintf (Disp1, "_%3d", TempUst);
					sprintf (Disp2, "%4d", TempUstIn);
				}
				if (TempMode == 1) {
					sprintf (Disp1, "%4d", TempUst);		// температура воды
					sprintf (Disp2, "_%3d", TempUstIn);
				}
			}

			if (mode == 2){ 							// установка температуры воды
				if (TempMode == 1) {mode++; fm =0;}// если режим по помещению
				else {	
					if (fm == 0) {Temp = TempUst; fm =1;}	// запоминаем параметр для редактирования и меняем после
					else TempUst = Temp;	
					if (TempUst < 10) Temp=TempUst = 10;			// нижнее ограничение региулировки
					if (TempUst < TempPump+1) TempPump = TempUst-1; // при снижении температуры ниже темп. насоса снижаем температуру насоса
					if (TempUst > Alarm) Temp=TempUst = Alarm;	// верхнее ограничение от аварийной уставки
					sprintf (Disp1, "o%3d", TempUst);
					sprintf (Disp2, "%4d", temp2);
				}
			}

			if (mode == 3){ 							// установка температуры помещение
				if (TempMode == 0) {mode++; fm =0;}// если режим по помещению
				else {	
					if (fm == 0) {Temp = TempUstIn; fm =1;}	// запоминаем параметр для редактирования и меняем после
					else TempUstIn = Temp;	
					if (TempUstIn < 5) Temp=TempUstIn = 5;			// нижнее ограничение региулировки
					if (TempUstIn > 30) Temp=TempUstIn = 30;			// верхнее ограничение региулировки
					sprintf (Disp1, "%4d", temp1);		// температура воды
					sprintf (Disp2, "o%3d", TempUstIn);
				}
			}

			if (mode == 4){								// настройка насоса
				if (fm == 0) {Temp = TempPump; fm =1;}	// запоминаем параметр для редактирования и меняем после
				else TempPump = Temp;
//				if (TempPump < TempUst ) Temp=TempPump = TempUst;		// нижнее ограничение  Не пойму почему я так сделал
				if (TempPump < 10 ) Temp=TempPump = 10;		// нижнее ограничение  Не пойму почему я так сделал
				if (TempPump > Alarm-10) Temp=TempPump = Alarm-10;			// верхнее ограничение
				sprintf (Disp1, " NAS");
				sprintf (Disp2, "%4d", TempPump);
			}



			if (mode == 5){ 							// настройка нагревателя 1
				if (fm == 0) {Temp = TempTe1; fm =1;}	// запоминаем параметр для редактирования и меняем после
				else TempTe1 = Temp;
				if (TempTe1 < -10) Temp=TempTe1 = -10;		// нижнее ограничение
				if (TempTe1 > 10) Temp=TempTe1 = 10;			// верхнее ограничение
				sprintf (Disp1, "TE-1");
				sprintf (Disp2, "%4d", TempTe1);
			}
			if (mode == 6){ 							// настройка нагревателя 2
				if (fm == 0) {Temp = TempTe2; fm =1;}	// запоминаем параметр для редактирования и меняем после
				else TempTe2 = Temp;
				if (TempTe2 < -10) Temp=TempTe2 = -10;		// нижнее ограничение
				if (TempTe2 > 10) Temp=TempTe2 = 10;			// верхнее ограничение
				sprintf (Disp1, "TE-2");
				sprintf (Disp2, "%4d", TempTe2);
			}
			if (mode == 7){ 							// настройка нагревателя 3
				if (fm == 0) {Temp = TempTe3; fm =1;}	// запоминаем параметр для редактирования и меняем после
				else TempTe3 = Temp;
				if (TempTe3 < -10) Temp=TempTe3 = -10;		// нижнее ограничение
				if (TempTe3 > 10) Temp=TempTe3 = 10;			// верхнее ограничение
				sprintf (Disp1, "TE-3");
				sprintf (Disp2, "%4d", TempTe3);
			}

			if (mode == 8){ 							// настройка гистерезиса
				if (fm == 0) {Temp = Hyst; fm =1;}		// запоминаем параметр для редактирования и меняем после
				else Hyst = Temp;
				if (Hyst < 0 ) Temp=Hyst= 0;		// нижнее ограничение
				if (Hyst > 5) Temp=Hyst = 5;			// верхнее ограничение
				sprintf (Disp1, "HYST");
				sprintf (Disp2, "%4d", Hyst);
			}
			if (mode == 9){ 							// настройка аварийной сигнализации
				if (fm == 0) {Temp = Alarm; fm =1;}		// запоминаем параметр для редактирования и меняем после
				else Alarm = Temp;
				if (Alarm < TempUst ) Temp=Alarm= TempUst;		// нижнее ограничение
				if (Alarm > 100) Temp=Alarm = 100;			// верхнее ограничение
				sprintf (Disp1, "ALAR");
				sprintf (Disp2, "%4d", Alarm);
			}
//			if (mode == 9){ //  настройка насоса
//				if (fm == 0) {TimeMenu = 3; fm =1;}// конец меню, уменьшаем задержку до 2 сек.
//				sprintf (Disp1, " END");
//				sprintf (Disp2, "%4d", TimeMenu);
//			}

//		if (TimeStart != 0) {


			
		}

		// тут обрабатываются уставки
		// обработка включения насоса
		if (temp1 < TempPump - Hyst+1) PUMP = 1; //  если температуры меньше уставки - гистерезис, то включаем насос. 
		if (temp1 > TempPump + Hyst-1) PUMP = 0; //  если температуры меньше уставки - гистерезис, то выключаем насос. 
			RezervOUT = PUMP;
		FAlarm = 0;								// сброс кода аварии, перед проверкой наличия аварийных сигналов

		if (PUMP == 0){							// если висит команда на включение насоса
			if((PUMPOK == 1) && (TimePump++ > 2)) {FAlarm = 2; TimePump=3;} 		// если насос не включился за 2 сек
		}
		if (PUMPOK == 0) TimePump=0;	
		if (temp1 > Alarm) {FAlarm = 1; ON == 0;} 			// если температура выше аварийной сигнализации

		if (temp1 > 130) {FAlarm = 3; PUMP = 0;}		// неисправность датчика 1
		if (temp2 > 130) {FAlarm = 4; TempMode = 0;}	// неисправность датчика 2

		if (ON == 1) {
			if (TempMode == 0) { //  ругулировка по воде)
				// обработка включения нагревателя 1
				if (temp1 < TempUst - TempTe1 - Hyst+1) TEN1 = 0; //  если температуры меньше уставки - гистерезис, то включаем насос. 
				if (temp1 > TempUst - TempTe1 + Hyst-1) {TEN1 = 1; bTen1=0;}//  если температуры меньше уставки - гистерезис, то выключаем насос. 
				// обработка включения нагревателя 2
				if (temp1 < TempUst - TempTe2 - Hyst+1) bTen2=1; //TEN2 = 0; //  если температуры меньше уставки - гистерезис, то включаем насос. 
				if (temp1 > TempUst - TempTe2 + Hyst-1) {TEN2 = 1; bTen2=0;} //  если температуры меньше уставки - гистерезис, то выключаем насос. 
				// обработка включения нагревателя 1
				if (temp1 < TempUst - TempTe3 - Hyst+1) bTen3=1; // TEN3 = 0; //  если температуры меньше уставки - гистерезис, то включаем насос. 
				if (temp1 > TempUst - TempTe3 + Hyst-1) {TEN3 = 1; bTen3=0;} //  если температуры меньше уставки - гистерезис, то выключаем насос. 
			}
			if (TempMode == 1) { //  ругулировка по помещению)
				// обработка включения нагревателя 1
				if (temp2 < TempUstIn - TempTe1 +1) TEN1 = 0; //  если температуры меньше уставки - гистерезис, то включаем насос. 
				if (temp2 > TempUstIn - TempTe1 -1) {TEN1 = 1; bTen1=0;}//  если температуры меньше уставки - гистерезис, то выключаем насос. 
				// обработка включения нагревателя 2
				if (temp2 < TempUstIn - TempTe2 +1) bTen2=1; //TEN2 = 0; //  если температуры меньше уставки - гистерезис, то включаем насос. 
				if (temp2 > TempUstIn - TempTe2 -1) {TEN2 = 1; bTen2=0;} //  если температуры меньше уставки - гистерезис, то выключаем насос. 
				// обработка включения нагревателя 1
				if (temp2 < TempUstIn - TempTe3 +1) bTen3=1; // TEN3 = 0; //  если температуры меньше уставки - гистерезис, то включаем насос. 
				if (temp2 > TempUstIn - TempTe3 -1) {TEN3 = 1; bTen3=0;} //  если температуры меньше уставки - гистерезис, то выключаем насос. 
			}

			if (bTen2 == 1) {
				if(TimeTen2++ > 3) {TimeTen2 = 4; TEN2 = 0;}
			}
			else TimeTen2 = 0;
			if (bTen3 == 1) {
				if(TimeTen3++ > 6) {TimeTen3 = 7; TEN3 = 0;}
			}		
			else TimeTen3 = 0;
		}
		else{
			TEN1 = 1;TEN2 = 1;TEN3 = 1;TimeTen2 = 0;TimeTen3 = 0;
		}
			
//		sprintf (s7d, "%s%3d", "P", Tsec);

		TempEnable = 0;		//  обнуляем флаг после обработки всего модуля
	}

//	if (ENdisp++ > 100) {		// вызывается каждый вызов таймера
	if (ENdisp == 1) {		// вызывается каждый вызов таймера
		disp();				// вызываем вывод данных на дисплей
	 	ValButton = 0;
		if (KEY1 == 0) ValButton = 1;
		if (KEY2 == 0) ValButton = 2;
		if (KEY3 == 0) ValButton = 3;
		if (KEY4 == 0) ValButton = 4;

		if (ValButton != Button) {	//  проверка для разовой обработки модуля и обработка функций кнопок
			Button = ValButton;


			if (Button != 0 ) TimeMenu = 10;	// задержка перед возвратом в главный экран
			if (Button == 1) {mode++; fm=0;	} 
			if (mode > 9) mode = 0;	// выбор режимов меню

			if (Button == 2) {
				if (mode == 0) mode = 2; 	// если кнопка нажата в главном экране меняем экран
				else --Temp;				// уменьшение параметра
			}			
			if (Button == 3) {											
				if (mode == 0) mode = 2; 								// если кнопка нажата в главном экране меняем экран
				else Temp++;											// увеличение параметра
			}
//			clc = clc^1;
			if (Button == 4) {				// кнопка включение и выключения и квитирования
//				if ((FAlarm > 0) && (AlarmBlok == 0)) AlarmBlok = 1
				if (FAlarm > 0) AlarmBlok = AlarmBlok^1;	// при аварии квитируем, при повторном нажатии снимаем квитирование
				else {
					if (mode > 0) {	//  нажата не в главном экране
						TimeMenu = 0;	// c,hfcsdftv
					}
					else 	ON=ON^1; 				//  без аварии меняем режим работа или ожидание
				}
				
			}
		}

		if  ((TimeMenu == 0)&& (mode !=0)) {mode = 0; fm=0; Param_Write();}	// время автовозврата вышло, мерейдем в главный экран запишем параметры в память.
//		if  (TimeMenu == 1) {mode = 0; fm=0; Param_Write();}
//		Button = 0;
		ENdisp = 0; 			//  обнуляем флаг после обработки всего модуля
	}



	
	
// МУСОР.  пробные варианты.

//BUZZ = PUMPOK;

//strcpy(string, "P");	// заплнить строку
//strcat(string, r);		// добавить к строке новую строку
//sprintf (s7d, "%s%d", "P", -23);

	}			// конец цикла
}				// конец программы


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

#7 Пользователь онлайн   Alex 

  • Убиватель МК
  • PipPipPipPip
  • Группа: Пользователи
  • Сообщений: 1 876
  • Регистрация: 15 Февраль 11

Отправлено 16 Февраль 2017 - 01:29

Цитата

Как победить?
Перенести индикацию в обработчик прерывания по таймеру.
Не говорите что мне делать, и я не скажу куда Вам идти !
0

#8 Пользователь офлайн   Mizar 

  • Знаток
  • PipPip
  • Группа: Пользователи
  • Сообщений: 161
  • Регистрация: 09 Март 11

Отправлено 16 Февраль 2017 - 11:13

Хорошо бы, но...
Чем больше кода в обработчике прерывания, тем меньше остается времени вне обработчика.
Может получиться так, что код еще не завершен, но уже пришло время нового прерывания по таймеру.
Второй момент.
Если во время чтения температуры с датчика вызывается прерывание, результат температуры с ошибкой.
Получается что нужно перед чтением отключать прерывание, после чтения включать.
Любая сложная задача имеет простое, легкое для понимания неправильное решение...
0

#9 Пользователь онлайн   Alex 

  • Убиватель МК
  • PipPipPipPip
  • Группа: Пользователи
  • Сообщений: 1 876
  • Регистрация: 15 Февраль 11

Отправлено 16 Февраль 2017 - 22:11

Цитата

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

Цитата

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

PS:
Ваш код не помешало бы пооптимизировать немного. Например, все int'ы, где не нужны большие числа, заменить на (unsigned) char. И ОЗУ жрать меньше будет и программа пошустрее работать.
Да и код работы с датчиками пересмотреть бы.
Плюс, обязательно, проверка контрольной суммы данных от датчиков. Иначе, если от температуры будете чем-нибудь управлять, можете нарваться на неприятности.
Не говорите что мне делать, и я не скажу куда Вам идти !
0

#10 Пользователь офлайн   MAZ 

  • Консерватор - до мозга костей и суставов
  • PipPipPipPip
  • Группа: SuperMod
  • Сообщений: 1 368
  • Регистрация: 15 Февраль 11
  • ГородРоссия

Отправлено 16 Февраль 2017 - 22:47

Не давно делал устройство с динамикой, UART, DS18B20, и т.д.
Динамика в прерываниях через 5 мс. Все функции работы датчика ( разбитые мной) выполняются последовательно, через 5мс. Также в течении 5мс, между прерываниями, идет куча различных процессов. Задержки, звуки, кнопки и т.д. Даже прием по UART, дешифровка. (485 сеть на 120 устройств)
Все успевает и очень четко работает. Разрядов шесть.
Правда пишу только на асм. Так мне интересней.
Если бы Бог не был консерватором, вместо десяти заповедей мы имели бы десять предложений
0

Поделиться темой:


Страница 1 из 1
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

1 человек читают эту тему
0 пользователей, 1 гостей, 0 скрытых пользователей