Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Тема закрыта

Re: Обработка нажатия кнопки в AVR...

Вс дек 19, 2010 14:18:57

Нашёл вот такой код:
Код:
#include <mega16.h>
#include <m8_128.h>
#include <delay.h>
#include <stdio.h>

char pwm = 0; // Величина ШИМ начальная PWM в %

u32 pwm_val; // для хранения величины ШИМ PWM в  1/1024

void main(void)
{
PORTA=0x00; DDRA=0x00;

PORTB=0x00; DDRB=0x00;

PORTC=0x00; DDRC=0x00;

PORTD=0x00; DDRD=0x30;

TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

TCCR1A=0xA3;
TCCR1B=0x09;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH = 0x00;  // PWM(PD4) OCR1B / 10.23  (%)
OCR1BL = 0xFF;  // PWM(PD4)  255 / 10.23 = 24.9 (%)

ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

MCUCR=0x00;
MCUCSR=0x00;
TIMSK=0x00;

ACSR=0x80;
SFIOR=0x00;

while (1){   
     
if (pwm > 102) { //если ШИМ уже более 100 %
       pwm = 0;  // обнулить величину ШИМ           
       };
               
pwm_val = ((1023 * (u32)pwm)/100);
// pwm_val - это число от 0 до 1023
// PWM(PD5) = OCR1A / 10.23  (%)
OCR1AH = (char)(pwm_val>>8);
OCR1AL = (char)pwm_val;       

if(PINA.0==1){
pwm += 10; //увеличим ШИМ на 10%
}
   
delay_ms(20); // пауза   

      };
     
}


Можете разъяснить, принцип работы этого кода и почему мы делим на 10.23
Код:
OCR1BH = 0x00;  // PWM(PD4) OCR1B / 10.23  (%)
OCR1BL = 0xFF;  // PWM(PD4)  255 / 10.23 = 24.9 (%)
и берем частоту МК 7.37 МГц

Re: Обработка нажатия кнопки в AVR...

Пн дек 20, 2010 00:43:21

С кодом немного разобрался, только не понятно, как сделать ШИМ для произвольного вывода МК, т.е. программно, а не аппаратно.

Re: Обработка нажатия кнопки в AVR...

Пн дек 20, 2010 12:51:08

Сделал так :
Код:
unsigned char b;
void pow (unsigned char port0,unsigned char port1,unsigned char port2,unsigned char port3)
{
if ( TCNT1>port0)PORTB.0 =0;
else PORTB.0 =1;
if ( TCNT1>port1)PORTB.1 =0;
else PORTB.1 =1;
if ( TCNT1>port2)PORTB.2 =0;
else PORTB.2 =1;
if ( TCNT1>port3)PORTB.3 =0;
else PORTB.3 =1;
}

interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{

}
.
.
.
while (1)
      {
      pow(20, 40, 60, 78);     
      };


Какие ещё есть варианты?

Re: Обработка нажатия кнопки в AVR...

Ср дек 22, 2010 00:45:49

Читая тему, хочу помощи от знатоков и совет для начинающих. Неоднократно повторялось на форуме о том что для отсчета пауз, временных интервалов и т.д. необходимо использовать таймеры. Приведу пример на фото
Изображение.
В данной задаче НЕДОПУСТИМО использования задержек и разных delay-ев, т.к. нарушается подсчет по опорной частоте. Суть в втом, что генерится опорная частота и по подсчетам которой дергаем ногами в двух портах. Начинается отсчет от синхроимпульса. На картинке видны настройки таймеров и работа в целом. Пока проект в протэусе, на днях буду пробовать в железе.
Задействованы два таймера, 3-прерывания.
Жду советов.

Re: Обработка нажатия кнопки в AVR...

Ср дек 22, 2010 01:25:11

