Обсуждаем контроллеры компании Atmel.
Ответить

Re: Таймеры/счётчики в AVR

Пн апр 24, 2017 19:12:23

Кстати, цеплял к тиньке кварц 3.2768 МГц - тоже завышало порядка 0.1% независимо от конденсаторов. ЧЯДНТ?

Re: Таймеры/счётчики в AVR

Вт июн 20, 2017 10:24:04

Подскажите, пожалуйста, почему не срабатывает прерывание по совпадению таймера, точнее прерывание то есть, только оно попадает на другой вектор почему то. МК - ATmega164. Вроде все перепроверил, все настройки правильные, но в AVR Studio 6 и в Proteuse прерывание попадает на строку компаратора или АЦП в таблице векторов :dont_know:
Спойлер
Код:
.include "m164pdef.inc"

.def   temp = r16              ; Буфер
.def   Counter = r17           ; Переменная цикла

.equ   deley_vkl_0 = 35       

      .cseg                   ; Выбор сегмента программного кода

;---------- Начало программного кода

      .org   0                  ; Установка текущего адреса на ноль

               jmp   RESET           ; Переход на начало программы
      reti                        ; jmp EXT_INT0   ; Внешнее прерывание 0
       reti                        ; jmp INT1        ; Внешнее прерывание 1
      reti                        ; jmp INT2
      reti                        ; jmp PCINT0 ; PCINT0 Handler
        reti                        ; jmp PCINT1 ; PCINT1 Handler
        reti                        ; jmp PCINT2 ; PCINT2 Handler
      reti                        ; jmp PCINT3
        reti                        ; jmp WDT ; Watchdog Timer Handler
        reti                        ; jmp TIMER2_COMPA ; Timer2 Compare A Handler
        reti                        ; jmp TIMER2_COMPB ; Timer2 Compare B Handler
        reti                        ; jmp TIMER2_OVF ; Timer2 Overflow Handler
        reti                        ; jmp TIMER1_CAPT ; Timer1 Capture Handler
                jmp TIMER1_COMPA    ; Timer1 Compare A Handler
        reti                        ; jmp TIMER1_COMPB ; Timer1 Compare B Handler
        reti                        ; jmp TIMER1_OVF ; Timer1 Overflow Handler
        reti                        ; jmp TIMER0_COMPA    ; Timer0 Compare A Handler
        reti                        ; jmp TIMER0_COMPB ; Timer0 Compare B Handler
        reti                        ; jmp TIMER0_OVF ; Timer0 Overflow Handler
        reti                        ; jmp SPI, STC ; SPI Transfer Complete Handler
        reti                        ; jmp USART0, RX ; USART, RX Complete Handler
        reti                        ; jmp USART0, UDRE ; USART, UDR Empty Handler
        reti                        ; jmp USART0, TX ; USART, TX Complete Handler
      reti                        ; jmp ANA_COMP
        reti                        ; jmp ADC ; ADC Conversion Complete Handler
        reti                        ; jmp EE_RDY ; EEPROM Ready Handler
        reti                        ; jmp TWI ; 2-wire Serial Interface Handler
        reti                        ; jmp SPM_RDY ; Store Program Memory Ready Handler
      reti                        ; jmp USART1, RX
      reti                        ; jmp USART1, UDRE
      reti                        ; jmp USART1, TX

; ---------- Модуль инициализации ----------
RESET:
;---------- Инициализация портов ВВ ----------
      
      clr      temp      ; Записываем 0 в регистр temp
      out      PORTD, temp   ; порт PD0-PD5: выход =0, PD6: вход =Z
      ldi      temp,  0x7B
      out      DDRD,  temp ; 01111011 - "1"-выход, "0"-вход, 2-й бит на вход - внешнее прерывание INT0

      clr      temp      
      out      PORTB, temp
      ldi     temp,  0xFF ; 11111111 все на выход
      out      DDRB,  temp

      ldi      temp,  0x80   ; Аналог. компаратор откл.
      out      ACSR,  temp

;---------- Инициализация таймера T1 ----------

        ldi     temp,   0x0A        ; 00001010 - режим СТС - сброс по совпадению и запуск таймера
      sts     0x81,   temp        ; TCCR1B
      ldi      temp,   deley_vkl_0   
      sts     0x88,   temp        ; в OCR1A записали число 35
      ldi     temp,   0x02
      sts     0x6F,   temp        ; разрешаем прерывание по событию "Совпадение А" TIMSK1
      
;---------- Инициализация стека ----------

        ldi    temp,low(RAMEND)   ; Выбор адреса вершины стека (адрес конца RAM)
      out      SPL,temp         ; Запись его в регистр стека
      ldi    temp,high(RAMEND)   ;
      out    SPH, temp
      sei
