EmbedElektrik 0 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба Задача получить серию импульсов строго заданной продолжительности и количества. Использую PWM. В приведенном коде я хочу получить два импульса по 10 мкс с паузой 40. основной код ................. tim_init(); TIM2->CNT=15;//предустановка счетчика в пределах низкой фазы pulses_cnt=2;// количество импульсов TIM_Cmd(TIM2,ENABLE); // запускаем счёт } //************************************************************************** void TIM2_IRQHandler() { if(TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC3); GPIO_ResetBits(GPIOE, GPIO_Pin_9);// сброс по COMPARE pulses_cnt--; if(pulses_cnt==0)TIM_Cmd(TIM2, DISABLE); } if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); GPIO_SetBits(GPIOE, GPIO_Pin_9); // фронт по UPDATE } } //**************************************************************************** void tim_init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); TIM_OCStructInit(&oc_init); oc_init.TIM_OCMode = TIM_OCMode_PWM1; // работаем в режиме ШИМ ( PWM ) oc_init.TIM_OutputState = TIM_OutputState_Enable; oc_init.TIM_Pulse = 10; // oc_init.TIM_OCPolarity = TIM_OCPolarity_High; // положительная полярность TIM_OC3Init(TIM2,&oc_init); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable); TIM_TimeBaseStructInit(&base_timer); base_timer.TIM_Prescaler = 84 - 1; // делитель частоты base_timer.TIM_Period = 50-1; // период base_timer.TIM_CounterMode = TIM_CounterMode_Up; // счёт вверх TIM_TimeBaseInit(TIM2, &base_timer); TIM_ITConfig(TIM2, TIM_IT_CC3 | TIM_IT_Update, ENABLE); TIM_ARRPreloadConfig(TIM2,DISABLE); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); NVIC_EnableIRQ(TIM2_IRQn); } В итоге получаю следующую картинку. Красный - мой вывод PWM, с двумя требуемыми импульсами, но перед ними влезает какой-то мелкий пик природу появления которого я не могу понять. Желтым цветом вывожу прерывания таймера - нарастающий фронт соответсвует событию таймера UPDATE, спадающий - COMPARE. Видно, что при первом прерывании update PWM как и требуется поднимается в 1, но почему-то тут же падает в 0 через странные 1.6 мкс и взводится опять через 35 мкс. После вывод PWM начинает работать как и планировалось. Теоретически можно отрубить первый мусорный импульс, но это костыль. Хотелось бы понять почему я в трех соснах заблудился. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба Что-то как-то через одно место, если честно. Зачем таймер в ШИМе если вы ноги дергаете руками? по сути вопроса думаю что это библиотечка так работает. ШИМ параметры скважности применяются когда таймер досчитал, потому после первой их задачи обычно дергают таймер так чтобы он как бы досчитал и обновил состояние, это думаю вы и наблюдаете Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба Зачем таймер в ШИМе если вы ноги дергаете руками? Действительно. Какой-то абсурд. В STM32 можно сделать нужную пачку импульсов чисто на таймерах, процессор может вообще спать. Но для этого нужно почитать, как таймеры работают - они там хитровывернутые. Зато после чтения такие вопросы возникать не будут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба Действительно. Какой-то абсурд. Видимо, это как раз управление желтым каналом осциллографа. Красный канал - аппаратный. Попробуйте на строчку веше, чем TIM_ITConfig(TIM2, TIM_IT_CC3 | TIM_IT_Update, ENABLE); прописать нечто, вида: TIM2->EGR = TIM_EGR_UG; // 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EmbedElektrik 0 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба Что-то как-то через одно место, если честно. Зачем таймер в ШИМе если вы ноги дергаете руками? по сути вопроса думаю что это библиотечка так работает. ШИМ параметры скважности применяются когда таймер досчитал, потому после первой их задачи обычно дергают таймер так чтобы он как бы досчитал и обновил состояние, это думаю вы и наблюдаете Я руками не дергаю. Желтый канал для дебага - чтобы сравнивать поведение прерываний относительно фазы PWM. Видимо, это как раз управление желтым каналом осциллографа. Красный канал - аппаратный. Попробуйте на строчку веше, чем TIM_ITConfig(TIM2, TIM_IT_CC3 | TIM_IT_Update, ENABLE); прописать нечто, вида: TIM2->EGR = TIM_EGR_UG; // 1 увы, картина не изменилась :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба #define PULSE_ACT (10) #define PULSE_INACT (40) #define PULSE_NUM (2) volatile int puls = 0; //----------------------------------------------------------------------------- // void TIM2_IRQHandler(void) //----------------------------------------------------------------------------- void TIM2_IRQHandler(void) { if(TIM2->SR & (1 << TIM_SR_UIF)) { TIM2->SR = ~(1 << TIM_SR_UIF); if(puls) puls--; else { set_pin(LED_ACTIVE_PIN, 0); TIM2->CR1 = 0; } } } //----------------------------------------------------------------------------- // void ufunc_demo(void *p) //----------------------------------------------------------------------------- void ufunc_demo(void *p) { NVIC->ISER[0] = (1 << NVIC_ISER0_TIM2); TIM2->PSC = FPLL / 2 / 1000000 - 1; TIM2->ARR = PULSE_ACT + PULSE_INACT - 1; TIM2->CCR1 = TIM2->ARR + 1 - PULSE_ACT; TIM2->CCMR1 = (OC_MODE_PWM2 << TIM_CCMR1_OC1M); TIM2->EGR = (1 << TIM_EGR_UG); TIM2->CCER = (1 << TIM_CCER_CC1E); TIM2->DIER = (1 << TIM_DIER_UIE); TIM2->CNT = TIM2->CCR1; puls = PULSE_NUM - 1; TIM2->CR1 = (1 << TIM_CR1_CEN); set_pin(LED_ACTIVE_PIN, 1); } Я библиотеками не пользуюсь. Управляю напрямую регистрами. Названия битов соответствуют номеру бита, а не маске. TIM2_CH1 - красная линия LED_ACTIVE_PIN - желтая линия Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EmbedElektrik 0 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба Я библиотеками не пользуюсь. Управляю напрямую регистрами. Названия битов соответствуют номеру бита, а не маске. TIM2_CH1 - красная линия LED_ACTIVE_PIN - желтая линия Спасибо, идея инверсии понятна. У меня заработало. Но непонятки с моей изначальной инициализацией остались :( С управлением регистрами напрямую все равно этот импульс пролазит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба Но непонятки с моей изначальной инициализацией остались :( Я не особо понимаю, что там с первым импульсом, меня больше волнует окончание последовательности: PWM1 примечателен тем, что в момент UPDATE он устанавливает пин в лог. 1, т.е. в конце последовательности вывод установится в лог. 1. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VCucumber 0 8 июля, 2015 Опубликовано 8 июля, 2015 · Жалоба 1. остановили таймер 2. отключили буферизацию 3. заполнили регистры делителей, счетчиков, сравнения 4. включили буферизацию 5. запустили таймер Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ArtDenis 0 9 июля, 2015 Опубликовано 9 июля, 2015 (изменено) · Жалоба EmbedElektrik, на самом деле всё очень просто. Регистр делителя частоты - буферизованный. Твоё заданное значение будет переписано в рабочий регистр только после первого события апдейта таймера. Изменено 9 июля, 2015 пользователем ArtDenis Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 9 июля, 2015 Опубликовано 9 июля, 2015 · Жалоба Регистр делителя частоты - буферизованный. Твоё заданное значение будет переписано в рабочий регистра только после первого события апдейта таймера. В сообщении №5 ТС сказал, что апдейт не помогает (никак не меняет картину). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ArtDenis 0 9 июля, 2015 Опубликовано 9 июля, 2015 · Жалоба В сообщении №5 ТС сказал, что апдейт не помогает (никак не меняет картину). Усп. Не увидел. Ну значит проблема где-то в коде. Лично меня немного напрягает строка TIM2->CNT=15; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 9 июля, 2015 Опубликовано 9 июля, 2015 · Жалоба Лично меня немного напрягает строка TIM2->CNT=15; Хоть намекните чем? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ArtDenis 0 9 июля, 2015 Опубликовано 9 июля, 2015 · Жалоба Хоть намекните чем? Ну вообще судя по приведённому коду он не должен влиять. Скважность шима = 10, а значение счётчика - 15. По умолчанию таймер на выходе ШИМа должен выдавать 0. Так возможно, что проблема в коде, который ТС не привёл. Ещё идея. По умолчанию, счётчик равен 0. Значит на выходе ШИМа сразу после настройки таймера должен быть 1. Если между настройкой таймера и кодом TIM2->CNT=15; стоит ещё какой-то код (который ТС не показал), то на выходе некоторое время будет держаться 1. PS: всякие TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable) и им подобные не надо делать перед заданием значений, а не после как у ТС? PPS: ТС-у лучше привести минимальный компилируемый код, который воспроизводит ошибку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 9 июля, 2015 Опубликовано 9 июля, 2015 · Жалоба PPS: ТС-у лучше привести минимальный компилируемый код, который воспроизводит ошибку. У ТС сейчас есть рабочий код. Есть ли смысл воспроизводить и анализировать нерабочий код? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться