Jump to content
Sign in to follow this  
forestdozor

Некорректно работает режим захвата таймера в Atmega 328

Recommended Posts

Здравствуйте!

Мне нужно измерить длительность импульса. Для этого сначала применял внешнее прерывание, а теперь перешел на режим захвата таймера в Atmega 328.
Однако сейчас происходит странное: Через определенное таймер просто останавливается. Гугл результатов не дает, ни у кого захват таймера 1 не останавливается.

Подскажите пожалуйста, что делать?

Среда разработки CodeVisionAVR v3.12. Сейчас попробовал версию 3.3, толку нет. Не работает. Код максимально упростил, но по прежнему толку ноль.

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

Может немножко подождать, и увеличить значение счетчика current_timp еще на пару значений... Совсем не знаю что делать.
 

 

interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{

TCNT1H = 0x00;
TCNT1L = 0x00;

}

// Timer1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
 
       TCNT1H = 0x00;
       TCNT1L = 0x00;           // Это уже уровень танцев с бубном "авось поможет" - не помогает.
   
        current_timp++;          // Все упрощено до максимума. Мне бы он хоть количество периодов для начала...
        
  //  }

}

// Прерывание по переполнению первого таймера
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Обнуление счетного регистра.
TCNT0=0x00;

    
    counter ++;
    if (counter > 10)
    {
            lcd_clear();
            sprintf(buffer,"%d us", current_timp);
            lcd_gotoxy(0,0);
            lcd_puts(buffer);
            counter = 0;
    }
    
    

}


// Главный цикл программы
void main(void)
{


#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif


// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit6=In Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRC=(0<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
// State: Bit6=T Bit5=1 Bit4=1 Bit3=1 Bit2=1 Bit1=1 Bit0=1
PORTC=(0<<PORTC6) | (1<<PORTC5) | (1<<PORTC4) | (1<<PORTC3) | (1<<PORTC2) | (1<<PORTC1) | (1<<PORTC0);

// Port D initialization
// Function: Bit7=Out Bit6=Out Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(1<<DDD7) | (1<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=1 Bit6=1 Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(1<<PORTD7) | (1<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Делители таймера 0 рассчитаны таким образом , что его тактовая частота = 15,625 КГц. Расчет был на применение в схеме семисегментников, но с LCD индикатором будет информативнее.
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (1<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

 

// Настройка таймера 1

TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(1<<ICNC1) | (1<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Разрешение прерывания по переполнению таймера 0
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (1<<TOIE0);

// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=(1<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (1<<TOIE1);

Edited by forestdozor

Share this post


Link to post
Share on other sites
18 минут назад, forestdozor сказал:

interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{

TCNT1H = 0x00;
TCNT1L = 0x00;

}

// Timer1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
 
       TCNT1H = 0x00;
       TCNT1L = 0x00;           // Это уже уровень танцев с бубном "авось поможет" - не помогает.
   
        current_timp++;          // Все упрощено до максимума. Мне бы он хоть количество периодов для начала...
        
  //  }

}

на timer1 два прерывания?

оставь только

interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{

// твой код

}

Share this post


Link to post
Share on other sites

Да, два прерывания. Подразумевается, что в обработчике переполнений будет счетчик кол-ва переполнений.
В коде я планировал считывать значение таймера в момент переднего фронта, кол-во переполнений между передним фронтом и спадом, и значение таймера в момент спада.
Вычесть разницу между фронтами и умножить количество переполнений между передним и задним фронтом на 2^16.

Отключил в TIMSK1 прерывание по переполнению. Не помогло :(

Share this post


Link to post
Share on other sites

Приглашаем на вебинар «Новинки и уникальные решения Molex. На что обратить внимание и почему»

15 апреля приглашаем на вебинар, который будет интересен разработчикам и инженерам-схемотехникам, интересующимся тенденциями рынка, новыми перспективными решениями для соединений «провод-провод», «провод-плата», «плата-плата». Для инженеров КИПиА и IT будут освещены уникальные решения Molex для «удлинения» интерфейсов HDMI, DisplayPort и USB даже в условиях сильного зашумления, а также семейство бесконтактных датчиков Contrinex. Помимо этого, будет уделено внимание дальнейшему развитию направления антенн, где Molex имеет ряд интересных и уникальных решений.

Подробнее

Для начала перенесите индикацию из прерывания в основной цикл.

Share this post


Link to post
Share on other sites

Как минимум, не определен источник триггера захвата и нет работы с битом ICESn (в начале прерывания по захвату его значение необходимо менять на противоположное, чтобы получать следующее прерывание по другому фронту измеряемого импульса), иначе Вы будете измерять не длительность импульса, а период между импульсами.

Share this post


Link to post
Share on other sites
                     

Как снизить потери при включении силового ключа: простая схема управления скоростью нарастания

Снижение потерь на переключения в силовых электронных системах, например, в приводах, зачастую противоречит требованиям ЭМС и ограничивается таким параметром как скорость нарастания напряжения. Простой способ решения, предлагаемый Infineon – параллельное использование двух традиционных драйверов.

Читать статью

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Similar Content

    • Guest Роман
      By Guest Роман
      Добрый день, форумчане. Такая задача. Хочу создать несколько устройств на светодиодах. Задача каждого в том, чтобы от движения (датчик вибрации, наклона) светодиод начинал моргать, переливаться и т.д. Подпитывается всё от батарейки, конечно же как можно меньших размеров (таблетка).
      Собственно я уже реализовал такое пробное устройство на ATtiny13, вибродатчике 18015 и батарейке CR1220. Всё работает, но хотелось бы это дело и удешевить и уменьшить в размерах, если это конечно же возможно. Особо в параметрах МК я не разбираюсь, но могу сказать что мне от неё точно нужно:
      1) Маленький размер
      2) Как минимум 1 канал ШИМ (а лучше 3, для переливания трёх светодиодов RGB)
      3) Память на 1Кб (программу для одного такого устройства приложу ниже, может её можно и сократить, но не факт что такую же, но на три диода получится ужать)
      4) Низкое потребление или возможность подключения режимов с низким потреблением.
      5) Работа от 3В. (от таблетки)
      6) Возможность программирования через Arduino UNO (но другие варианты тоже рассматриваю, просто Arduino уже есть)

      Повторюсь пока что нашел и использовал только ATtiny13, который меня вполне устроил, но он достаточно дорогой и в корпусе SOIC его найти достаточно проблематично. К тому же как мне показалось, он слишком хорош для такого проекта. Повторюсь, я чайник, и может есть какие-то более дешевые аналоги.

      Очень надеюсь на Вашу помощь. Заранее большое Вам спасибо!
      Прикладываю обещанный мною код:
      int vib = 4; int led = 0; long loopTime = 5000; void setup() { pinMode(led, OUTPUT); pinMode(vib, INPUT); } void loop() { if (digitalRead(vib)){ unsigned long currentMillis = millis(); while(millis()-currentMillis<=loopTime) { for(int fadeValue = 0; fadeValue <=255; fadeValue+=5){ analogWrite(led,fadeValue); delay(2); } for(int fadeValue = 255; fadeValue >=0; fadeValue-=5){ analogWrite(led,fadeValue); delay(2); } for(int fadeValue = 0; fadeValue <=255; fadeValue+=5){ analogWrite(led,fadeValue); delay(2); } for(int fadeValue = 255; fadeValue >=0; fadeValue-=5){ analogWrite(led,fadeValue); delay(2); } digitalWrite(led, LOW); delay(600); } } }  
    • By Evgeniy90
      Здравствуйте! Столкнулся со следующей проблемой: при сборке МД "Шанс" дошел до этапа прошивки МК, в итоге запорол 3 атмеги. Прошивал 3 способами:
      1. Через Arduino UNO(As ISP) просто МК
      2. Через Arduino UNO(As ISP) МК внутрисхемно(соответственно с обвязкой)
      3. Через USB ASP внутрисхемно(с обвязкой соответственно).
      Вышло так, что в наличии кварца 11.0592 МГц не было, и я временно впаял 12 МГц. Прошил трижды всё правильно(фьюзы , контакты и т.д). После прошивки просто не видит МК (ну и плата не работает без МК.да и Бог с ней, но МК всеравно не могу считать). В чем причина понять не могу. Одно думаю, что это разница между 11.0592 и 12 МГц. Посоветуйте как решить проблему.
      Коды ошибок после прошивки во всех трёх случаях одинаковые:
      Sinaprog -invalid device signature
      Averdude -avrdude: warning: cannot set sck period, please check for usbasp firmware update
      target don't answer
    • By Engineerr
      Кто использует microPascal for AVR? 
      Полезные ссылки, программы, примеры.
    • By Sova
      Добрый день. Опять ATMega, опять таймер 1, вопрос рутинный, но я за сегодня уже извёлся. Что я хотел сделать: МК должен рассчитывать положения моторов (SG90, регулируются временем импульса), включать их все вместе по совпадению таймера 2, затем рассчитывать, когда какой мотор надо отключить, получившийся список сортировать и ставить таймер 1. Таймер 1 сработал - выключили мотор, переставили таймер 1 на подальше. Снова сработал - снова что-то там сделали, увеличили OCR1A и так далее. Конечно же с первого раза не заработало и я начал упрощать и локализировать проблему.
      Получилось вот что: при срабатывании прерывания на совпадение таймера 1 с OCR1A я смотрю в отладчик - а там во-первых TIFR = OCF1A + OCF1B + TOV1, а TCNT1 равен чему угодно, но не OCR1A. Таймер как будто срабатывает не тогда. А когда я ставлю значение поменьше, допустим, OCR1A = 1000 и перехожу в пустой цикл while(1){}, то при наступлении OCR1A == 1000 просто ничего не происходит, прерывание не срабатывает. В целом так. Сейчас очень упрощённый, минимально не работающий код выглядит так:
      #define SET(_REGISTER, _BIT) _REGISTER |= 1 << _BIT #define UNSET(_REGISTER, _BIT) _REGISTER &= ~(1 << _BIT) void local_timer_setup(void) { SET(TCCR1B, CS10); //Setting timer 1 to x1 mode }; void local_timer_start(void) { TCNT1 = 0; SET(TIMSK, OCIE1A); //Allow timer 1 match A interruption }; void local_timer_off(void) { UNSET(TIMSK, OCIE1A); //Prohibit timer 1 match A interruption }; ISR(TIMER1_COMPA_vect) { PORTD = 0xFF; local_timer_off(); }; ISR(TIMER2_COMP_vect) { if (global_timer_count == 2) { global_timer_count = 0; TIFR = 0; PORTD = 0; if (current_step < 10) OCR1A = 0xFFF; else OCR1A = 0xFFFF; if (current_step == 20) current_step = 0; else current_step++; local_timer_start(); } else global_timer_count++; }; Полный код в файле. sei() не забыл. Кстати, таймер нормально выключать/включать через TIMSK, как у меня? Заранее спасибо. 
      Scarecrow_embeded.rar
    • By dron92
      Подскажите как вернуть к жизни контролер или в утиль!
      Решил собрать программатор AVRISP mkII купил микросхему собрал подключил а устройств нет в диспетчере и  Flip не видит его!
      Начал искать косяки в сборке не нашел решил спаять Отладочная плату
      тот же результат, попробовал подключить через ISP не отвечает !
      Решил пойти на крайние меры  подключил через FuseDoctor сигнатуру он не видел вел 1e9482 вроде увидел но результата сбросить не проучилось но теперь он начал видится в таком формате фото внизу




×
×
  • Create New...