Запуск Таймера-счетчика из прерывания INT0

Обсуждаем контроллеры компании Atmel.
Ответить
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Может кто помочь разобраться как правильно инициализировать регистры для таймера счетчика на тини461 или тини26L, А то уже день убил а все стоит на мертвой точке.

Инициализация INT0:

Код: Выделить всё

//настраиваем на срабатывание INT0 по переднему фронту
MCUCR |= (1<<ISC01)|(0<<ISC00);
GIMSK|=(1<<6); 
С внешнем прерыванием вроде все понятно.

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

Код: Выделить всё

1. TIMSK |= (1<<6); 
2. OCR1A = 0xFF; 
3. TCCR1A |= (1<<CS12);
1 активируем режим OCIE1A для сравнения таймера с счетчиком.
2 записываем в регистр максимальное число для сравнения
3 установим делитель на 8 (cs12 по датишу на461) тоесть счетчик у нас будет считать с частотой 1Mhz.

а вот что делать ?)

также для прерывания по совпадению счетчика с OCR1A , надо обЪявить функцию ISR (TIMER1_COMPA_vect)
andrei23061996@gmail.com
.................................................................................................................
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Кроме риторического вопроса "Что делать?" я других не увидел. Уточните вопрос.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

не могу понять почему не запускается таймер и не срабатывает прерывание ?
Спойлер

Код: Выделить всё

#define F_CPU   8000000

#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>

#define SET_B(x) |= (1<<x) // "установить"
#define CLR_B(x) &=~(1<<x) // "очистить"  бит
#define INV_B(x) ^=(1<<x)  // инвертировать 

#define  En_INT0      GIMSK|=(1<<6);      // включаем прерывание INT0
#define  Dis_INT0     GIMSK&=~(1<<6);     // выключаем прерывание INT0
#define  En_INT_T0    TIMSK|=(1<<1);      // включаем прерывание TIMER0
#define  Dis_INT_T0   TIMSK&=~(1<<1);     // выключаем прерывание TIMER0
unsigned char i;

void segchar (unsigned char seg)
{
	switch (seg)
	{
		case 1: PORTA = 0b01111100; break;
		case 2: PORTA = 0b10000100; break;
		case 3: PORTA = 0b01000100; break;
		case 4: PORTA = 0b01101000; break;
		case 5: PORTA = 0b01000010; break;
		case 6: PORTA = 0b00000010; break;
		case 7: PORTA = 0b01110100; break;
		case 8: PORTA = 0b00000000; break;
		case 9: PORTA = 0b01000000; break;
		case 0: PORTA = 0b00010000; break;
	}
}

void int0_init( void )
{
	//настраиваем на срабатывание INT0 по переднему фронту
	MCUCR |= (1<<ISC01)|(0<<ISC00);
	//разрешаем внешнее прерывание INT0
	En_INT0
	
}

void init_io()
{
	//порт, к которому подкл. сегменты
	DDRA = 0xff;
	PORTA = 0xff;
	//порт, к которому подкл. катод
	DDRB |=(1<<0)|(1<<1)|(1<<2);
	PORTB =0x00;
}

void timer_ini(void)
{
	TIMSK |= (1<<6);
	OCR1A = 0xFF; //записываем в регистр число для сравнения
	TCCR1A |= (1<<CS12);//установим делитель.
}

ISR (TIMER1_COMPA_vect)
{
	PORTA SET_B(1);
	_delay_ms(10);
	PORTA CLR_B(1);
	_delay_ms(10);
	PORTA SET_B(1);
	_delay_ms(10);
	PORTA CLR_B(1);
	_delay_ms(10);
}

ISR(INT0_vect)
{
	
}

int main(void)
{
	int0_init();
	init_io();
	timer_ini();
	sei();
    while(1)
    {
    }
}
andrei23061996@gmail.com
.................................................................................................................
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

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

Добавлено after 1 minute 39 seconds:
Поглядите в ДШ регистры таймера, особенно регистр в котором устанавливается предделитель. А потом посмотрите в какой Вы пишите.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

B что-то мне подсказывает, что за 10 мс у вас таймер не один раз переполнится... а вы лепите задержку в прерывании по совпадению аж 40 мс в сумме! так не делают
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

AVR, а как правильно посчитать сколько времени дается на прерывания ? время на исполнения кода в прерывание не должно превышать время счета счетчика который.
andrei23061996@gmail.com
.................................................................................................................
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Ваш счетчик с частотой тактирования 1МГц до считает до 0xFF за 255 мкс.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Код: Выделить всё

