roboforum.ru

Технический форум по робототехнике.

 

Помогите с программой для tiny2313

Программирование микроконтроллеров AVR, PIC, ARM.
Разработка и изготовление печатных плат для модулей.

Помогите с программой для tiny2313

Сообщение Lockdog » 14 июл 2010, 23:37

Есть МК ATtiny2313, настроил таймеры в режим СТС, чтобы тактированние шло либо на ножку PB3, либо PB4, в зависимости от того, какой из входов PD0 или PA1 замкнут на "землю", так же в зависимости от того какая из кнопок на ножках PA0, PD2 нажата, то частота либо понижается, либо повышается.
Но это нифига не работает, прошу помощи.
Код: Выделить всёРазвернуть
#include <ioavr.h>
#include <intrinsics.h>

int freq[] = {1132, 132, 66, 43, 32, 26, 21, 18, 16, 14, 12};
int i = 0;

void init_timer1_r(void)
{
  TCCR1A = 0x00;
  TCCR1B = 0x00;
  TCCR1A |= (1<<COM1A0); //Режим CTC
  TCCR1B = (1<<WGM12)|(1<<CS10);
  OCR1A=freq[i];
}

void init_timer1_l(void)
{
  TCCR1A = 0x00;
  TCCR1B = 0x00;
  TCCR1A |= (1<<COM1B0); //Режим CTC
  TCCR1B = (1<<WGM12)|(1<<CS10);
  OCR1B=freq[i];
}

void timer1_stop(void)
{
  OCR1A=0;
  OCR1B=0;
  __delay_cycles(8000000);
}

//#pragma vector=TIMER1_COMPA_vect

int main( void )
{

  DDRD = 0x00;
  DDRA = 0x00;
  PORTA = 0xFF;
  PORTD = 0xFF;
  DDRB = 0xFF;
  PORTB = 0xFF;
  //init_timer1_r();
  __enable_interrupt();
  while(1)
  {
    PORTB &= ~(1<<PB2);

    if ((PINA & (1<<PA1)) == 0) init_timer1_r();
    if ((PIND & (1<<PD1)) == 0) timer1_stop();
    if ((PIND & (1<<PD0)) == 0) init_timer1_l();
   

      if ((PINA & (1<<PA0)) == 0)
      {
        if (i != 10)
        {
          i++;
          OCR1A = freq[i];
          OCR1B = freq[i];
        }
      }
   
      if ((PIND & (1<<PD2)) == 0)
      {
        if (i != 0)
        {
          i--;
          OCR1A = freq[i];
          OCR1B = freq[i];
        }
      }
  }
}

Пишу на IAR, частота - 8 Мгц
Вложения
main.c
(1.26 КиБ) Скачиваний: 35
Аватара пользователя
Lockdog
 
Сообщения: 639
Зарегистрирован: 06 июл 2006, 20:42
Откуда: Москва
прог. языки: C/C++, Pascal, Delphi
ФИО: Анатолий Зимин

Re: Помогите с программой для tiny2313

Сообщение blindman » 15 июл 2010, 03:23

OCR1B не может использоваться как максимальное значение счетчика - только OCR1A.
Проект [[Open Robotics]] - универсальные модули для построения роботов
Модули Open Robotics можно приобрести в магазине shop.roboforum.ru

Day OFF? You must be pulling my leg! Stop making humor before someone sees you, fool!

Аватара пользователя
blindman
 
Сообщения: 4130
Зарегистрирован: 29 апр 2008, 21:15
Откуда: Хабаровск
прог. языки: C,C++,Assembler,PHP,Javascript,Ruby, SPIN,Java(?)
ФИО: Андрей Юрьевич

Re: Помогите с программой для tiny2313

Сообщение $ilent » 15 июл 2010, 09:51

А что тут __enable_interrupt(); происходит?
Убери кнопки и просто запусти, потом кнопки повесишь.
$ilent
 

Re: Помогите с программой для tiny2313

Сообщение Lockdog » 15 июл 2010, 10:08

