Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по конфигурации входа на захват для 2012
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Vladimir_T
Уважаемые коллеги, подскажите, пожалуйста. Нужно мерить длительность импульса на ноге P1.1 (MSP430F2012) , самое простое - это подключить к нему таймер в режиме захвата CCI и захват делать по обоим фронтам. Но вход никак не конфигурируется, как CCIA , после инициализации он находится в третьем состоянии, хотя я его подтянул, все входные импульсы игнорирует. В чем может быть дело?
Код
/****************************************************************************
  Функция приема данных через 1-проводный интерфейс
****************************************************************************/
#define BQ2016   BIT1       // сигнал управления 1-проводным

unsigned char Init_HBQ (void)
{
  Flg_Rcv = true;
    
  P1OUT |= BQ2016;               // P1.1 Set HI    
  P1DIR &= ~BQ2016;              // P1.1 Set as Input
  P1REN |= BQ2016;                // P1.1 Pul Up Res
  P1SEL |= BQ2016;                 // P1.1 Set as CCIA input

  
  CCR0 = T_CYCH;                         // Data Hold
  TACTL = TASSEL_2 + MC_1;          // SMCLK = 1 mHz, up-mode
  TACCTL0 = CM_3 + CAP + CCIE;   // Capture on the both edge, CCIA + CCIFG
  
return 1;
} //
rezident
А как вы определили что не работает? Вы разрешили прерывание от CCR0, а где обработчик этого прерывания? Вообще следует все регистры инициализировать явными значениями, а не накладывать маски на дефолтные. Вдобавок нужно неиспользуемые вектора прерываний обозначить хотя бы NOPом, а еще лучше вечными циклами ( for( ; ; ); ), чтобы сразу выловить "левые" прерывания. Которые бывают весьма часто когда ленятся инициализировать все регистры периферии.
Vladimir_T
Функция обаботки вектора прерывания от CCR0 имеется, регистры конфигурирются корректно, отладчиком просматривал неоднократно. Явными значениями конфигурирую регистры при старте программы, а потом с уверенностью накладываю маски, получается нормально. Я не могу понять почему после этих установок:
Код
  P1DIR &= ~BQ2016;              // P1.1 Set as Input
  P1SEL |= BQ2016;                 // P1.1 Set as CCIA input

на P1.1 устанавливается низкий уровень и тогда никаких фронтов на входе CCIA таймеры не бывает. Вот об этом поведении я только и хотел сказать.
А так как вход CCIA не конфигурируется, пришлось измерять период между фронтами на P1.1 с помощью прерываний от порта P1 и того же тайиера. Такая связка работает, но есть осадок от того, что не удается реализовать эффективней.
rezident
"Тяжело ловить черную кошку в темной комнате". И заниматься телепатией нисколько не менее сложно laughing.gif В цитируемых вами строках криминала нет. Поэтому разумнее было бы привести весь исходник или проект. А то может у вас где-то перекрестная инициализация регистров имеется. Или, например, работа с ADC10, где вы неудачно ADC10AE прописали.
А еще не мешало бы errata внимательно просмотреть. Например, вот
Vladimir_T
Вы привели выдержку для выходной функции выводов, тут все соответствует действительности, а вот мне нужно сконфигурировать пин, как вход для запуска таймера. Причем к этому входу должны внутри подключиться оба входа CCI0A и CCI1A для запуска таймера по переднему фронту и останова по заднему. Проект только начал, так что исходник почти весь и привел. rolleyes.gif А при отладки уперся в то, что сигнала на входе нет (он просто коротится на землю), а ведь я его подтягиваю до питания, потому что у м/с BQ2016 выход - открытый исток. Ну да ладно, отстану я от этих внутренних резисторов (P1REN), прилужу снаружи резистор, все должно работать у таймера.
rezident
Цитата(Vladimir_T @ Apr 21 2010, 14:30) *
Вы привели выдержку для выходной функции выводов, тут все соответствует действительности, а вот мне нужно сконфигурировать пин, как вход для запуска таймера.
Я-то понял вашу задачу, но вы видимо не совсем поняли описания этого бага. Сделать перевод?
Цитата(Vladimir_T @ Apr 21 2010, 14:30) *
Ну да ладно, отстану я от этих внутренних резисторов (P1REN), прилужу снаружи резистор, все должно работать у таймера.
Вот это правильно! Внешний pull-up он всегда надежней, потому что материален и визуально наблюдаем smile.gif
Vladimir_T
Знать бы такое дело, то заложил бы на плате этот резистор, а теперь придеться навешивать. Каждая навеска - это недоработка или недопонятки или ошибки .... unsure.gif
Vladimir_T
Уважаемые, коллеги, в продолжении начатой темы. Спасибо rezidentу, показал мне, где нужно читать внимательно. Но в ревизии D процессора эта ошибка будет исправлена.
Сейчас вход таймера конфигурируется для захвата и прерывания нормально идут, Но не пойму, почему в прерывании из TACCR0 вычитываются очень часто нули? Сигнал на входе таймера с переменной длительностью 50 - 150 мксек, тактирование таймера - 1 мГц. Почему нули в TACCR0, ведь между фронтами запуска таймера время на менее 40 мксек? Буду очень благодарен, если кто-нибудь мне подскажет.