void B1_SUB(void)
{
if ((PIND&(1<<6))==0) //на порте D6 висит кнопка, проверяем нажата ли
__{
____B1++;//инкремент переменной подсчета кол-ва периодов нажатия
____ if (B1==B1_N)//если продержали долгое время и переменная дошла до необходимого значения
_____{
______B1_PUSHED=1;//выставляем флаг нажатой кнопки
______MODE=1;//выполняем действие по нажатию кнопки (у меня 2 команды)
______MODE_CHGD=1;
_____}
__}
else//если кнопка не нажата, очищаем переменную подсчета кол-ва периодов нажатия
B1=0;

if(B1_PUSHED)//теперь проверяем флаг нажатой кнопки, он означает что была нажата кнопка и было выполнено действие по нажатию
__{
___B1=0;//если он установлен (кнопка была нажата и действие по нажатию уже было выполнено), очищаем переменную подсчета кол-ва периодов нажатия
___if(PIND&(1<<6)) //теперь, если она уже отпущена
____{
_____B1_PUSHED=0; //очищаем флаг нажатой кнопки
_____MODE=0;//и выполняем действие по отпусканию кнопки (у меня их 2)
_____MODE_CHGD=1;
____}
__}
}
//вставлять действия "по отпускании" и "по нажатию" по Вашему усмотрению, можно одно исключить
//эта программа должна вызываться по таймеру либо в главном цикле вертеться
//число
B1_N рассчитывается исходя из максимального времени дребезга контактов, Tдр.
//B1_N = Tдр.* Tвыз., время в одинаковых единицах. Tвыз. - период вызова функции.


ОФФ ТОПИК ДЛЯ АДМИНИСТРАЦИИ: СДЕЛАЙТЕ УЖЕ НОРМАЛЬНЫЕ ФОРМАТЫ ДЛЯ [code]. ТО ЧТО СЕЙЧАС НЕВОЗМОЖНО ЧИТАТЬ!!! З***ЛСЯ ФОРМАТИТЬ, ЧТОБЫ И КОМЕНТЫ ОТДЕЛИТЬ ОТ КОДА ЦВЕТОМ И ОСТАВИТЬ ТАБУЛЯЦИЮ.

Re: Обработка нажатия кнопки в AVR...

Пт сен 23, 2011 16:57:12

Люди help подскажыте как в AvrStudio4 реализовать 1 кнопку?

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 04:37:19

