Изменил несколько код, повыкидывал лишнее, подправил кое где. Запускается в Протеусе, ..но несколько "но".
1.
В начале, во время установки температуры LCD моргает редко и очень короткими вспышками, что-либо разглядеть проблематично.
2.
Результат АЦП отображается на дисплее как +40 градусов, независимо от положения потенциометоров, имитирующих датчики температуры.
3.
При отображении температуры выбранного датчика, первая строчка LCD отображается нормально, вторая медленно мигает ???
А в остальном всё работает как задумывалось. Пока ничего в голову путнего не пришло как исправить эти баги.
Ниже приведён исправленный код:
PHP код:
|
/************************************************** ***
Программа управления тепличными нагревателями, в диапазоне температур от 10 до 40 градусов цельсия.
Управляет 8-ю нагревателями по сигналам датчиков, а также отображает температуру выбранного датчика.
Chip type : ATmega16
Program type : Application
AVR Core Clock frequency: 1.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
************************************************** ***/
#include ‹mega16.h›
#include ‹stdio.h›
#include ‹delay.h›
#include ‹io.h›
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include ‹lcd.h›
//Подпрограммы
void Zad_temp();
void Chek_Botton();
void Check_bounds();
void Check_OK();
void ADC_IN();
void Temp_Ind();
void Out_ON();
void Out_OFF();
//Объявление переменных
volatile short ADC_VALUE;
volatile char T_MIN;
volatile char COUNTER;
volatile char T_MAX;
volatile char SENSOR_SEL;
volatile char SENSOR;
volatile char TEMP_def;
volatile char T_ZAD;
//LCD
char lcd_buffer[33];
//ADC interrupt service routine; Обработчик прерывания АЦП
interrupt [ADC_INT] void adc_isr(void)
{
ADC_VALUE=ADCW;
}
//Реализация АЦП
void __ADC_SampleADC()
{
ADCSRA = 0x8B; //0b10001011 - ADC Enable; ADC Interrupt Enable; ADC Prescaler-8;
#asm("sei")
ADMUX = COUNTER; //0b00000xxx - ADLAR, выравнивание вправо
//начать преобразование
ADCSRA |= 0x40;
//while(ADCSRA & 0x40);
}
void Zad_temp()
{
T_MIN = 10; // T_min = 10 нижняя граница диапазона
T_MAX = 40; // T_max = 40 верхняя граница диапазона
T_ZAD = (T_MAX + T_MIN) / 2; // Середина диапазона для начальной настройки:
}
void Chek_Botton()
{
//Опрос пина D4_"+"; Увеличение заданной температуры
if (PIND.4 == 0)
{
//Устранение дребезга. Delay: 200 ms
delay_ms(200);
//Нажата "+"?
if (PIND.4 == 0)
{
T_ZAD = T_ZAD + 1;
}
}
//Опрос пина D5_"-"; Понижение заданной температуры
if (PIND.5 == 0)
{
//Устранение дребезга. Delay: 200 ms
delay_ms(200);
//Нажата "-"?
if (PIND.5 == 0)
{
T_ZAD = T_ZAD - 1;
}
}
}
void Check_bounds()
{
// Проверка верхней границы T_zad›T_max?
if (T_ZAD›T_MAX)
{
T_ZAD = T_MAX;
}
// Проверка нижней границы T_zad‹T_min?
if (T_ZAD‹T_MIN)
{
T_ZAD = T_MIN;
}
}
void Check_OK()
{
B__Check_OK:
//Цикл проверки "OK"
if (PIND.6 == 0)
{
//Устранение дребезга. Delay: 200 ms
delay_ms(200);
//Нажата D6_OK?
if (PIND.6 == 0)
{
//Переход на метку
goto A__Check_OK;
}
}
else
{
//Вызов подпрограммы: Chek_Botton
Chek_Botton();
//Вызов подпрограммы: Check_bounds
Check_bounds();
};
//Вывод на дисплей заданной температуры
//Очистка дисплея
lcd_clear();
sprintf(lcd_buffer," Set temp %u grd",T_ZAD);
lcd_init(16);
lcd_gotoxy(0, 0);
lcd_puts(lcd_buffer);
//Возврат на метку
goto B__Check_OK;
//Выход из цикла
A__Check_OK:
//Очистка дисплея
lcd_clear();
}
void ADC_IN()
{
//Организация цикла опроса АЦП
while (COUNTER‹8)
{
//Выбор датчика
DDRD = DDRD & 0x07;
SENSOR_SEL = ((~PIND) & 0x07);
//Вызов подпрограммы АЦП: __ADC_SampleADC()
__ADC_SampleADC();
//Temp_Ind
//Вызов подпрограммы: Temp_Ind
Temp_Ind();
//АЦП Counter
if (COUNTER==7)
{
//Сброс счетчика
COUNTER = 0;
}
else
{
//Инкремент счетчика
COUNTER = COUNTER + 1;
}
}
}
void Temp_Ind()
{
//Преобразование данных АЦП в градусы
TEMP_def = ADC_VALUE / 33 + T_MIN - 1;
//Включение нагревателей
if (TEMP_def‹T_ZAD)
{
//Вызов подпрограммы: Out_ON
Out_ON();
}
//Выключение нагревателей
if (TEMP_def›T_ZAD)
{
//Вызов подпрограммы: Out_OFF
Out_OFF();
}
//Индикация температуры выбранного датчика
if (COUNTER==SENSOR_SEL)
{
SENSOR = SENSOR_SEL + 1;
delay_ms(50);
sprintf(lcd_buffer," Temp sensor %u %u grd",SENSOR,TEMP_def);
lcd_init(16);
lcd_gotoxy(1, 0);
lcd_puts(lcd_buffer);
delay_ms(200);
}
}
void Out_ON()
{
//Output_ON
DDRC = DDRC | (1‹‹COUNTER);
PORTC = PORTC & ~(1 ‹‹ COUNTER);
}
void Out_OFF()
{
//Output_ON
DDRC = DDRC | (1‹‹COUNTER);
PORTC = (PORTC & (1 ‹‹ COUNTER));
}
void main(void)
{
//Инициализация
MCUCSR=0x00;
#asm("wdr")
//Вызов подпрограммы: Zad_temp
Zad_temp();
//Вызов подпрограммы: Check_OK
Check_OK();
// Установка сетчика. Counter = 0
COUNTER = 0;
//Вызов подпрограммы: ADC_IN
ADC_IN();
}
|