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

Avr+codevision


Юрец

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

Здравствуйте!

проблема в следующем:

имеем atmega8. работаю с АЦП (считываю напряжение на ножке). нужно, чтобы при резком увеличении/снижении напряжения на входе АЦП показ значения напряжения менялся не скачком, а плавно (это как корпус стрелочной измерительной головки наполнен густым веществом, типа масла). т.е. стрелка имеет инерционность.

p.s. до сих пор пытаюсь усовершенствовать цифровой датчик топлива в машину.

по коду: всё работает, но только когда напряжение уменьшается. временно поставил переменный резистор (2 крайние ноги на "+" и "-" , а средний вывод на вход adc(0) ). когда резко кручу ручку резистора в сторону уменьшения напряжения (по коду : if (read_v<result_v){result_v=result_v-0.1;lcd_result_v();} ), то индикация res_v происходит плавно. на вращение ручки резистора в сторону увеличения напряжения (по коду : if (read_v>result_v){result_v=result_v+0.1;lcd_result_v();} ) изменения res_v не происходит.

в чём может быть запарка?

p.s.s. резистор рабочий, т.к. при установке в min или max его положение и последующем включении девайса res_v =0 при min ,и res_v =1023 при max.


#include <mega8.h>

// Alphanumeric LCD Module functions
#asm
  .equ __lcd_port=0x18 ;PORTB
#endasm

#include <lcd.h>
#include <delay.h>
#include <stdio.h>
//#include <stdlib.h>

#define ADC_VREF_TYPE 0x00

unsigned  int read_v=0;  //содержит результат преобразования для volt_adc(0) 0-1023
unsigned  int result_v=0;   //фактический показ на lcd 
unsigned char buffer_dec [33]; //объявляем  буфер из трех чисел, каждое не больше 255 (число символов ASCII) для десятичной записи

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}


void lcd_result_v(void){
sprintf (buffer_dec, "%4d", result_v[b]/10[/b]); //в результате выполнения функции в буфере окажутся четыре числа 
lcd_gotoxy(12, 0);
//пересылаем контроллеру дисплея набор кодов отображаемых символов
lcd_puts(buffer_dec);
}

void main(void)
{  
PORTB=0x00;
DDRB=0xFF;


PORTC=0x00;
DDRC=0x00;

PORTD=0x0F;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

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

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;

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

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

// ADC initialization
// ADC Clock frequency: 125,000 kHz
// ADC Voltage Reference: AREF pin
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x86;

// LCD module initialization
PORTB=0x00; //Выставляем все выходы PORTB на ноль

DDRB=0x00; // Выставляем все выходы PORTB как входы

lcd_init(16); // Инициализация ЖКИ на 16 символов

lcd_clear();
lcd_gotoxy(0, 0);
lcd_putsf ("volt_adc(0)");  

//заполняем буфера


read_v=read_adc(0);
result_v=read_v;
lcd_res_v();
// первый показ res_v на lcd до цикла while (1), т.е. устанавливается опорное res_v

while (1)

     { 
read_v=read_adc(0);
if (read_v>result_v){[b]result_v=result_v+1[/b];lcd_result_v();}; //если результат ацп > 	//значение result_v, показанного на индикаторе, то result_v уменьшить на 0.1
if (read_v<result_v){[b]result_v=result_v-1[/b];lcd_result_v();};[b]// почему-то result_v=result_v++ не работает![/b]

delay_ms(10);



     }; 

}

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

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

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

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

Програмно можно поппробовать сделать так: за некоторый промежуток времени, допустим 1сек, с маленьким интервалом(допустим 0,01сек) считываем значения ацп, после чего считаем среднее арифметическое значение этих чисел, и уж апасля выводим на экран.

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

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

>хорошо бы поставить на вход ацп (после делителя) конденсатор этак на 1мкф.

пробовал - слабо помогает.

Програмно можно поппробовать сделать так: за некоторый промежуток времени, допустим 1сек, с маленьким интервалом(допустим 0,01сек) считываем значения ацп, после чего считаем среднее арифметическое значение этих чисел, и уж апасля выводим на экран.

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

максимально спасает алгоритм фильтра БИХ первого порядка (статья в журнале Схемотехника за

2004г -автомобильный компьютер). там автор применил именно этот алгоритм для скачкообразного изменения уровня топлива. к сожалению автор на мои письма не отвечает , а разобраться в алгоритм фильтра БИХ первого порядка у меня не получилось. кое-что нашел по этому алгоритму, но там куча математических вычислений, привязанных ко времени.

могу нарисовать график (примерный) резкого изменения уровня топлива, и то, что (теоретически) я хочу добиться в программе. общими словами: реальный уровень топлива будет нарастать/спадать не так лавинообразно ,и в течении 4-10сек можно узнать средний уровень топлива.

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

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

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

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

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

Во-первых, что бросается в глаза. Вы к переменной типа int прибавляете/отнимаете 0.1 (которое флоат). CAVR приведение типов самостоятельно не делает. Что он делает, х/з, ибо значения все же меняются... Плавное уменьшение показаний при снижении напряжения может объяснятся присутствием конденсатора, а не алгоритмом. Для начала попробуйте примерно так:

//...

if (read_v>result_v){result_v=result_v++;lcd_result_v();};

if (read_v<result_v){result_v=result_v--;lcd_result_v();};

//...

От "дрожания" разрядов это не избавит, но некоторая плавность, возможно, будет...

Изменено пользователем Goodefine

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

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

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

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

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

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

,и в течении 4-10сек можно узнать средний уровень топлива.

так в чем проблемы?

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

Кстати, можно сделать аналоговый фильтр НЧ на ОУ, чтобы "скачки" уже не пропускал. Нужно только определить частоту среза. Графики желательно с временными интервалами.

да, кстати, у меня появился вопрос по теме: каким образом считав значение ацп умножить его на 0,02 и это число (понятно что оно будет не целым) вывести на лсд "как есть" тоесть чтобы он показывал 15,65 например ???

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

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

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

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

Для плавного вывода значений нужно использовать круговой буфер - чем длинше - тем плавней будет плавать число. Круговой буфер это просто берём например 64 ячейки и записываем новое считаное число всегда в следующую ячейку и при достижении конца буфера перескакиваем на первую ячейку... При выводе на дисплей выводим всегда среднее арефмитическое буфера... Всё.. Плавней не придумаете... Проверено на спидометре. Кстати длина буфера может быть любая... Можно подгонять до одному байту :) Занять всю оставшуюся память..

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

а если просто поставить конденсатор и побольше на вход ацп? поидее тогда скачков небудет ни при уменьшении уровня ни при увеличении

зы: скажем 47-200мкф

Изменено пользователем NebsteR

> Правила форума <

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

...это не дым от канифоли, нет... это души умерших транзисторов....

Первый закон Ома: никому не рассказывать про Ома!

Ну вот, а ты говорил ноль...

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

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

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

ответьте пжлст на вопрос..

да, кстати, у меня появился вопрос по теме: каким образом считав значение ацп умножить его на 0,02 и это число (понятно что оно будет не целым) вывести на лсд "как есть" тоесть чтобы он показывал 15,65 например ???

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

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

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

> Правила форума <

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

...это не дым от канифоли, нет... это души умерших транзисторов....

Первый закон Ома: никому не рассказывать про Ома!

Ну вот, а ты говорил ноль...

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

Уже много раз обсуждалось. Для умножения на дробь надо перевести как дробь так и то что будем умножать в целые числа уножением (в вашем случае на 100 ) и при выводе результата просто перенести запятую туда куда надо.

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

получилась так, как я и хотел (на мою ошибку указал Goodefine) - спасибо!

исправления внесены в код в 1-м посте жирным шрифтом. в принципе алгоритм остался тем-же.

так-же спасибо всем откликнувшимся!

а теперь к делу:

1. to NebsteR, to l-e-o-n-a-r-d-o :конденсатор я не вешал ВООБЩЕ! большой пользы от его включения на реальной конструкции не заметил (и ограничивал ток заряда/разряда, экспериментировал с его емкостью...).

2. to wowa: идея с массивом мне попадалась и раньше. тоже есть небольшая загвоздка. (по крайней мере у меня не получилось сгладить резкие скачки).

3. to l-e-o-n-a-r-d-o :>А графики не помешали бы.

рисую. позже выложу.

вот видео:25_02_09_1818.rar

rar переименовать в 3gp

p.s. далее девайс нужно проверить в реальных условиях, а потом делать выводы...

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

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

if (read_v<result_v){result_v=result_v-1;lcd_result_v();};// почему-то result_v=result_v++ не работает!

Естественно, надо просто ++ или --(просто не заметил :) ):

if (read_v<result_v){result_v--;lcd_result_v();};

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

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

А резкие скачки и не надо сглаживать или интегрировать. Их нужно сбрасывать из массива измерений. Т.е. нужно проводить статистическую обработку и находить весовой центр массива. Размер массива должен соответствовать возможной скорости изменения уровня.

戦う前に相手のベルトの色に注目

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

А этот алгоритм как раз и подходит только для демпфирования. В реале нужно вводить хотя-бы минимальную стат. обработку. А потом заменить "read_v" на "statistic_v"...

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

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

Да не я не особенно верю насчёт того что не сглаживало.. У меня прищлось уменьшать буфер чтобы не плаааааааваааааалоооооо :) Попробуйте посчитать пощитать среднее для 64 "0x55" значений и когда туда подкинете десяток "0xFF" - резщультат не на много двинется.. А вообще я рад что человек сообщает о результатах вообще..

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

Попробуйте посчитать пощитать среднее для 64 "0x55" значений и когда туда подкинете десяток "0xFF" - резщультат не на много двинется..

а нельзя посмотреть на пример реализации работы с таким кольцевым массивом? (видимо я опять что-то начудил при написании программы с использованием Вашего метода)...

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

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

Да не я не особенно верю насчёт того что не сглаживало.. У меня прищлось уменьшать буфер чтобы не плаааааааваааааалоооооо :) Попробуйте посчитать пощитать среднее для 64 "0x55" значений и когда туда подкинете десяток "0xFF" - резщультат не на много двинется.. А вообще я рад что человек сообщает о результатах вообще..

Странны вообще разговоры об усреднении ВСЕХ отсчетов, когда очевидно можно предсказать, что скачки выше прогноза на темпы расхода-заправки вообще не могут существовать и их попросту нужно выбросить. Т.е. или в баке должно быть несколько разнесенных датчиков или мы должны совместить прогноз и стат обработку, тогда и массив будет небольшим и инерционность прибора будет оптимальной (например в режиме заправки, когда полезно оценить недолив).

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

戦う前に相手のベルトの色に注目

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

Самого устройства у меня уже нет - оно катается на велике знакомой :) Поищю вечером исходник... Вообще my504 говорит правду. Если входные данные отличаются от прошлого среднего на более чем 5% нужно записать среднее... И всё. Я вот об этом как то не подумал.. У меня небыло скачков более чем на 10% так что у меня их буфер сгладил без проблем.

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

а вот и график того, что у меня получилось:Image2.rar

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

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

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

  • 3 недели спустя...

Здравствуйте!

проект почти закончен.

опять уперся в грабли, а именно:

нужно реализовать алгоритм изменения яркости подсветки ЖК индикатора используя таймер.

у меня получилось так:

#include <mega8.h>
#include <delay.h>
int work,pause=0;
int counter=0;

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
counter++;
if((counter==work)&(PORTB.0==1)){PORTB.0=0;TCNT0=0;counter=0;}; 
if((counter==pause)&(PORTB.0==0)){PORTB.0=1;TCNT0=0;counter=0;};
TCNT0=0x10;
}


void main(void)
{
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out 
// State7=T State6=T State5=T State4=T State3=T State2=P State1=P State0=0 
PORTB=0x06;
DDRB=0x01;

// PORTB.1 и PORTB.2 это кнопки на "-". входы с подтяжкой.
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
TCCR0=0x01;
TCNT0=0x10;

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

#asm("sei")

//work=100; //на выводе PORTB.0          2.7V
//pause=0; 

//work=50; //на выводе PORTB.0           2.5V
//pause=50;

work=25; //на выводе PORTB.0             0.6V
pause=75;

//work=1; //на выводе PORTB.0            0.1V
//pause=99;

while (1)
     {
     if((!PORTB.1)&(pause>0)){delay_ms(5);work++;pause--;}; // если нажата кнопка LIGHT+
     if((!PORTB.2)&(work>0)){delay_ms(5);work--;pause++;};// если нажата кнопка LIGHT-
     };
}
;

по программе: переменные work-длительность импульса ШИМ, pause = 100-work.

проблема в том, что на изменение work и pause в цикле while(1) ничего не происходит. действия с work и pause до цикла while(1) работают, т.е. яркость светодиода изменяется .

совсем запутался.....

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

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

...if((!PORTB.1)&...

Т.е. Вы опрашиваете защелку. Правильно

...if((!PINB.1)&...

Везде, естественно... Только вчера тут обсуждали подобное :)... Подробнее не смотрел.

А чего бы не воспользоваться аппаратным ШИМом?

З.Ы. Вопрос частично снимается (не глянул что мега8). Таймер2 занят? Там есть аппаратный ШИМ...

З.Ы.Ы. Нашел вторые грабли.

while (1)
{
if((!PORTB.1)&(pause>0)){delay_ms(5);work++;pause--;}; // если нажата кнопка LIGHT+
if((!PORTB.2)&(work>0)){delay_ms(5);work--;pause++;};// если нажата кнопка LIGHT-
};

Условия:

(pause>0) и (work>0)

Не выполнятся никогда (они равны 0), поэтому входа в блоки не будет никогда.. Правильно ">="

Изменено пользователем Goodefine

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

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

Спасибо!

ларчик просто открывался...

всё получилось, изменив код так: (жирным)


#include <mega8.h>
#include <delay.h>
int work,pause=1;
int counter=0;

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
counter++;
if((counter==work)&([b]PINB[/b].0==1)){PORTB.0=0;TCNT0=0;counter=0;}; 
if((counter==pause)&([b]PINB[/b].0==0)){PORTB.0=1;TCNT0=0;counter=0;};
TCNT0=0x10;
}


void main(void)
{
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out 
// State7=T State6=T State5=T State4=T State3=T State2=P State1=P State0=0 
PORTB=0x06;
DDRB=0x01;
// PORTB.1 и PORTB.2 это кнопки на "-". входы с подтяжкой.

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
TCCR0=0x01;
TCNT0=0x10;

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

#asm("sei")

work=10; //на выводе PORTB.0          2.7V
pause=1; 



while (1)
     {
     if((![b]PINB[/b].1)&(pause[b]>[/b]1)){delay_ms(100);work++;pause--;[b]counter=0;[/b]}; // если нажата кнопка LIGHT+
     if((![b]PINB[/b].2)&(work[b]>[/b]1)){delay_ms(100);work--;pause++;[b]counter=0;[/b]};  // если нажата кнопка LIGHT- 
     };
}

;

