Jump to content
pavelm-ks

Прошу помощи с прерываниями Attiny13!

Recommended Posts

Добрый день!

Пишу элементарную ( казалось бы) прогу в Codevision 3.12- делитель на 4  входяших импульсов для автомобильного спидометра (надо адаптировать импульсы под блок круиз контроля).

Все как обычно , прерывание по таймеру для счетчика длит импульсов, входящий сигнал- внешнее  прерывание по нисходящему фронту .

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

В том же прерывании по полученному таймеру длит импульсов дергаю Port.0 - путем инвертирования значения.  

Но уже неделю не могу победить глюки, которые возникают из-за того (как я уже выснил) , что при совпадении внешнего прерывания с обработкой (обнулением или переприсваиванием) переменной  длит. периода эта переменная (двубайтовая кстати) становится в ракообразное состояние (прерывание не дает завершить операцию с этой переменной корректно) в итоге имею или пропуски импульсов или множественне импульсы больше чем надо в пределах одного периода входящего сигнала - следующее прерывание все нормализует. Отчасти полечил путем переприсваивания этой переменной в внешем прерывании  , но тогда пляшет длительность импульсов ,что тоже не хорошо . 

1 )Вот хочу спросить , какого хера внешнее прерывание приводит к некорректным вычислениям? Это не может быть глюк самого компилятора ?

2 )Или это стандарный прикол при работе с двубайтовыми переменными и внешним прерыванием ? 

3) Запретить прерывания на время работы с переменной не могу т.к. тогда появляются пропуски прерываний и плывет значение периода входящего сигнала при таком совпадении, что тоже сказывается на выходном сигнале .

4) Разве логика компиллера вообще не должна выстраивать некую очередь прерываний по типу - ага, вижу внешнее прервыние, ставлю его в очередь , заканчиваю текущую операцию с двубайтовой переменной и тогда отрабатываю прерывание, ага вижу прерывание по таймеру , заканчиваю с внешним прерыванием (отрабатываю его до конца) и бегу отрабатывать прерывание по таймеру?

Раньше писал достаточно сложные проги в CVAVR v 2.02 и как-то вообще не сталкивался с подобными проблемами, но на нем лицензия гавкнулась. Может это быть проблема компиллятора (CVAVR v 3.12) ? Может в новой версии просто  что-то настроить надо?

Спасибо!

 

Share this post


Link to post
Share on other sites

Программу не видно. Целиком.


Я не раздаю удочки. Я продаю рыбу.

Share this post


Link to post
Share on other sites
6 часов назад, pavelm-ks сказал:

Разве логика компиллера вообще не должна выстраивать некую очередь прерываний по типу - ага, вижу внешнее прервыние, ставлю его в очередь , заканчиваю текущую операцию с двубайтовой переменной и тогда отрабатываю прерывание,

с какого перепугу?

6 часов назад, pavelm-ks сказал:

Или это стандарный прикол при работе с двубайтовыми переменными и внешним прерыванием ? 

атомарный доступ.... не слышали? спросите у гугля он о нем знает...

Share this post


Link to post
Share on other sites

Приглашаем на вебинар «Экономичные решения МЕAN WELL для надежных разработок» (30.09.2021)

Компания Компэл приглашает 30 сентября на вебинар посвященный экономичным решениям МЕAN WELL. На вебинаре мы рассмотрим, как решения MEAN WELL позволяют сэкономить при выборе недорогого источника питания. Будут представлены основные группы источников питания по конструктивным признакам и по областям применения в контексте их стоимости или их особенностей, позволяющих снизить затраты на электропитание конечного устройства.
Подробнее

11 часов назад, pavelm-ks сказал:

Все как обычно , прерывание по таймеру для счетчика длит импульсов,

А кто вам сказал что это как обычно? Где вы видели что кто то так делал без операционной системы и успешно?

А вообще для компилятора прерывание это просто функция (ну может с парой спец атрибутов), а о том чтобы ее вызов не портил переменные фоновой программы или переменные другой функции-прерывания это исключительно ваша проблема, в стандарте С/С++ нет такого понятия "прерывания" поэтому для компилятора это просто функция с некоторыми дополнительными спец атрибутами по генерации пролога и эпилогов.


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites

Модульные RJ-соединители KLS — масштабное пополнение склада Компэл

Продуктовая линейка компании KLS на складе Компэл пополнилась модульными соединителями типа RJ. Ассортимент представлен неэкранированными соединителями RJ11, RJ12 и RJ45 для построения базовых информационных сетей, а также экранированными RJ45 с трансформатором для реализации систем передачи данных между узлами ЛВС.

Подробнее

36 минут назад, ruhi сказал:

А кто вам сказал что это как обычно? Где вы видели что кто то так делал без операционной системы и успешно?

А вообще для компилятора прерывание это просто функция (ну может с парой спец атрибутов), а о том чтобы ее вызов не портил переменные фоновой программы или переменные другой функции-прерывания это исключительно ваша проблема, в стандарте С/С++ нет такого понятия "прерывания" поэтому для компилятора это просто функция с некоторыми дополнительными спец атрибутами по генерации пролога и эпилогов.

Печаль , я то могу сделать чтобы не портил (запретить внешнее прерывание на время вычисления) , но тогда идут пропуски внешних прерываний , прога не ставит его в очередь , с тупо игнорит. 

Читал про флаги всякие , можно как-то на время вычисления запрещать внешнее прерывание , но взводить некий флаг когда было событие требуещее вызова прерывания , чтобы после снятия запрета оно отработалось ? Есть какие-то регистры для этого ?

Share this post


Link to post
Share on other sites

Вебинар «Microchip и современный подход к искусственному интеллекту. Разворачиваем нейронную сеть на 32-битном микроконтроллере» (13.10.2021)

Приглашаем всех желающих 13 октября 2021 г. посетить вебинар, посвященный искусственному интеллекту, машинному обучению и решениям для их реализации от Microchip. Современные среды для глубинного обучения нейронных сетей позволяют без детального изучения предмета развернуть искусственную нейронную сеть (ANN) не только на производительных микропроцессорах и ПЛИС, но и на 32-битных микроконтроллерах. А благодаря широкому портфолио Microchip, включающему в себя диапазон компонентов от микроконтроллеров и датчиков до ПЛИС, средств скоростной передачи и хранения информации, возможно решить весь спектр задач, возникающий при обучении, верификации и развёртывании модели ANN.
Подробнее

21 минуту назад, pavelm-ks сказал:

Печаль , я то могу сделать чтобы не портил (запретить внешнее прерывание на время вычисления) , но тогда идут пропуски внешних прерываний

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

Если флаг прерывания не сброшен, то процессор будет вызывать обработчик прерывания постоянно.
О каких других флагах вы говорите?

Share this post


Link to post
Share on other sites

Копаю просторы , и все больше склоняюсь к тому , что какой-то глючный компилятор у меня . Атомарные операции и т.п. все интересно , но не работает . Для теста переделал все на однобайтовые переменные и глюки никуда не ушли . Плюс читаю статейку , где пишут ровно как я и считал - что проц получив прерывание завершает текущую операцию и только потом переходит к обработчику прерывания и что пока не закончит его другие не обрабатывает , а получив в процессе другое прерывание просто взводит флаг , заканчивает текущее и только потом переходит к взвешенному .  А у меня получается, что во время обработки прерывания по таймеру проц спокойно себе не закончив дело улетает посреди обработчика по таймеру на обработку внешнего прерывания. Т.к. переменная , которая слетает фигурирует только в прерывании по таймеру , плюс слетает даже однобайтовая переменная . Видимо прерывание по таймеру, которое возникает посреди внешнего его тоже прерывает. В итоге полная хрень которой раньше не было . Вот только незадача найти другой ломанный релиз кодевижена сейчас проблема. Или вот этот глючный или с просроченными лицензиями .  

Share this post


Link to post
Share on other sites

Блин , таки нет , нашел старый ноут , откомпилил , та же беда 

Share this post


Link to post
Share on other sites
6 часов назад, pavelm-ks сказал:

А у меня получается, что во время обработки прерывания по таймеру проц спокойно себе не закончив дело улетает посреди обработчика по таймеру на обработку внешнего прерывания.

Причём тут компилятор ? Такое физически невозможно :wacko: Конечно, если нагло и тупо не разрешить прерывания, не дав доработать обработку другого.

Вы бы не статейки всяческие читали, а изучали контроллеры изнутри.

Share this post


Link to post
Share on other sites
10 часов назад, pavelm-ks сказал:

и все больше склоняюсь к тому , что какой-то глючный компилятор у меня

то что вы придумали не соответствует действительности, ну и получается что вы ищете то чего нет с очевидным результатом.

Забудьте свою стройную красивую теорию и начинайте изучать то что имеет отношение к практике: стек для переменных, регистры, волотильные переменные, векторы/таблица/приоритеты прерываний, флаги разрешения прерываний, флаги запроса прерываний, ... вообще с ассемблером не мешает познакомится если вы действительно хотите что то понимать про прерывания.

18 часов назад, pavelm-ks сказал:

можно как-то на время вычисления запрещать внешнее прерывание

Кстати, я не думаю что в вашем контексте надо различать внешние прерывания от внутренних прерываний, насколько я вижу из ваших обрывочных пояснений для вашей программы нет разницы пришло прерывание от внутреннего таймера или с внешней линии- с ноги контроллера. Попытайтесь хоть что то понять не с позиции того как это ПО ВАШЕМУ должно работать, а с позиции того как вам это излагают-обосновывают.


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
28.04.2021 в 00:49, pavelm-ks сказал:

Разве логика компиллера вообще не должна выстраивать некую очередь прерываний по типу - ага, вижу внешнее прервыние, ставлю его в очередь

Создайте очередь программно

Прерывание по таймеру работает с переменной 1 (или переменными). Внешнее Прерывание работает с переменной 2. По окончанию обработки прерывания по таймеру проверьте переменную 2 и обработайте. Как то так...

Share this post


Link to post
Share on other sites
14 часов назад, pavelm-ks сказал:

Для теста переделал все на однобайтовые переменные и глюки никуда не ушли . 

На си пишете? Вы считаете, что одна команда на си равна одной машинной команде? Это заблуждение.

Вам правильно рекомендуют - не статейки читайте, а начните с азов.

Цифровая логика, машина состояний, самые простые процессоры. Тот же 8080 - отличное начало, чтобы понять как оно в процессоре устроено. Как работают прерывания и т.д.
После этого можно переходить к изучению того, как оно было сделано на заре персональных компьютеров. Тут надо изучать 8086 - всю серию микросхем. Придет понимание работы ДМА.

После этого не будут пугать ни АВР микроконтроллеры, ни АРМ. Оно всё примерно по одному принципу функционирует

Share this post


Link to post
Share on other sites
On 4/27/2021 at 10:49 PM, pavelm-ks said:

Запретить прерывания

Ради любопыства заглянул в мануал Attiny13. И шо вы думаете, в первых же строчках мануала про прерывания написано, что "при возникновении прерывания тут же автоматически сбрасывается Глобальное Разрешение Прерываний". Процессор переходит в обработчик прерывания и спокойно всё там делает, никакие другие прерывания его не волнуют, т.к. они запрещены. По выходу из обработчика это самое Глобальное Разрешение Прерываний автоматически восстанавливается. Всё это уже делается железом, программе не надо беспокоиться о вложенных прерываниях.

По ходу у ТС что-то в программе намудрено, без кода сложно понять в чём проблема.

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

:lol2::rake::lol2:  тут по ушам ездил, что прерывания запрещать низя, аоновонакак софтдетект форева

Share this post


Link to post
Share on other sites
Posted (edited)

глючный код вот :

 

Chip type               : ATtiny13
AVR Core Clock frequency: 9,600000 MHz
Memory model            : Tiny
External RAM size       : 0
Data Stack size         : 16
*****************************************************/

#include <tiny13.h>


volatile unsigned char mlpr=0; 
volatile unsigned int intimer=0, fmultiplied=0,fmultcounter=0;

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
fmultiplied=intimer>>mlpr;   //расчитываем таймер для дергания выхода  ( напрмер сдвиг на 3 (делим на 8 чтобы полчить чатоту в 4 раза выше) просто делить то можно выспаться пока AVR закончит деление)
intimer=0;  //обнуляем таймер входго сигнала  

}

// Timer !!!!!!!!!0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0xC0; //уствовка начального значения таймера для умеличения чатоты прерываний таймера

intimer++;  //интременируем таймер длительности периода вход сигнала
fmultcounter++; // инкременируем счетчик таймера выходного сигнала
  if(fmultcounter>fmultiplied)    //проверяем условие периода для дергания ногой выхода
    {
     fmultcounter=0;// обнуляем таймер выходного сигнала
     PORTB.0=~PORTB.0; //инвертируем выход
    }; 

#asm("wdr")  //сброс собаки
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0xA0;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Function: Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out 
DDRB=(0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0);
// State: Bit5=P Bit4=P Bit3=P Bit2=P Bit1=P Bit0=0 
PORTB=(1<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (1<<PORTB2) | (1<<PORTB1) | (0<<PORTB0);


// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9600,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 0,026667 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (1<<TOIE0);

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=(1<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC01) | (0<<ISC00);
GIFR=(1<<INTF0) | (0<<PCIF);

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR0=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/64k
// Watchdog Timer interrupt: Off
#pragma optsize-
WDTCR=0x1D;
WDTCR=0x0D;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Global enable interrupts
#asm("sei")
if (PINB.4==0 & PINB.3==0 ){mlpr=3;}; //начальная установка множителя
if (PINB.4==1 & PINB.3==0 ){mlpr=2;}; //начальная установка множителя
if (PINB.4==1 & PINB.3==1 ){mlpr=4;}; //начальная установка множителя
if (PINB.4==0 & PINB.3==1 ){mlpr=2;}; //начальная установка множителя

while (1)
      {   
        
      }
}


Результат  - вот такие периодические срывы (вход синий выход желтый):

image.png.742b8cbdcb6960c08ab18fa5ad2501f6.png

 

Безглючный, но менее точный код вот  (никаких срывов и пропусков при сумуляции не наблюдается):

 

Chip type               : ATtiny13A
AVR Core Clock frequency: 9,600000 MHz
Memory model            : Tiny
External RAM size       : 0
Data Stack size         : 16
*******************************************************/

#include <tiny13a.h>

 
 volatile unsigned char mlpr=0,x=0,y=0;//stoper=0; 
 volatile unsigned int intimer=0, fmultiplied=0,fmultcounter=0;

  
 // Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x20;
               intimer++;
fmultcounter++;
          if (PINB.1==1)  // проверяем вход 
              { 
              x=1;   //запоминаем состояние для хай левел 
              } else {x=0;};  //запоминаем состояние для лоу
              if (x==0&y==1) // сравниваем предыдущее состояние и новое
              { 
                             fmultiplied=intimer>>mlpr; //расчет таймера выходного сигнала если имеет место нисходящий фронт 
               intimer=0; // обнуляем таймер входящего сигнала
              };    
              y=x;  //присваиваем переменной старого состояния текущее
              
               if(fmultcounter>fmultiplied&fmultiplied>1&fmultiplied<(64<<mlpr)) //fmultiplied<(64<<mlpr) - заглушка, чтобы не было генерации при отсутствии сигнала на входе 
                  {
                   fmultcounter=0;
                    PORTB.0=~PORTB.0;    
                    };     
               
             #asm("wdr")
      
    }

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Function: Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out 
DDRB=(0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0);
// State: Bit5=P Bit4=P Bit3=P Bit2=P Bit1=P Bit0=1 
PORTB=(1<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (1<<PORTB2) | (1<<PORTB1) | (1<<PORTB0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9600,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 0,026667 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
         /*
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1200,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 0,21333 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
     */
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (1<<TOIE0);

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=(0<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC01) | (0<<ISC00);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIS1) | (0<<ACIS0);
ADCSRB=(0<<ACME);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR0=(0<<AIN0D) | (0<<AIN1D);

// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);


// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/32k
// Watchdog timeout action: Reset
#pragma optsize-
WDTCR=(0<<WDTIF) | (0<<WDTIE) | (0<<WDP3) | (1<<WDCE) | (1<<WDE) | (1<<WDP2) | (0<<WDP1) | (0<<WDP0);
WDTCR=(0<<WDTIF) | (0<<WDTIE) | (0<<WDP3) | (0<<WDCE) | (1<<WDE) | (1<<WDP2) | (0<<WDP1) | (0<<WDP0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Global enable interrupts
#asm("sei")
if (PINB.4==0 & PINB.3==0 ){mlpr=3;};  //делитель на 4
if (PINB.4==1 & PINB.3==0 ){mlpr=2;};  //делитель на 2 
if (PINB.4==1 & PINB.3==1 ){mlpr=4;}; //делитель на 8
if (PINB.4==0 & PINB.3==1 ){mlpr=2;}; //делитель на 2 

while (1)
      {   
   
      }
}

 

 

Edited by pavelm-ks

Share this post


Link to post
Share on other sites
24 минуты назад, pavelm-ks сказал:

 fmultiplied=intimer>>mlpr; //расчет таймера выходного сигнала если имеет место нисходящий фронт 

вы хотя бы теоретически представляете во что компилятор разворачивает эту конструкцию?

 

25 минут назад, pavelm-ks сказал:

if (PINB.4==0 & PINB.3==0 ){mlpr=3;};  //делитель на 4

шта эта ?

Share this post


Link to post
Share on other sites
22 минуты назад, pavelm-ks сказал:

Результат  - вот такие периодические срывы (вход синий выход желтый):

Так вы хотите частоту выходного меандра сделать в 4 раза выше чем у входного? А как у вас обрабатывается ситуация когда следующий период короче предыдущего? Вы же поделить можете только на основании значения длительности полученной из предыдущего периода, и если следующий меньше вы вылетаете за его пределы, и как вы эту ситуацию обрабатываете? в чем идея? Она вообще есть эта идея?

Что толку в коде если у автора нет понимания того какой метод обработки событий и параметров он хочет реализовать? Если у автора нет идеи которую он хочет реализовать!

31 минуту назад, pavelm-ks сказал:

if(fmultcounter>fmultiplied&fmultiplied>1&fmultiplied<(64<<mlpr))

и тут тоже прикольно. Да уж какие нафик идеи, очем это я...


Можно сделать все! Но чем больше можно, тем больше нельзя!

Share this post


Link to post
Share on other sites
Posted (edited)

@pavelm-ks  У вас происходит двойное срабатывание на ниспадающем фронте внешнего импульса. Даже на картинке это заметно, что фронт дребезжит. Поэтому второе прерывание наступает сразу же вслед за первым, переменная intimer уже = 0, поэтому fmultiplied тоже = 0 , и получается сумашедшая частота на выходе. Следующий внешний фронт нормальный и исправляет неправильное вычисление для fmultiplied.

Надо просто проверять во внешнем прерывании величину intimer. Если intimer меньше какой-то величины, то просто игнорировать вычисление для fmultiplied.

Edited by Yurkin2015

Share this post


Link to post
Share on other sites

 

3 часа назад, Yurkin2015 сказал:

@pavelm-ks  У вас происходит двойное срабатывание на ниспадающем фронте внешнего импульса. Даже на картинке это заметно, что фронт дребезжит. Поэтому второе прерывание наступает сразу же вслед за первым

Надо просто проверять во внешнем прерывании величину intimer. Если intimer меньше какой-то величины, то просто игнорировать вычисление для fmultiplied.

Так, интересно , это же симуляция протеуса, как тут может быть дребезг ? Обычный ниспадающий фронт ,  да, он не мгновенно ниспадает , но дребезга точно нет.

Была такая идея , но ума не приложу почему тут может дважды срабатывать прерывание ведь оно настроено именно на ниспадающий фронт? Как видно на осциллограмме срыв происходит при очень точном совпадении прерываний поэтому думаю что причина в последовательности обработки прерываний.

Share this post


Link to post
Share on other sites
5 часов назад, ruhi сказал:

 в чем идея? Она вообще есть эта идея?

Что толку в коде если у автора нет понимания того какой метод обработки событий и параметров он хочет реализовать? Если у автора нет идеи которую он хочет реализовать!

и тут тоже прикольно. Да уж какие нафик идеи, очем это я...

Любят тут посылать почитать - хотите знать идею - почитайте мой первый пост там все сказано в первом предложении

if(fmultcounter>fmultiplied&fmultiplied>1&fmultiplied<(64<<mlpr))  снова лень читать , спрашивается зачем писать если лень читать ? - описание дано в коментах к коду может с небольшими очепятками, fmultiplied>1&fmultiplied<(64<<mlpr))   это заглушка краевых условий, чтобы не было генерации импульсов на выходе при отсутствующем нуле. Коэфициент деления зависит от комбинации 0 и 1 на выводах 3 4 (при загрузке идет инициализация коэф. деления  путем присвоения переменной mlpr  значения сдвига ). Чтобы нижний край диапазона частот входящих импульсов   был одинаковый во всех режимах используется вот эта структура 64<<mlpr.

Короче, не хотел давать код  т.к. занал, что начнут разводить сопли по стекловате, умничать , понадобится 100500 объяснений  и таки был прав.

Все тему закрываем!

 

Share this post


Link to post
Share on other sites
6 часов назад, pavelm-ks сказал:

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
fmultiplied=intimer>>mlpr;   //расчитываем таймер для дергания выхода  ( напрмер сдвиг на 3 (делим на 8 чтобы полчить чатоту в 4 раза выше) просто делить то можно выспаться пока AVR закончит деление)
intimer=0;  //обнуляем таймер входго сигнала  

}

// Timer !!!!!!!!!0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0xC0; //уствовка начального значения таймера для умеличения чатоты прерываний таймера

intimer++;  //интременируем таймер длительности периода вход сигнала
fmultcounter++; // инкременируем счетчик таймера выходного сигнала
  if(fmultcounter>fmultiplied)    //проверяем условие периода для дергания ногой выхода
    {
     fmultcounter=0;// обнуляем таймер выходного сигнала
     PORTB.0=~PORTB.0; //инвертируем выход
    }; 

#asm("wdr")  //сброс собаки
}

Сделайте модификацию значения fmultiplied в прерывании таймера, и строго после прохождения очередного периода выходного сигнала.
А на внешнем прерывании оставьте только подсчёт периода входного сигнала.

1. Так будет правильнее с точки зрения логики работы устройства. Значение следующего периода будет обновляться после прохождения текущего.
2. Так будет правильнее с точки зрения программы. Переменная будет модифицироваться там, где и используется.

Share this post


Link to post
Share on other sites

Ещё необходимо будет добавить условие по большому значению переменной fmultcounter. Это если сигнал будет отсутствоать, либо будет слишком низкая входная частота.

Share this post


Link to post
Share on other sites
11 часов назад, pavelm-ks сказал:

Короче, не хотел давать код  т.к. занал, что начнут разводить сопли по стекловате, умничать , понадобится 100500 объяснений  и таки был прав.

Вам прямо говорят, что вы совершенно не понимаете как работает язык си, как работает процессор. И предлагают не "почитать", а изучить предмет.

Вы хотя-бы понимаете разницу между & и && ?

Да, в некоторых случаях, & будет работать как &&. Но далеко не всегда.
Код у вас мутный. Вы это понимаете, потому и не хотели выкладывать его.

Не стыдно не знать, стыдно не учиться.

Share this post


Link to post
Share on other sites
Posted (edited)
18 часов назад, Alex сказал:

Сделайте модификацию значения fmultiplied в прерывании таймера, и строго после прохождения очередного периода выходного сигнала.
А на внешнем прерывании оставьте только подсчёт периода входного сигнала.

1. Так будет правильнее с точки зрения логики работы устройства. Значение следующего периода будет обновляться после прохождения текущего.
2. Так будет правильнее с точки зрения программы. Переменная будет модифицироваться там, где и используется.

сделал вот так:

volatile unsigned char mlpr=0, x=0; 
volatile unsigned int intimer=0, fmultiplied=0,fmultcounter=0,timer=0;

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
timer=intimer;   //присваиваем значение длительности периода входного сигнала другой переменной, чтобы можно было использовать в любом месте кода в любое время 
intimer=0;  //обнуляем таймер входного сигнала  
}

// Timer !!!!!!!!!0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0xC0;                            //установка начального значения таймера для увеличения частоты прерываний таймера

intimer++;                                    //инкрементируем таймер длительности периода вход сигнала
fmultcounter++;                           // инкрементируем счетчик таймера выходного сигнала
  if(fmultcounter>fmultiplied)    //проверяем условие четвертьпериода для дергания ногой выхода
    {
     x++;                                          //считаем кол-во четверть периодов
     fmultcounter=0;                     // обнуляем таймер выходного сигнала
     PORTB.0=~PORTB.0;             //инвертируем выход  
     if (x==8){fmultiplied=timer>>mlpr;x=0;}; // проверка условия прохождения полного периода выходного сигнала (8 четвертьпериодов) , если да - расчет таймера четвертьпериода , обнуляем счетчик четвертьпериодов.
    }; 

#asm("wdr")  //сброс собаки
}

 

получил такой результат :(

image.png.47dce7a83dffe62b0aeffd9d15e3ccc6.png

Edited by pavelm-ks

Share this post


Link to post
Share on other sites

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...

  • Сообщения

    • пересмотрел внимательней, пп в лайке делайте? Если набросаю Вам пригодиться?
    • Лучше накопите денежек и купите станцию с отсосом. С такими вопросами соседи лишатся квартиры. Будете всю жизнь отрабатывать.
    • По мне это недоработка программы. Это придется теперь рисовать 4 полигона, чтобы обогнуть нужную область... Благодарю за ответ.
    • Во это я вчера на мурлыкался. 
    • Мечта любого радиолюбителя сделать удобный инструмент для демонтажа. У меня есть идея такая, не знаю насколько она будет хорошей, сделать паяльник с оловоотсосом.. Да, такие существуют, но скажем так, качеством вакуума они мало радуют, тем более нужно постоянно возводить поршень, и т.п. И вот я задумался, а чтобы не сделать самому паяльник-оловоотсос. Допустим есть вакуумный насос, который выкачивает воздух в балоне, при нажатии на клапан, воздух всасывается. Для жала я выбрал стальную трубку 5мм. Корпус (ручка) дерево. Так как я раньше паяльники не мотал, подскажите пожалуйста люди с опытом, сколько выдерживает дерево нагрев? Ведь жало будет нагреваться до 300 градусов и выше. Второй вопрос. Как подобрать толщину и длину нихромовой проволоки? Эксперементальным путём? Третье, видел что мотают нихромовую проволоку на какую-то слюду или стекловолоконную ткань. На что мотать лучше? Ну и последнее, что бы трубка для насоса не расплавилась если надеть на жало, то в корпусе паяльника, есть разрыв. Но там скорее всего будет скапливаться припой, есть ли какие-то идеи чтобы заполнить этот разрыв? Боюсь стеклянная трубка треснет от жала 300 градусов. Ну и конечно, хорошо бы чтобы припой не приставал к жалу и жало не деградировало, я выбрал стальную трубку, может алюминиевая трубка лучше, как вы думаете?
    • R2 - 119.2К,  C2 - оказался м33р (32pf), и в пакетике, подписанном 20pf - все такие, продавец ладно, а вот я при монтаже прошляпил. Зато появился подозреваемый. Сегодня скорее всего не успею с экспериментами.  Звуковая карта, пока без регулятора громкости, то есть програмный win7.
    • Вот и займите нишу, конкурентов то нет. Сам покупаю б.у неисправное за копейки и ремонтирую. В вашем случае - при неисправности самого драйвера(выгорании платы), ставлю диодные ленты на 12V. Приходиться правда одну матовую плёнку убирать и иногда добавлять интегральный стабилизатор на 12V типа 78L12 на 1А. Но вы, судя по вопросам - сам клиент сервиса. Требуется лишь добавить кнопочку за 15 руб, т.к. ключ доб. лень. Мониторы все с разбора за копейки. Если матрица целая - ремонт рентабелен. Сделано порядка 6 шт. Можно наверное и мощнее ленты и ярче поставить, просто это самая дешёвая. А ремонт копеечный.  Есть уже и пара тв с подобной темой. Но там надо ленты рассчитывать, 12V там не пройдёт. И ток другой. В тв и матрицу снять нельзя с перепугу. Опыт обязателен. Сам тренировался на сломанных тв с сломанной матрицей.
×
×
  • Create New...