blindman писал(а):OCR1B не может использоваться как максимальное значение счетчика - только OCR1A.

Спасибо, в протеусе всё равно не работает, на железе пока проверить не могу.

Добавлено спустя 2 минуты 59 секунд:
$ilent писал(а):А что тут __enable_interrupt(); происходит?
Убери кнопки и просто запусти, потом кнопки повесишь.

на __enable не обращай внимание, осталось от старой процедуры =)

Мне интересно, почему эта конструкция не работает:
Код: Выделить всёРазвернуть
if ((PINA & (1<<PA0)) == 0)
      {
        if (i != 10)
        {
          i++;
          OCR1A = freq[i];
        }
      }
   
      if ((PIND & (1<<PD2)) == 0)
      {
        if (i != 0)
        {
          i--;
          OCR1A = freq[i];
        }
      }
Аватара пользователя
Lockdog
 
Сообщения: 639
Зарегистрирован: 06 июл 2006, 20:42
Откуда: Москва
прог. языки: C/C++, Pascal, Delphi
ФИО: Анатолий Зимин

Re: Помогите с программой для tiny2313

Сообщение $ilent » 15 июл 2010, 11:27

  1. Ты за одно нажатие на клавишу летаешь по диапазону значений своего: int freq[] = {1132, 132, 66, 43, 32, 26, 21, 18, 16, 14, 12};
    Одно нажатие - смещение на одну позицию, а не фиг знает на сколько увеличится твоя int i = 0; переменная.
$ilent
 

Re: Помогите с программой для tiny2313

Сообщение Lockdog » 15 июл 2010, 11:40

$ilent писал(а):
  1. Ты за одно нажатие на клавишу летаешь по диапазону значений своего: int freq[] = {1132, 132, 66, 43, 32, 26, 21, 18, 16, 14, 12};
    Одно нажатие - смещение на одну позицию, а не фиг знает на сколько увеличится твоя int i = 0; переменная.


Хм, почему я по всему диапазону летаю? Разве не на одну позицию и будет смещаться?
Аватара пользователя
Lockdog
 
Сообщения: 639
Зарегистрирован: 06 июл 2006, 20:42
Откуда: Москва
прог. языки: C/C++, Pascal, Delphi
ФИО: Анатолий Зимин

Re: Помогите с программой для tiny2313

Сообщение $ilent » 15 июл 2010, 12:52

Нет.

"Если нажата кнопка", то падаем ниже.
"Если и не 10", то "и++".
Выходим.

НО!!! кнопка-то ещё нажата!!! Мы же с частотой 8МГц проверяем её!!!
Вот и попадаем опять туда же.

Тебе нужно хотя бы пустой "ждать отпускания кнопки" добавить, между двумя "если".
$ilent
 

Re: Помогите с программой для tiny2313

Сообщение Lockdog » 15 июл 2010, 13:19

$ilent писал(а):Тебе нужно хотя бы пустой "ждать отпускания кнопки" добавить, между двумя "если".

Вот так: while((PINA & (1<<PA0)) == 0) {} ?

Добавлено спустя 1 минуту 51 секунду:
Фиг с этими кнопками, у меня не работает сам таймер.
Сейчас код выглядит так:
Код: Выделить всёРазвернуть
#include <ioavr.h>
#include <intrinsics.h>

__flash int freq[] = {1132, 132, 66, 43, 32, 26, 21, 18, 16, 14, 12};
int i = 0;

void init_timer1_r(void)
{
  TCCR1A &= ~(1<<COM1B0);
  TCCR1A |= (1<<COM1A0);//Режим CTC
  TCCR1B |= (1<<WGM12)|(1<<CS10);
  OCR1A = freq[i];
  PORTB |= (1<<PB4);
}

void init_timer1_l(void)
{
  TCCR1A &= ~(1<<COM1A0);
  TCCR1A |= (1<<COM1B0); //Режим CTC
  TCCR1B |= (1<<WGM12)|(1<<CS10);
  OCR1A = freq[i];
  PORTB |= (1<<PB3);
}

void timer1_stop(void)
{
  OCR1A=0;
  __delay_cycles(8000000);
}


int main( void )
{

  DDRD = 0x00;
  DDRA = 0x00;
  PORTA = 0xFF;
  PORTD = 0xFF;
  DDRB = 0xFF;
  PORTB = 0x00;
  init_timer1_r();
  while(1)
  {

//   if ((PIND & (1<<PD0)) == 0) init_timer1_r();
//   if ((PIND & (1<<PD1)) == 0) timer1_stop();
//   if ((PINA & (1<<PA1)) == 0) init_timer1_l();
   

      if ((PINA & (1<<PA0)) == 0)
      {
        while((PINA & (1<<PA0)) == 0) {}
        if (i != 10)
        {
          i = i+1;
          OCR1A = freq[i];
        }
      }
   
      if ((PIND & (1<<PD2)) == 0)
      {
        while((PINA & (1<<PA0)) == 0) {}
        if (i != 0)
        {
          i = i-1;
          OCR1A = freq[i];
        }
      }
  }
}
Аватара пользователя
Lockdog
 
Сообщения: 639
Зарегистрирован: 06 июл 2006, 20:42
Откуда: Москва
прог. языки: C/C++, Pascal, Delphi
ФИО: Анатолий Зимин

Re: Помогите с программой для tiny2313

Сообщение $ilent » 15 июл 2010, 13:23

ага.
while ((PINA & (1<<PA0)) == 0){}
или
while (!PINA & (1<<PA0)){}

Запусти таймер по-человечески. Останови, запомни СРЕГ, инициализируй, восстанови СРЕГ, разреши прерывания.
И покажи наконец ту функцию. Может ты там забыл забыл разрешить что-то.
Последний раз редактировалось $ilent 15 июл 2010, 13:37, всего редактировалось 1 раз.
$ilent
 

Re: Помогите с программой для tiny2313

Сообщение blindman » 15 июл 2010, 13:37

while (!PINA & (1<<PA0)){}

Не пойдет :no:
Проект [[Open Robotics]] - универсальные модули для построения роботов
Модули Open Robotics можно приобрести в магазине shop.roboforum.ru

Day OFF? You must be pulling my leg! Stop making humor before someone sees you, fool!

Аватара пользователя
blindman
 
Сообщения: 4130
Зарегистрирован: 29 апр 2008, 21:15
Откуда: Хабаровск
прог. языки: C,C++,Assembler,PHP,Javascript,Ruby, SPIN,Java(?)
ФИО: Андрей Юрьевич

Re: Помогите с программой для tiny2313

Сообщение Lockdog » 15 июл 2010, 13:58

blindman писал(а):
while (!PINA & (1<<PA0)){}

Не пойдет :no:

