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

 
 
 
Reply to this topicStart new topic
> проблемма с таймером, проблемма с таймером
jjjjjjein
сообщение Oct 31 2011, 06:01
Сообщение #1


Участник
*

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



Хочу, что бы 2 светодиода меняли своё состояние с разным периодом. Один, раз в 100 мс, второй - в 500мс. Ошибка в обработчике прерываний. Как её исправить? подскажите, кто знает)


int main( void )
{
WDTCTL = WDTPW + WDTHOLD; // Остановка сторожевого таймера, чтобы предотвратить время сброса
_DINT(); // Запрещаем прерывания
InitializationPortIO (); // Вызов функции инициализации портов ввода/вывода микроконтроллера
InitializationTimersMSP430 (); // Вызов функции инициализации внутренних аппаратных таймеров микроконтроллера MSP430F135
_EINT(); // Разрещаем прерывания

while (1)

{
if (Flag_500ms == true) // Если поставлен флаг 500мс
{
P4OUT = ~(P4OUT & BIT4); // Состояние 3 вывода 4 порта меняется
Flag_500ms = false; // Флаг убирается
}
if (Flag_100ms == true) // Если поставлен флаг 100мс
{
P4OUT = ~(P4OUT & BIT3); // Состояние 4 вывода 4 порта меняется
Flag_100ms = false; // Флаг убирается
}
}
}
//********************************************************************************
*********************************************************************************
******************************
//********************************************************** ОБРАБОТЧИКИ ПРЕРЫВАНИЙ ********************************************************************************
*********************
#pragma vector = TIMERA0_VECTOR // Прерывание от таймера А (срабатывает каждые 10 мс)
__interrupt void isr_TACCR0() // прерывание
{
t ++;
y ++;
if ( t >= 10 )
{
Flag_100ms = true;
t = 0;
}
if ( y >= 50 )
{
Flag_500ms = true;
y = 0;
}
}
Go to the top of the page
 
+Quote Post
SanvaldYV
сообщение Oct 31 2011, 10:06
Сообщение #2


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

Группа: Свой
Сообщений: 125
Регистрация: 21-03-07
Из: Санкт-Петербург
Пользователь №: 26 371



Цитата(jjjjjjein @ Oct 31 2011, 09:01) *
Хочу, что бы 2 светодиода меняли своё состояние с разным периодом. Один, раз в 100 мс, второй - в 500мс. Ошибка в обработчике прерываний. Как её исправить? подскажите, кто знает)


А почему Вы думаете, что ошибка в обработчике прерывания? Оно у Вас вообще происходит, это прерывание? В обработчик программа попадает? Как это проверяли? Инициализация портов и таймера не приведена, так что трудно что то сказать...
Go to the top of the page
 
+Quote Post
jjjjjjein
сообщение Nov 1 2011, 10:34
Сообщение #3


Участник
*

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



Цитата(Юрий Санвальд @ Oct 31 2011, 13:06) *
А почему Вы думаете, что ошибка в обработчике прерывания? Оно у Вас вообще происходит, это прерывание? В обработчик программа попадает? Как это проверяли? Инициализация портов и таймера не приведена, так что трудно что то сказать...

Если закоментировать изменение состояния светодиода через 100мс, то второй светодиод будет мигать четко раз в 500 мс. И наоборот: если закоментировать изменение состояния светодиода через 500мс, то другой светодиод будет мигать четко раз в 100 мс. А если оставить оба флага, то и у первого и у второго светодиода частота сбивается.



[code]
int main( void )
{
WDTCTL = WDTPW + WDTHOLD; // Остановка сторожевого таймера, чтобы предотвратить время сброса
_DINT(); // Запрещаем прерывания
InitializationPortIO (); // Вызов функции инициализации портов ввода/вывода микроконтроллера
InitializationTimersMSP430 (); // Вызов функции инициализации внутренних аппаратных таймеров микроконтроллера MSP430F135
_EINT(); // Разрещаем прерывания

while (1)

{
if (Flag_500ms == true) // Если поставлен флаг 500мс
{
P4OUT = ~(P4OUT & BIT4); // Состояние 5 вывода 4 порта меняется
Flag_500ms = false; // Флаг убирается
}
/*
if (Flag_100ms == true) // Если поставлен флаг 100мс
{
P4OUT = ~(P4OUT & BIT3); // Состояние 4 вывода 4 порта меняется
Flag_100ms = false; // Флаг убирается
}
*/
}
}
//********************************************************************************
*********************************************************************************
******************************
//********************************************************** ОБРАБОТЧИКИ ПРЕРЫВАНИЙ ********************************************************************************
*********************
#pragma vector = TIMERA0_VECTOR // Прерывание от таймера А (срабатывает каждые 10 мс)
__interrupt void isr_TACCR0() // прерывание
{
/*
t ++;
if ( t >= 10 )
{
Flag_100ms = true;
t = 0;
}
*/
y ++;
if ( y >= 50 )
{
Flag_500ms = true;
y = 0;
}
}

//********************************************************************************
*********************************************************************************
******************************
//************************************************************* ОПИСАНИЯ ФУНКЦИЙ ********************************************************************************
************************
void InitializationTimersMSP430 (void) // Функция инициализации внутренних аппаратных таймеров микроконтроллера MSP430F135
{
// Общая инициализвция модуля тактирования микроконтроллера


BCSCTL1 = 0x00; // Обнуление управляющего регистра BCSCTL1
IFG1 &= ~XT2OFF; // XT2 = HF XTAL
int y; // Включение XT2
do
{
IFG1 &= ~OFIFG; // Очистка флага OFIFG
for (y = 0xFF; y > 0; y--); // Задержка
}
while (IFG1 & OFIFG); // проверка

BCSCTL2 = 0x00; // Обнуление управляющего регистра BCSCTL2
DCOCTL = DCO0 | DCO1 | DCO2 | // Частота генератора -> МАКСИМУМ (8000000 Гц)
MOD0 | MOD1 | MOD2 | MOD3 | MOD4; // Модулятор тактовой частоты DCO -> МАКСИМУМ
BCSCTL1 = RSEL0 | RSEL1 | RSEL2; // Сопротивление внутреннего резистора -> МАКСИМУМ
BCSCTL2 = SELM_2 | // Источник тактирования MCLK -> XT2CLK
DIVM_0 | // Делитель MCLK -> 1
SELS | // Источник тактирования SMCLK -> XT2CLK
DIVS_0 ; // Делитель SMCLK -> 1
LPM4; // Генераторы DCO и LFXT1 отключены


// Инициализация таймера А
TACTL = TASSEL_2 | // Источник тактирования таймера -> сигнал SMCLK (8МГц)
ID_3 | // Предделитель таймера -> 8
MC_1; // Режим работы таймера -> счёт вверх до значения TACCR0

TACCR0 = 10000; // Счёт до значения -> 10000
TACCTL0 = CCIE; // Разрешение прерывания по захвату/сравнению, разрешение запроса прерывания от флага CCIFG

}


//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void InitializationPortIO (void) // Функция инициализации портов ввода вывода микроконтроллера
{

// Инициализация порта ввода/вывода №4
P4SEL = 0x00; // Все выводы порта настроены как цыфровые линии
P4OUT = 0x00; // На всех выводах порта установлены логические "0"
P4DIR = 0x18; // 4,5 вывод порта настроены как выходы



}
Go to the top of the page
 
+Quote Post
rezident
сообщение Nov 1 2011, 22:35
Сообщение #4


Гуру
******

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



Го-о-оспидя, как все запущено! laughing.gif
Обычно задуманное вами делается так.
Определяете прерывание с "тиком" 1 мс или 10мс или 100мс, как удобнее.. Инкрементируете в прерывании некую переменную "системных тиков" на величину веса/цены системного тика. Это будут ваши "часы", единые для всей программы. Далее в основном цикле для каждого события отводите по переменной в которых будут храниться значения временнЫх меток. Сравниваете текущее показание "часов" и значение временнОй метки путем беззнакового вычитания. Если разница больше периода возникновения события, то реализуете его (событие) и запоминаете вновь текущее значение "часов". Вот и вся недолга!
Важное замечание. Переменная "тиков" должна быть объявлена как беззнаковое целое (unsigned int) и обязательно с квалификатором volatile. Разрядность переменной "тиков" определяется требованиями к максимальному периоду событий. Если предположим, что "вес" системного тика - 1мс, то 16-и разрядная переменная типа unsigned int позволяет определить максимальный период 65,535с. Если этого мало, то используйте 32-х разрядный тип unsigned long int, тогда при том же "весе" тика (1мс) максимальный период составит немного больше 1,5 месяцев. Только в последнем случае следует обязательно обеспечить атомарность считывания переменной "тиков" потому, что она инкрементируется в прерывании, а значение ее считывается в основном цикле программы. Притом, что значение переменной превышает нативную разрядность MSP430. Если для реализации атомарности чтения не прибегать к запрету прерываний, то типовым способом является такой, как в примере ниже (функция clock_ms).

Код
...
#include <stdint.h>

#define ADD_SYSTICK_VALUE 1UL //цена системного тика - 1 мс
#define LED1_BLINKPERIOD 100UL //период мерцания LED1 [в мс]
#define LED2_BLINKPERIOD 500UL //период мерцания LED2 [в мс]

volatile uint32_t SystemTick;

uint32_t clock_ms(void)
{ uint32_t tmp1, tmp2;
  do
  { tmp1=SystemTick;
    tmp2=SystemTick;
  } while(tmp1 != tmp2);
  return tmp2;
}

void main (void)
{ uint32_t timeStampLed1, timeStampLed2;
...
  timeStampLed1 = clock_ms();
  timeStampLed2 = clock_ms();
...
  for (;;)
  {
...
    if ((clock_ms() - timeStampLed1) >= LED1_BLINKPERIOD) //проверка периода мерцания LED1
    { P4OUT ^= BIT3;
      timeStampLed1 = clock_ms();
    }
    if ((clock_ms() - timeStampLed2) >= LED2_BLINKPERIOD) //проверка периода мерцания LED2
    { P4OUT ^= BIT4;
      timeStampLed2 = clock_ms();
    }
...
  }
}

#pragma vector=TIMERA0_VECTOR
@pragma type_attrinute=__interrupt
void SYSTICK_ISR(void)
{ SystemTick += ADD_SYSTICK_VALUE; //инкремент переменной системного тика
}
Go to the top of the page
 
+Quote Post
jjjjjjein
сообщение Nov 2 2011, 03:36
Сообщение #5


Участник
*

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



Большое спасибо sm.gif
Мне очень помогло, всё очень подробно и понятно
Go to the top of the page
 
+Quote Post

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

 


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


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