Перейти к содержанию

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


pavelm-ks

Рекомендуемые сообщения

Добрый день!

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

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

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

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

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

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

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

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

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

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

Спасибо!

 

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Литиевые аккумуляторы EVE Energy и решения для управления перезаряжаемыми источниками тока (материалы вебинара)

Опубликованы материалы вебинара Компэл, посвященного литиевым аккумуляторам EVE Energy и решениям для управления перезаряжаемыми источниками тока.

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

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

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

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

28.04.2021 в 00:49, pavelm-ks сказал:

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

On 4/27/2021 at 10:49 PM, pavelm-ks said:

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

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

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

 

Ссылка на комментарий
Поделиться на другие сайты

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

Ссылка на комментарий
Поделиться на другие сайты

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

 

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)
      {   
   
      }
}

 

 

Изменено пользователем pavelm-ks
Ссылка на комментарий
Поделиться на другие сайты

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

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

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

 

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

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

шта эта ?

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

 

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

5 часов назад, ruhi сказал:

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

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

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

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

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

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

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

 

Ссылка на комментарий
Поделиться на другие сайты

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. Так будет правильнее с точки зрения программы. Переменная будет модифицироваться там, где и используется.

Ссылка на комментарий
Поделиться на другие сайты

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

Изменено пользователем pavelm-ks
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...