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

Глюки AVRStudio+WinAVR или в моей голове

вот листинг моей программы , это грубо говоря пищалка против клопов ультро звуковая ,

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

Но факт в том что программа на каторой компелируется текст начинает глючить , то проходит через прерывание таймера Т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;

 

 

 

 

 

}

 

 

Поделиться сообщением


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

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 что бы узнать об окончании конверсии?

Изменено пользователем alexeyv

Поделиться сообщением


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

Проц Mega16l , Тактовая частота 16 мегагерц .

Пытаюсь настроить колебания на частоту от 16килогерц до 50.

Динамик приходится качать в два раза чаще.

К порту В к выводам 0 и 1 подключены через 4 транзистора динамик и попарно он качается то одним

плечем то другим.

Проблемма в управлении, его нет.

Я создавал приблуды и посерьезнее но проблемма одна программа глючит.

 

TCNT1 = 65535 - 500 + ADC/3;

Согласно вашей формуле если за место ADC подставить 1000 то TCNT = FE25.

 

А из-за того что я разложил все действия результат оказался верным FF58.

я его проверял на калькуляторе.

 

Но вопрос не в этом а в чем писать и чем проверять программу ?

Winavr 2008 12 05

AvrStudio 4.18

Это то вчем я работаю.

Поделиться сообщением


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

Пытаюсь настроить колебания на частоту от 16килогерц до 50.

Насколькоя понимаю - вы используете таймер в Normal mode. Это - мягко говоря, не лучшее решение: после переполнения и "дрыгания" ногами, Вы выставляете признак обновления счетчика таймера (переменная а), но в ветке обновления счетчика (метка horo) у Вас стоит задержка в целую секунду...

Логичнее использовать CTC mode. Да, и для генерации сигнала, вероятно, лучше использовать вывод ОС1х, предварительно настроив вывод таймера на него.

 

 

Поделиться сообщением


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

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? По окончании задержки запустите в одиночном измерении и дождитесь окончании конверсии

Изменено пользователем alexeyv

Поделиться сообщением


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

Насколькоя понимаю - вы используете таймер в Normal mode. Это - мягко говоря, не лучшее решение: после переполнения и "дрыгания" ногами, Вы выставляете признак обновления счетчика таймера (переменная а), но в ветке обновления счетчика (метка horo) у Вас стоит задержка в целую секунду...

Логичнее использовать CTC mode. Да, и для генерации сигнала, вероятно, лучше использовать вывод ОС1х, предварительно настроив вывод таймера на него.

я поставил задержку в надежде что появится регулировка от ацп спасибо за подсказку.

с временем я что-то под ошибся .

 

 

Господа программисты посмотрите этот клипп и обьясните почему он себя так ведет.

 

не могу вставить пока , файл 1.5 мегабайта сайт не принимает

Поделиться сообщением


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

Нашел , скачивайте и посмотрите .

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. Такая задержка это ошибка , я ее уже устранил .

 

Алексей тоже посмотрите ролик мне интересно ваше мнение.

Поделиться сообщением


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

1 .Зачем мне включать делитель если частотой управляет формула?

Формула должна управлять выходной частотой для динамика, а не рабочей частотой от которой работает АЦП - не путайте понятия!!

 

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

Не верю. Жаль мне сейчас не на чем проверить. Это всего лишь эквивалентные преобразования.

 

3. Хорошая мысль Попробую после того как программа заработает.

Это надо сделать ДЛЯ того что бы программа заработала, причем правильно!!

 

По поводу ролика:

Какой режим оптимизации включен? При включенной оптимизации компилятор как раз выкинет все ваши присваивания и приведет все к виду:

TCNT1 = 65035 + _function_divide(ADC,3);

переменная ADCCompare также выкинется как лишняя.

 

Замечания по поводу алгоритма

1. Зачем вообще так часто сканировать номинал резистора или он быстро меняется. Достаточно это делать раз в секунду. Причем в Single-mode. Делать это в главном цикле в задержкой в 1 сек и ожиданием окончания конверсии после старта

2. Согласен с Палыч'ем - необходимо использовать тайммер в СТС режиме. В прерывании от него необходимо проверять не изменилось ли значение резистора и только после этого менять период работа таймера. Не изменилось - пусть себе дальше пашет. Использование ОС1х - не обязательно, надо смотреть как у Вас все подлючено и можно ли перебросить выводы.

 

Поделиться сообщением


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

Переделал вот листинг

#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 , ПРИ ЧЕМ НИ КАКИЕ ТОЧКИ ОСТАНОВА РАССТАВЛЕННЫЕ В РАЗНЫХ МЕСТАХ ПРОГРАММЫ И ПРЕРЫВАНИЯ НЕ СРАБАТЫВАЮТ. КАК ТО РАЗ ДАЖЕ ОСТАНОВИ ПРОГРАММУ ГДЕ СТРЕЛА ВЫШЛА ЗА ЛИСТИНГ ПРОГРАММЫ . кАК ОТЛАЖИВАТЬ ПРОГРАММУ ВООБЩЕ НЕ ПОНЯТНО((

Поделиться сообщением


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

Вставьте:

 

asm("nop");

 

и на этой строке сделайте точку останова.

 

Помогает.

Поделиться сообщением


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

(( Попробывал Теже яйца только в профиль.

Я вот все думаю если есть этот Сайт Созданы эти микроконтроллеры есть этот глючный AVR Studio ,

Есть наверное прога в каторой все программируют отлаживают и в тихушку молчат . Это мое мнение.

 

 

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

Поделиться сообщением


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

этот глючный 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;

 

 

 

?

Поделиться сообщением


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

Где-то примерно так:

#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		
}
}

Поделиться сообщением


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

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

Поделиться сообщением


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

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

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

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

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

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

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

×
×
  • Создать...