Да опечатался наверное, вот так пойдёт:
while (!(PINA & (1<<PA0)) {}

Добавлено спустя 37 секунд:
Помогите с таймером разобраться, плиз
Аватара пользователя
Lockdog
 
Сообщения: 639
Зарегистрирован: 06 июл 2006, 20:42
Откуда: Москва
прог. языки: C/C++, Pascal, Delphi
ФИО: Анатолий Зимин

Re: Помогите с программой для tiny2313

Сообщение $ilent » 15 июл 2010, 22:53

Вот те для кнопки нормальная обработка:
Код: Выделить всёРазвернуть
uint8_t key1 = 0;

uint8_t scan_keys (void)
{
uint8_t key_number = 0;
uint16_t i;
   if (key1 == 1) //Если произошло нажатие на клавишу 1
   {
      key1 = 0;
      while (!CHECKBIT (KEY_PIN, KEY1_BIT)){}
   }
   else
   {
      if (!CHECKBIT (KEY_PIN, KEY1_BIT))
      {
         for(i=0; i<10000; i++)
         {
            asm ("nop");
         }
         if (!CHECKBIT (KEY_PIN, KEY1_BIT))
         {
            key1 = 1;
            key_number = key_left;
            init_timer0 (0);
            SETBIT (LED_PORT, LED_BIT);
            beep(100);
         }
      }   
   }
   return key_number;
}

А вот для таймера. Делай по образу подобия. У меня считает импульсы на Т1 ноге - переделай под себя:
Код: Выделить всёРазвернуть
/* Таймер опроса датчика температуры, часов и записи значений в EEPROM.
   Таймер работает в режиме CTC с TOP = OCR1A
   Принимает на вход значение минут.
   Вызывает прерывание по совпадению с регистром компаратора А.
*/
uint8_t init_timer1 (uint8_t minuts)
{
   uint16_t secunds = 0;
   secunds = ((minuts * 60) - 1);
   sreg = SREG;      // сохраняем глобальные флаги
   cli();
   TCCR1B = 0x00;
   TCCR1A = 0x00;
   TCNT1 = 0x0000;
   OCR1A = secunds;
   TCCR1B |= (1 << WGM12) | (1 << CS12) | (1 << CS11);
   SREG = sreg;
   sei(); //re-enable interrupts
   return 0;
}

ISR (TIMER1_COMPA_vect)
{
//compare occured TCNT1=OCR1A
   beep(150);
}

деф файл:
Код: Выделить всёРазвернуть
#define BIT(x)              (1 << (x))
#define SETBIT(x, y)         (x |= y)
#define CLEARBIT(x, y)       (x &= ~y)
#define CHECKBIT(x, y)       (x & y)
#define INVERT(x, y)       (x ^= y)

#define KEY_PORT PORTA
#define KEY_DIR DDRA
#define KEY_PIN PINA
#define KEY1_BIT BIT3
#define KEY2_BIT BIT4
#define KEY3_BIT BIT5

Не забываем про:
Код: Выделить всёРазвернуть
TIMSK |= (1 << OCIE1A);
$ilent
 

Re: Помогите с программой для tiny2313

Сообщение Lockdog » 16 июл 2010, 00:26

$ilent писал(а):Не забываем про:
Код: Выделить всёРазвернуть
TIMSK |= (1 << OCIE1A);

Мне прерывание по совпадению вызывать не нужно.

$ilent писал(а):А вот для таймера. Делай по образу подобия. У меня считает импульсы на Т1 ноге - переделай под себя:
[code]
uint8_t init_timer1 (uint8_t minuts)
{
uint16_t secunds = 0;
secunds = ((minuts * 60) - 1);
sreg = SREG; // сохраняем глобальные флаги
cli();
TCCR1B = 0x00;
TCCR1A = 0x00;
TCNT1 = 0x0000;
OCR1A = secunds;
TCCR1B |= (1 << WGM12) | (1 << CS12) | (1 << CS11);
SREG = sreg;
sei(); //re-enable interrupts
return 0;
}

Собственно у меня примерно тоже самое

Добавлено спустя 7 минут 8 секунд:
Кстати, когда моделю в протеусе, то у меня тактирование на ноги идёт, только, если нажаты обе кнопки на PD0 и PA1
Аватара пользователя
Lockdog
 
Сообщения: 639
Зарегистрирован: 06 июл 2006, 20:42
Откуда: Москва
прог. языки: C/C++, Pascal, Delphi
ФИО: Анатолий Зимин

Re: Помогите с программой для tiny2313

Сообщение $ilent » 16 июл 2010, 09:09

Если не нужно прерываться, то зачем вообще таймер юзать?
$ilent
 

Re: Помогите с программой для tiny2313

Сообщение Lockdog » 16 июл 2010, 17:51

$ilent писал(а):Если не нужно прерываться, то зачем вообще таймер юзать?

Мне нужно, чтобы при переполнении таймера менялось состояние пина OC1A или OC1B, а это можно делать и без прерывания.
Вложения
tmr.jpg
Аватара пользователя
Lockdog
 
Сообщения: 639
Зарегистрирован: 06 июл 2006, 20:42
Откуда: Москва
прог. языки: C/C++, Pascal, Delphi
ФИО: Анатолий Зимин

След.

Вернуться в Микроконтроллеры

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Mail.ru counter