Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помоните новичку!
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Allregia
Только осваиваю MSP, задавал вопросы тут рядом, в теме о длительности цикла. С тем вроде понятно.
но помогите плиз, посмотрите - где у меня тут ошибка?
Пытаюсь помигать светодиодом по прерыванию от Таймера A:
CODE
#include "defs.h"
#include "ports.h"
//#include "display.h"
//-----------------------------------------------
#pragma vector=TIMERA0_VECTOR
__interrupt void timera0_interrurpt(){
LED_BAT1_TOGGLE;
#ifndef DEBUG
WDTCTL = WDTPW + WDTCNTCL;
#endif
}
//-----------------------------------------------

#pragma vector=TIMERB0_VECTOR
__interrupt void timerb0_interrupt(){
//LED_BAT1_TOGGLE;
//LEDS_ON; _NOP(); LEDS_OFF;
#ifndef DEBUG
WDTCTL = WDTPW + WDTCNTCL;
#endif

}

//------------------------------------------------
void SwitchToHighClock(void){ // XT1=ON, XT2=ON, MLCK=XT2, SMCLK=XT2, ACLK=XT1
int i;
BCSCTL1 = 0; // Turn on XTL2
do{
IFG1 &= ~OFIFG; //clear OFIFG
for (i=0x0F; i>0; i--) _NOP();
} while( (IFG1 & OFIFG)!=0);
BCSCTL2 = SELM1+SELS; // MCLK = XTL2, /1, SMCLK=XT2, /1, IntRes DCO
__bic_SR_register(SCG1); // Turn on SMCLK
}

void SwitchToLowClock(void){ // XT1=ON, XT2=OFF, MLCK=XT1, SMCLK=OFF, ACLK=XT1
int i;
BCSCTL1 = 0x80; // Turn off XTL2
do{
IFG1 &= ~OFIFG; //clear OFIFG
for (i=0x0F; i>0; i--) _NOP();
} while( (IFG1 & OFIFG)!=0);
BCSCTL2 = SELM1+SELM0 + SELS; // MCLK = XTL1, /1, SMCLK=XT2, /1, IntRes DCO
__bis_SR_register(SCG1); // Turn off SMCLK
}

void SetClock(){
__bic_SR_register(OSCOFF); // turn ON clock generator
SwitchToLowClock();
}
//--
void InitTimers(){
// Timer A
TACTL = TASSEL_2+MC_1+ID_3; // XT2 Select (8Mhz), Up to CCR0, divide by 8 to get 1Mhz
TACCR0 = 62500-1; // Interrunt every 1/16 Sec
TACCTL0 = CCIE;
TAR = 0;
TACTL |=TAIE;
// Timer B
TBCTL = TBSSEL_1 + MC_1; // ACLK Clock input
TBCCTL0 = CCIE;
TBCCR0 = 3333; // ~ 0.1 Sec @ 32.768kHz XT1
TBR=0;
//TBCTL |= TBIE;
}
//================================================================================
========
void main( void ){
//int i;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

// Clock init
SetClock();
SwitchToHighClock();
//initPorts();
P2DIR = 0xFF;
P3DIR = 0x0B;
P4DIR = 0x03;
P5DIR = 0x7F;
DDIR = 0xFF;

InitTimers();

__enable_interrupt();
while(1){
WDTCTL = WDTPW + WDTCNTCL;
}
}
}


Таймер B я там подготовил к такой-же процедуре, но пока его прерывание не включено.
В чем проблема - оно мигает, но на обоих фронтах есть глитч. Т.е. переходит из 0 в 1
потом примерно через 2.3мс переходит из 1 на половину уровня, еще через 3.7мс
возвращяется к 1.
Если не образать внимание на глитч, то период примерно правильный.
Но (!) - почему-то на совсем другом порту, который я не трогаю, возникают импульсы
с периодом как у моего светодиода, и длительностью - как у глитча. Какого?!

Подскажите - что я не заметил или не знаю ?
rezident
Цитата(Allregia @ May 21 2009, 19:33) *
Подскажите - что я не заметил или не знаю ?
Подсказываю. Вы неправильно работаете с таймером.
Во-первых, нужно сначала инициализировать его и только потом запускать. И во время работы обнулять TAR нельзя. Для этого бит TACLR в TACTL имеется. Т.е. ваша инициализация должна выглядеть так.
Код
         // Timer A
         TACTL   = TASSEL_2|ID_3|TACLR;   // XT2 Select (8Mhz), Up to CCR0, divide by 8 to get 1Mhz
         TACCR0  = 62500-1;                // Interrunt every 1/16 Sec
         TACCTL0 = CCIE;
         TACTL   |= MC_1;

