alex1985 0 17 января, 2011 Опубликовано 17 января, 2011 (изменено) · Жалоба Доброго всем времени суток! В программе используется таймер 2, в прерывании по переполнению которого корректируется значение счетчика этого таймера (TIM2->CNT). На данный момент значение выставляется фиксированным (100). Первый канал таймера настроен на выход в режиме PWM Mode 1. Так вот когда я смотрю выходной сигнал, наблюдается сильное дрожание фронтов (в пределах 10-12 тактов), хотя, как мне кажется дрожание должно быть в пределах 1-3 тактов (в зависимости от текущей команды, которая совпадает с моментом возникновения прерывания). В чем ошибка? Код инициализации таймера: TIM_TimeBaseInitTypeDef tb2; TIM_OCInitTypeDef TIM_OCInitStructure; //Таймер 2 -------------------------------------------- tb2.TIM_Period = 7200; tb2.TIM_Prescaler = 0; tb2.TIM_ClockDivision = 0; tb2.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &tb2); // PWM1 Mode configuration: Channel1 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 3600; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable); TIM_ARRPreloadConfig(TIM2, DISABLE); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_ClearFlag(TIM2, TIM_FLAG_Update); // TIM2 enable counter TIM_Cmd(TIM2, ENABLE); Код инициализации прерывания: NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = 28; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); Код прерывания: void TIM2_IRQHandler(void) { TIM2->CNT = 0x0000; TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } Ну и на всякий случай настройка порта: GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); Пробовал проделывать тоже самое на меге128 - дрожание есть, но в пределах 2-х тактов. Еще заметил такую особенность: если в прерывании присваивать значение таймера какой-то переменной: void TIM2_IRQHandler(void) { TIM2->CNT = cnt; TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } , а в основном цикле по нажатию кнопки менять значение этой переменной, то в зависимости от уровня оптимизации наюлюдается разное дрожание. Дрожание также меняется в зависимости от настройки приоритета прерывания и от количества конструкций типа if. Так можно ли добиться какой-нибудь стабильности? Не хочется переходить на мегу128 :( Изменено 18 января, 2011 пользователем Sprite Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex1985 0 19 января, 2011 Опубликовано 19 января, 2011 · Жалоба Поставлю вопрос по другому: какое максимальное количество тактов может занимать одна инструкция процессора (stm32f103)? Если 10-12 тактов, то вопрос закрыт, иначе буду думать, где слабое звено программы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zoddy 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба Поставлю вопрос по другому: какое максимальное количество тактов может занимать одна инструкция процессора (stm32f103)? Если 10-12 тактов, то вопрос закрыт, иначе буду думать, где слабое звено программы. Ну, я так полагаю, ... Вы не там копаете... Разберитесь сперва с тем, что вы хотите в конечном итоге получить... Судя по приведенным фрагментам кода, Вы настраиваете таймер на переполнение при CNT=7200, при достижении счетчиком CNT=3600 произойдет махание ножкой в соответствии с режимом PWM1. По переполнению счетчика, происходит событие Update, счетчик итак начинает считать с CNT=0 и вы опять же зачем-то подсовываете в него значение 0x00, при этом, учитывая, что событие Update генерируется с задержной на несколько тактов, плюс вход в прерывание 12 тактов... , а счетчик уже начал считать... и на каком-то такте вы его снова обнулили.... вот и получается ваше дрожжжжание фронта. В данном случае, логичней было бы изменять длительность периода таймера в регистре ARR... или значение длительности импульса в регистре совпадения CCR1.... а не пытаться изменить значение счетного регистра, да еще при этом на запущенном таймере. В общем, не мешало бы вам почитать вдумчиво Reference Manual. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться