Юрец

Avr+codevision

38 сообщений в этой теме

Юрец    7

огромнейшее СПАСИБО!

всё работает отлично!

можно несколько вопросов по синтаксису написания Вашего кода?

1. в чем разница между if((условие1)&(условие2)) и if((условие1)&&(условие2))

2. выражение (pwm_counter<pwm_value)? (PWM_PIN=1):(PWM_PIN=0); это то-же самое, что и

if (pwm_counter<pwm_value){ PWM_PIN=1;} else{PWM_PIN=0;}; ?

p.s. загляните в свои личные сообщения.

Поделиться сообщением


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

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
Goodefine    92
1. в чем разница между if((условие1)&(условие2)) и if((условие1)&&(условие2))

"&" работает с отдельными битами, а "&&" - с байтами (т.е. если хотя бы один бит байта не равен нулю, условие выполнится)

2. выражение (pwm_counter<pwm_value)? (PWM_PIN=1):(PWM_PIN=0); это то-же самое, что и

if (pwm_counter<pwm_value){ PWM_PIN=1;} else{PWM_PIN=0;}; ?

Да. Это аналог с использованием тернарного оператора. Имхо, нагляднее...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    7

с этим разобрались.

а как вывести звук, используя таймер (задействован пока только timer0, остальные свободны), типа как в автомагнитолах: нажимаешь любую кнопку, а в динамиках слышно кратковременное П-И-И-К. звук нужно выводить на пьезоизлучатель (типа ЗП1, ЗП3, или как в китайских мультиметрах).

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
а как вывести звук, используя таймер (задействован пока только timer0, остальные свободны), типа как в автомагнитолах: нажимаешь любую кнопку, а в динамиках слышно кратковременное П-И-И-К. звук нужно выводить на пьезоизлучатель (типа ЗП1, ЗП3, или как в китайских мультиметрах).

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

элементарно. В прерывании от таймера, настроегого на частоту звучания (время=1/частота) меняем на противополножное состояния ножек к которому подключено пьезо (ну а так же обнулить тайммер) чтот типа такого:

ддр...

PORTB.x=!PORTB.у;

прерывание

{

PORTB.x=!PORTB.x;

PORTB.y=!PORTB.y;

обнулить таймер.

}

х,у - ножки куда подключено пьезо.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Goodefine    92
...а как вывести звук, используя таймер (задействован пока только timer0, остальные свободны)...

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

Резонансную частоту не нужно. С частотой около 4Кгц (чтоб проще было) и так нормально будет. Второго таймера не надо. Немного дорабатываем обработчик Т0, цепляем пьезо-пищалку на лапу и все. Пока подсветка регулируется - одно нажатие - один писк(длительность просто регулируется в программе). Когда достигаем реверсивных положений (нажатие есть, а регулировки уже нет - крайние положения), тогда орет когда нажимаем и продолжает пока держим кнопку. Такой вот полезный побочный эффект - сразу слышно, что регулировки больше нет. Аналогично и другие кнопки можно озвучить. Например (дефайны подправить, если надо):

//-----------МАКРООПРЕДЕЛЕНИЯ
#define PWM_GRADATION 10   //число градаций PWM
#define BEEP_TIME 1000 //длительность ок.250мс
//задаем константу антидребезга
//при константе 100 и текущих настройках таймера
//кнопки опрашиваются примерно раз в 25мс
#define ANTI_DRB_SENCIVITY 100
#define PWM_PIN PORTB.0     //выходной пин
#define BUTTON_LIGHT_PLUS  PINB.1
#define BUTTON_LIGHT_MINUS PINB.2
#define BEEP_PORT_PIN PORTB.3
#define BEEP_PIN_PIN PINB.3

//------------переменные для PWM
unsigned char pwm_value;    //текущее значение
unsigned char pwm_counter;  //счетчик
unsigned char fl_butt_pl;   //флаги для однократного инкрементирования
unsigned char fl_butt_mn;   //(декрементирования) при нажатии и удержании
unsigned char anti_drb_counter; //счетчик, для антидребезга при коммутации
//-----------переменные для Beep
unsigned char fl_beep_enable; //флаг разрешеня звукового сигнала
unsigned int beep_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(!fl_beep_enable&&!fl_butt_pl) fl_beep_enable=1;
       if((pwm_value<=PWM_GRADATION)&&(!fl_butt_pl)){pwm_value++;fl_butt_pl=1;}
                         }else{fl_butt_pl=0;}

   if(!BUTTON_LIGHT_MINUS){if(!fl_beep_enable&&!fl_butt_mn) fl_beep_enable=1;
       if((pwm_value)&&(!fl_butt_mn)){pwm_value--;fl_butt_mn=1;fl_beep_enable=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++);
//формируем звуковой сигнал
       if(fl_beep_enable){//если звук разрешен (нажатие)
             if(beep_counter==BEEP_TIME){beep_counter=0;BEEP_PORT_PIN=0;fl_beep_enable=0;}
                     else{(BEEP_PIN_PIN)?(BEEP_PORT_PIN=0):(BEEP_PORT_PIN=1);beep_counter++;}
                           }

}
//--

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
rtfcnf    1

Goodefine, действительно красивое решение. Надо будет запомнить

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    7

>Goodefine, действительно красивое решение.

полностью согласен!

вопрос: как правильно реализовать вызов менюшки с подпунктами для вывода на экран LCD?

как я понял, технически грамотным будет в прерывании таймера опрашивать кнопки , менять значение переменной screen (к примеру screen=1 : показать первый пункт главного меню; screen=2 : показать второй...), а показ меню реализовать в главном цикле программы: while(1){if (screen==1) {lcd_putsf ("main menu_1");}; if (screen==2) {lcd_putsf ("main menu_2");}; и т.д.

так?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Юрец    7

не получилось прикрутить опрос кнопок в таймере...

что-то наваял, но неправильно:

******************************************
#define MENU_KEY !PIND.0 //кнопки
#define OK_KEY !PIND.1 
#define UP_KEY !PIND.2
#define DOWN_KEY !PIND.3
#define PWM_GRADATION 10   //число градаций PWM
#define ANTI_DRB_SENCIVITY 100 //константа антидребезга
#define LIGHT_PIN PORTD.4 //выходной пин для яркости lcd
#define BEEP_PORT_PIN PORTD.7//выход для биппера
#define BEEP_PIN_PIN PIND.7
#define BEEP_TIME 1000 //длительность ок.250мс

unsigned char [b]screen[/b]=1; //текущее значение картинки LCD
unsigned char pwm_value;    //текущее значение
unsigned char pwm_counter;  //счетчик
unsigned char fl_butt_up;   //флаги для однократного инкрементирования
unsigned char fl_butt_down;   //(декрементирования) при нажатии и удержании
unsigned char fl_butt_ok; 
unsigned char fl_butt_menu;
unsigned char anti_drb_counter; //счетчик, для антидребезга при коммутации
unsigned char fl_beep_enable; //флаг разрешения звукового сигнала
unsigned int beep_counter; //переменная, отмеряющая длительность сигнала
***************************************


void lcd_cls(void){
lcd_gotoxy(0, 0);
lcd_putsf ("                                "); //32 пробела для индикатора 16х2. работает быстрее, чем lcd_clear
}
***************************************
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
//---антидребезг
   if(anti_drb_counter==ANTI_DRB_SENCIVITY){
   //обработка нажатий с проверкой диапазонов и однократности нажатия    

   if((UP_KEY)&(screen==1))   {
                                               if(!fl_beep_enable&&!fl_butt_up) fl_beep_enable=1;
			                if((pwm_value<=PWM_GRADATION)&&(!fl_butt_up){pwm_value++fl_butt_up=1;}
			                }elsе{fl_butt_up=0;}


   if((DOWN_KEY)&(screen==1))   {
                                                     if(!fl_beep_enable&&!fl_butt_down) fl_beep_enable=1;
                                                     if((pwm_value)&&(!fl_butt_down)){pwm_value--;fl_butt_down=1;}
                                                     }else{fl_butt_down=0;}



   if((MENU_KEY)&(screen==1)){
                                                 if(!fl_beep_enable&&!fl_butt_menu) fl_beep_enable=1;
                                          if(!fl_butt_menu){fl_butt_menu=1;screen=2;lcd_cls();}
                                          }else{fl_butt_menu=0;}

   if((UP_KEY)&(screen==2))	{
                                               if((!fl_beep_enable)&&(!fl_butt_up)) {fl_beep_enable=1;};
                                        if(!fl_butt_up){fl_butt_up=1;screen=3;lcd_cls();}
                                        }else{fl_butt_up=0;}

   if((UP_KEY)&(screen==3))	{
                                               if((!fl_beep_enable)&&(!fl_butt_up)) {fl_beep_enable=1;};
                                        if(!fl_butt_up){fl_butt_up=1;screen=4;lcd_cls();}
                                        }else{fl_butt_up=0;}

   if((DOWN_KEY)&(screen==4)){
                                                  if((!fl_beep_enable)&&(!fl_butt_down)) {fl_beep_enable=1;};
                                           if(!fl_butt_down){fl_butt_down=1;screen=3;lcd_cls();}
                                           }else{fl_butt_down=0;}

   if((DOWN_KEY)&(screen==3)){
                                                  if((!fl_beep_enable)&&(!fl_butt_down)) {fl_beep_enable=1;};
                                           if(!fl_butt_down){fl_butt_down=1;screen=2;lcd_cls();}
                                           }else{fl_butt_down=0;}

   if((DOWN_KEY)&(screen==2)){
                                                  if((!fl_beep_enable)&&(!fl_butt_down)) {fl_beep_enable=1;};
                                           if(!fl_butt_down){fl_butt_down=1;screen=1;lcd_cls();}
                                           }else{fl_butt_down=0;}

    anti_drb_counter=0;   }else anti_drb_counter++;  
   //-----------
       (pwm_counter<pwm_value)? (LIGHT_PIN=1):(LIGHT_PIN=0);
      (pwm_counter==PWM_GRADATION)? (pwm_counter=0):(pwm_counter++);
if(fl_beep_enable){//если звук разрешен (нажатие)
if(beep_counter==BEEP_TIME){beep_counter=0;BEEP_PORT_PIN=0;fl_beep_enable=0;}
else{(BEEP_PIN_PIN)?(BEEP_PORT_PIN=0):(BEEP_PORT_PIN=1);beep_counter++;}
}
}

while (1)
     {
switch (screen) {
   case 1:{бла-бла-бла ;break;}
   case 2:{бла-бла-бла ;break;}  
   case 3:{бла-бла-бла ;break;} 
   case 4:{бла-бла-бла ;break;} 
   };            
}      
}
';

а в работе получается, что при однократном нажатии UP_KEY при screen=2 переменная screen меняет значение с 2 на 3, и сразу на 4, а не на 3.

думаю, что решение простое, но ничего в голову не приходит...

p.s. как убрать "побочный эффект" постоянного звучания биппера ?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
rtfcnf    1

Не очень хочеться въежать в Ваш код поэтому напишу как мне видеться.

//Создаем глобальные переменные (любителем ООП дальше не читать :lol: )
unsigned char key_kod;
unsigned char key_tmp;
unsigned char key_count;

//В прерывании пишем

key_kod =/* порт + маска*/;
if(Key_kod == key_temp)
{
 key_count++;
} 
else
  {
key_temp = key_kod;
key_count= 0;
  }
//Автоматом сняли дребезг

//В основном цикле пишем
if(key_count > /*подбираем исходя из скорости таймера*/)
{
 //Обработчик кода кнопки. код в key_kod
// да после обработки не забываем
key_temp = 0;
key_count= 0;
}

Я при написании для AVR практикую подход, есть основной цикл постоянно крутящийся, и есть события которые его прерывают.

События у меня двух типов:

Быстрые(требующие немедленной оброботки), как правило прерывания

И медленные накопительные (не требующие особой скорости для оброботки) создаються счетчиками в основном цикле либо в прерывании

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Goodefine    92
не получилось прикрутить опрос кнопок в таймере...

что-то наваял, но...

Если задача расширяется, то необходимо структурировать программу. В обработчике прерываний не следует делать вызов функций типа lcd_slc()(относительно долго выполняется, содержит вложенные функции), опрос менюшных кнопок(ибо для меню нужен анализ текущего положения указателя меню, соответствующая работа с дисплеем и т.д.) - оставляем только звук и ШИМ. Вместо опроса, после антидребезга, выставляем флаг разрешения опроса кнопок(который сбросим в опросе). По этому флагу в основном цикле работает опрос кнопок, вынесенный в отдельную функцию, возвращающую код нажатой клавиши(флаг разрешения звукового сигнала выставляется в ней же) . Далее вызывается функция-диспетчер, которая в зависимости от текущего положения(в меню) и кода нажатой кнопки вызывает нужную функцию, обновляет соответствующим образом дисплей(тоже немаловажная задача), затем модифицирует указатель на текущий элемент меню. Обычно меню представляют в виде структуры, хранящей необходимые для него элементы (связанные списки и т.д). В нете есть примеры реализации. Диспетчер может работать с массивом указателей на функции. В любом случае, такая задача "в лоб" не решается - иначе вместо программы, получите нечто нерасширяемое...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gunya    0

