Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

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

Пн дек 21, 2015 11:54:28

Доброго времени суток! Проблема заключается в следующем: При первом запуске, любой из таймеров (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 раз.

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

Пн дек 21, 2015 12:11:32

Ничего там аномального нет кроме самой проги и недочитанного RM. А так как написано так и работает. Всё правильно.
ARPE установлен. Значит значения в регистры таймера попадут только по апдэйту. Что и наблюдается на картинке.

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

Пн дек 21, 2015 12:14:36

scorpi_0n писал(а):Ничего там аномального нет кроме самой проги и недочитанного RM. А так как написано так и работает. Всё правильно.
ARPE установлен. Значит значения в регистры таймера попадут только по апдэйту. Что и наблюдается на картинке.


Увы, но с ARPE = 0, происходит такая же борода.

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

Пн дек 21, 2015 12:26:49

Ваша борода тянется от пустого инита таймера. Настройте его как положено и установите бит URS регистра TIM_CR1 чтобы данные вступили в силу. А так у вас первый импульс имеет значения по умолчанию а не те что вы хотите.

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

Пн дек 21, 2015 13:32:26

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

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

Пн дек 21, 2015 13:51:43

Решено посредством выставления бита UG в Event generation register.

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

Вт июл 02, 2019 10:26:02

Пример кода конечно ужасен, но меня поразил советчик.
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 со степень двойки, тут просто степень двойки как есть.
Ответить