:(

получается около 10 градаций яркости на простом светодиоде. подключу ЖКиндикаторную подсветку через транзистор(думаю КТ972,973 хватит с головой), и посмотрю что получится.

>(pause>0) и (work>0)

>Не выполнятся никогда (они равны 0), поэтому входа в блоки не будет никогда..

перед while(1) переменные заполняются work=10;pause=1;...

ещё раз СПАСИБО!

p.s. на подобные грабли (типа PIN, PORT)уже неоднократно наступаю :( , хоть записывай...

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

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

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

>И наверняка двойное надобно &&

зачем??? codevision avr работает с одним &.

появились очередные грабли при подключении ds18b20 (подключен к PORTС.4):

когда работает таймер

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{

counter++;

// ПОДСВЕТКА ЖК НА PORTD.4

if((counter==work)&(PIND.4==1)) {PORTD.4=0;counter=0;};

if((counter==pause)&(PIND.4==0)) {PORTD.4=1;counter=0;};

TCNT0=0x10;

}

то слетает показ температуры (становится -9999).

КАК только убираю из тела обработчика таймера две строки с if (выделено жирным), то показ температуры датчика ds18b20 становится нормальным.

где грабли?

p.s. полный код нужен?

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

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

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

Грабли могут быть где угодно. Может стек переполняется (попробуйте увеличить), либо обработчик банально слишком много ресурсов отбирает (вызывается он у Вас часто). Попробуйте этот код - в вечном цикле ничего не делается, все в обработчике. Удобная настройка антидребезга, выбор числа градаций. Все просто, только под используемые выводы дефайны поправьте(если надо), да таймер настройте в ините как TCCR0=0x02; TCNT0=0x00;

//....
//-----------МАКРООПРЕДЕЛЕНИЯ
#define PWM_GRADATION 10   //число градаций PWM
//задаем константу антидребезга 
//при константе 100 и текущих настройках таймера
//кнопки опрашиваются примерно раз в 25мс
#define ANTI_DRB_SENCIVITY 100 
#define PWM_PIN PORTB.0	 //выходной пин
#define BUTTON_LIGHT_PLUS  PINB.1 
#define BUTTON_LIGHT_MINUS PINB.2
//------------переменные для PWM
unsigned char pwm_value;	//текущее значение 
unsigned char pwm_counter;  //счетчик
unsigned char fl_butt_pl;   //флаги для однократного инкрементирования
unsigned char fl_butt_mn;   //(декрементирования) при нажатии и удержании 
unsigned char anti_drb_counter; //счетчик, для антидребезга при коммутации
//...
//--------------------------Обработчик Т0-----------------------------------//
//Таймер настроен на тактирование 1МГц, при 8МГц тактовой (TCCR0=0x02;)
//(потребляет меньше, удобные интервалы). Частота PWM около 350Гц
//при числе градаций ANTI_DRB_SENCIVITY равным 10
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{//в обработчике делаем все: 
//---антидребезг
if(anti_drb_counter==ANTI_DRB_SENCIVITY){
//обработка нажатий с проверкой диапазонов и однократности нажатия	
if(!BUTTON_LIGHT_PLUS){
	if((pwm_value<=PWM_GRADATION)&&(!fl_butt_pl)){pwm_value++;fl_butt_pl=1;}
					  }else{fl_butt_pl=0;}

if(!BUTTON_LIGHT_MINUS){
	if((pwm_value)&&(!fl_butt_mn)){pwm_value--;fl_butt_mn=1;}
					   }else{fl_butt_mn=0;}  

 anti_drb_counter=0;   }else anti_drb_counter++;  
//-----------
//если значение счетчика больше текущего значения PWM,
//устанавливаем пин в ноль, иначе в ед.
	(pwm_counter<pwm_value)? (PWM_PIN=1):(PWM_PIN=0);
//проверяем, достиг ли счетчик предельного значения градаций,
//если да - обнуляем, иначе - инкрементируем
   (pwm_counter==PWM_GRADATION)? (pwm_counter=0):(pwm_counter++);
}
//==============================================================================//
//...

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

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

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

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

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

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

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

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

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

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

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

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