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

 
 
 
Reply to this topicStart new topic
> разделение источников в прерывании TIMERB1, какой то глюк с TBIV
-=Space=-
сообщение Oct 24 2006, 09:44
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 105
Регистрация: 14-01-05
Из: Москва Зеленоград
Пользователь №: 1 962



есть 4 исмпульсных сигнала, частоту которых необходимо померить.
Для этого хочу использовать режим захвата таймера B
входы TB0-TB3
c TB0 все нормальнго , для него отдельное прервывание TIMERB0
а вот на 3 сигнала TB1-TB3 вектор один - TIMERB1
в мануале предлагается по регистру TBIV определять сточник прерывания
даже есть примерчик на асме.

Я пришу прогу на IAR C
вот код прерывания:
Код
#pragma vector=TIMERB1_VECTOR
__interrupt void Timer_B1 (void)
{
unsigned char tbiv = TBIV;        // (1)

if(tbiv == 0x02)                       // (2)
    {
    delta1 = TBCCR1 - count1;
    count1 = TBCCR1;
    }
if(tbiv == 0x04)
    {
    delta2 = TBCCR2 - count2;
    count2 = TBCCR2;
    }
if(tbiv == 0x06)
    {
    delta3 = TBCCR3 - count3;
    count3 = TBCCR3;
    }

}


однако ни одна ветка не не выполняется в режиме реального времени, хотя
в отладке по шагам все работает
если поставить точки останова в строках (1) и (2),
и после остановки в (1) выполнить переход по шагам то tbiv получает парвильное значение и все работает
если после остановки в (1) нажать F5 то программа остановится в (2) но tbiv будет =0, и ниодна ветка не сработает, хотя отлабчик упорно показывает что TBIV = 0x2.

У меня мысль что TBIV сбрасывается еще до входа в прерывание , а при отладке по шагам TBIV вновь устанавливается от нового захвата (импульсы продолжают идти)
Вообщем я уже порядочно запутался.
Go to the top of the page
 
+Quote Post
VAI
сообщение Oct 24 2006, 13:19
Сообщение #2


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

Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37



А почему Вы не использовали swith, интересно. Вот мой код из изделия, все работает прекрасно.
Тут, правда, измеряется 1 сигнал, но не в этом проблема, в другом изделии измеряется несколько.
В третьем 2 последовательных порта на таймереА в дуплексе молотят, правда со скорость 19200.
Код
#define QUANTUM_B   ID_0                // Входной делитель для таймера В (квант таймера В)

#if ( QUANTUM_B == ID_0 )               // == 1 (2/3 us)
  #define MAGIC_tax   180000000L        // Постоянная для перевода измереного в квантах периода в об/мин
  #define MAX_tax_h   0x0132            // приблизительно 9 об/мин = 13.3 секунд период
  #define tax_h_0300  0x0009            // приблизительно 300 об/мин
  #define tax_h_0700  0x0004            // приблизительно 700 об/мин
#elif ( QUANTUM_B == ID_1 )             // == 2 (4/3 us)
  #define MAGIC_tax   90000000L         // Постоянная для перевода измереного в квантах периода в об/мин
  #define MAX_tax_h   0x0099            // приблизительно 9 об/мин = 13.3 секунд период
  #define tax_h_0300  0x0005            // приблизительно 300 об/мин
  #define tax_h_0700  0x0002            // приблизительно 700 об/мин
#elif ( QUANTUM_B == ID_2 )             // == 4 (8/3 us)
  #define MAGIC_tax   45000000L         // Постоянная для перевода измереного в квантах периода в об/мин
  #define MAX_tax_h   0x004d            // приблизительно 9 об/мин = 13.3 секунд период
  #define tax_h_0300  0x0002            // приблизительно 300 об/мин
  #define tax_h_0700  0x0001            // приблизительно 700 об/мин
#endif  //QUANTUM_B

#define tax_T_MAX     ULONG_MAX

void tax_ini( void )
{
  tax_T = tax_T_MAX;
  tax_h = MAX_tax_h;
  P4SEL = BINARY( 01000000 );           // Capture6
  P4DIR = BINARY( 00111111 );
  P4OUT = BINARY( 00000000 );

// Capture6 по фронту, входной сигнал CCI6A, Синхронный, Режим захвата, прерывание
  TBCCTL6 = CM_1 + CCIS_0 + SCS + CAP + CCIE;
// Настроим таймер B
  TBCTL = TBSSEL_2                      // тактирование от SMCLK = 1.5 МГц
        + QUANTUM_B                     // входной делитель
        + MC_2                          // Непрерывный режим: таймер считает вверх к 0ffffh
        + TBIE;                         // прерывание
}


