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

pavelm-ks

Members
  • Постов

    73
  • Зарегистрирован

  • Посещение

Информация

  • Город
    Киев

Электроника

  • Стаж в электронике
    Не связан с электроникой

Посетители профиля

1 631 просмотр профиля

Достижения pavelm-ks

Стажер

Стажер (3/14)

  • 10 постов на форуме
  • Неделя на форуме
  • Месяц на форуме
  • Год на форуме

Последние значки

1

Репутация

  1. Так ведь можно запитать ОУ от максимального напряжения батареи (для LM 324 30вольт если не ошибаюсь для замера 4х банок лития точно хватит ). На выходе резистор на 20КОМ чтобы не перегрузить порт проца или мультиплексора ,когда вдруг на одном входе будет ноль, а на втором 14вольт. Задачка становится сложнее когда надо мерить 16 банок лития как у меня :). ОУ на такую напругу если и надешь то ценик конский . Вот думаю запитать от четверти напряжения батареи и каскадами по 4шт применять делители на 2,4,8
  2. И побеждает ......... Yurkin2015 !!!!! Причину указал верно - двойное срабатывание внешнего прерывания на одном фронте (блин часа 3 курил как в протеусе выловить это баг ) . Полечил пока одной строчкой (проверкой чтобы значение счетчика длительности периода вход сигнала было больше минимума) // External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { //counter_buffer =intimer; if (intimer>10) { fmultiplied=intimer>>mlpr ; //рассчитываем таймер для дергания выхода ( например сдвиг на 3 (делим на 8 чтобы получить частоту в 4 раза выше) просто делить то можно выспаться пока AVR закончит деление) intimer=0; //обнуляем таймер входного сигнала }; Теперь вопрос какого лешего? Происходит только именно в момент когда внешнее прерывание совпадает с прерыванием по таймеру. Как-то прерывание по таймеру не дает сбросить флаг внешнего прерывания что-ли ? Как такое может быть ? Где в протеусе где-то можно посмотреть состояние этого GICR в процессе симуляции ? С SREG все ок - в процессе обработки прерываний глобально прерывания запрещены. частота мизерная 1-500Гц.с на скрине около 80
  3. сделал вот так: 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") //сброс собаки } получил такой результат
  4. Любят тут посылать почитать - хотите знать идею - почитайте мой первый пост там все сказано в первом предложении if(fmultcounter>fmultiplied&fmultiplied>1&fmultiplied<(64<<mlpr)) снова лень читать , спрашивается зачем писать если лень читать ? - описание дано в коментах к коду может с небольшими очепятками, fmultiplied>1&fmultiplied<(64<<mlpr)) это заглушка краевых условий, чтобы не было генерации импульсов на выходе при отсутствующем нуле. Коэфициент деления зависит от комбинации 0 и 1 на выводах 3 4 (при загрузке идет инициализация коэф. деления путем присвоения переменной mlpr значения сдвига ). Чтобы нижний край диапазона частот входящих импульсов был одинаковый во всех режимах используется вот эта структура 64<<mlpr. Короче, не хотел давать код т.к. занал, что начнут разводить сопли по стекловате, умничать , понадобится 100500 объяснений и таки был прав. Все тему закрываем!
  5. Так, интересно , это же симуляция протеуса, как тут может быть дребезг ? Обычный ниспадающий фронт , да, он не мгновенно ниспадает , но дребезга точно нет. Была такая идея , но ума не приложу почему тут может дважды срабатывать прерывание ведь оно настроено именно на ниспадающий фронт? Как видно на осциллограмме срыв происходит при очень точном совпадении прерываний поэтому думаю что причина в последовательности обработки прерываний.
  6. глючный код вот : 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) { } } Результат - вот такие периодические срывы (вход синий выход желтый): Безглючный, но менее точный код вот (никаких срывов и пропусков при сумуляции не наблюдается): 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) { } }
  7. Не знаю чего такого я там мог намудрить , но победить баг тот только что получилось переносом всей логики в обработчик прывания по таймеру и софтовой детекцией периода входящего сигнала без внешнего прерывания . Конечно рабочий диапазон частоты пострадал и абсолютная точность , но для моих целей хватает .
  8. Блин , таки нет , нашел старый ноут , откомпилил , та же беда
  9. Копаю просторы , и все больше склоняюсь к тому , что какой-то глючный компилятор у меня . Атомарные операции и т.п. все интересно , но не работает . Для теста переделал все на однобайтовые переменные и глюки никуда не ушли . Плюс читаю статейку , где пишут ровно как я и считал - что проц получив прерывание завершает текущую операцию и только потом переходит к обработчику прерывания и что пока не закончит его другие не обрабатывает , а получив в процессе другое прерывание просто взводит флаг , заканчивает текущее и только потом переходит к взвешенному . А у меня получается, что во время обработки прерывания по таймеру проц спокойно себе не закончив дело улетает посреди обработчика по таймеру на обработку внешнего прерывания. Т.к. переменная , которая слетает фигурирует только в прерывании по таймеру , плюс слетает даже однобайтовая переменная . Видимо прерывание по таймеру, которое возникает посреди внешнего его тоже прерывает. В итоге полная хрень которой раньше не было . Вот только незадача найти другой ломанный релиз кодевижена сейчас проблема. Или вот этот глючный или с просроченными лицензиями .
  10. Печаль , я то могу сделать чтобы не портил (запретить внешнее прерывание на время вычисления) , но тогда идут пропуски внешних прерываний , прога не ставит его в очередь , с тупо игнорит. Читал про флаги всякие , можно как-то на время вычисления запрещать внешнее прерывание , но взводить некий флаг когда было событие требуещее вызова прерывания , чтобы после снятия запрета оно отработалось ? Есть какие-то регистры для этого ?
  11. Добрый день! Пишу элементарную ( казалось бы) прогу в Codevision 3.12- делитель на 4 входяших импульсов для автомобильного спидометра (надо адаптировать импульсы под блок круиз контроля). Все как обычно , прерывание по таймеру для счетчика длит импульсов, входящий сигнал- внешнее прерывание по нисходящему фронту . В прерывании по таймеру инкреминируется счетчик длит. периода импульсов. Во внешнем запоминаю длительность и сдвигом делю на 4 длит для импульсов делителя. В том же прерывании по полученному таймеру длит импульсов дергаю Port.0 - путем инвертирования значения. Но уже неделю не могу победить глюки, которые возникают из-за того (как я уже выснил) , что при совпадении внешнего прерывания с обработкой (обнулением или переприсваиванием) переменной длит. периода эта переменная (двубайтовая кстати) становится в ракообразное состояние (прерывание не дает завершить операцию с этой переменной корректно) в итоге имею или пропуски импульсов или множественне импульсы больше чем надо в пределах одного периода входящего сигнала - следующее прерывание все нормализует. Отчасти полечил путем переприсваивания этой переменной в внешем прерывании , но тогда пляшет длительность импульсов ,что тоже не хорошо . 1 )Вот хочу спросить , какого хера внешнее прерывание приводит к некорректным вычислениям? Это не может быть глюк самого компилятора ? 2 )Или это стандарный прикол при работе с двубайтовыми переменными и внешним прерыванием ? 3) Запретить прерывания на время работы с переменной не могу т.к. тогда появляются пропуски прерываний и плывет значение периода входящего сигнала при таком совпадении, что тоже сказывается на выходном сигнале . 4) Разве логика компиллера вообще не должна выстраивать некую очередь прерываний по типу - ага, вижу внешнее прервыние, ставлю его в очередь , заканчиваю текущую операцию с двубайтовой переменной и тогда отрабатываю прерывание, ага вижу прерывание по таймеру , заканчиваю с внешним прерыванием (отрабатываю его до конца) и бегу отрабатывать прерывание по таймеру? Раньше писал достаточно сложные проги в CVAVR v 2.02 и как-то вообще не сталкивался с подобными проблемами, но на нем лицензия гавкнулась. Может это быть проблема компиллятора (CVAVR v 3.12) ? Может в новой версии просто что-то настроить надо? Спасибо!
  12. Да, походу контингент на форуме не особо продвинутый . Кто читает не работал с spi , а кто работал не читает форум. Т.к. тоже спросил почему протеус тупит когда выставляю SCK high вместо LOW -идей ноль. Судя по вашему посту протеус глючноват в симуляции SPI. Все что не мастер и не режим 0,1 тупит .
  13. Запуск двигателя контролируется по моменту старта , при этом напряжение железно проседает ниже 11 вольт. Это самый надёжный способ. В итоге например в опросе достаточно кинуть постоянную массу под гайку плафона и вуаля, мы имеем постоянный плюс и минус которым можно манипулировать через МК на свое усмотрение , сигнал датчика двери берём с минуса лампочки , сигнал запуска двигателя по просадке в момент пуска. Система получается постоянно под напругой в режиме ожидания. При использовании ldo стаба типа lp2905 потребление всего 0.1мА. это если система по вочдогу просыпается каждые 0.5 сек для опроса датчика двери. Если сильно попросите могу расширить готовый проект софитной лампочки где все смонтировано на одной плате и светодиоды и элементы управления . Но там плата только для пром повторения , нужна металлизация или если плафон позволяет , то немного переделать покрупнее, тогда можно и в домашних условиях повторить
  14. Мне бы просто понять это я туплю , протеус или кодевижен ? Если протеус (часто за ним грешки водятся ), то можно было бы забить, разработать при Лоу клок Айдл, а потом в железе реализовать как надо . Но если кодевижен криво компилит , то не хочется бестолковых приседаний.
  15. Всем привет! Решил освоить дисплей на ST7567 контроллере , но т.к . с SPI не работал решить начать с малого - погонять SPI в Протеусе. Пишу в CVAVR v2.05, в режиме с LOW SCK idle проблем нет, все симулируется, данные передаются, SPI дебагер все отлавливает. Но ST7567 требует HIGH SCK idle и тут начинаются проблемы - при запуске симуляции доходит до передачи данных по SPI и выдает ошибку: сам код (не работающий) : // SPI initialization // SPI Type: Master // SPI Clock Rate: 500,000 kHz // SPI Clock Phase: Cycle Half // SPI Clock Polarity: High // SPI Data Order: LSB First SPCR=0x7D; SPSR=0x00; // TWI initialization // TWI disabled TWCR=0x00; #asm("sei") while (1) { if (i==0) { spi(0b00101110); DDRD=0xff; PORTD=0xff; i=1; }; } } Работающий код отличается только SPCR=0x71, а не SPCR=0x7D ; протеус юзаю 8.9 SP2 Может кто сталкивался с такой бедой?
×
×
  • Создать...