Код
/****************************************************************************
  Функция приема данных через 1-провoдный интерфейс
****************************************************************************/
unsigned int T_P [18];

unsigned char Rcv_HDQ (void)
{unsigned int Tick_W;    

  P1OUT |= BQ2016;                // P1.1 Set HI    
  P1DIR &= ~BQ2016;               // P1.1 Set as Input
  P1SEL |= BQ2016;                 // P1.1 Set as CCIA input

   Cnt_Bit =0;  
   Tick_W = Tick_ms + Lim_Wait_HDQ;
  
  TAR = 0;
  TACTL = TASSEL_2 + MC_1;                  // SMCLK = 1 mHz, up-mode
  TACCTL0 = CM_3 + CAP + CCIE + SCS;      // Capture on the both edge, CCIA + CCIFG

while ((Cnt_Bit != 16) && (Tick_W > Tick_ms));  // Ожидане окончания приема

  CCTL0 &= ~CCIE;           // CCR0 interrupt disabled
  TACCTL0 = 0;              // No Capture mode
  P1SEL &= ~BQ2016;         // P1.1 Set as GPIO input

  if (Tick_W < Tick_ms) return (0);  // если таймаут не исчерпан и получен ответ, то ошибки приема нет
else return (1);  // в противном случае - ошибка приема
} //  Rcv_HBQ (void)


// Timer A0 interrupt service routine
// State Mashine 1-Wire protocol

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
      T_P [Cnt_Bit++] = TACCR0;  
} //  __interrupt void Timer_A (void)
rezident
Цитата(Vladimir_T @ May 12 2010, 13:03) *
Но не пойму, почему в прерывании из TACCR0 вычитываются очень часто нули?
Видимо потому, что вы используете таймер в режиме Up-mode, а хотели наверняка в режиме Continuous-mode. Либо Up-mode, но при этом следует использовать другой вход захвата, который связан с CCR1, а не с CCR0. И соответственно использовать другой вектор прерывания. Почитайте внимательно в User's Guide про режимы работы таймера.
Кроме того, вот здесь у вас потенциальная ошибка зарыта.
Цитата(Vladimir_T @ May 12 2010, 13:03) *
Код
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
      T_P [Cnt_Bit++] = TACCR0;  
} //  __interrupt void Timer_A (void)

Буферизация без явной проверки на выход за границы буфера это типовая ошибка и потенциальный глюкодром.
Vladimir_T
Буферизация без явной проверки на выход за границы буфера это типовая ошибка и потенциальный глюкодром.
[/quote]

Спасибо за ответ. Но хотел пояснить почему нет проверки на выход за границы буфера: ответ от м/с BQ2016 по олнопроводному интерфейсу получаю байтом, который передается побитно. Количество фронтов получается аппаратно фиксировано, т.е. 8*2=16. Потому и не стал делать проверку. У меня так мало памяти осталось в проце, вот и стал экономить, а нужно еще функции анализа вставить.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.