Halfback 0 13 июня, 2010 Опубликовано 13 июня, 2010 · Жалоба Всем привет! Настраиваю таймер 3. Работает так: постоянно считает до T=1000 мсек (с шагом t=1мс) и сбрасывается. Авторелоад включен. В какой-то момент времени нужно отмерить интервал времени t1=400мс. Текущее состояние таймера = t0 Если t1+t0 <= T то компаратор можно назначить через время = t1+t0 и всё будет хорошо, а вот если t1+t0 >= T то получается немного сложнее т.к. захват нужен после релоада счетчика. А раз так, то получается t1<t0 и компаратор сразу сработает после назначения нового порога. Есть идея использовать событие по переполнению таймера и там делать переинициализацию на новый порог захвата - в этом случае компаратор словит всё как надо но это как то не красиво. Есть у кого идеи по решению задачи? Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 14 июня, 2010 Опубликовано 14 июня, 2010 · Жалоба Есть у кого идеи по решению задачи? Отказаться от авторелода и отпустить таймер в свободный забег :) А ежели надо, чтоб что-то случалось через каждые 1000 тиков - использовать один модуль compare этого таймера. (Или специально предназначенный для этого System Timer). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 14 июня, 2010 Опубликовано 14 июня, 2010 (изменено) · Жалоба AHTOXA Что значит свободный забег? не понял. и как это может помочь в настоящей задаче? Может не совсем доходчиво объяснил но хочется, чтобы событие возникало не при t0>=t1 а только при t0==t1. Может штатные таймеры такое позволяют? На счет System Timer не знаю - пока не думал и про него даже не читал. Но тут еще одно дело - замеров может быть 4 и все на разные интервалы и могут перекрывать друг друга (поэтому удобно использовать CC1...CC4). Т.е. в то время когда идет замер 400мс по СС1 может произойти замер на 200мс по СС2 и/или 650мс по СС3. Изменено 14 июня, 2010 пользователем Halfback Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
*ZEVS* 0 14 июня, 2010 Опубликовано 14 июня, 2010 · Жалоба Используйте под каждый замер разный таймер. Ведь у микроконтроллере не один таймер. Можно в прерывании от таймера увеличивать переменные (переменных выделяется столько, сколько нужно делать замеров). По событию вы берете значения переменных это и будут ваши замеры. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 14 июня, 2010 Опубликовано 14 июня, 2010 · Жалоба Что значит свободный забег? не понял. и как это может помочь в настоящей задаче? Ну, без автозагрузки. Чтоб считал до 0xFFFF, потом снова 0. Может не совсем доходчиво объяснил но хочется, чтобы событие возникало не при t0>=t1 а только при t0==t1. Может штатные таймеры такое позволяют? Именно так всё и работает:) . Compare match = совпадение (равенство). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 14 июня, 2010 Опубликовано 14 июня, 2010 (изменено) · Жалоба Предлагаю ближе к делу: Таймер конфигурируется так (конкретные значения периода, прескалеров привести не могу т.к. проект не под рукой): TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_Cmd(TIM3, ENABLE); Захват вот так: TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM3, &TIM_OCInitStructure); Далее в момент времени таймера = 800 (таймер считает до 1000 и перезагружается, начинает считать с 0) надо отмерить 400мс и делаю TIM_SetCompare1(TIM3,400-(1000-800)); TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE) и сразу вылетаю в обработчик прерывания. Почему это происходит понятно, т.к. 800>(400-(1000-800)) Так вот надо чтобы таймер обнулился, начал считать заново и сделал событие в момент времени (400-(1000-800)). Потом попробую отработать событие TIM_EventSource_COM Может это то что надо. Изменено 14 июня, 2010 пользователем Halfback Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 14 июня, 2010 Опубликовано 14 июня, 2010 · Жалоба TIM_EventSource_COM не то, да и работает на 1 и 8 таймерах. -SANYCH- остальные таймера заняты другими задачами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Halfback 0 14 июня, 2010 Опубликовано 14 июня, 2010 (изменено) · Жалоба На данный момент проблему решил так: когда надо делать замер то делал TIM_SetCompare2(400-(1000-800)) на событие не активировал а активировал событие по Update. В событии Update по наличию спец. программного флага активировал событие TIM_ITConfig(TIM3,TIM_IT_CC2,ENABLE); Ес-но сбрасывал соответствующие битики событий чтобы не вываливаться в обработчик сразу после активации события. Не самое красивое решение но главное что работает и других идей лично у меня нет. Изменено 14 июня, 2010 пользователем Halfback Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 15 июня, 2010 Опубликовано 15 июня, 2010 · Жалоба Далее в момент времени таймера = 800 (таймер считает до 1000 и перезагружается, начинает считать с 0) надо отмерить 400мс и делаю TIM_SetCompare1(TIM3,400-(1000-800)); TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE) и сразу вылетаю в обработчик прерывания. Почему это происходит понятно, т.к. 800>(400-(1000-800)) Что за чушь? Ещё раз повторю: компаратор сравнивает не на "больше", а на "равно". В обработчик вы вылетаете по другой причине. Посмотрите пример к библиотеке в папке TIM\OCToggle - это то, что вам надо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
koyodza 0 21 июня, 2010 Опубликовано 21 июня, 2010 · Жалоба Не вижу смысла на такие большие времена использовать аппаратный таймер. Сделайте "системный тик" с периодом 1мсек, и считайте хоть 100 разных задержек любой разрядности и длительности с дискретностью этого системного тика Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Maks 0 8 июля, 2010 Опубликовано 8 июля, 2010 · Жалоба Подскажите, на брекпоинте таймер перестает работать? Интересует, что будет с ШИМ в режиме отладки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
klen 1 8 июля, 2010 Опубликовано 8 июля, 2010 · Жалоба Подскажите, на брекпоинте таймер перестает работать? Интересует, что будет с ШИМ в режиме отладки. как настроиш, можно сказать микосхеме чтоб вставал таймер, по умолчанию молотит дальше - это сделали для того чтоб можно былобы ШИМ отлаживать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ELEKTROS 0 29 июня, 2011 Опубликовано 29 июня, 2011 (изменено) · Жалоба Добрый день. Проблема похожа чем то: прерывания работают но не все, в частности использую TIM1, TIM2, TIM3, прерывания от TIM1 c фиксированной частотой по переполнению, TIM2 - захват 1 и переполнение, TIM3 - сравнение 1 и переполнение. не работают переполнения во всех. Вот так настраиваю: TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_ICInitTypeDef TIM_ICInitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseInitStruct.TIM_Prescaler=3664; // TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; // TIM_TimeBaseInitStruct.TIM_Period=0xFFFF; TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1; // TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct); TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct); //TIM_PrescalerConfig(TIM2, 900, TIM_PSCReloadMode_Update); // //TIM_SetAutoreload(TIM3,0xFFFF);// //TIM_SetCompare1(TIM3, 0x0045); // TIM_ICInitStruct.TIM_Channel=TIM_Channel_1; TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICFilter=0; TIM_ICInit(TIM2, &TIM_ICInitStruct); TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_Timing; TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable; TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable; TIM_OCInitStruct.TIM_Pulse=0x00FF; // TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_Low; TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset; TIM_OC1Init(TIM3, &TIM_OCInitStruct); //TIM_SelectOCxM(TIM3); TIM_UpdateDisableConfig(TIM1,ENABLE); TIM_UpdateDisableConfig(TIM2,ENABLE); TIM_UpdateDisableConfig(TIM3,ENABLE); TIM_Cmd(TIM1,ENABLE); TIM_Cmd(TIM2,ENABLE); TIM_Cmd(TIM3,ENABLE); TIM_ITConfig(TIM1,TIM_IT_Update, ENABLE); // TIM_ITConfig(TIM2, TIM_IT_Update | TIM_IT_CC1, ENABLE);// TIM_ITConfig(TIM3, TIM_IT_Update | TIM_IT_CC1,ENABLE); // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM16_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); Вот так обработчик прерываний: void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); /*какой то код*/ } if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); /*какой то код*/ } TIM3->SR=0; } void TIM1_UP_TIM16_IRQHandler(void) { if(TIM_GetITStatus(TIM1,TIM_IT_Update)!=RESET) { TIM_ClearITPendingBit(TIM1, TIM_IT_Update); /*какой то код*/ } TIM1->SR=0; } void TIM2_IRQHandler(void) { /*** Ôóíêöèÿ ïðåðûâàíèÿ ïî çàõâàòó ñ ÄÏÐ ***/ if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!=RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); /*какойто код*/ } if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); freq=0; } TIM2->SR=0; } Изменено 29 июня, 2011 пользователем IgorKossak [codebox] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=F8= 0 29 июня, 2011 Опубликовано 29 июня, 2011 · Жалоба Прерывания по CCx не использовал, но DMA в режиме TIM_OCMode_Timing тоже не работало. Заработало только в режиме TIM_OCMode_PWM1. Правда если соотв пин. находится в режиме в режиме AF_Out тогда... Как особо извращенный вариант при наличии "лишних" таймеров могу предложить такое: 1. Настраиваете один из неиспользуемых таймеров в режим slave TIM_SlaveMode_Reset(функ. TIM_SelectSlaveMode), в качестве мастера выбираете ваш таймер. 2. В качестве выхода тригера в мастере выбираем необходимое СС(функ. TIM_SelectOutputTrigger). 3. Используем update прерывания от slave. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться