Ёвгений 0 2 декабря, 2012 Опубликовано 2 декабря, 2012 · Жалоба вот листинг моей программы , это грубо говоря пищалка против клопов ультро звуковая , должна настраиваться переменным резистором подключенным к порту а на нужной частоте. Но факт в том что программа на каторой компелируется текст начинает глючить , то проходит через прерывание таймера Т1 по три раза , то скачет через строчку и появляется после нескольких десятков нажатий F11 в разных местах. Самое интересное что эту же программу я заредил в VMLAB Она и там показала ту же окалесицу. Я с этой бедой борюсь больше 2 лет ( а мне не смешно.) Голова кругом!!! То-ли менять компилятор (я к этому то долгл приноравливался ) , То ли писать на Ассемблере. Я бы с Удовольствием выложил видео Файл Что эта программа вытворяет , если покажите куда. #include <avr/io.h> #include <stdio.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/signal.h> volatile unsigned char a; #define INVBIT(x,y) (x^=(1<<y)) ISR(TIMER1_OVF_vect) { INVBIT(PORTB,PB1);// управление светодиод INVBIT(PORTB,PB0);// управление светодиод a=0; } void display(void); int main(void) { TIFR =0; TIMSK=0x04;// прерывание по перепол т1 TCCR1A=0; TCCR1B=1; TCNT1=65535-500; sei(); SFIOR=0; ADCSRA=0xe0; SFIOR=0; DDRA=0x00;//in DDRB=0xff;//out DDRC=0xff;//out DDRD=0x00;//in PORTA=0x00; PORTB=0x01; PORTC=0x00; PORTD=0x00; ADMUX=1;//vibor vhoda horo: ADMUX=1; _delay_ms(1000); ADCCompare=ADC; ADCCompare=ADCCompare/3; ADCCompare=500-ADCCompare; TCNT1=65535-ADCCompare; a=1; horo1: if (a==0) {goto horo;} goto horo1; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexeyv 0 3 декабря, 2012 Опубликовано 3 декабря, 2012 (изменено) · Жалоба 1. Какой чип? 2. Какая тактовая частота? В даташите написано тактовая на АЦП д.б. 50...200кГц, а у Вас делитель на 2. 3. Зачем постоянно выбираете 1-й канал? Одного раза разве не достаточно? 4. Так наверное будет и понятнее и проще: ADMUX=1; while(1) { if(a) continue; a=1; TCNT1 = 65535 - 500 + ADC/3; _delay_ms(1000); } 5. А разве не надо опрашивать флаг ADIF что бы узнать об окончании конверсии? Изменено 3 декабря, 2012 пользователем alexeyv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ёвгений 0 3 декабря, 2012 Опубликовано 3 декабря, 2012 · Жалоба Проц Mega16l , Тактовая частота 16 мегагерц . Пытаюсь настроить колебания на частоту от 16килогерц до 50. Динамик приходится качать в два раза чаще. К порту В к выводам 0 и 1 подключены через 4 транзистора динамик и попарно он качается то одним плечем то другим. Проблемма в управлении, его нет. Я создавал приблуды и посерьезнее но проблемма одна программа глючит. TCNT1 = 65535 - 500 + ADC/3; Согласно вашей формуле если за место ADC подставить 1000 то TCNT = FE25. А из-за того что я разложил все действия результат оказался верным FF58. я его проверял на калькуляторе. Но вопрос не в этом а в чем писать и чем проверять программу ? Winavr 2008 12 05 AvrStudio 4.18 Это то вчем я работаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 6 3 декабря, 2012 Опубликовано 3 декабря, 2012 · Жалоба Пытаюсь настроить колебания на частоту от 16килогерц до 50. Насколькоя понимаю - вы используете таймер в Normal mode. Это - мягко говоря, не лучшее решение: после переполнения и "дрыгания" ногами, Вы выставляете признак обновления счетчика таймера (переменная а), но в ветке обновления счетчика (метка horo) у Вас стоит задержка в целую секунду... Логичнее использовать CTC mode. Да, и для генерации сигнала, вероятно, лучше использовать вывод ОС1х, предварительно настроив вывод таймера на него. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexeyv 0 3 декабря, 2012 Опубликовано 3 декабря, 2012 (изменено) · Жалоба 1. Если FCPU =16МГц, то необходимо поставить делитель АЦП равным 128 (тактовая на АЦП будет 125КГц) 2. TCNT1 = 65535 - 500 + ADC/3; Согласно вашей формуле если за место ADC подставить 1000 то TCNT = FE25. Странно!! А у меня получилось FF58. Объясните мне разницу между TCNT1 = 65535 - 500 + ADC/3; и ADCCompare=ADC; ADCCompare=ADCCompare/3; ADCCompare=500-ADCCompare; TCNT1=65535-ADCCompare; 3. Где опрос флага ADIF и его сброс? Ваша проблема понятна - Вы считываете данные с АЦП тогда, когда еще нет точного результата конверсии 4. Для проверки алгоритма поставьте несколько констант вместо считывания с АЦП и проверьте зависимость выхода(частоты) от констант. Если на выходе будет нужная частота, то проблема в считывании показаний с АЦП. Также, если есть к-либо отладочный порт (USART), можете вывести значения АЦП на ПК и посмотреть как они считываются/изменяются. 5. Если у вас задержки порядка секунды, зачем запускать АЦП во Free Runing? По окончании задержки запустите в одиночном измерении и дождитесь окончании конверсии Изменено 3 декабря, 2012 пользователем alexeyv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ёвгений 0 3 декабря, 2012 Опубликовано 3 декабря, 2012 · Жалоба Насколькоя понимаю - вы используете таймер в Normal mode. Это - мягко говоря, не лучшее решение: после переполнения и "дрыгания" ногами, Вы выставляете признак обновления счетчика таймера (переменная а), но в ветке обновления счетчика (метка horo) у Вас стоит задержка в целую секунду... Логичнее использовать CTC mode. Да, и для генерации сигнала, вероятно, лучше использовать вывод ОС1х, предварительно настроив вывод таймера на него. я поставил задержку в надежде что появится регулировка от ацп спасибо за подсказку. с временем я что-то под ошибся . Господа программисты посмотрите этот клипп и обьясните почему он себя так ведет. не могу вставить пока , файл 1.5 мегабайта сайт не принимает Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 3 декабря, 2012 Опубликовано 3 декабря, 2012 · Жалоба Есть столько сайтов , что бы сбросить и дать ссылку Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ёвгений 0 4 декабря, 2012 Опубликовано 4 декабря, 2012 · Жалоба Нашел , скачивайте и посмотрите . http://files.mail.ru/IF38YS 1. Если FCPU =16МГц, то необходимо поставить делитель АЦП равным 128 (тактовая на АЦП будет 125КГц) 2. Странно!! А у меня получилось FF58. Объясните мне разницу между TCNT1 = 65535 - 500 + ADC/3; и ADCCompare=ADC; ADCCompare=ADCCompare/3; ADCCompare=500-ADCCompare; TCNT1=65535-ADCCompare; 3. Где опрос флага ADIF и его сброс? Ваша проблема понятна - Вы считываете данные с АЦП тогда, когда еще нет точного результата конверсии 4. Для проверки алгоритма поставьте несколько констант вместо считывания с АЦП и проверьте зависимость выхода(частоты) от констант. Если на выходе будет нужная частота, то проблема в считывании показаний с АЦП. Также, если есть к-либо отладочный порт (USART), можете вывести значения АЦП на ПК и посмотреть как они считываются/изменяются. 5. Если у вас задержки порядка секунды, зачем запускать АЦП во Free Runing? По окончании задержки запустите в одиночном измерении и дождитесь окончании конверсии 1 .Зачем мне включать делитель если частотой управляет формула? 2 .Разница лишь в том что если вашу формулу я вставляю в код программы и свой ,я получаю разные результаты. 3. Хорошая мысль Попробую после того как программа заработает. 4. Попробую. 5. Такая задержка это ошибка , я ее уже устранил . Алексей тоже посмотрите ролик мне интересно ваше мнение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexeyv 0 5 декабря, 2012 Опубликовано 5 декабря, 2012 · Жалоба 1 .Зачем мне включать делитель если частотой управляет формула? Формула должна управлять выходной частотой для динамика, а не рабочей частотой от которой работает АЦП - не путайте понятия!! 2 .Разница лишь в том что если вашу формулу я вставляю в код программы и свой ,я получаю разные результаты. Не верю. Жаль мне сейчас не на чем проверить. Это всего лишь эквивалентные преобразования. 3. Хорошая мысль Попробую после того как программа заработает. Это надо сделать ДЛЯ того что бы программа заработала, причем правильно!! По поводу ролика: Какой режим оптимизации включен? При включенной оптимизации компилятор как раз выкинет все ваши присваивания и приведет все к виду: TCNT1 = 65035 + _function_divide(ADC,3); переменная ADCCompare также выкинется как лишняя. Замечания по поводу алгоритма 1. Зачем вообще так часто сканировать номинал резистора или он быстро меняется. Достаточно это делать раз в секунду. Причем в Single-mode. Делать это в главном цикле в задержкой в 1 сек и ожиданием окончания конверсии после старта 2. Согласен с Палыч'ем - необходимо использовать тайммер в СТС режиме. В прерывании от него необходимо проверять не изменилось ли значение резистора и только после этого менять период работа таймера. Не изменилось - пусть себе дальше пашет. Использование ОС1х - не обязательно, надо смотреть как у Вас все подлючено и можно ли перебросить выводы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ёвгений 0 7 декабря, 2012 Опубликовано 7 декабря, 2012 · Жалоба Переделал вот листинг #include <avr/io.h> #include <stdio.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/signal.h> volatile unsigned int a; // èçìåíÿåìàÿ äëèòåëüíîñòü ìîðãàíèé volatile unsigned int ADCCompare; // #define SETBIT(x,y) (x|=(1<<y)) #define CLRBIT(x,y) (x&=~(1<<y)) #define INVBIT(x,y) (x^=(1<<y)) #define CHKBIT(x,y) (x&(1<<y)) #define BITON(x,y) (x&(1<<y)) #define BITOFF(x,y) (!(x&(1<<y))) ISR(TIMER1_OVF_vect) { INVBIT(PORTB,PB1);// INVBIT(PORTB,PB0);// a=0; } // ((PIND & 0x04) == 0 ) ïðîâåðèòü åñëè 4 áèò = 0 // ((PIND & 0x04) != 0 ) ïðîâåðèòü åñëè 4 áèò = 1 // 7654 3210 // 1000 0000 = 80 // 0100 0000 = 40 // 0010 0000 = 20 // 0001 0000 = 10 // 0000 1000 = 08 // 0000 0100 = 04 // 0000 0010 = 02 // 0000 0001 = 01 int main(void) { TIFR =0; TIMSK=0x04;// ïðåðûâàíèå ïî ïåðåïîë ò1 TCCR1A=0; TCCR1B=1; TCNT1=65535-500; cli(); SFIOR=0; ADCSRA=0xe7; SFIOR=0; DDRA=0x00;//in DDRB=0xff;//out DDRC=0xff;//out DDRD=0x00;//in PORTA=0x00; PORTB=0x01; PORTC=0x00; PORTD=0x00; ADMUX=1;//vibor vhoda horo: TCNT1=65535-(500-(ADC/3)); a=1; horo1: if ( ADIF==1) {goto horo;} goto horo1; } Оптимизацию сделал на ноль и на один тоже ставил в листинге на строчке а=1 в программе проподает стрелка при значении CYCLE COUNTER 204 А ЕСЛИ НАЖАТЬ ПАУЗУ ЭТО ЖЕ ЗНАЧЕНИЕ УЖЕ РАВНО 3206010 , ПРИ ЧЕМ НИ КАКИЕ ТОЧКИ ОСТАНОВА РАССТАВЛЕННЫЕ В РАЗНЫХ МЕСТАХ ПРОГРАММЫ И ПРЕРЫВАНИЯ НЕ СРАБАТЫВАЮТ. КАК ТО РАЗ ДАЖЕ ОСТАНОВИ ПРОГРАММУ ГДЕ СТРЕЛА ВЫШЛА ЗА ЛИСТИНГ ПРОГРАММЫ . кАК ОТЛАЖИВАТЬ ПРОГРАММУ ВООБЩЕ НЕ ПОНЯТНО(( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
massa 0 7 декабря, 2012 Опубликовано 7 декабря, 2012 · Жалоба Вставьте: asm("nop"); и на этой строке сделайте точку останова. Помогает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ёвгений 0 8 декабря, 2012 Опубликовано 8 декабря, 2012 · Жалоба (( Попробывал Теже яйца только в профиль. Я вот все думаю если есть этот Сайт Созданы эти микроконтроллеры есть этот глючный AVR Studio , Есть наверное прога в каторой все программируют отлаживают и в тихушку молчат . Это мое мнение. Неужели в аське писать прогу , просто не понятно как представлять данные выходящие за значение одного байта, как совершать деление и др операции это же вчерашний век . Вот Блин, руки опускаются с такой перспективой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 8 декабря, 2012 Опубликовано 8 декабря, 2012 · Жалоба этот глючный AVR Studio , В чём претензия к AVRStudio? Есть наверное прога в каторой все программируют отлаживают и в тихушку молчат . Есть такая программа, AVRStudio называется. Есть и другие программы. Вот Блин, руки опускаются с такой перспективой. Дело всё в вашей программе - что она делать-то должна? Что странно: horo: ADMUX=1; _delay_ms(1000); ADCCompare=ADC; ADCCompare=ADCCompare/3; ADCCompare=500-ADCCompare; TCNT1=65535-ADCCompare; результат АЦП получается 1 раз в секунду, в зависимости от результата устанавливается "период" таймера. Остальное время прерывания переполнения возникают через 65536 циклов. Может как-то так надо: volatile unsigned short Timer1ReloadValue=65535-500; ISR(TIMER1_OVF_vect) { TCNT1=Timer1ReloadValue; INVBIT(PORTB,PB1);// управление светодиод INVBIT(PORTB,PB0);// управление светодиод a=0; } ADMUX=1; _delay_ms(1000); ADCCompare=ADC; ADCCompare=ADCCompare/3; ADCCompare=500-ADCCompare; Timer1ReloadValue=65535-ADCCompare; ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexeyv 0 10 декабря, 2012 Опубликовано 10 декабря, 2012 · Жалоба Где-то примерно так: #include <avr/io.h> #include <stdio.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/signal.h> volatile unsigned int ADCCompare_new =0; volatile unsigned int ADCCompare_old =0; #define SETBIT(x,y) (x|=(1<<y)) #define CLRBIT(x,y) (x&=~(1<<y)) #define INVBIT(x,y) (x^=(1<<y)) #define CHKBIT(x,y) (x&(1<<y)) #define BITON(x,y) (x&(1<<y)) #define BITOFF(x,y) (!(x&(1<<y))) ISR(TIMER1_COMPA_vect) { INVBIT(PORTB,PB1);// INVBIT(PORTB,PB0);// if(ADCCompare_new != ADCCompare_old) { OCR1A = ADCCompare_old = ADCCompare_new; } } int main(void) { cli(); // Init TC1 - CTC Mode TCCR1A = 0; TCCR1B = (1<<WGM12) | (1<<CS10); OCR1A = 510; TCNT1 = 0; TIMSK = (1<<OCIE1A); // Init ADC SFIOR=0; ADCSRA = (1<<ADEN)|(0<<ADSC)|(0<<ADATE)|(0<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); ADMUX=1; //vibor vhoda // Init Port's DDRA=0x00; //in DDRB=0xff; //out DDRC=0xff; //out DDRD=0x00; //in PORTA=0x00; PORTB=0x01; PORTC=0x00; PORTD=0x00; TIFR = 0xFF; sei(); while(1) { _delay_ms(1000); ADCSRA |= (1<<ADSC); // Start ADC Conversion while((ADCSRA & (1<<ADIF)) != 0x10);// Wait till conversion is complete ADCCompare_new = 510 - (ADC/3); // Read the ADC Result ADCSRA |= (1 << ADIF); // Clear ADC Conversion Interrupt Flag } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
TriD 0 10 декабря, 2012 Опубликовано 10 декабря, 2012 · Жалоба Не вдаваясь в тонкости реализации программы, скажу, что студия эмулирует сишный код несколько своеобразно. При ошибках в коде может вообще убрать целые фрагменты кода, которые с точки зрения компилятора выполнять никогда не будут. Для получения полного представления того, что там накомпилилось из вашей программы, отлаживаейте ее в окне дизассемблера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться