Модераторы: PILOT, ManiaK, Mazzi
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Программа виснит по непонятной причине. 
:(
    Опции темы
seatouch
Дата 5.1.2009, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 27.11.2008

Репутация: нет
Всего: нет



Уважаемые инженеры, поздравляю Всех с наступившим Новым Годом и с наступающем Рождеством!!!

Предлагаю приколоться над работой AVR Studio и AVR-gcc. Как только программа проводит 15 измерений, проходит все проверки, посылает управляющий импульс и доходит до конца функции ISR(TIMER1_COMPA_vect), она «уходит в себя» на неопределенное время, и не останавливается нигде. Только если нажать «паузу» почему-то останавливается на  sei() ; хотя если там же поставить BreakPoint сама там не останавливается. Глюки? Или специфика работы AVR-Studio. Программа написана для atMega644.

Код

//05 января 2009
#include <avr\io.h>
#include <avr\signal.h>
#include <avr\interrupt.h>
//#include <avr\delay.h>

#define INERTZONE 3 // Зона нечувствительности.
#define LIGHTIME 40 // Задержка включения светодиода после поворота ручки (умножить на время срабатывания таймера = сек).
#define IZMNUM 15 // Проводим такое кол-во измерений перед тем как начать вращение
#define COEFF 0.0732422


volatile unsigned int iDelay, iADCResult, iADCResultOld, iADCResultMin, iADCResultMax, i, iLightDelay ;  //время задержки моргания светодиода.
volatile unsigned char cIzmCount ; //исчетчик количества измерений перед тем как начать вращение
unsigned int iADCResultArray[IZMNUM] ; //Массив в котором будут хранится измерения. 
double fCoeff ;
unsigned char cGoodToRottate ; //Устраивает ли нас точность измерений и будем ли вращать машинку.
unsigned char cRottating ; //Если 0xFF идет вращение, если 0x00 вращение не идет.
unsigned int iADCResultLoc ; 
unsigned char cADCReg ;


int main(void)
{
cRottating = 0x00 ;
fCoeff = 0.0732422 ;

//---------Настройка Таймера 0-------  
//  TCCR0A = 0x00; 
//  TCCR0B = 0x00; //стоп

//  TCNT0 = 0x00; 
//  OCR0A  = 0x4F;

//  TIMSK0 = 0x02; //прерывание по совпадению с OCR0A
//  TCCR0B = 0x04; //старт с делителем
//---------------------------------  

//---------Настройка Таймера 1-------  
//  TCCR1A = 0x00; 
  TCCR1B = 0x00; //стоп


  TCNT1 = 0x00; 
//  OCR1AH  = 0x04;
//  OCR1AL  = 0x00;
//  OCR1A = 976 ; //1 сек с делителем на 1024
//  OCR1A = 48 ; //0.05 сек с делителем на 1024
  OCR1A = 20 ; //0.02 сек с делителем на 1024


  TIMSK1 = 0x02; //прерывание по совпадению с OCR0A
  TCCR1B = 0x05; //старт с делителем на 1024
//---------------------------------  

//----------Настройка АЦП----------
DDRD = 0x0 ;
PORTD = 0x0 ;
DIDR0=0x01 ; // Использовать для АЦП будем PA0
//ADMUX = 0b11100000 ; //Внутреннее опорное напряжение 2.56В и результат со сдвигом влево.
ADMUX = 0b11000000 ; //Внутреннее опорное напряжение 2.56В и результат со сдвигом вправо.
ADCSRA = 0b10000000 ;  //Включение АЦП без прерывания.
ADCSRA |= 0x40 ; //Запускаем преобразование.
//----------------------------------

  DDRB = 0x05 ;
  PORTB = 0x01 ; //Выключаем с.д.
  iLightDelay = 0 ; //Эта переменная считает длительность горения с.д.
  cIzmCount = 0 ;  //Считает количество проведенных измерений.

  sei() ;
  while(1)
  {
  }
}

unsigned int Izmerenie(void)  //Функция измерения АЦП
{

        TCNT1 = 0x00; //reload counter value

     //Запускаем АЦП
        ADCSRA|=0x40; // как только измерение закончится 
                              //этот бит пропадет, зато установится
                              // бит ADIF.
        
        //Ждем завершения преобразования
        cADCReg = 0b01010000 & ADCSRA ;

        while (cADCReg != 0b00010000)
        {
            cADCReg = 0b01010000 & ADCSRA ;  //Делаем поразрядное "и" 
                                             //что бы оставить только 
                                             //нужные нам биты ADSC и ADIF.
        }

        //Считываем данные ADC
        iADCResultLoc = ADC ;

        return (iADCResultLoc) ;
}


ISR(TIMER1_COMPA_vect)
{
                
cGoodToRottate = 0x00 ; //
        
        
        if (cRottating == 0x00)  //Если еще идет предыдущее вращение, не делаем ничего.
        {
            if (cIzmCount<IZMNUM)  //Проводим несколько измерений (IZMNUM) и смотрим устраивает ли нас точность.
            {
             iADCResultArray[cIzmCount] = Izmerenie() ;
                cIzmCount ++ ;
            }
            else
            {  //Если измерения выполнены смотрим устраивает ли нас точность измерений.
                iADCResultMax = 0 ;
                iADCResultMin = 0xFFFF ;

                for (cIzmCount=0; cIzmCount<IZMNUM; cIzmCount++)
                {
                   //все результаты не должны сильно отличатся друг от друга
                   //Ищем максимум и минимум
                    if (iADCResultMax < iADCResultArray[cIzmCount] )
                        iADCResultMax = iADCResultArray[cIzmCount] ;
                    if (iADCResultMin > iADCResultArray[cIzmCount] )
                        iADCResultMin = iADCResultArray[cIzmCount] ;
                }
                //Пусть измерения укладываются в 15 ;
                if (iADCResultMax-iADCResultMin<15)
                {  // Если точность устраивает, расчитываем среднеарифметическое 
                   //и сравниваем со старым значением
                    iADCResult=0 ;
                    for (cIzmCount=0; cIzmCount<IZMNUM; cIzmCount++)
                    {
                        iADCResult = iADCResult + iADCResultArray[cIzmCount] ;
                    }
                    iADCResult = iADCResult/IZMNUM ;
                    cIzmCount = 0 ;
                    //Проверяем на сколько полученое значение отличается от пошлого. 
                    //Если превышает зону не чувствительности (INERTZONE) запускаем вращение машинки
                    if (iADCResult > iADCResultOld+INERTZONE || iADCResult < iADCResultOld-INERTZONE)  //Зона не чувствительности.
                    {
                        cGoodToRottate = 0xFF ; //Если все ОК запускаем вращение сервы.
                        iADCResultOld = iADCResult ;
                    }
                    
                }
            }
        }

        if (cGoodToRottate==0xFF)
        {
            //Расчиттываем задержку моргания светодиода
            iDelay = (iADCResult+1)*COEFF+37 ; //это будет время задержки моргания светодиода 

            cRottating = 0xFF ; //Устанавливаем переменную в режим вращения ;
            PORTB=PORTB & 0x04 ; //включаем светодиод (лог 0 на 1ую ножку).
        }    

        if ( cRottating == 0xFF && iLightDelay<LIGHTIME)  //Если идет вращение 
        {
            i=0;
            PORTB=PORTB | 0x04 ;  //Запускаем управляющий импульс (лог 1 на 3ю ножку)
            while(i<iDelay)
            {
                i++ ;
            }
            PORTB=PORTB & 0x01 ;    //Останавливаем управляющий импульс (лог 1 на 3ю ножку, значение ножки 1 (с.д. не меняется))
            iLightDelay ++ ;    
        }
        else
        {
            cRottating = 0x00 ;  //Выключаем вращение
            PORTB=PORTB | 0x01 ; //выключаем с.д. (лог 1 на 1ую ножку) если время его горения вышло (значение бита управления сервой останется неизменным)
            iLightDelay = 0 ;
        }

}


PM MAIL   Вверх
Mazzi
Дата 6.1.2009, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Правильный
**


Профиль
Группа: Комодератор
Сообщений: 825
Регистрация: 3.4.2003

Репутация: 9
Всего: 21



Если отладка проводится на микросхеме, то скорее всего у тебя неправильно установлены фьюзы,
зайди сюда, почитай http://ulei.by.ru/Fuses_Ru.htm

Если в симуляторе, то скорее всего ошибка в коде.


--------------------
Мне нужны помощники.
PM MAIL WWW   Вверх
cardinal
Дата 6.1.2009, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Инженер
****


Профиль
Группа: Экс. модератор
Сообщений: 6003
Регистрация: 26.3.2002
Где: Германия

Репутация: 8
Всего: 99



А в main у тебя нет return 1... smile 


--------------------
Немецкая оппозиция потребовала упростить натурализацию иммигрантов
В моем блоге: Разные истории из жизни в Германии

"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино".  А. и Б. Стругацкие
PM   Вверх
seatouch
Дата 6.1.2009, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 27.11.2008

Репутация: нет
Всего: нет



Отлаживаю без использования реальной микросхемы. Только AVR-Studio.
Оказалось функция прерывания длится дольше чем интервал времени. Получается переполнение и задержка в 67108864 циклов что для отладки равно бесконечности. smile 
Поторопился тему открывать. Правильно говорят: "Утро вечера мудренее"!
Всем спасибо!

To cardinal
А принципиально, что бы был именно return 1? Обычно вроде 0 ставят? Если задумываться о хорошем тоне программирования то конечно return нужен. Но может ли он как-нибудь повлиять на данную программу?
Спасибо!

Это сообщение отредактировал(а) seatouch - 6.1.2009, 12:59
PM MAIL   Вверх
Mazzi
Дата 6.1.2009, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Правильный
**


Профиль
Группа: Комодератор
Сообщений: 825
Регистрация: 3.4.2003

Репутация: 9
Всего: 21



Цитата(seatouch @ 6.1.2009,  12:54)
А принципиально, что бы был именно return 1? Обычно вроде 0 ставят? Если задумываться о хорошем тоне программирования то конечно return нужен. Но может ли он как-нибудь повлиять на данную программу?
Спасибо!

Да это он пошутил. В контроллерных программах нет выхода из main.


--------------------
Мне нужны помощники.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Микроконтроллеры (MCU) и микропроцессоры (MPU)"
PILOT ManiaK
UniBomb Mazzi

На данный раздел помимо Правил форума распространяются текже следующие правила:


  • Прежде чем создать тему воспользуйтесь поиском или посмотрите в faq. Возможно на форуме уже есть ответ на ваш или близкий к вашему вопрос.
  • В заголовке темы в квадратных скобках обозначьте используемое семейство микроконтроллера: [avr],[pic],[arm].
  • При создании темы с вопросом указывайте участок кода с ошибкой, версию компилятора, схемы подключения, fuse биты и прочие данные, которые помогут найти правильный ответ. Для форматирования текста программ используйте кнопку код.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Для флуда, просьб выполнить задание, поиска партнёров или исполнителей существуют свои разделы.
  • Если вы заметили несовместимое с правилами сообщение, то можете уведомить об этом модератора раздела нажав кнопку Репорт у соответствующего сообщения.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, PILOT, ManiaK, UniBomb, Mazzi.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Микроконтроллеры (MCU) и микропроцессоры (MPU) | Следующая тема »


 




[ Время генерации скрипта: 0.0692 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.