;---------- Начало основной программы
lp00:   

loop5:   sbic   PIND, 7            ; ждём приход 1 втечение 0.51(мс) если 6-й бит регистра PIND = 0, то след. команда пропускается
         jmp     loop6
       in       temp, TIFR1
       sbrs   temp, 1
       jmp       loop5
       jmp       lp00
loop6:

;====================
;       Подпрограмма обработки прерываний
;====================

TIMER1_COMPA:
        clr      temp
      
      reti
Вложения
ATmega164.gif
(188.49 KiB) Скачиваний: 501

Re: Таймеры/счётчики в AVR

Сб июн 24, 2017 06:15:13

Если ещё актуально. Проще явно указать адрес вектора
Регистр OCR1A двухбайтовый и для таких регистров периферии есть определенный порядок записи/чтения
Спойлер
Код:
      .org   0                  ; Установка текущего адреса на ноль

               jmp   RESET           ; Переход на начало программы
      reti                        ; jmp EXT_INT0   ; Внешнее прерывание 0
       reti                        ; jmp INT1        ; Внешнее прерывание 1
      reti                        ; jmp INT2
      reti                        ; jmp PCINT0 ; PCINT0 Handler
        reti                        ; jmp PCINT1 ; PCINT1 Handler
        reti                        ; jmp PCINT2 ; PCINT2 Handler
      reti                        ; jmp PCINT3
        reti                        ; jmp WDT ; Watchdog Timer Handler
        reti                        ; jmp TIMER2_COMPA ; Timer2 Compare A Handler
        reti                        ; jmp TIMER2_COMPB ; Timer2 Compare B Handler
        reti                        ; jmp TIMER2_OVF ; Timer2 Overflow Handler
        reti                        ; jmp TIMER1_CAPT ; Timer1 Capture Handler

      .org   0x001A                  ; Установка вектора сравнения таймера 1А
                jmp TIMER1_COMPA    ; Timer1 Compare A Handler
;
;
;
;
;
;
;---------- Инициализация таймера T1 ----------
    LDI   XH,HIGH(deley_vkl_0)
    LDI   XL,LOW(deley_vkl_0)
    STS  OCR1AH,XH
    STS  OCR1AL,XL

    LDI   R16,1<<OCIE1A
    STS  TIMSK1,R16        ; разрешаем прерывание по событию "Совпадение А" TIMSK1

    LDI   R16,1<<WGM12|1<<CS11
    STS TCCR1B,R16       ;режим СТС - сброс по совпадению и запуск таймера Fclk/8

;        ldi     temp,   0x0A        ; 00001010 - режим СТС - сброс по совпадению и запуск таймера
;      sts     0x81,   temp        ; TCCR1B
;      ldi      temp,   deley_vkl_0   
;      sts     0x88,   temp        ; в OCR1A записали число 35
;      ldi     temp,   0x02
;      sts     0x6F,   temp        ; разрешаем прерывание по событию "Совпадение А" TIMSK1
     

Re: Таймеры/счётчики в AVR

Сб июн 24, 2017 11:17:28

artemik32 писал(а):только оно попадает на другой вектор почему то.
Попадает оно на тот вектор, это Вы таблицу векторов неправильно заполнили. Поглядите таблицу векторов в ДШ, у данного камня один вектор занимает два слова памяти программ. Команда-затычка RETI однословная команда. На Вашем скрине как раз видно, что программный счетчик указывает на 0x1A, т.е. это адрес нужного Вам вектора.


Можно вставить двухсловные команды на неиспользуемые вектора, например
Код:
jmp  RESET

, или две однословные команды на один вектор, например
Код:
nop
nop
.
Можно в вектор вставить директиву .dw 0x0000.
Или воспользуйтесь директивой .ORG, как указал akl.

Re: Таймеры/счётчики в AVR

Сб июн 24, 2017 11:44:22

akl писал(а):Проще явно указать адрес вектора
тем более что для каждого адреса вектора уже определены соответствующие символьные константы. И это не только проще, но и правильнее - я об этом неоднократно говорил, и буду говорить.

Re: Таймеры/счётчики в AVR

Вс июл 02, 2017 19:41:29

Да спасибо, я уже написал конкретный адрес перехода на вектор как предложил akl. Так нормально работает, а с младшими мегами таких проблем не было, у которых используется команда rjmp вместо jmp, и памяти у них 8 кб и меньше.

Re: Таймеры/счётчики в AVR

Ср июл 26, 2017 05:27:12

Код:
      .org   0                  ; Установка текущего адреса на ноль

               jmp   RESET           ; Переход на начало программы
      reti                        ; jmp EXT_INT0   ; Внешнее прерывание 0
       reti                        ; jmp INT1        ; Внешнее прерывание 1
      reti                        ; jmp INT2
      reti                        ; jmp PCINT0 ; PCINT0 Handler
        reti                        ; jmp PCINT1 ; PCINT1 Handler
        reti                        ; jmp PCINT2 ; PCINT2 Handler
      reti                        ; jmp PCINT3
        reti                        ; jmp WDT ; Watchdog Timer Handler
        reti                        ; jmp TIMER2_COMPA ; Timer2 Compare A Handler
        reti                        ; jmp TIMER2_COMPB ; Timer2 Compare B Handler
        reti                        ; jmp TIMER2_OVF ; Timer2 Overflow Handler
        reti                        ; jmp TIMER1_CAPT ; Timer1 Capture Handler

      .org   0x001A                  ; Установка вектора сравнения таймера 1А
                jmp TIMER1_COMPA    ; Timer1 Compare A Handler

Неправильно! JMP - два слова. RETI - одно слово. И два RETI займет один вектор. Правильно нужно писать так:
Код:
.org 0x0000
      jmp RESET ; Reset Handler
.org   OC2addr
      jmp TIM2_COMP ; Timer2 Compare Handler
.org URXC0addr
      jmp RS232_VESS; USART0 RX Complete Handler
.org ADCCaddr
      jmp ADC_Complet
.org URXC1addr
      jmp USART1_RXC; USART1 RX Complete Handler
.org UDRE1addr
      jmp USART1_UDRE; USART1 TX Complete Handler


Такая запись будет верной:
Код:
.org UDRE1addr
      reti ; jmp USART1_UDRE; USART1 TX Complete Handler

Re: Таймеры/счётчики в AVR

Вс авг 13, 2017 19:10:13

Друзья, всем привет.
Пытаюсь разобраться с таймерами, и столкнулся с непонятной для меня информацией. Пишу в Ардуино ИДЕ. Микроконтроллер: Атмега168
Цель: нужно вызывать функцию 1 раз в секунду (по сути это часы, только назначение другое). Решил все это делать на таймере. Залез в даташит: 0-й и 2-й таймеры 8-мибитные, значит отпадают, остается 1-й таймер. По настройке немного сложно, делаю в первый раз, но в принципе разобраться можно.
Вот примерно что я собираюсь делать, Так правильно? и нужно ли делать сброс таймера?:

Код:
TCCR1B |= (1<<WGM12);
TCCR1B |= (1<<CS12); // делитель 256
TIMSK |=(1<<OCIE1A); // прерывание по совпадению
OCR1AH = 0b11110100; // число для сравнения 62500
OCR1AL = 0b00100100;
 
....
ISR (TIMER1_COMPA_vect)
{
    // какое-то действие
}


Добавлено after 44 minutes 55 seconds:
Пробую, но ничего не работает... код:
Код:
int i=10;

ISR (TIM1_COMPA)
{
  // какое-то действие
  i=i+1;
}

void setup(void) {
  // flip screen, if required
  // u8g.setRot180();
  TCCR1B |= (1<<WGM12);
  TCCR1B |= (1<<CS12); // делитель 256
  TIMSK1 |=(1<<OCIE1A); // прерывание по совпадению
  OCR1AH = 0b11110100; // число для сравнения 62500
  OCR1AL = 0b00100100;
  Serial.begin(9600);
}

void loop(void) {
  Serial.println(i);
 
  // rebuild the picture after some delay
  delay(100);
}

Re: Таймеры/счётчики в AVR

Вс авг 13, 2017 20:30:19

в режиме СТС он сам сбрасывается

Добавлено after 2 minutes 38 seconds:
разрешение прерываний (глобальное)?

Re: Таймеры/счётчики в AVR

Вс авг 13, 2017 20:46:15

Да вроде как по умолчанию они включены.
Пробовал дописывать sei() но это ничего не изменило. В общем я в ступоре... Может что-то элементарное пропускаю? С тем же ISR не все понятно. В одних местах он прописан как TIM1_COMPA в других по-другому. Пробовал и так и так - нет результата.

Re: Таймеры/счётчики в AVR

Вс авг 13, 2017 21:31:38

Пробую, но ничего не работает...

Попробуйте так. Глобальные прерывания нужно разрешать в вашем случае.
Спойлер
Код:
int i=10;

ISR (TIMER1_OVF_vect)
{
TCNT1 = 0xC2F7;
  // какое-то действие
  i++;
}

void setup(void) {
   
  //Инициализация таймера 1
   TCCR1B = 0b101; // делитель на 1024
   TIMSK1 |= (1<<TOIE1);   //активировать прерывание по переполнению таймера
   TCNT1 = 0xC2F7;       // частота прерываний 1 Гц для F_CPU = 16 000 000
   
   Serial.begin(9600);
   
   sei();
}

void loop(void) {
  Serial.println(i);
 
  // rebuild the picture after some delay
  delay(100);
}

Re: Таймеры/счётчики в AVR

Пн авг 14, 2017 05:13:40

forfrends писал(а):Пробую, но ничего не работает
volatile int i=10;

Re: Таймеры/счётчики в AVR

Пн авг 14, 2017 07:04:31

... Так правильно?
Код:
TCCR1B |= (1<<WGM12);
TCCR1B |= (1<<CS12); // делитель 256
TIMSK |=(1<<OCIE1A); // прерывание по совпадению
OCR1AH = 0b11110100; // число для сравнения 62500
OCR1AL = 0b00100100;
...
ISR (TIMER1_COMPA_vect)
{
    // какое-то действие
}
Замечу, в OCR1x(ICR1) для точной выдержки времени нужно заносить значение на 1 меньшее, особенно при использовании предделителя. Т.е. 62500-1

Re: Таймеры/счётчики в AVR

Чт окт 12, 2017 18:42:08

Помогите. В протеусе все симулирует чётко. Загружаю в МК не отрабатывает прерывание по переполнению таймера1. Мк аттини85.
Правильно ли инициализировал прерывание?

Код:
//инициализация таймера1
void timer1_ini (void){
   TCCR1 |= (1 << CTC1) //режим CTC
   |(0<<COM1A1)|(0<<COM1A0) //отключаем OC1A
   |(1 << CS13)|(0 << CS12)|(1 << CS11)|(0 << CS10);  //Делитель 512
   TCNT1 = 0x00;                  //сброс счетчика
   OCR1A = 0xFF;                //регистр сравнения
   TIMSK |=(1<<TOIE1);      //включаем прерывания по переполнению   
 }

//обработка прерывания таймера1
ISR(TIMER1_OVF_vect){
   PORTB |= (1<<PB1);         
   }

Re: Таймеры/счётчики в AVR

Пт окт 13, 2017 03:49:59

SEI не хватает.

Re: Таймеры/счётчики в AVR

Пт окт 13, 2017 04:54:47

SEI не хватает.

В функции инициализации глобальное включение прерываний не обязано быть. Только после инициализации всей нужной периферии.

Re: Таймеры/счётчики в AVR

Пт окт 13, 2017 07:57:47

SEI есть в программе, даже есть ещё одно прерывание по таймеру0 (TIMER0_COMPA_vect) и оно работает, а по этому вектору нет, да и интересно почему в протеусе все как надо работает, а в реальном МК нет? мб МК бракованный >_<

Re: Таймеры/счётчики в AVR

Пт окт 13, 2017 08:06:12

fulky писал(а):интересно почему в протеусе все как надо работает, а в реальном МК нет? мб МК бракованный
МК бракованный... еще может быть компилятор лажает - это две любимые причины всех проблем начинающих.

у вас схема протеуса на 100% соответствует реальной? в реальной ошибок нет? что вы ждете от обработчика с единственным оператором, какие эффекты быть должны, а их нет? ни схемы, ни всей программы, одни загадки-догадки.

я вам точно скажу, в чем причина: у вас есть ошибка. полегчало? ;) только где именно - не скажу

Re: Таймеры/счётчики в AVR

Пт окт 13, 2017 08:09:45

Думаю, прерывание по переполнению никогда не возникает, т.к. таймер работает до 0xFF. Попробуйте прерывание OCIE1A

Re: Таймеры/счётчики в AVR

Пт окт 13, 2017 09:06:06

МК бракованный... еще может быть компилятор лажает - это две любимые причины всех проблем начинающих.


из-за оптимизации такое может происходить, (-O) выставлена?

Режимы работы реле
Изображение

1. Потенциометром задается режим от 1 до 4, как на картинке, удержанием кнопки переход на следующий шаг
2. Задается время t1
3. Указываются в чем считать С, М, Ч
4. Задается время t2
5. Указываются в чем считать С, М, Ч
6. Происходит запуск (PB1 рулит реле по выбранному режиму)

Косяк в том, что нет бегающей индикации во время работы

Добавлено after 31 minute 54 seconds:
Думаю, прерывание по переполнению никогда не возникает, т.к. таймер работает до 0xFF. Попробуйте прерывание OCIE1A

т.е. сделать по вектору TIMER1_COMPA и через сравнение с OCR1A??
Вложения
AVR.rar
код и протеус
(85.26 KiB) Скачиваний: 188
Ответить