как только не пробовал... не реагирует на кнопки (

укажите плиз, где может быть ошибка?

вот код:
Код:
#include <ioavr.h>
#include <intrinsics.h>
#include <stdlib.h>

int interval = 200;
int delitel = 5;
int effect = 0;

void delay(long unsigned int Pause)
{
  long int i;
  long int i2;
  i2=Pause*100;
 
  for(i=0; i<i2; ++i )
    asm("nop");
}

int main( void )
{
  __enable_interrupt();
  char del;
  int i;
 
  PORTB = 0xFF;
  DDRB = 0xFF;
 
  PORTD = 0xFF;
  DDRD = 0x00;
 
 
  /* if (PIND == 0x01)
  // if((PIND &(1<<0))==0)  ;// если  нажата   pd3  на корпус
  {
  interval = interval - 200;
}
 
  if (PIND == 0x02)
  {
  delitel++;
}
 
  if (PIND == 0x04)
  {
  delitel--;
}
 
  if (PIND == 0x08)
  {
  interval = interval + 200;
}
 
  //if (PIND == 0x10)
  if((PIND &(1<<PINd.bit4))==1)  ;// если  нажата   pd3  на корпус
  {
  effect++;
  if (effect > 4) effect = 0;
}*/
 
  if (PIND != 0)
    //if ((PIND & (1<<4))==1)
  {
    delay(50);
    effect++;
    if (effect >4) effect=0;
  };
 
  switch(effect)
  {
  case 0: PORTB=0x00;
  break;
  case 1:
    PORTB=0xFF;
    break;
  case 2:
    PORTB=0xFF;
    del = 5 / delitel;
    i = interval * del ;
    delay(i);
    PORTB=0x00;
    i = interval * (1/del);
    delay(i);
    break;
  case 3:
    PORTB=0xFF;
    delay(1<<interval);
    PORTB=0x00;
    delay(1>>interval);
    break;
  }
  return 0;
}

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 06:50:41

Для начала засуньте обработчики в цикл. В случае работы с МК до выхода из main дело доходить не должно.

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 13:20:17

засунул...

но все равно на нажатия кнопки не реагирует...
Код:
int main( void )
{
  __enable_interrupt();
  char del;
  int i;
 
  PORTB = 0xFF;
  DDRB = 0xFF;
 
  PORTD = 0xFF;
  DDRD = 0x00;
 
  while(1)
  {
    /* if (PIND == 0x01)
    // if((PIND &(1<<0))==0)  ;// если  нажата   pd3  на корпус
    {
    interval = interval - 200;
  }
   
    if (PIND == 0x02)
    {
    delitel++;
  }
   
    if (PIND == 0x04)
    {
    delitel--;
  }
   
    if (PIND == 0x08)
    {
    interval = interval + 200;
  }
   
    //if (PIND == 0x10)
    {
    effect++;
    if (effect > 4) effect = 0;
  }*/
   
  if ((PIND & (1<<4))==1)
    {
      delay(50);
      effect++;
      if (effect >4) effect=0;
    };
   
    switch(effect)
    {
    case 0: PORTB=0x00;
    break;
    case 1:
      PORTB=0xFF;
      break;
    case 2:
      PORTB=0xFF;
      del = 5 / delitel;
      i = interval * del ;
      delay(i);
      PORTB=0x00;
      i = interval * (1/del);
      delay(i);
      break;
    case 3:
      PORTB=0xFF;
      delay(1<<interval);
      PORTB=0x00;
      delay(1>>interval);
      break;
    }
  }
  return 0;
}

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 13:27:50

Код:
if ((PIND & (1<<4))==1)
{
delay(50);
effect++;
if (effect >4) effect=0;
};

В вашем случае результат всегда ложен. Вот так лучше:
Код:
if (PIND & (1<<4))
{
delay(50);
effect++;
if (effect >4) effect=0;
};
Советую задуматься так же над опросом кнопок. Для того чтобы одно нажатие не обрабатывалось много раз, надо вводить антидребезг, паузы и т.п.
Последний раз редактировалось BerZerK-ku Пн янв 16, 2012 13:32:01, всего редактировалось 1 раз.

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 13:31:51

я очень рекомендую сначала продумать логику работы программы, а затем кодить :) у вас вырисовывается примерно такой алгоритм: есть переменная, содержащая номер эффекта, есть какие-то кнопки, нажатие на которые изменяет эту переменную. вы в бесконечном цикле должны опрашивать кнопки и в зависимости от того, какая нажата, выполнять изменение переменной. теперь рассуждаем: опрос кнопок - это задача, которая имеет самостоятельную ценность, как бы независимость от остального - значит, судьба этой задачи быть в виде отдельной функции. анализ разных вариантов нажатых кнопок - это обычный оператор Си switch. значит, "ядро" вашей задачи выглядит так:
Код:
while(1){ // бесконечный цикл
   switch(get_key_pressed()){ // при помощи функции get_key_pressed получаем код нажатой кнопки
   case KEY_1:
      // увеличение переменной
      effect++;
      break;
   case KEY_2:
      // уменьшение переменной
      effect--;
      break;
   }
}
теперь вам остается лишь продумать, как должна быть сделана функция получения кода нажатой кнопки, описать эти коды (KEY_1, KEY_2 и т.д.) и добавить сколько нужно вариантов в оператор switch.

программа получается читаемой, аккуратной, понятной и логичной, легко модифицируемой. сумеете? ;)

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 13:46:22

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

Код:
if (PIND & (1<<4))
{
delay(50);
effect++;
if (effect >4) effect=0;
};

я пытался поймать нажатие на кнопку PD4
на платке у меня кнопочки на ногах от PD0 до PD4 и светодиод на PB
PD0 и PD3 - изменяют частоту моргания светодиода
PD1 и PD2 - меняют скважность свечения
PD4 - выбирает эффект (не гореть, гореть постоянно, моргать)

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 14:44:55

не можете поймать нажатие кнопки? поступайте, как я вам рассказывал :))) итак, задача: есть порт МК, к которому на землю подключено до 8 кнопок. надо отловить их нажатия. как поступить? заранее настроить порт на ввод с встроенными подтяжками, тогда чтение порта с ненажатыми кнопками вернет единицы во всех разрядах байта, а если будет что-то нажато - в том месте будет ноль. кнопка может "дребезжать", т.е. некоторое время (10-25 мс) не иметь постоянного контакта - этого нужно избежать. как? опрашиваем порт, запоминаем результат. ждем 10-25 мс и снова опрашиваем порт, сравнивая результат с запомненным: если они совпали, значит, дребезг уже закончился (или не начинался) и считаны именно данны о нажатых кнопках. теперь, когда на словах разобрались с алгоритмом, опишем его на языке Си, вспоминая ранее данные рекомендации о кодах кнопок:
Код:
#define KEY_1 (1<<PB0)
#define KEY_2 (1<<PB1)
// и так далее хоть все 8 кнопок
#define ANY_KEY (KEY_1 | KEY_2) /* тут надо перечислить все существующие кнопки, и не слушайте тех, кто скажет, что скобки лишние */
#define NO_KEY   0

// настройка порта на ввод с подтяжками - делается где-то в начале main()
DDRB &= ~ANY_KEY;
PORTB |= ANY_KEY;

// функция получения кода нажатых кнопок
unsigned char get_key_pressed(void){
   unsigned char key;
   key = ~(PINB & ANY_KEY);
   delay_ms(15); // задержка для подавления дребезга
   if(key == ~(PINB & ANY_KEY))
      return key;
   else
      return NO_KEY; // если дребезг - вернем 0, что будет означать: не нажата ни одна кнопка
}

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

вопросы? ;)

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 15:55:18

Мастер Ломастер писал(а):не можете поймать нажатие кнопки? поступайте, как я вам рассказывал :))) итак, задача: есть порт МК, к которому на землю подключено до 8 кнопок. надо отловить их нажатия. как поступить? заранее настроить порт на ввод с встроенными подтяжками, тогда чтение порта с ненажатыми кнопками вернет единицы во всех разрядах байта, а если будет что-то нажато - в том месте будет ноль. кнопка может "дребезжать", т.е. некоторое время (10-25 мс) не иметь постоянного контакта - этого нужно избежать. как? опрашиваем порт, запоминаем результат. ждем 10-25 мс и снова опрашиваем порт, сравнивая результат с запомненным: если они совпали, значит, дребезг уже закончился (или не начинался) и считаны именно данны о нажатых кнопках. теперь, когда на словах разобрались с алгоритмом, опишем его на языке Си, вспоминая ранее данные рекомендации о кодах кнопок:
Код:
#define KEY_1 (1<<PB0)
#define KEY_2 (1<<PB1)
// и так далее хоть все 8 кнопок
#define ANY_KEY (KEY_1 | KEY_2) /* тут надо перечислить все существующие кнопки, и не слушайте тех, кто скажет, что скобки лишние */
#define NO_KEY   0

// настройка порта на ввод с подтяжками - делается где-то в начале main()
DDRB &= ~ANY_KEY;
PORTB |= ANY_KEY;

// функция получения кода нажатых кнопок
unsigned char get_key_pressed(void){
   unsigned char key;
   key = ~(PINB & ANY_KEY);
   delay_ms(15); // задержка для подавления дребезга
   if(key == ~(PINB & ANY_KEY))
      return key;
   else
      return NO_KEY; // если дребезг - вернем 0, что будет означать: не нажата ни одна кнопка
}

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

вопросы? ;)


делаю как вы сказали
ругается вот так (((
Error[Pe020]: identifier "PD0" is undefined D:\atmel\MK\proj\IAR2\main.c 40

а когда пишу #define KEY_1 (1<<PD,0)
Error[Pe020]: identifier "PD" is undefined D:\atmel\MK\proj\IAR2\main.c 38

--- > 38 строка DDRD &= ~ANY_KEY;
на ANY_KEY ругается...
P.S. пишу IARe

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 16:39:38

Вместо PD, PB в IAR используйте PORTB0, PORTD1 и т.п.
И включите опцию General Options->System->Enable bit definition in I/O-Include files.

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 17:01:21

BerZerK-ku писал(а):Вместо PD, PB в IAR используйте PORTB0, PORTD1 и т.п.
И включите опцию General Options->System->Enable bit definition in I/O-Include files.


включил... спасибо

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 17:02:01

не реагирует на нажатия все равно (((

Код:
#include <ioavr.h>
#include <intrinsics.h>
#include <stdlib.h>

#define KEY_1 (1<<PIND0)
#define KEY_2 (1<<PIND1)
#define KEY_3 (1<<PIND2)
#define KEY_4 (1<<PIND3)
#define KEY_5 (1<<PIND4)

#define ANY_KEY (KEY_1 | KEY_2 | KEY_3 | KEY_4 | KEY_5 )

#define NO_KEY 0

int interval = 200;
int delitel = 5;
int effect = 0;

void delay(long unsigned int Pause)
{
  long int i;
  long int i2;
  i2=Pause*100;
 
  for(i=0; i<i2; ++i )
    asm("nop");
}

// функция получения кода нажатых кнопок
unsigned char get_key_pressed(void)
{
  unsigned char key;
  key = ~(PIND & ANY_KEY);
  delay(15); // задержка для подавления дребезга
  if(key == ~(PIND & ANY_KEY))
    return key;
  else
    return NO_KEY; // если дребезг - вернем 0, что будет означать: не нажата ни одна кнопка
}

int main( void )
{
  char del;
  int i;
 
  PORTB = 0xFF;
  DDRB = 0xFF;
 
  DDRD &= ~ANY_KEY;
  PORTD |= ANY_KEY;
 
  while(1)
  {
    switch(get_key_pressed()) // при помощи функции get_key_pressed получаем код нажатой кнопки
    {
    case KEY_5:
      // след.эффект
      effect++;
      if (effect>3) effect = 0;
      break;
    }
   
    switch(effect)
    {
    case 0:
      PORTB=0x00;
      break;
    case 1:
      PORTB=0xFF;
      break;
    case 2:
      PORTB=0xFF;
      del = 5 / delitel;
      i = interval * del ;
      delay(i);
      PORTB=0x00;
      i = interval * (1/del);
      delay(i);
      break;
    }
  }
  return 0;
}


вместо
#define KEY_1 (1<<PIND0)
#define KEY_2 (1<<PIND1)
#define KEY_3 (1<<PIND2)
#define KEY_4 (1<<PIND3)
#define KEY_5 (1<<PIND4)
ставил
#define KEY_1 (1<<PORTD0)
#define KEY_2 (1<<PORTD1)
#define KEY_3 (1<<PORTD2)
#define KEY_4 (1<<PORTD3)
#define KEY_5 (1<<PORTD4)
все равно также

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 18:01:33

А вы попробуйте чего-нибудь простенькое:
Код:
void main(void)
{
    PORTB = 0xFF;
    DDRB = 0xFF;
   
    DDRD = 0;
    PORTD = 0xFF;

   while(1)
    {
         PORTB = PIND;
    }
}
Горят/тухнут светодиоды при нажатии на кнопку? Если нет, ищите проблему в железе или прошиваете не так.

Re: Обработка нажатия кнопки в AVR...

Пн янв 16, 2012 21:22:58

не реагирует((( горит постоянно чтоб не нажимал

вот так подключаю

Изображение
Вложения
ledline.JPG
(214.2 KiB) Скачиваний: 380

Re: Обработка нажатия кнопки в AVR...

Вт янв 17, 2012 05:19:11

Ну при таком включении ничего и не будет ) Замените строчку в цикле на:
Код:
if ( (PIND & 0x1F) != 0x1F )
    PORTB = (1 << PORTB7);
else
    PORTB = 0;
Тема закрыта