void init_io()
{
	//порт, к которому подкл. сегменты
	DDRA = 0xff;
	PORTA = 0xff;
	//порт, к которому подкл. катод
	DDRB |=(1<<0)|(1<<1)|(1<<2);
	PORTB =0x00;
}

void timer_ini(void)
{
	TIMSK |= (1<<6);
	OCR1A = 0x10; //записываем в регистр число для сравнения  в десятичном счисление 16 
	TCCR1A |= (1<<CS13)|(1<<CS11);//установим делитель 512 
}

ISR (TIMER1_COMPA_vect)
{
	PORTA = ~PORTA;
}


int main(void)
{
	init_io();
	timer_ini();
	sei();
    while(1)
    {
    }
}
К примеру я настроил конфиги таймера таким способом . как я предполагал должно вызываться прерывания каждую 1ms и инвертировать Порт Б по прерыванию (TIMER1_COMPA_vect) совпадения счетчика с OCR1A . можете помочь разобраться почему не вызываются прерывания теперь то ?
andrei23061996@gmail.com
.................................................................................................................
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

7seg писал(а):можете помочь разобраться почему не вызываются прерывания теперь то ?
ну как минимум потому, что таймер у вас остановлен. включается он записью предделителя в регистр TCCR1B, а не TCCR1A - читайте даташит внимательно.
7seg писал(а):TCCR1A |= (1<<CS13)|(1<<CS11);//установим делитель 512
и что-то мне подсказывает, что предделителя 512 не бывает в первом таймере...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

из дш

Table 12-17. Timer/Counter1 Prescaler Select

1 0 1 0 PCK/512 CK/512

или мб я как то не правильно понял эту таблицу ?
andrei23061996@gmail.com
.................................................................................................................
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

ARV писал(а):и что-то мне подсказывает, что предделителя 512 не бывает в первом таймере...
У данного МК таймер1 имеет больше делителей чем обычно, но зато 8 битный.
ARV писал(а): включается он записью предделителя в регистр TCCR1B, а не TCCR1A - читайте даташит внимательно.
Я это уже написал ТСу, правда не явно, думал сам найдет ошибку. Но он даже не попробовал.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

