Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Таймер и с чем его есть (а точнее как)...
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
d7d1cd
Привет всем. Возникла необходимость использовать в работе таймер в микроконтроллере MSP430F149, а точнее чтобы через определенный промежуток времени вызывалось прерывание. И у таймера А и у таймера В в таблице векторов прерываний есть по 2 вектора. Вопросы такие:

1. Зачем каждому таймеру по 2 вектора?

2. Возможно ли как-то использовать таймеры без использования прерывания от них?

3. Можно привести пример простейшей программы, инициализирующей, например, таймер А, в результате чего таймер через определенный промежуток времени генерирует прерывание?




P.S. Не судите строго. Я только начал изучать. User Guide читал, но мало что понял.

controller_m30
Если что, есть в нете русский вариант user guide http://cwer.ws/node/183511/ Проверил ссылку на депозитфайл - там качается.

1. Два вектора потому, что один только для одного источника TACCR0 CCIFG, а второй вектор общий для нескольких источников сразу: TACCR1 CCIFG, TACCR2 CCIFG, TAIFG . Во втором случае надо делать дополнительное программное определение источника прерывания по его вектору в спец.регистре TAIV. Но если известно заранее, что будет только один источник прерывания (напр. TAIFG ) - то ничего дополнительно вычислять не надо, а сразу обрабатывать прерывание как обычно. Тоже и для таймера В.

2. Ну как... они считают и без прерываний... просто при событии выставляют флаги (переполнение, захват, и проч.), а за флагами тогда надо следить программно.

3. Это я не могу привести, бо не работал с этой моделью, и под рукой нет проверенного примера.
d7d1cd
Как я понимаю, в нормальной программе таймер надо использовать с прерыванием, а не программно делать опрос битов... User Guide я в переводе читал, но все равно мало что понятно. А что-то типа "регистр захвата\сравнения" для меня вообще темный лес...
Жаль, что нет ответа на 3 вопрос. Подскажите, кто знает.
_Артём_
Цитата(d7d1cd @ Sep 13 2012, 20:15) *
Жаль, что нет ответа на 3 вопрос. Подскажите, кто знает.

d7d1cd MSP430 уже десяток лет существуют, примеров кода полно. Пробовали поискать на сайте TI(www.ti.com)?
megabuks
Держи. Для кварца 32768 прерывание раз в секунду
CODE

;---------------
;config TIMER A
;---------------
bis #TACLR,&TA0CTL ;reset all presetting
mov.w #0x0110,&TA0CTL ;15-10=0(free);9,8=01(aclk);7,6=11(/8);5,4=01(up to taccr0)
;3=0(free);2=0(TACLR);1=1(прерывание разрешено);0=0(прерывания нет)
mov #0x7fff,&TA0CCR0 ;32768 interval 1c interrupt
bis #CCIE,&TA0CCTL0 ;
mov #0x0000,&TA0CCTL1;
; config TA0 end

собственно прерывание, в котором переключается пин (моргает св.диод)
;===================
; Interrupt Vector
;===================
;------------
;Timer A0
;------------
TA0_CCR0_INT:
bic #0x0001,&TA0CTL
bit.b #0x02,P1OUT
jnz te1
bis.b #0x02,P1OUT
jmp te3
te1:
bic.b #0x02,P1OUT
te3:

reti

TA0_INT:
add.w &TA0IV,PC ; Add Timer_A offset vector
reti ; CCR0 - no source
jmp INT_CCR1 ; Vector 2: TA0CCR1 2
jmp CCIFG_2_HND ; Vector 4: TA0CCR2 2
jmp CCIFG_3_HND ; Vector 6: TA0CCR3 2
jmp CCIFG_4_HND ; Vector 8: TA0CCR4 2
jmp CCIFG_5_HND ; Vector 10: TA0CCR5 2
jmp CCIFG_6_HND ; Vector 12: TA0CCR6 2reti ; jmp INT_CCR2 ; CCR2
TA0_over:
; nop
reti ; Return from overflow ISR bic #0x0001,&TACTL
CCIFG_6_HND: ; Vector 12: TA0CCR6 2
reti ;
CCIFG_5_HND: ; Vector 10: TA0CCR5 2
reti
CCIFG_4_HND: ; Vector 8: TA0CCR4 2
reti
CCIFG_3_HND: ; Vector 6: TA0CCR3 2
reti
CCIFG_2_HND: ;Vector 4: TA0CCR2 2
reti
INT_CCR1:
reti
d7d1cd
Спасибо за код. Поясните его последнюю часть:
Код
TA0_INT:
        add.w   &TA0IV,PC               ; Add Timer_A offset vector
        reti                           ; CCR0 - no source
        jmp   INT_CCR1   ; Vector 2: TA0CCR1 2
        jmp   CCIFG_2_HND; Vector 4: TA0CCR2 2
        jmp   CCIFG_3_HND; Vector 6: TA0CCR3 2
        jmp   CCIFG_4_HND; Vector 8: TA0CCR4 2
        jmp   CCIFG_5_HND; Vector 10: TA0CCR5 2
        jmp   CCIFG_6_HND; Vector 12: TA0CCR6 2reti ;            jmp   INT_CCR2  ; CCR2
TA0_over:
      ; nop
        reti                           ; Return from overflow ISR                bic #0x0001,&TACTL
CCIFG_6_HND:; Vector 12: TA0CCR6 2
        reti ;
CCIFG_5_HND:; Vector 10: TA0CCR5 2
        reti
CCIFG_4_HND:; Vector 8: TA0CCR4 2
        reti
CCIFG_3_HND:; Vector 6: TA0CCR3 2
        reti
CCIFG_2_HND:             ;Vector 4: TA0CCR2 2
        reti  
INT_CCR1:
         reti
MrYuran
Цитата(d7d1cd @ Sep 13 2012, 21:15) *
Как я понимаю, в нормальной программе таймер надо использовать с прерыванием, а не программно делать опрос битов...

Можно и без прерываний, и без опроса, если используются аппаратные выходы защелок.
То есть таймер молотит совершенно автономно, как цифровой автомат, и выдает на выходы сигналы определенной длительности и полярности.

В обычном режиме тоже работает просто.
Счетчик крутится с заданной частотой (определяется источником тактирования и делителем 0/2/4/8), либо по кругу (0-ffff), либо от нуля до значения в CCR0, либо туда-обратно. Флаги прерываний выставляются, когда значение счетчика совпадает со значением соответствующей защелки. В зависимости от маски прерываний (бит IE в CCTLx) по флагу может вызываться прерывание.
megabuks
Цитата(d7d1cd @ Sep 14 2012, 05:53) *
Спасибо за код. Поясните его последнюю часть:
Код
TA0_INT:
        add.w   &TA0IV,PC              ; Add Timer_A offset vector
        reti                          ; CCR0 - no source
        jmp   INT_CCR1  ; Vector 2: TA0CCR1 2
        jmp   CCIFG_2_HND; Vector 4: TA0CCR2 2
        jmp   CCIFG_3_HND; Vector 6: TA0CCR3 2
        jmp   CCIFG_4_HND; Vector 8: TA0CCR4 2
        jmp   CCIFG_5_HND; Vector 10: TA0CCR5 2
        jmp   CCIFG_6_HND; Vector 12: TA0CCR6 2reti;            
        reti
CCIFG_2_HND:            ;Vector 4: TA0CCR2 2
        reti  
INT_CCR1:
         reti

См. вложение. там описано как это работает. В моем коде эта часть не используется.у меня просто привычка на неиспользованые вектора прерывания ставить reti
hash20
Ну а если на сишке то можно вот так сбацать:
(подключен внешний кварц на 8мгц, инициализацию системы тактирования не привожу)
Код
void Timer_Init (void)
{
   TACCR0=8000;         /* load period register =1 msek */
   TACCTL0=0x10;
   TACTL=0x0110;         /* start Timer_A  up to CCR0,/1,ACLK,*/

__enable_interrupt();
}



#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0(void)  // time 1 msec
{


yes_time_1msec=1; //1 msec

cntr_10msec++;
if(cntr_10msec>10)
   { cntr_10msec=0;
     yes_time_10msec=0xff; //10 msec

   }

if(cnt_32msec==0)
{ // time 32 msec
   cnt_32msec=32;
   yes_32msec=1;
}
else cnt_32msec--;

}


А на таймере B можно шим сделать с выводом на ссответств ножку порта P4:

Код
void TimerB_Init (void)
{
TBCTL = CNTL_2 | TBSSEL_1 | ID0 | MC1 ;
TBCCR5 = 0x512;
TBCCTL5  =  OUTMOD_3;
TBCCTL5 &=~ CAP;

TBCCR4 = 0x1024;
TBCCTL4  =  OUTMOD_3;
TBCCTL4 &=~ CAP;

TBCTL &=~ TBIFG;

__enable_interrupt();
}


d7d1cd
Подскажите, правильно ли я понял работу таймера А, а именно:

1. Основная функция таймера - это увеличивать (или увеличивать-уменьшать) содержимое регистра TAR.
2. Режим сравнения - это установка флага прерывания, если содержимое регистра TAR становится равным содержимому регистра захвата/сравнения.
3. Режим захвата - это копирование содержимого регистра TAR в регистр захвата/сравнения при наступлении какого-либо события и установка флага прерывания.
4. Если при режиме сравнения я использую только 1 регистр захвата/сравнения, то для неиспользуемых регистров захвата/сравнения необходимо запретить прерывание от них. При этом неиспользуемые регистры можно использовать для собственных нужд (например, для хранения каких то своих переменных).
MrYuran
Все верно, за исключением 4.2, а именно использования регистров под переменные.
Поскольку архитектура классическая им. Фоннеймана, профита по сравнению с памятью никакого, а вот геморрой можно поиметь.
d7d1cd
Цитата(MrYuran @ Sep 18 2012, 21:27) *
...профита по сравнению с памятью никакого, а вот геморрой можно поиметь.


Какой конкретно геморрой можно поиметь, эксплуатируя незадействованные регистры таймера?
rezident
Цитата(d7d1cd @ Sep 19 2012, 07:55) *
Какой конкретно геморрой можно поиметь, эксплуатируя незадействованные регистры таймера?

Конкретный гемморой зависит от конкретной ситуации. Например, в режиме захвата содержимое CCRx может меняться даже, если у таймера отключено тактирование.
d7d1cd
Цитата(rezident @ Sep 19 2012, 22:53) *
Конкретный гемморой зависит от конкретной ситуации. Например, в режиме захвата содержимое CCRx может меняться даже, если у таймера отключено тактирование.





У меня режим сравнения. Используется только регистр CCR0. Остальные регистры тоже настроены на сравнение, но прерывание от них отключено. Могу ли я безболезненно использовать их как временное хранилище переменных?

d7d1cd
Цитата(d7d1cd @ Sep 20 2012, 06:54) *
У меня режим сравнения. Используется только регистр CCR0. Остальные регистры тоже настроены на сравнение, но прерывание от них отключено. Могу ли я безболезненно использовать их как временное хранилище переменных?

Ну что, кто-то подскажет по данному вопросу?
E.V.G.
Лично я использовал в своих проектах запись в регистры модулей, которые не используются в работе. Пока не каких проблем нет. Использовал регистры TACCRx, TBCCRx, ADC12MEMx, PxOUT, DAC12xDAT. Главное при этом, чтобы регистры, контролирующие изменение состояния выше названных регистров были правильно настроены и не допускали произвольного изменения состояния используемых вами. Лучше всего использовать их под локальные переменные. При этом желательно каждый раз явно инициализировать регистры конфигурации, чтобы при сбоях не было проблем.

Например, для TACCRx нужно выбрать режим захвата (CAP=1, CM=00), запрет прерывания (CCIE=0).
rezident
Цитата(E.V.G. @ Sep 24 2012, 10:18) *
Например, для TACCRx нужно выбрать режим захвата (CAP=1, CM=00), запрет прерывания (CCIE=0).

Это (выбирать режим capture, установкой бита CAP) делать категорически не рекомендуется! Причину я описал в сообщении выше. А если уж используете регистры под временные переменные в режиме capture, то биты CCIS должны иметь значение 0x2 или 0x3, но никак не 0x0 или 0x1.
d7d1cd
Цитата(rezident @ Sep 24 2012, 15:44) *
Это (выбирать режим capture, установкой бита CAP) делать категорически не рекомендуется! Причину я описал в сообщении выше. А если уж используете регистры под временные переменные в режиме capture, то биты CCIS должны иметь значение 0x2 или 0x3, но никак не 0x0 или 0x1.

А если у меня не capture режим, а режим сравнения, то каких, так сказать подводных камней, мне остерегаться при использовании регистров под временные переменные?
E.V.G.
В режиме сравнения тоже можно работать. При этом будет формироваться флаг CCIFG, но это не создаст проблем.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.