Народ, помогите пожалуйста! Кароче у меня диплом, тема разработать часы реального времени с двухканальным термометром и термостатом. Планирую использовать в проэкте микросхемы DS18B20 - термометр, DS1307 - часики соответственно! Контроллер - любая атмега(8, 16, 32) Выводится все на символьный ЖК индикатор! Писать буду на кодевижнавр, вот только незнаю как организовать главный алгоритм сего сложного устройства :unsure: ведь микросхема DS18B20 преобразовывает температуру почти 0.5 секунд!! а в это время прийдется запретить все прерывания, по сути дела контроллер будет тупо ждать 0.5 секунд до окончания преобразования, и нельзя будет ничего сделать, даже кнопки считать невозможно! Планирую сделать так - сначала проинициализировать датчики, считать температуру и сохранить в ОЗУ, настроить прерывания по таймеру, так чтобы допустим каждые 5 секунд читать температуру из датчиков, и обновлять в ОЗУ, после этого идет инициализация остальной периферии, часов, дисплея, и все начинает тикать! Только наступает прерывание считывания датчиков - все стихает, и мы ждем окончания преобразования, запретив при этом остальные прерывания! По окончанию все востанавливается назад, и устройство снова начинает тикать! :rolleyes:

Думаю что даный алгоритм неидеален, помогите пожалуйста те, кто работал с датчиками DS18B20 и микросхемой DS1307! Может ктото предложит лучший алгоритм! Проэкт нужно закончить до сердины лета! ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
gunya    0

Че никто не работал с датчиками DS18B20???? Помогите пожалуйста! Кто может!

Поделиться сообщением


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

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сообщения

    • 13007 - до ~400 Вт (при Ic макс=6 А, допустимо - 8 А), 13009 - до ~600 Вт (при Ic макс=9 А, допустимо - 12 А), Только знание одного этого факта вам ничего не гарантирует - вслед за сменой ключей, потребуется замена обвязки базовых цепей, и, возможно, управляющего трансформатора с транзисторами раскачки.  
    • Здравствуйте. Я делаю сетевой фильтр http://cxem.net/pitanie/5-183.php Мотаю вторую катушку. Автор статьи пишет, что нужно 2 обмотки по 78 витков, и индуктивность каждой катушки 120 мГн. У меня есть пару вопросов. Я хочу измерять индуктивность по этой методике: 1. Можно ли не 10 кГц а 1 кГц использовать? 2. Какая должна быть амплитуда сигнала? 0.775 В с аудиокарты пойдет или надо больше? Могу через усилитель больше подать. Но надо ли? 3. Точно форму сигнала надо синусоиду? 4. Какой мощности нужно ставить переменный резистор, я прикинул, при 120 мГн и 1000 Гц, резистор надо около 1.5 кОм, ну или переменник на 4.7 кОм и покрутить. Возможно легче поставить 1.5 кОм а потом катушку отматывать\наматывать, пока не будет одинаковое напряжение. Я же правильно все понимаю, из этой формулы расчетное сопротивление катушки должно быть 2*Пи*f*L = 6.28*1000*0.12 (120 мГн = 0.12 Гн) = 1500 Ом примерно. Правда тут интересный момент, там написано f=10 кГц, а я взял как будто измерения проводятся при 1000 Гц. Можно ли мерять таким способом индуктивность 120 мГн при частоте источника 1000 Гц? Потому, что вдруг сопротивление как-то еще зависит от частоты генератора, или допустим частоту генератора надо подбирать в соответствии с диапазоном в который попадает измеряемая индуктивность? Кстати проблемы мерять напряжение при 10 кГц в принципе у меня нету. Можно взять стрелочный вольтметр. Ему же все равно какая частота по большому счету. Либо через диодный мостик пустить стрелочный вольтметр по постоянному току.  
    • Их можно скучковать
    • Стабилизатор Назара лучше посмотреть на его странице: стаб
      А приведённая выше схема к Назару, на сколько знаю, отношения не имеет. 
    • Кажется вот в чём проблема. Не знаю видно ли это будет здесь на фото. Вот на резинке со стороны контактов, где нанесён этот чёрный токопроводящий слой, есть такие пимпочки с как бы кольцами что ли... И вот, на некоторых клавишах оби эти пимпочки с кольцами торчат нормально, а на некоторых одна торчит, а другая вдавлена. Пробовал выпрямить - не хочет. Только одного не пойму: обе должны торчать или обе должны быть вдавлены, скорее всего думаю, что выпуклыми должны быть обе, но в любом случае по ходу неисправность нашлась. С этой резиной уже вряд ли что-то сделаешь, как-то где-то теперь искать...