TCCR1А ужу изменил на TCCR1B но по ка что не смог заставить реагировать порт а на прерывания.(

Добавлено after 3 minutes 50 seconds:
Вот я думаю не нужно ли тогда изменить TIMSK с OCIE1A на OCIE1B
andrei23061996@gmail.com
.................................................................................................................
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Счетчик то тикает?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Судя по загрузке ЦПУ в протеусе то да.
andrei23061996@gmail.com
.................................................................................................................
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Z_h_e писал(а):У данного МК таймер1 имеет больше делителей чем обычно, но зато 8 битный
понаделали разновидностей, смущают честной народ :oops:
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Сейчас попробую с дебаг меню атмел студии разобраться.
andrei23061996@gmail.com
.................................................................................................................
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

[uquote="7seg",url="/forum/viewtopic.php?p=3102337#p3102337"]Судя по загрузке ЦПУ в протеусе то да.[/uquote] Это плохой ориентир. Поставте Шпротеус на паузу и поглядите значения счетчика.

В протеусе глюк есть с режимом сравнения. Если включить режим СТС, то прерывание по сравнению срабатывает, если таймер в обычном режиме то хрен. Я правда на другом МК это выяснил. Может на Вашем нет такого.

Добавлено after 2 minutes 47 seconds:
Используйте прерывание по переполнению. Оно все равно будет с той же частотой срабатывать без сброса счетчика.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

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

старый пример с прерыванием по переполнению.
Спойлер

Код: Выделить всё

#define F_CPU   8000000          //Hz

#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>

#define T0_TICK_RATE    200     // Hz
#define T0_CLK  ((F_CPU)/1024)
#define T0_TICKS  (0x100 - T0_CLK / T0_TICK_RATE)

#define DEBOUNCE_TIME          20

#define BUTTON_PIN             PINB
#define POWER_BIT            PB3
#define UP_BIT               PB4
#define DOWN_BIT            PB5

#define KEY_POWER         0b00001000
#define KEY_DOWN         0b00100000
#define KEY_UP            0b00010000

#define  En_INT0      GIMSK|=(1<<6);
#define  Dis_INT0     GIMSK&=~(1<<6);     // выключаем прерывание INT0

volatile unsigned char data1=0;
volatile unsigned char data2=0;
volatile unsigned char value;
volatile int _buzzer = 0;
volatile int _pressed = 0;

void init_io();
void segchar(unsigned char seg);
void handle_button(int key);
void handle_buttons();
void process_power();
void process_up();
void process_down();

//настройка внешнего прерывния INT0
void int0_init( void )
{
   //настраиваем на срабатывание INT0 по переднему фронту
   MCUCR |= (1<<ISC01)|(0<<ISC00);
   //разрешаем внешнее прерывание INT0
   En_INT0
}


ISR(INT0_vect)
{ 
   int i=100;
   int tempMS=(value+1);
   for (;;)
   {
      i--;
      _delay_us(10);
      if (i<=tempMS)
      {
         break;
      }
   }
   int k;
   for(k=0; k<5; k++)
   {
   PORTB |= (1<<1);
   _delay_us(2);
   PORTB &= ~(1<<1);
   _delay_us(2);
   }
}

int main(void)
{
   value=0;
   init_io();
   sei();
   int0_init();
   while(1)
   {
      handle_buttons();
   }
   return 0;
}


void segchar (unsigned char seg)
{
   switch (seg)
   {
      case 1: PORTA = 0b01111100; break;
      case 2: PORTA = 0b10000100; break;
      case 3: PORTA = 0b01000100; break;
      case 4: PORTA = 0b01101000; break;
      case 5: PORTA = 0b01000010; break;
      case 6: PORTA = 0b00000010; break;
      case 7: PORTA = 0b01110100; break;
      case 8: PORTA = 0b00000000; break;
      case 9: PORTA = 0b01000000; break;
      case 0: PORTA = 0b00010000; break;
   }
}

void init_io()
{
   //порт, к которому подкл. сегменты
   PORTA = 0xff;
   DDRA = 0xff;
   //порт, к которому подкл. катод
   DDRB |=(1<<0)|(1<<1)|(1<<2);
   PORTB =0x00;
   //инициализация таймера Т0
   TIMSK = (1<<TOIE0);
   TCCR0B = (1<<CS02)|(0<<CS01)|(1<<CS00);  // правка на 461
   TCNT0L =  T0_TICKS;  //правка на  461
   //иницилизация прерываний
   
}

//прерывания таймера Т0 - вывод на индикатор
ISR(TIMER0_OVF_vect)  //правка на 461 
{
   static unsigned char count = 0;
   TCNT0L += T0_TICKS; //правка на 461 
   //гасим оба разряда
   PORTB |=(1<<PB0);
   PORTB |=(1<<PB2);
   PORTA = 0b11111110;   
   //зажигаем следующий разряд
   if (count == 0)
   {
      segchar(data2);
      PORTB &= ~(1<<2);
   }
   if (count == 1)
   {
      segchar(data1);
      PORTB &= ~(1<<0);
   }
   count++;
   if (count == 2) count = 0;
}

void handle_button(int key)
{
   int bit;
   switch (key)
   {
      case KEY_POWER: bit = POWER_BIT; break;
      case KEY_UP:    bit = UP_BIT; break;
      case KEY_DOWN:    bit = DOWN_BIT; break;
      default: return;
   }

   if (bit_is_clear(BUTTON_PIN, bit))
   {
      if (_pressed == 0)
      {
         _delay_ms(DEBOUNCE_TIME);
         if (bit_is_clear(BUTTON_PIN, bit))
         {
            _pressed |= key;
            
            // key action
            switch (key)
            {
               case KEY_POWER: process_power(); break;
               case KEY_UP:    process_up(); break;
               case KEY_DOWN:    process_down(); break;
            }
         }
      }
   }
   else
   {
      _pressed &= ~key;
   }
}

void handle_buttons()
{
   handle_button(KEY_POWER);
   handle_button(KEY_DOWN);
   handle_button(KEY_UP);
}

void process_power()
{
   
}
void process_up()
{
   if (value < 99)
   {
      value++;
      unsigned char tmp;
      tmp = value % 10;
      data1 = tmp;
      tmp = value/10;
      data2= tmp;
   }
}
void process_down()
{
   if (value > 0)
   {
      value--;
      unsigned char tmp;
      tmp = value % 10;
      data1 = tmp;
      tmp = value/10;
      data2= tmp;
   }
}
andrei23061996@gmail.com
.................................................................................................................
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Диммер чтоли делаете?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 303
Зарегистрирован: Ср май 03, 2017 03:22:26

Сообщение 7seg »

Димер, или Регулятор мощности с фиу.

Добавлено after 2 hours 47 minutes 26 seconds:
Z_h_e, А можете простенький код перевести с таймером по сравнению чтоб к примеру он моргал PA1 0\1 . c какой либо частотой.

Если конечно это вас не затруднит. Зарание спасибо, а пока что буду пытаться в месте с гуглом переводчиком выкурить датишь ))
andrei23061996@gmail.com
.................................................................................................................
Ответить

Вернуться в «AVR»