Страница 1 из 2
Запуск Таймера-счетчика из прерывания INT0
Добавлено: Ср май 10, 2017 12:21:48
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)
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Ср май 10, 2017 12:25:54
Z_h_e
Кроме риторического вопроса "Что делать?" я других не увидел. Уточните вопрос.
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Ср май 10, 2017 12:41:04
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)
{
}
}
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Ср май 10, 2017 12:58:14
Z_h_e
Выполните по шагам свою программу в симуляторе и поглядите значение регистров таймера. Сразу бы нашли ошибку. Это ведь не трудно.
Добавлено after 1 minute 39 seconds:
Поглядите в ДШ регистры таймера, особенно регистр в котором устанавливается предделитель. А потом посмотрите в какой Вы пишите.
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Ср май 10, 2017 13:03:01
ARV
B что-то мне подсказывает, что за 10 мс у вас таймер не один раз переполнится... а вы лепите задержку в прерывании по совпадению аж 40 мс в сумме! так не делают
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Ср май 10, 2017 13:22:35
7seg
AVR, а как правильно посчитать сколько времени дается на прерывания ? время на исполнения кода в прерывание не должно превышать время счета счетчика который.
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Ср май 10, 2017 13:25:33
Z_h_e
Ваш счетчик с частотой тактирования 1МГц до считает до 0xFF за 255 мкс.
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 04:06:16
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 . можете помочь разобраться почему не вызываются прерывания теперь то ?
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 06:40:09
ARV
7seg писал(а):можете помочь разобраться почему не вызываются прерывания теперь то ?
ну как минимум потому, что таймер у вас остановлен. включается он записью предделителя в регистр TCCR1B, а не TCCR1A - читайте даташит внимательно.
7seg писал(а):TCCR1A |= (1<<CS13)|(1<<CS11);//установим делитель 512
и что-то мне подсказывает, что предделителя 512 не бывает в первом таймере...
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 06:45:09
7seg
из дш
Table 12-17. Timer/Counter1 Prescaler Select
1 0 1 0 PCK/512 CK/512
или мб я как то не правильно понял эту таблицу ?
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 06:47:52
Z_h_e
ARV писал(а):и что-то мне подсказывает, что предделителя 512 не бывает в первом таймере...
У данного МК таймер1 имеет больше делителей чем обычно, но зато 8 битный.
ARV писал(а): включается он записью предделителя в регистр TCCR1B, а не TCCR1A - читайте даташит внимательно.
Я это уже написал ТСу, правда не явно, думал сам найдет ошибку. Но он даже не попробовал.
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 06:55:12
7seg
TCCR1А ужу изменил на TCCR1B но по ка что не смог заставить реагировать порт а на прерывания.(
Добавлено after 3 minutes 50 seconds:
Вот я думаю не нужно ли тогда изменить TIMSK с OCIE1A на OCIE1B
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 06:56:50
Z_h_e
Счетчик то тикает?
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 07:01:26
7seg
Судя по загрузке ЦПУ в протеусе то да.
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 07:01:42
ARV
Z_h_e писал(а):У данного МК таймер1 имеет больше делителей чем обычно, но зато 8 битный
понаделали разновидностей, смущают честной народ

Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 07:02:59
7seg
Сейчас попробую с дебаг меню атмел студии разобраться.
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 07:11:30
Z_h_e
[uquote="7seg",url="/forum/viewtopic.php?p=3102337#p3102337"]Судя по загрузке ЦПУ в протеусе то да.[/uquote] Это плохой ориентир. Поставте Шпротеус на паузу и поглядите значения счетчика.
В протеусе глюк есть с режимом сравнения. Если включить режим СТС, то прерывание по сравнению срабатывает, если таймер в обычном режиме то хрен. Я правда на другом МК это выяснил. Может на Вашем нет такого.
Добавлено after 2 minutes 47 seconds:
Используйте прерывание по переполнению. Оно все равно будет с той же частотой срабатывать без сброса счетчика.
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 07:20:29
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;
}
}
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 07:24:06
Z_h_e
Диммер чтоли делаете?
Re: Запуск Таймера-счетчика из прерывания INT0
Добавлено: Чт май 11, 2017 10:17:16
7seg
Димер, или Регулятор мощности с фиу.
Добавлено after 2 hours 47 minutes 26 seconds:
Z_h_e, А можете простенький код перевести с таймером по сравнению чтоб к примеру он моргал PA1 0\1 . c какой либо частотой.
Если конечно это вас не затруднит. Зарание спасибо, а пока что буду пытаться в месте с гуглом переводчиком выкурить датишь ))