|
Помогите разобраться с TIMER_A, как заставить работать PWM и прерывания по переполнению |
|
|
|
Jul 6 2009, 20:20
|
Участник

Группа: Участник
Сообщений: 48
Регистрация: 4-11-08
Пользователь №: 41 361

|
Возможно ли включить прерывание по переполнению таймера при задействовании PWM ? Вот код : Код CCR0 = 1024-1; // PWM Period CCTL1 = OUTMOD_7; // CCR1 reset/set CCR1 = 250; // CCR1 PWM duty cycle CCTL2 = OUTMOD_7; // CCR2 reset/set CCR2 = 128; // CCR2 PWM duty cycle TACTL = TASSEL_2 + MC_1 + ID_3; А если сделать так: Код CCR0 = 1024-1; // PWM Period CCTL1 = OUTMOD_7; // CCR1 reset/set CCR1 = 250; // CCR1 PWM duty cycle CCTL2 = OUTMOD_7; // CCR2 reset/set CCR2 = 128; // CCR2 PWM duty cycle TACTL = TASSEL_2 + MC_1 + ID_3 + TAIE; ... __enable_interrupt(); ... ... // Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A0 (void) { if( !(BIT5 & P2IN) )chanel = 0; else chanel = 1; } То попадая в прерывание мк выполняет то что там написано по кругу и из прерывания не выходит. Что я делаю не правильно?
|
|
|
|
|
Jul 7 2009, 05:16
|
Участник

Группа: Участник
Сообщений: 48
Регистрация: 5-12-06
Пользователь №: 23 143

|
У Вас неверно задан вектор прерывания. Для прерывания по переполнению используется TIMERA1_VECTOR (см. раздел "Timer_A Interrupts" в юзергайде)
|
|
|
|
|
Jul 7 2009, 09:33
|
Участник

Группа: Участник
Сообщений: 48
Регистрация: 4-11-08
Пользователь №: 41 361

|
Спасибо, просмотрел указанный раздел юзергайда , но так все равно не работает. Если не включаю PWM то все работает как надо, не получается использовать прерывание по переполнению при задействованном PWM.
|
|
|
|
|
Jul 7 2009, 12:19
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(rezident @ Jul 7 2009, 16:07)  TIMERA1_VECTOR расшарен для трех источников прерывания CCR1 CCIFG, CCR2 CCIFG и TAIFG. Поэтому нужно использовать TAIV внутри обработчика так, как это описано в User's Guide. Судя по коду, CCR1 и CCR2 прерывания не формируют (выключен CCIE) Кстати, с CCR0 тоже неочевидно (не видно инициализации CCTL0) Если всё время сидит в прерывании, значит, либо вызывается TIMERA1_VECTOR и не считывается TBIV (предположительно), соответственно CCIFG остаётся стоять и вызывает прерывание опять. Ещё возможно, что определён один вектор, а вызывается другой, соответственно программа улетает в неведомую даль. (опять же, предположение)
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Jul 7 2009, 13:10
|
Участник

Группа: Участник
Сообщений: 54
Регистрация: 25-09-07
Пользователь №: 30 836

|
Цитата(MrYuran @ Jul 7 2009, 16:19)  ... не считывается TBIV (предположительно), соответственно CCIFG остаётся стоять и вызывает прерывание опять ... Очень может быть. Нарывался на это как-то.
|
|
|
|
|
Jul 7 2009, 13:11
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(MrYuran @ Jul 7 2009, 18:19)  Если всё время сидит в прерывании, значит, либо вызывается TIMERA1_VECTOR и не считывается TBIV (предположительно), соответственно CCIFG остаётся стоять и вызывает прерывание опять. Насколько я понял, "все время сидит в прерывании" относится к первому варианту с обработчиком вектора TIMERA0_VECTOR. Считывание TAIV при этом ни при чем, т.к. TACCR0 CCIFG, в отличие от остальных, сбрасывается автоматически при переходе на вектор TIMERA0_VECTOR. Думаю, что дело в другом. Это особенности работы дебаггера C-CPY в IAR. Я такое тоже замечал. Иногда дебаггер все время начинает вылетать в какое-то таймерное прерывание (которое у меня вызывается периодически), несмотря на то, что breakpoint стоит совсем в другом месте. Помогает либо перезапуск, либо последовательность действий: снять все breakpoint, отпустить устройство "в свободный полет" и затем снова установить breakpoint. А насчет "не считывается TAIV" я уже написал выше Цитата нужно использовать TAIV внутри обработчика так, как это описано в User's Guide.
|
|
|
|
|
Jul 7 2009, 16:35
|
Участник

Группа: Участник
Сообщений: 48
Регистрация: 4-11-08
Пользователь №: 41 361

|
Спасибо всем за помощь. Цитата(rezident) Поэтому нужно использовать TAIV внутри обработчика так, как это описано в User's Guide. Так правильно? Код #pragma vector=TIMERA1_VECTOR __interrupt void Timer_A (void) { switch (TAIV) { case 2: break; case 4: break; case 10: P1OUT ^= 0x01; break; } Если можно обясните почему 2,4,10 ? К чему относятся эти числа? Цитата(MrYuran) ... не считывается TBIV (предположительно), соответственно CCIFG остаётся стоять и вызывает прерывание опять ... Как побороть? Сбросить вручную CCIFG не получается.... IAR матерится....
Сообщение отредактировал Left Radio - Jul 7 2009, 16:38
|
|
|
|
|
Jul 7 2009, 16:48
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Left Radio @ Jul 7 2009, 22:35)  Так правильно? Вполне. Цитата(Left Radio @ Jul 7 2009, 22:35)  Если можно обясните почему 2,4,10 ? К чему относятся эти числа? А вы User's Guide читать не пробовали? Цитата(Left Radio @ Jul 7 2009, 22:35)  Как побороть? Сбросить вручную CCIFG не получается.... IAR матерится.... "Вручную" это как? Записью в TAIV? Дык он же read-only! У вас все верно в примере написано, поэтому ничего "вручную" сбрасывать не нужно. Еще раз советую внимательно читать User's Guide. Хотя бы в раздел описания регистров Timer_A загляните.
Эскизы прикрепленных изображений
|
|
|
|
|
Jul 7 2009, 17:20
|
Участник

Группа: Участник
Сообщений: 48
Регистрация: 4-11-08
Пользователь №: 41 361

|
Цитата(rezident @ Jul 7 2009, 19:48)  "Вручную" это как? Записью в TAIV? Дык он же read-only! У вас все верно в примере написано, поэтому ничего "вручную" сбрасывать не нужно. Еще раз советую внимательно читать User's Guide. Хотя бы в раздел описания регистров Timer_A загляните. Спасибо понял, все заработало  Причиной была моя невнимательность
Сообщение отредактировал Left Radio - Jul 7 2009, 17:21
|
|
|
|
|
Jul 8 2009, 09:33
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(Left Radio @ Jul 7 2009, 20:35)  Код #pragma vector=TIMERA1_VECTOR __interrupt void Timer_A (void) { switch (TAIV) { case 2: break; case 4: break; case 10: P1OUT ^= 0x01; break; } Если можно обясните почему 2,4,10 ? К чему относятся эти числа? первые 2 кейса можно было и не писать, так как они всё равно пустые. ТАIV определяет, какой сигнал вызвал прерывание TIMERA1_VECTOR. Очень удобно, что "проградуирован" он через 2. Можно очень просто организовать таблицу переходов (описано в руководстве), либо в ИАРе есть такая примочка для кейса - Even_in_range(), которая оптимизирует switch/case, если аргумент чётный и входит в ограниченный диапазон. Фактически, формируется та же таблица переходов. В прерывании бывает очень актуально.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|