Во-вторых, вы разрешаете два прерывания от TimerA, но обработчик прерывания только один вектор обрабатывает (от TACCR0). Команда
Код
         TACTL   |=TAIE;
ненужная потому, что бит TAIE разрешает прерывание от переполнения таймера, а вы его не используете и функцию обработчика по вектору от переполнения прерывания (TIMERA1_VECTOR) не разместили . Вот поэтому-то (отсутствие обработчика прерывания) видимо и происходит ваш глитч.
Кстати, WDT в вашем случае сбрасывать не обязательно, т.к. вы его запретили первой командой в main
Код
WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
Allregia
Цитата(rezident @ May 21 2009, 19:06) *
Во-вторых, вы разрешаете два прерывания от TimerA, но обработчик прерывания только один вектор обрабатывает (от TACCR0). Команда
Код
         TACTL   |=TAIE;
ненужная потому, что бит TAIE разрешает прерывание от переполнения таймера, а вы его не используете и функцию обработчика по вектору от переполнения прерывания (TIMERA1_VECTOR) не разместили . Вот поэтому-то (отсутствие обработчика прерывания) видимо и происходит ваш глитч.


Вот блин, и на старуху бывает проруха...
Я что-то подобное и предполагал, что вызывается переход на несуществующий обработчик, только не мог понять откуда оно берется.
В эмуляторе видел что программа рестартует.

Огромное спасибо, это моя невнимательность и доверчивость - кусок инициализации таймеров я скопировал с чужой программы.
Только непонятно - как она работает? А ведь работает.
Кстати в той же программе они клок переключают тоже без ожидания (о чем мы в теме рядом говорили).

"Как же он работал в очистке?"(с)Собачье Сердце.

Цитата
Кстати, WDT в вашем случае сбрасывать не обязательно, т.к. вы его запретили первой командой в main
Код
WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer


Это просто на будущее, когда вотчдог будет работать.

Еще раз спасибо, пойду теперь с АЦП разбираться, там тоже наворочено всего...
rezident
Цитата(Allregia @ May 22 2009, 00:38) *
Я что-то подобное и предполагал, что вызывается переход на несуществующий обработчик, только не мог понять откуда оно берется.
В эмуляторе видел что программа рестартует.
Для себя принял такое правило, если не идет борьба за каждый байт (случалось и такое), то я инициализирую все вектора прерываний, имеющиеся в кристалле. Хотя бы один NOP в обработчик вставляю. При отладке будет проще отловить такой конфуз как вызов неиспользуемого прерывания.
Allregia
Цитата(rezident @ May 22 2009, 00:29) *
Для себя принял такое правило, если не идет борьба за каждый байт (случалось и такое), то я инициализирую все вектора прерываний, имеющиеся в кристалле. Хотя бы один NOP в обработчик вставляю. При отладке будет проще отловить такой конфуз как вызов неиспользуемого прерывания.


№ меня к счастью 1611, у него памяти более чем достаточно для этого устройства.
Правда, играюсь я пока со 148-м (есть готовая платка от другогоприбора я ее как макет использую).

Про инициализицию всего - мысль хорошая. А можно набраться наглости, и попросить полный список? А то я начну составлять- обязательно что-то пропущу по неопытности с этим проциком.
rezident
Цитата(Allregia @ May 22 2009, 03:44) *
А можно набраться наглости, и попросить полный список? А то я начну составлять- обязательно что-то пропущу по неопытности с этим проциком.
Дык в хедерах от TI (в IAR они тоже включены) весь список векторов имеется wink.gif Вот фрагмет из msp430x14x.h
Код
/************************************************************
* Interrupt Vectors (offset from 0xFFE0)
************************************************************/

#define PORT2_VECTOR        (1 * 2u)  /* 0xFFE2 Port 2 */
#define USART1TX_VECTOR     (2 * 2u)  /* 0xFFE4 USART 1 Transmit */
#define USART1RX_VECTOR     (3 * 2u)  /* 0xFFE6 USART 1 Receive */
#define PORT1_VECTOR        (4 * 2u)  /* 0xFFE8 Port 1 */
#define TIMERA1_VECTOR      (5 * 2u)  /* 0xFFEA Timer A CC1-2, TA */
#define TIMERA0_VECTOR      (6 * 2u)  /* 0xFFEC Timer A CC0 */
#define ADC12_VECTOR          (7 * 2u)  /* 0xFFEE ADC */
#define USART0TX_VECTOR     (8 * 2u)  /* 0xFFF0 USART 0 Transmit */
#define USART0RX_VECTOR     (9 * 2u)  /* 0xFFF2 USART 0 Receive */
#define WDT_VECTOR          (10 * 2u) /* 0xFFF4 Watchdog Timer */
#define COMPARATORA_VECTOR  (11 * 2u) /* 0xFFF6 Comparator A */
#define TIMERB1_VECTOR      (12 * 2u) /* 0xFFF8 Timer B CC1-6, TB */
#define TIMERB0_VECTOR      (13 * 2u) /* 0xFFFA Timer B CC0 */
#define NMI_VECTOR          (14 * 2u) /* 0xFFFC Non-maskable */
#define RESET_VECTOR        (15 * 2u) /* 0xFFFE Reset [Highest Priority] */

#define UART1TX_VECTOR      USART1TX_VECTOR
#define UART1RX_VECTOR      USART1RX_VECTOR
#define UART0TX_VECTOR      USART0TX_VECTOR
#define UART0RX_VECTOR      USART0RX_VECTOR
#define ADC_VECTOR          ADC12_VECTOR

Кстати, в IAR EW есть два вида заголовочных файлов: msp430x....h это от производителя (TI), а io430x....h это от IAR. Я предпочитаю хедеры от TI использовать.
MrYuran
Цитата(rezident @ May 21 2009, 20:06) *
Кстати, WDT в вашем случае сбрасывать не обязательно, т.к. вы его запретили первой командой в main
Код
WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

А после команды
WDTCTL = WDTPW + WDTCNTCL;
он начинает щёлкать, причем при тактировании от 8МГц - очень быстро.
Может, он и сбрасывает
Dog Pawlowa
Цитата(rezident @ May 22 2009, 00:29) *
Для себя принял такое правило, если не идет борьба за каждый байт (случалось и такое), то я инициализирую все вектора прерываний, имеющиеся в кристалле. Хотя бы один NOP в обработчик вставляю.

Ну или так. Под отладчиком сразу видно, что произошло что-то.

Код
#pragma vector=COMPARATORA_VECTOR
__interrupt void StayHere6()
{      for (;;);     }
Сергей Борщ
Цитата(Allregia @ May 21 2009, 21:38) *
Кстати в той же программе они клок переключают тоже без ожидания (о чем мы в теме рядом говорили).
А в той программе случайно не было обработчика прерывания OFIFG? Я так и делаю - переколючаюсь сразу и разрешаю прерывание. Фактически переключение произойдет в обработчике, из плюсов - переключение повторится, если автоматика переключит тактирование на DCO из-за сбоя. При переключении на старте и сбое вы навсегда перейдете на тактирование от DCO.
rezident
Цитата(MrYuran @ May 22 2009, 10:57) *
он начинает щёлкать, причем при тактировании от 8МГц - очень быстро.
Не, не очень быстро. SMCLK/32768=8МГц/32768=244Гц всего. laughing.gif
Цитата(Сергей Борщ @ May 22 2009, 14:12) *
Я так и делаю - переколючаюсь сразу и разрешаю прерывание.
Аналогично. Только я, не переключаясь, принудительно устанавливаю бит OFIFG, а затем сразу разрешаю прерывание битом OFIE.
Allregia
Цитата
А в той программе случайно не было обработчика прерывания OFIFG?


Неа.

А с таймерами я разобрался, большое всем спасибо.
Allregia
Еще небольшой вопрос:
Мне надо некоторые параметры, буквально десяток байт,периодически (раз в 5 минут) запоминать в энергонезависимой памяти (небольшой лог).
Но как я понял, в МСП430 нет ЕЕПРОМ а есть только флеш (256 байт в 1611), в которую нельзя писать произвольные данные. Т.е. каждый раз надо все стирать.
Как вы решаете подобные вопросы?


P.S. Или не морочить себе голову и прилепить снаружи 24хх или 96хх ?
dxp
Цитата(Allregia @ May 23 2009, 13:23) *
Еще небольшой вопрос:
Мне надо некоторые параметры, буквально десяток байт,периодически (раз в 5 минут) запоминать в энергонезависимой памяти (небольшой лог).
Но как я понял, в МСП430 нет ЕЕПРОМ а есть только флеш (256 байт в 1611), в которую нельзя писать произвольные данные. Т.е. каждый раз надо все стирать.
Как вы решаете подобные вопросы?

Да, чтобы обновить хотя бы бит, надо стирать весь сегмент. На то она и флешь. Там для этого специально выделено два сегмента (в новых моделях их, вроде уже больше) для этих целей - в одном лежит текущая копия данных, при необходимости обновить - данные с обновлениями пишутся в другой сегмент, а текущий стирается. В следующий раз - то же самое, только сегменты меняются местами. Не очень удобно, может показаться, но написав один раз код, он работает без проблем. С EEPROM'ом тоже не все так безоблачно - для надежного хранения надо там и контрольные суммы делать, а то и копии резервные держать и т.д. Возни тоже хватает.

Следует только обратить внимание на два момента:

  1. ресурс флеши - гарантируется, AFAIR, 10 000 циклов стирания;
  2. время стирания сегмента - оно может окзаться неприемлимо большим (десятки миллисекунд, точно не скажу, забыл, под рукой данных нет). Хотя запись слова производится довольно быстро - ставил эксперимент еще на F149 - там выходило что-то порядка 100-125 мк.
Цитата(Allregia @ May 23 2009, 13:23) *
P.S. Или не морочить себе голову и прилепить снаружи 24хх или 96хх ?


Это уже вам виднее. smile.gif
MrYuran
Цитата(Allregia @ May 23 2009, 10:23) *
Но как я понял, в МСП430 нет ЕЕПРОМ а есть только флеш (256 байт в 1611), в которую нельзя писать произвольные данные. Т.е. каждый раз надо все стирать.
Как вы решаете подобные вопросы?

Если параметров немного, можно писать циклически, постепенно заполняя сегмент.
При достижении конца сегмента - стирать.

Хотя можно и не ограничиваться одним сегментом, наверняка пустых много.
Allregia
Цитата(dxp @ May 23 2009, 10:54) *
С EEPROM'ом тоже не все так безоблачно - для надежного хранения надо там и контрольные суммы делать


В ЕЕПРОМ типа 24хх/96хх это уже все внутри. Именно за счет избыточности (Хеминга) там и достигаются огромные (по сравнению с флеш) значения endurance.

Цитата
, а то и копии резервные держать и т.д. Возни тоже хватает.

Следует только обратить внимание на два момента:

  1. ресурс флеши - гарантируется, AFAIR, 10 000 циклов стирания;
  2. время стирания сегмента - оно может окзаться неприемлимо большим (десятки миллисекунд, точно не скажу, забыл, под рукой данных нет). Хотя запись слова производится довольно быстро - ставил эксперимент еще на F149 - там выходило что-то порядка 100-125 мк.


Это уже вам виднее. smile.gif


Видимо придется, у ЕЕПРОМ ресурс минимум на порядок больше, типично - на два порядка (1М), а иногда и на три (10М).
dxp
Цитата(Allregia @ May 23 2009, 17:11) *
Видимо придется, у ЕЕПРОМ ресурс минимум на порядок больше, типично - на два порядка (1М), а иногда и на три (10М).


Если FRAM применить, то вообще об этом думать не надо - пиши хоть непрерывно в одну и ту же ячейку на максимальной скорости... Интерфейс у нее совместимый. Только она подороже, вроде.
Allregia
Цитата(dxp @ May 23 2009, 13:32) *
Если FRAM применить, то вообще об этом думать не надо - пиши хоть непрерывно в одну и ту же ячейку на максимальной скорости... Интерфейс у нее совместимый. Только она подороже, вроде.


О FRAM я слышал последний раз лет 5-6 назад, в ру.эмбеддед или су.хардв.схемз., они вообще еще живы, или померли как ЦМД-память?
dxp
Цитата(Allregia @ May 23 2009, 18:51) *
О FRAM я слышал последний раз лет 5-6 назад, в ру.эмбеддед или су.хардв.схемз., они вообще еще живы, или померли как ЦМД-память?


Да, вроде, живо все. На любой вкус - SPI'ные, I2C'шные. Их главный минус, насколько знаю, - цена по сравнению с EEPROM'ными аналогами.
Allregia
С УАРТОм вроде разобрался, но непонятки у меня продолжаются - теперь с АЦП.
Пока не готов сформулировать вопрос, попробую еще сам помучаться. Не получиться - буду опять просить "помощь Клуба".
dxp
Цитата(Allregia @ May 25 2009, 03:09) *
Пока не готов сформулировать вопрос, попробую еще сам помучаться. Не получиться - буду опять просить "помощь Клуба".

У TI на сайте есть пачка примеров на Си и асме для всей имеющейся периферии - инициализация, запуск. На старте весьма помогает разобраться с нюансами.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.