stm8l051 - аномалия таймеров

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
CinRock
Родился
Сообщения: 4
Зарегистрирован: Пн дек 21, 2015 11:21:12

stm8l051 - аномалия таймеров

Сообщение CinRock »

Доброго времени суток! Проблема заключается в следующем: При первом запуске, любой из таймеров (tim2, tim3, tim4), не выполняет то, что от него требуется. Для примера выводим меандр с частотой 50мс, используя таймер TIM3, настроенный таким образом, что 1 тик = 1 мкс, и наблюдаем то, что на картинке (прошу прощения за фотографию, не было возможности сделать скрин). Пример кода прилагается.

Код: Выделить всё

void main( void )
{
  CLK_ECKR_bit.HSEON = 1;            // Вкючаем HSE (Внешний кварц - 8Мгц.)

  while(CLK_ECKR_bit.HSERDY != 1) {} //Ждем готовности источника тактирования
  CLK_CKDIVR = 0;                    // Предделитель равен нулю
  CLK_SWCR_bit.SWEN=1;               // Разрешаем переключение источника тактовой частоты
  CLK_SWR = 0x04;                    // Выбираем HSE источником тактовой частоты
  
  while (CLK_SWCR_bit.SWBSY==1) {}   // Ждем готовности переключения
  CLK_SWCR_bit.SWBSY = 0;
  
  //Инициализация пина, на котором буду выводить меандр
  PC_DDR_bit.DDR6 = 1;
  PC_CR1_bit.C16 = 1;
  PC_CR2_bit.C26 = 1;
  PC_ODR_bit.ODR6 = 1;  //Переключаем вывод в 1
  
  TIM3_Init();
  
  while(1)
  { 
    PC_ODR_bit.ODR6 ^= 1;       //Инвертируем состояние вывода
    TIM3_Start(50000);
    TIM3_Wait();
  }
}

void TIM3_Init(void)
{
  CLK_PCKENR1_bit.PCKEN11 = 1;  //Включаем тактирование таймера №3
  TIM3_PSCR_bit.PSC = 3;  //Длительность такта таймера 1 мкс
  TIM3_CR1_bit.ARPE = 1;  
  TIM3_CR1_bit.CEN = 0;  //Таймер выключен
}

void TIM3_Start(uint16_t StopTime)
{
  TIM3_CR1_bit.CEN = 0; //Выключим таймер
  TIM3_SR1_bit.UIF = 0; //Сбросить флаг переполнения таймера
  TIM3_ARRH = (StopTime) >> 8;  //Устанавливаем время таймера (Старший байт)
  TIM3_ARRL = (StopTime) & 0xFF;        //Устанавливаем время таймера (Младший байт)
  TIM3_CR1_bit.CEN = 1; //Включаем таймер
}

void TIM3_Wait(void)
{
  while(TIM3_SR1_bit.UIF == 0){;}        //Ждем переполнения таймера
}
Изображение
Последний раз редактировалось CinRock Пн дек 21, 2015 12:20:38, всего редактировалось 1 раз.
Реклама
Аватара пользователя
scorpi_0n
Вымогатель припоя
Сообщения: 616
Зарегистрирован: Вс ноя 01, 2015 13:13:49

Re: stm8l051 - аномалия таймеров

Сообщение scorpi_0n »

Ничего там аномального нет кроме самой проги и недочитанного RM. А так как написано так и работает. Всё правильно.
ARPE установлен. Значит значения в регистры таймера попадут только по апдэйту. Что и наблюдается на картинке.
Реклама
CinRock
Родился
Сообщения: 4
Зарегистрирован: Пн дек 21, 2015 11:21:12

Re: stm8l051 - аномалия таймеров

Сообщение CinRock »

scorpi_0n писал(а):Ничего там аномального нет кроме самой проги и недочитанного RM. А так как написано так и работает. Всё правильно.
ARPE установлен. Значит значения в регистры таймера попадут только по апдэйту. Что и наблюдается на картинке.
Увы, но с ARPE = 0, происходит такая же борода.
Аватара пользователя
scorpi_0n
Вымогатель припоя
Сообщения: 616
Зарегистрирован: Вс ноя 01, 2015 13:13:49

Re: stm8l051 - аномалия таймеров

Сообщение scorpi_0n »

Ваша борода тянется от пустого инита таймера. Настройте его как положено и установите бит URS регистра TIM_CR1 чтобы данные вступили в силу. А так у вас первый импульс имеет значения по умолчанию а не те что вы хотите.
Реклама
Эиком - электронные компоненты и радиодетали
CinRock
Родился
Сообщения: 4
Зарегистрирован: Пн дек 21, 2015 11:21:12

Re: stm8l051 - аномалия таймеров

Сообщение CinRock »

При отладке и исследовании регистра TIM3_CNTRL обнаружилось, что в первый запуск таймер считает следующим образом: 0x02; 0x0A; 0x13... То есть не по порядку, в регистре TIM3_CNTRH наоборот же по порядку. В следующих запусках счет в обоих регистрах происходит по порядку.
Реклама
CinRock
Родился
Сообщения: 4
Зарегистрирован: Пн дек 21, 2015 11:21:12

Re: stm8l051 - аномалия таймеров

Сообщение CinRock »

Решено посредством выставления бита UG в Event generation register.
Реклама
dekus
Первый раз сказал Мяу!
Сообщения: 39
Зарегистрирован: Пн янв 16, 2012 00:49:07
Откуда: Москва

Re: stm8l051 - аномалия таймеров

Сообщение dekus »

Пример кода конечно ужасен, но меня поразил советчик.
URS регистра TIM_CR1 чтобы данные вступили в силу
Что за бред то. URS пропускает прерывание только от переполнения счетчика.
"This is to avoid generating both update and capture interrupts when clearing the counter on the capture event".
Что он в этом примере будет установлен, что нет, на что это может повлиять?

Я думаю это будет многим интересно, но я не претендую на истину :). И для STM8 и STM32.

PSC и ARR это не просто регистры. У них есть предварительные регистры, в которые мы и пишем значения, и есть рабочие (теневые) регистры, в которые данные загружаются из предварительных. И эта загрузка происходит по событию обновления UEV, которое вызывается переполнением счетчика.

То есть автор записал в предварительные регистры свои значения, а в реальных остались (после старта) значения по умолчанию, что сразу и привело к переполнению счетчика и к UEV, где значения PSC и ARR автора и загрузились в рабочие регистры.

И если в рабочий ARR можно сразу записать, если не устанавливать ARPE, то рабочий PSC можно обновить только по UEV!

Если нужно сразу обновить рабочие PSC и ARR, а не когда уже переполнится счетчик, то нужно программно вызвать UEV. Это и делается установкой UG в EGR. Принудительный программный вызов UEV. Что автор темы в конце концов и сделал, но никому не объяснил почему так. Только UIF еще после этого нужно сбросить.

Ну и до кучи, формула расчета таймера стр. 11-12, а то какие варианты только не увидишь.
Update_event = TIM_CLK/((PSC + 1)*(ARR + 1)*(RCR + 1))

То есть загружать в счетчики PSC и ARR нужно рассчитанные значения - 1.
Исключение регистр PSCR у STM8 со степень двойки, тут просто степень двойки как есть.
Ответить

Вернуться в «ARM»