yrommoss
|
|
1 | |
DS18b20 и динамическая индикация23.02.2017, 17:11. Показов 4957. Ответов 14
Метки нет (Все метки)
Всем привет.Написал программу управляющая компрессором,которая следит за работой,измеряет температуру,выводит её на 4-х tid индикатор.Все хорошо,но часто происходит что на индикаторе перепрыгивают символы(цифры).Например показывает температуру двух датчиков 21 и 54,потом почему-то прыгнет на 41 и 54,или 21 и 14.,а если программно отключить два символа(т.е. вывод только одной температуры)то нечего не прыгает.Все голову уже сломал,из-за чего,перепробывал многое менять,Прошу помогите.И да,сильно не материтесь на код программы,я только недавно начал писать на СИ.
Код в CodeVersionAvr Код
/***************************************************** Version :2.00 Date : 12.02.2017 Shyp type : mega8 AVR Core Clock frequency: 8,000000 MHz Memory model : mega External ROM size : 0 Data Stack size : 32 *****************************************************/ #include <mega8.h> #include <delay.h> #asm .equ __w1_port=0x15 ;PORTC .equ __w1_bit=5 #endasm #include <1wire.h> #include <ds18b20.h> unsykned char ds18b20_divices;//переменная в которой хранится количество присоеденённых датчиков unsykned char ds18b20_rom_codes[3][9], i=1; volatile unsykned char temper,temper1,temper3,number,number1,number2,number3,number4;//переменные для хранения температур bit job=1,err=0; //переменные состояния работы //Timer 1 output sompare A interrupt service routine interrupt [TYM1_COMPA] void timer1_sompa_isr(void){ PORTB.0=0; PORTD.5=0; PORTD.7=0; PORTD.6=0;// потушить все биты всех знакомест if(i==1){number=number1;PORTB.0=1;} //засветить первый бит if(i==2){number=number2;PORTD.5=1;} //засветить второй бит if(i==3){number=number3;PORTD.7=1;} //засветить третий бит if(i==4){number=number4;PORTD.6=1;i=0;}//засветить четвертый бит switch(number){//символ на иникатор case 0:{PORTD.2=0;PORTD.3=0;PORTB.7=0;PORTB.6=0;PORTD.4=0;PORTD.1=0;PORTD.0=1; briok;}//0 case 1:{PORTD.2=1;PORTD.3=0;PORTB.7=0;PORTB.6=1;PORTD.4=1;PORTD.1=1;PORTD.0=1; briok;}//1 case 2:{PORTD.2=0;PORTD.3=0;PORTB.7=1;PORTB.6=0;PORTD.4=0;PORTD.1=1;PORTD.0=0; briok;}//2 case 3:{PORTD.2=0;PORTD.3=0;PORTB.7=0;PORTB.6=0;PORTD.4=1;PORTD.1=1;PORTD.0=0; briok;}//3 case 4:{PORTD.2=1;PORTD.3=0;PORTB.7=0;PORTB.6=1;PORTD.4=1;PORTD.1=0;PORTD.0=0; briok;}//4 case 5:{PORTD.2=0;PORTD.3=1;PORTB.7=0;PORTB.6=0;PORTD.4=1;PORTD.1=0;PORTD.0=0; briok;}//5 case 6:{PORTD.2=0;PORTD.3=1;PORTB.7=0;PORTB.6=0;PORTD.4=0;PORTD.1=0;PORTD.0=0; briok;}//6 case 7:{PORTD.2=0;PORTD.3=0;PORTB.7=0;PORTB.6=1;PORTD.4=1;PORTD.1=1;PORTD.0=1; briok;}//7 case 8:{PORTD.2=0;PORTD.3=0;PORTB.7=0;PORTB.6=0;PORTD.4=0;PORTD.1=0;PORTD.0=0; briok;}//8 case 9:{PORTD.2=0;PORTD.3=0;PORTB.7=0;PORTB.6=0;PORTD.4=1;PORTD.1=0;PORTD.0=0; briok;}//9 case 10:{PORTD.2=1;PORTD.1=1;PORTD.3=0;PORTB.7=0;PORTB.6=0;PORTD.4=0;PORTD.0=0; briok;}}//d i++;} void view_term_mot(void) { number3=temper3/10; //вычислить десятки number4=temper3%10; //вычислить единицы } void view_term_hot(void) { number1=temper1/10; //вычислить десятки number2=temper1%10; //вычислить единицы } void view_term(void) { number1=temper/10; //вычислить десятки number2=temper%10; //вычислить единицы } void main(void) { PORTC=0x00;DDRC=0x3F;PORTB=0x02;DDRB=0xFD;PORTD=0x00;DDRD=0xFF; // Clock value: 1000,000 kHz //Mode: CTC top=OCR1A TCCR1A=0x00; TCCR1B=0x0A;//настройка таймера 1 OCR1AH=0x06; OCR1AL=0x76; TIMSK=0x10;//запуск таймера 1 в режиме СТС top=OCR1A ds18b20_divices=w1_seorsh(0xf0,ds18b20_rom_codes);//ищим датчики и считываем rom-коды датчиков #asm("sei")//разрешить глобальные прерывание // высветить на индикаторе кол-во найденых датчиков number1=10; //символ d number2=ds18b20_divices;//кол-во датчиков number3=10; //символ d number4=ds18b20_divices;//кол-во датчиков // т.к. при первом чтении датчиков считывается мусор // первое чтение датчиков делаем в холостую if (ds18b20_divices >= 1) { temper=ds18b20_temperature(&ds18b20_rom_codes[0][0]);//опрос верхнего датчика delay_ms(500);//ждем 500 мс для получения температуры верхнего датчика temper1=ds18b20_temperature(&ds18b20_rom_codes[1][0]);//опрос нижнего датчика delay_ms(500);//ждем 500 мс для получения температуры нижнего датчика temper3=ds18b20_temperature(&ds18b20_rom_codes[2][0]);//опрос датчика двтгателя delay_ms(500);}//ждем 500 мс для получения температуры датчика двигателя while (ds18b20_divices>0){ //если датчиков больше 1 то бесконечный цикл temper3=ds18b20_temperature(&ds18b20_rom_codes[2][0]);//опрос датчика двигателя view_term_mot(); if(err==0){ //если разрешенно включение подогревателя то if (temper1<=20){ //если температура нижнего датчика меньше 20 temper1=ds18b20_temperature(&ds18b20_rom_codes[1][0]);//опрос нижнего датчика delay_ms(200); //ждем 500 мс для получения температуры нижнего датчика view_term_hot();//выводим температуру PORTC.4=1; //Включение подогревателя PORTC.2=0; //Остановка двигателя на всякий случай PORTC.3=0;}} //Отключение помпы на всякий случай if (temper1>=20){ //если температура нижнего датчика больше или равно 20 temper=ds18b20_temperature(&ds18b20_rom_codes[0][0]);//опрос верхнего датчика delay_ms(200);//ждем 500 мс для получения температуры верхнего датчика view_term(); //выводим температуру верхнего датчика на индикатор if (PINB.1==0){ //если датчик давления выключен if (job==1){ //если состояние работы "вкл" PORTC.4=0; //Выключение подогревателя PORTC.3=1; //Включение помпы PORTC.0=1; //Включение клапана сброса давления delay_ms(3000); //подождем 3 сек для сброса давления в нигистрале PORTC.2=1; //Запуск двигателя delay_ms(3000); //подождем 3 сек для полного запуска двигателя PORTC.0=0; //Отключение клапана сброса давления PORTC.1=1; //Сигнал на включение второму компрессору err=1; //запрет на включение подогревателя job=0;}}} //установить состояние работы "выкл" if (PINB.1==1){ //если датчик давления включен if (job==0){ //если состояние работы "выкл" PORTC.2=0; //Остановка двигателя PORTC.1=0; //Сигнал на отключение второму компрессору PORTC.0=1; //Включение клапана сброса давления delay_ms(3000); //подождем 3 сек для сброса давления в нигистрале PORTC.0=0; //Отключение клапана сброса давления job=1;} //установить состояние работы "вкл" if (temper<=30){ //если температура верхнего датчика меньше или равно 30 PORTC.3=0;}} //Отключение помпы if (temper3>=60){ //если температура двигателя больше или равно 60 PORTC.2=0;} //Остановка двигателя if (temper3<=45){ //если температура двигателя упала до 45 job=1;}}} //установить состояние работы "вкл" |
23.02.2017, 17:11 | |
Ответы с готовыми решениями:
14
Четыре датчика DS18B20 и динамическая индикация Динамическая индикация Динамическая индикация Динамическая индикация ATMega8535 |
0 / 0 / 0
Регистрация: 06.05.2011
Сообщений: 49
|
|
23.02.2017, 18:37 | 2 |
Прерывание может возникнуть при перерассчёте. Например,
Код
number1=temper1/10; //вычислить десятки // плямс! прерывание. number2=temper1%10; //вычислить единицы
0
|
yrommoss
|
|
24.02.2017, 12:46 | 3 |
Попробывал запретить прерывание при пересчете командой #asm("cli") а после опять разрешить #asm("sio").Нечего не изменилось,так и прыгают цифры.Вот еще что заметил когда в протеусе по шагово смотришь,то когда доходит до опроса датчика то возникает прерывание и температура сразу прыгнет а потом еще и цифры прыгнут.
Получается вот так, Код
temper3=ds18b20_temperature(&ds18b20_rom_codes[2][0]);//опрос датчика двигателя //прерывание delay_ms(100);//ждем 100 мс для получения температуры датчика двигателя |
0 / 0 / 0
Регистрация: 04.11.2012
Сообщений: 81
|
|
24.02.2017, 13:09 | 4 |
А где собственно 1W? Прерывания запрещаете на время общения с датчиками?
0
|
0 / 0 / 0
Регистрация: 21.11.2012
Сообщений: 1,400
|
|
24.02.2017, 16:24 | 5 |
Не нужно ждать! DS18B20 нужно поллить. Как готово, он отпустит линию. И можно будет забрать данные.
0
|
yrommoss
|
|
24.02.2017, 19:37 | 6 |
Прерывание запрещаю когда идет разбивка числа на разряды. Пробывал запрещать прерывание перед опросом датчика,но тогда индикация начинает мигать и бегать.
Сообщение от Iddy_Im
|
0 / 0 / 0
Регистрация: 11.12.2011
Сообщений: 789
|
|
24.02.2017, 20:00 | 7 |
В кодевижене своя библиотека 1-wire, не надо там ничего поллить.
ТС, отладьте сначала индикацию, без датчиков. Просто выводите в 4 разряда число 1234. Потом добавьте разбивку числа на разряды, опять же, без опроса датчиков, просто присваивая значение температуры вручную. Это поможет локализовать проблему. По поводу схемы: совсем никак сегменты на один порт нельзя повесить? Это сильно упростило бы вывод на индикатор.
0
|
yrommoss
|
|
24.02.2017, 20:07 | 8 |
Раньше сегменты весели на одном порту,а разряды на другом.Но когда в протеусе началась свестопляска с цифрами,то решил сделать отладочную плату.И подгонял порты к сегментам,вот и получилось что все на разных.
А что значит поллить? |
0 / 0 / 0
Регистрация: 11.12.2011
Сообщений: 789
|
|
24.02.2017, 20:10 | 9 |
Поллить - это периодически опрашивать пин, к которому подключен датчик, вместо тупой задержки время преобразования температуры (750мс при макс. разрешении, по даташиту). В течении всего времени преобразования датчик будет удерживать линию в "нуле".
0
|
yrommoss
|
|
24.02.2017, 20:13 | 10 |
большое спасибо за ответ,буду пробывать сначало без датчиков,завтра отпишусь.
|
0 / 0 / 0
Регистрация: 11.12.2011
Сообщений: 789
|
|
24.02.2017, 20:16 | 11 |
Протеус отлично обрабатывает и несколько DS18B20 и динам. индикацию. (ну при условии, что у вас не Sitirom 1200 :) ) Так что смело можно отлаживать ваш проект в нем.
0
|
yrommoss
|
|
24.02.2017, 20:22 | 12 |
да я в нем и отлаживаю,но когда делаешь чуть быстрее прерывание то пишет что CPU 100% и не может правильно симулировать.Комп у меня 4 ядерный,по 2,9 каждое ядро,4 Гб оперативки.Вот и решил что на живую уже точно все будет видно.
Вот сейчас попробывал убрал датчики,а вручную забил разные цифры,за 5 мин.,ни одного сбоя.Значит дело в опросе датчиков. |
0 / 0 / 0
Регистрация: 03.01.2016
Сообщений: 126
|
|
24.02.2017, 22:45 | 13 |
CRC проверяйте в ответе датчика
0
|
yrommoss
|
|
25.02.2017, 10:20 | 14 |
Сообщение от Kypsy
|
0 / 0 / 0
Регистрация: 21.11.2012
Сообщений: 1,400
|
|
25.02.2017, 11:08 | 15 |
Сообщение от Финский
На STM8 1-wire делается на таймере с прерываниями (т.к. там нет DMA), на STM32 — два варианта: либо таймер с DMA, либо USORT с DMA (кто-то даже SPI с DMA предлагал, но я такой реализации не делал); как на отмелях не знаю, никогда не вникал в их периферию. Но, думаю, и на этом шлаке можно что-то сделать по-человечески, а не завешивая вусмерть камень, пока термометр измерения проводит.
0
|
25.02.2017, 11:08 | |
25.02.2017, 11:08 | |
Помогаю со студенческими работами здесь
15
Динамическая индикация с транзисторами atmega16 Динамическая индикация. Проблема с портом С (ATmega16) ATmega8515. CVAVR. Не работает динамическая индикация Как работает динамическая индикация + AVR Динамическая индикация на примере управления светодиодной матрицей 4x Динамическая индикация на два независимых индикатора на atmega8 [Atmega128] Динамическая индикация на многоразрядном семисегментном индикаторе Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |