реклама на сайте
подробности

 
 
> Глюки AVRStudio+WinAVR или в моей голове, нет возможности правильно Отладить программу на си
Чиппер
сообщение Dec 2 2012, 12:59
Сообщение #1





Группа: Участник
Сообщений: 10
Регистрация: 27-12-09
Пользователь №: 54 511



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





}

Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 14)
alexeyv
сообщение Dec 3 2012, 03:50
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



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 - Dec 3 2012, 08:36
Go to the top of the page
 
+Quote Post
Чиппер
сообщение Dec 3 2012, 06:53
Сообщение #3





Группа: Участник
Сообщений: 10
Регистрация: 27-12-09
Пользователь №: 54 511



Проц Mega16l , Тактовая частота 16 мегагерц .
Пытаюсь настроить колебания на частоту от 16килогерц до 50.
Динамик приходится качать в два раза чаще.
К порту В к выводам 0 и 1 подключены через 4 транзистора динамик и попарно он качается то одним
плечем то другим.
Проблемма в управлении, его нет.
Я создавал приблуды и посерьезнее но проблемма одна программа глючит.

TCNT1 = 65535 - 500 + ADC/3;
Согласно вашей формуле если за место ADC подставить 1000 то TCNT = FE25.

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

Но вопрос не в этом а в чем писать и чем проверять программу ?
Winavr 2008 12 05
AvrStudio 4.18
Это то вчем я работаю.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Dec 3 2012, 08:22
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Чиппер @ Dec 3 2012, 10:53) *
Пытаюсь настроить колебания на частоту от 16килогерц до 50.

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

Go to the top of the page
 
+Quote Post
alexeyv
сообщение Dec 3 2012, 08:33
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



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 - Dec 3 2012, 08:49
Go to the top of the page
 
+Quote Post
Чиппер
сообщение Dec 3 2012, 09:50
Сообщение #6





Группа: Участник
Сообщений: 10
Регистрация: 27-12-09
Пользователь №: 54 511



Цитата(Палыч @ Dec 3 2012, 21:22) *
Насколькоя понимаю - вы используете таймер в Normal mode. Это - мягко говоря, не лучшее решение: после переполнения и "дрыгания" ногами, Вы выставляете признак обновления счетчика таймера (переменная а), но в ветке обновления счетчика (метка horo) у Вас стоит задержка в целую секунду...
Логичнее использовать CTC mode. Да, и для генерации сигнала, вероятно, лучше использовать вывод ОС1х, предварительно настроив вывод таймера на него.
я поставил задержку в надежде что появится регулировка от ацп спасибо за подсказку.
с временем я что-то под ошибся .


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

не могу вставить пока , файл 1.5 мегабайта сайт не принимает
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Dec 3 2012, 12:58
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Есть столько сайтов , что бы сбросить и дать ссылку


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
Чиппер
сообщение Dec 4 2012, 13:44
Сообщение #8





Группа: Участник
Сообщений: 10
Регистрация: 27-12-09
Пользователь №: 54 511



Нашел , скачивайте и посмотрите .
http://files.mail.ru/IF38YS

Цитата(alexeyv @ Dec 3 2012, 21:33) *
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. Такая задержка это ошибка , я ее уже устранил .

Алексей тоже посмотрите ролик мне интересно ваше мнение.
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Dec 5 2012, 04:07
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



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

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

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

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

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

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

По поводу ролика:
Какой режим оптимизации включен? При включенной оптимизации компилятор как раз выкинет все ваши присваивания и приведет все к виду:
TCNT1 = 65035 + _function_divide(ADC,3);
переменная ADCCompare также выкинется как лишняя.

Замечания по поводу алгоритма
1. Зачем вообще так часто сканировать номинал резистора или он быстро меняется. Достаточно это делать раз в секунду. Причем в Single-mode. Делать это в главном цикле в задержкой в 1 сек и ожиданием окончания конверсии после старта
2. Согласен с Палыч'ем - необходимо использовать тайммер в СТС режиме. В прерывании от него необходимо проверять не изменилось ли значение резистора и только после этого менять период работа таймера. Не изменилось - пусть себе дальше пашет. Использование ОС1х - не обязательно, надо смотреть как у Вас все подлючено и можно ли перебросить выводы.
Go to the top of the page
 
+Quote Post
Чиппер
сообщение Dec 7 2012, 14:57
Сообщение #10





Группа: Участник
Сообщений: 10
Регистрация: 27-12-09
Пользователь №: 54 511



Переделал вот листинг
#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 , ПРИ ЧЕМ НИ КАКИЕ ТОЧКИ ОСТАНОВА РАССТАВЛЕННЫЕ В РАЗНЫХ МЕСТАХ ПРОГРАММЫ И ПРЕРЫВАНИЯ НЕ СРАБАТЫВАЮТ. КАК ТО РАЗ ДАЖЕ ОСТАНОВИ ПРОГРАММУ ГДЕ СТРЕЛА ВЫШЛА ЗА ЛИСТИНГ ПРОГРАММЫ . кАК ОТЛАЖИВАТЬ ПРОГРАММУ ВООБЩЕ НЕ ПОНЯТНО((
Go to the top of the page
 
+Quote Post
V.K
сообщение Dec 7 2012, 15:20
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 453
Регистрация: 6-05-06
Из: РФ
Пользователь №: 16 841



Вставьте:

asm("nop");

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

Помогает.
Go to the top of the page
 
+Quote Post
Чиппер
сообщение Dec 8 2012, 12:46
Сообщение #12





Группа: Участник
Сообщений: 10
Регистрация: 27-12-09
Пользователь №: 54 511



(( Попробывал Теже яйца только в профиль.
Я вот все думаю если есть этот Сайт Созданы эти микроконтроллеры есть этот глючный AVR Studio ,
Есть наверное прога в каторой все программируют отлаживают и в тихушку молчат . Это мое мнение.


Неужели в аське писать прогу , просто не понятно как представлять данные выходящие за значение одного байта, как совершать деление и др операции это же вчерашний век . Вот Блин, руки опускаются с такой перспективой.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Dec 8 2012, 14:09
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Чиппер @ Dec 8 2012, 14:46) *
этот глючный AVR Studio ,

В чём претензия к AVRStudio?

Цитата(Чиппер @ Dec 8 2012, 14:46) *
Есть наверное прога в каторой все программируют отлаживают и в тихушку молчат .

Есть такая программа, AVRStudio называется.
Есть и другие программы.

Цитата(Чиппер @ Dec 8 2012, 14:46) *
Вот Блин, руки опускаются с такой перспективой.

Дело всё в вашей программе - что она делать-то должна?
Что странно:
Код
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;




?
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Dec 10 2012, 04:45
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



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

#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
}
}
Go to the top of the page
 
+Quote Post
TriD
сообщение Dec 10 2012, 13:20
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 252
Регистрация: 29-12-04
Пользователь №: 1 728



Не вдаваясь в тонкости реализации программы, скажу, что студия эмулирует сишный код несколько своеобразно. При ошибках в коде может вообще убрать целые фрагменты кода, которые с точки зрения компилятора выполнять никогда не будут. Для получения полного представления того, что там накомпилилось из вашей программы, отлаживаейте ее в окне дизассемблера.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 22:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01494 секунд с 7
ELECTRONIX ©2004-2016