#pragma vector=TIMERB1_VECTOR
__interrupt  void TIMERB1_isr( void )   //    12 * 2 - 0xfff8 Timer B 1-7
{
unsigned long t;
static unsigned short c6zero;           // "нулевое" состояние таймера ("вес тары") для Capture6

  switch ( __even_in_range( TBIV, 0x0e ))
  {
// + Compare1 -
    case 0x02:
      break;
// - Compare1 -

// + Capture/Compare2 -
    case 0x04:
      break;
// - Capture/Compare2 -

// + Capture/Compare3 -
    case 0x06:
      break;
// - Capture/Compare3 -

// + Capture/Compare4 -
    case 0x08:
      break;
// - Capture/Compare4 -

// + Capture/Compare5 -
    case 0x0a:
      break;
// - Capture/Compare5 -

// + Capture6 - измерение периода вращения
    case 0x0c:
      t = tax_h * 0x10000L + TBCCR6;
      t -= c6zero;                      // вычтем "нулевое" состояние таймера ("вес тары")
      c6zero = TBCCR6;                  // сохраним "нулевое" состояние таймера ("вес тары")
      if ( tax_h > tax_h_0300 )
        tax_T = t;
      else if ( tax_h > tax_h_0700 )
        tax_T = ( tax_T + t ) / 2;      // Вращается быстро, немного усредним
      else
        tax_T = ( 3 * tax_T + t ) / 4;  // Вращается совсем быстро, усредним сильнее
      tax_h = 0;                        // сбросим старшее слово
      break;
// - Capture6 - измерение периода вращения

// + переполнение таймера, считаем старшее слово
    case 0x0e:                          // переполнение таймера, считаем старшее слово
      if ( tax_h < MAX_tax_h )          // ограничиваем минимальные обороты
        tax_h++;
      else
        tax_T = tax_T_MAX;              // минимальные обороты достигнуты
      break;
// - переполнение таймера, считаем старшее слово
  }
}


--------------------
Если зайца бить, его можно и спички научить зажигать
Сколько дурака не бей - умнее не будет. Зато опытнее
Go to the top of the page
 
+Quote Post
-=Space=-
сообщение Oct 25 2006, 06:23
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 105
Регистрация: 14-01-05
Из: Москва Зеленоград
Пользователь №: 1 962



как я понял вся разница в использовании или нет функции __even_in_range

насчет switch или if? у меня раньше и был switch, надо будет к ней вернуться

единственно что ни как не вкурю что за __even_in_range и что она делает
референсгуайд и нелп читал , не помогает
Цитата(CompilerReferenceGuide)
The interrupt vector register contains information about the interrupt source, and the
interrupt service routine normally uses a switch statement to find out which interrupt
source issued the interrupt. To help the compiler generate optimal code for the switch
statement, the intrinsic function __even_in_range must be used. The following
example defines a Timer A interrupt routine:
Код
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1_ISR(void)
{
switch (__even_in_range(TAIV, 10))
{
case 2: P1POUT ˆ= 0x04;
break;
case 4: P1POUT ˆ= 0x02;
break;
case 10: P1POUT ˆ= 0x01;
break;
}
}


The intrinsic function __even_in_range requires two parameters, the interrupt vector
register and the last value in the allowed range. The effect of the intrinsic function is that
the generated code can only handle even values within the given range, which is exactly
what is required in this case as the interrupt vector register for Timer A can only be 0,
2, 4, 6, 8, or 10. If the __even_in_range intrinsic function is used in a case where an
odd value, or a value outside the given range could occur, the program will fail.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 25 2006, 06:45
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(-=Space=- @ Oct 24 2006, 15:44) *
однако ни одна ветка не не выполняется в режиме реального времени, хотя
в отладке по шагам все работает
если поставить точки останова в строках (1) и (2),
и после остановки в (1) выполнить переход по шагам то tbiv получает парвильное значение и все работает
если после остановки в (1) нажать F5 то программа остановится в (2) но tbiv будет =0, и ниодна ветка не сработает, хотя отлабчик упорно показывает что TBIV = 0x2.

У меня мысль что TBIV сбрасывается еще до входа в прерывание , а при отладке по шагам TBIV вновь устанавливается от нового захвата (импульсы продолжают идти)
Вообщем я уже порядочно запутался.

Цитата из Компэловской книги "Семейство микроконтроллеров MSP430x1xx.
Руководство пользователя."
Код
Генератор вектора прерывания TBIV
Флаг TBIFG и флаги TBCCRx CCIFG (кроме TBCCR0 CCIFG) распределены по при-
оритетам и объединены в источник одного вектора прерывания. Регистр вектора пре-
рывания TBIV используется для определения, какой флаг запросил прерывание.
Разрешенное прерывание с наивысшим приоритетом (кроме TBCCR0
CCIFG) генерирует число в регистре TBIV (см. описание регистра). Можно оце-
нить это число или добавить его к программному счетчику для автоматическо-
го входа в соответствующую процедуру программы. Запрещенные прерывания
таймера В не воздействуют на значение TBIV.
Любой тип доступа: чтение или запись регистра TBIV автоматически сбра-
сывает флаг наивысшего ожидающего прерывания. Если установлен другой
флаг прерывания, будет немедленно сгенерировано другое прерывание после
обработки изначального прерывания. К примеру, если флаги TBCCR1 и TBCCR2
CCIFG установлены, когда процедура обработки прерывания обращается к ре-
гистру TBIV, флаг TBCCR1 CCIFG автоматически сбрасывается. После выпол-
нения команды процедуры обработки прерывания RETI, флаг TBCCR2 CCIFG
генерирует другое прерывание.

Во-первых, проверьте разрешены ли у вас идивидуальные прерывания от регистров capture - бит CCIE в регистрах TBCCTLx.
Во-вторых, для того чтобы обслужить все флаги в одном прерывании нужно прочитать TBIV столько раз сколько имеется источников прерываний в данном модуле (6+1). У вас же насколько я вижу TBIV читается один раз. Поэтому обрабатываться за одно прерывание может только один источник прерываний модуля TimerB. И для обработки трех установленных флагов (в вашем случае) прерывание должно быть вызвано последовательно три раза.
Go to the top of the page
 
+Quote Post
VAI
сообщение Oct 25 2006, 07:02
Сообщение #5


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

Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37



__even_in_range описана в файле "...\430\doc\EW430_CompilerReference.pdf"
Можно и без нее, просто оптимизируется switch..


--------------------
Если зайца бить, его можно и спички научить зажигать
Сколько дурака не бей - умнее не будет. Зато опытнее
Go to the top of the page
 
+Quote Post
-=Space=-
сообщение Oct 25 2006, 07:51
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 105
Регистрация: 14-01-05
Из: Москва Зеленоград
Пользователь №: 1 962



попробовал с функцией __even_in_range
вообщем она влияет на компиляциию и в асме видно что код становится короче
девайса пока нет, проверить в железе не могу, но в Симуляции НЕ работает!!!

прерывание вызывается, но ни в один из cаse не заходит
в симуляторе TBIV упорно хранит 0, хотя прерывания вызывал пачками

давайте выложу проект полностью
Прикрепленные файлы
Прикрепленный файл  project.zip ( 11.61 килобайт ) Кол-во скачиваний: 37
 
Go to the top of the page
 
+Quote Post
Shread
сообщение Oct 25 2006, 19:42
Сообщение #7


иногда заглядывающий
****

Группа: Свой
Сообщений: 900
Регистрация: 18-05-05
Из: Зеленоград
Пользователь №: 5 170



Цитата(-=Space=- @ Oct 25 2006, 11:51) *
попробовал с функцией __even_in_range
вообщем она влияет на компиляциию и в асме видно что код становится короче
девайса пока нет, проверить в железе не могу, но в Симуляции НЕ работает!!!

прерывание вызывается, но ни в один из cаse не заходит
в симуляторе TBIV упорно хранит 0, хотя прерывания вызывал пачками

давайте выложу проект полностью

Симулятор периферию не симулит, в том числе таймеры.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 25 2006, 20:58
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Shread @ Oct 26 2006, 01:42) *
Цитата(-=Space=- @ Oct 25 2006, 11:51) *

попробовал с функцией __even_in_range
вообщем она влияет на компиляциию и в асме видно что код становится короче
девайса пока нет, проверить в железе не могу, но в Симуляции НЕ работает!!!

прерывание вызывается, но ни в один из cаse не заходит
в симуляторе TBIV упорно хранит 0, хотя прерывания вызывал пачками

давайте выложу проект полностью

Симулятор периферию не симулит, в том числе таймеры.

Точнее будет сказать не полностью симулирует.
В C-CPY есть оконо Forced Interrupt Window, где можно симулировать прерывания, выбрав нужное и кликнув по кнопке Trigger. В поле Description этого окна указаны пары: маска прерывания и флаг прерывания. Например, у вектора TIMERB1_VECTOR можно вызвать прерывания с маской TBCCTLx.CCIE и флагом TBCCTLx.CCIFG (где x - номер соответствующего регистра capture/compare). Но если, остановив дебаггер, последовательно симулировать вызов нескольких разных прерываний с вектором TIMERB1_VECTOR, а потом немного пошагать, то видно что симулятор вполне правильно установил флаги соответствующих прерываний в регистрах TBCCTLx. И сбрасываются они по одному при каждом вызове прерывания с вектором TIMERB1_VECTOR в соответствии с их приоритетами. А вот TBIV при этом действительно не изменяется и если нужно проверить логику выполнения ветвлений по TBIV, то его значение следует выставлять в симуляторе ручками.
Go to the top of the page
 
+Quote Post
Shread
сообщение Oct 26 2006, 10:24
Сообщение #9


иногда заглядывающий
****

Группа: Свой
Сообщений: 900
Регистрация: 18-05-05
Из: Зеленоград
Пользователь №: 5 170



smile.gif даже чуть-чуть не симулит, то, что вы описали - это ядро процессора, а не модуль таймера, а вот то, что касается самого таймера приходится делать ручками. ИМХО удобнее в камне все сразу делать, да и вероятность ошибок ниже, мало ли чего он там насимулит.
Go to the top of the page
 
+Quote Post

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

 


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


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