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

STM8S время выполнения цикла...

Вт май 14, 2019 08:21:12

Случайно столкнулся с необъяснимым (пока) для меня фактом. Есть два устройства на базе STM8S, оба работают на внутреннем HSI 16мГц. Использую в обоих задержку для мигания светодиодом. Текст кода цикла:

Код:
if (k>400000) {
        GPIO_WriteReverse(GPIOC, GPIO_PIN_7);          //GPIOС->ODR ^= (uint8_t)GPIO_PIN_7;
        k=0;
}
else k++;


В первом устройстве в общем цикле опрашивается датчик DS18B20, во втором опрашиваются два цифровых входа. В первом устройстве светодиод мигает, во втором не мигает... Начал разбираться - обнаружил, что если во втором меняю количество итераций на 254 - светодиод начинает мигать примерно с той же частотой, что и в первом устройстве... Почему такая колоссальная разница? Опрос датчика получается быстрее в 1600 раз чем опрос двух цифровых входов?

Re: STM8S время выполнения цикла...

Вт май 14, 2019 08:37:33

Как объявлена переменная k?

Re: STM8S время выполнения цикла...

Вт май 14, 2019 10:09:48

Sergeba, думать начинай, на втором форуме опять приводишь бесполезный фрагмент кода, хотя на самом деле внутри цикла полно пауз на 5-10 ms, которые умноженные на 254 дают получаемую задержку.

Re: STM8S время выполнения цикла...

Вт май 14, 2019 10:14:34

во втором не мигает...
Что значит не мигает? Может там частота >100 Гц и ты её глазом не видишь? Прибор ткнуть надо.

Re: STM8S время выполнения цикла...

Вт май 14, 2019 10:16:39

Что значит не мигает? Может там частота >100 Гц и ты её глазом не видишь? Прибор ткнуть надо.

Наоборот, при 254 стало мигать с периодом 1.5с, а было видимо тоже 400000...

Re: STM8S время выполнения цикла...

Вт май 14, 2019 21:01:32

Как объявлена переменная k?


long int

Sergeba, бесполезный фрагмент кода, хотя на самом деле внутри цикла полно пауз на 5-10 ms, которые умноженные на 254 дают получаемую задержку.


Вы второй форум невнимательно читаете. Эти задержки не выполняются, когда на входах прибора отсутствуют сигналы, а они большую часть работы прибора отсутствуют т.к. это кнопки привода электромотора. (Для бОльшей убедительности я убрал эти задержки из кода программы - ничего не изменилось).

Наоборот, при 254 стало мигать с периодом 1.5с, а было видимо тоже 400000...


Всё верно, первое устройство делал с датчиком температуры и там цикл 400000 отрабатывал нормально, скопировал код во второй прибор - не мигает в таком цикле. Стал смотреть изменение переменной - увидел что изменение происходит медленнее, чем предполагал, изменил цикл на 254 - стал мигать.

Добавлено after 9 minutes 36 seconds:
Чтобы было понятно о чём речь - вот код, который выполняется 254 раза за 1,5 секунды:

Спойлер
Код:
while (1)
  {
     ( void )eMBPoll(  );
     if (usRegHoldingBuf[4]==0) {
      usRegHoldingBuf[2]=!GPIO_ReadInputPin(GPIOC, GPIO_PIN_3); //опрос входов
      usRegHoldingBuf[3]=!GPIO_ReadInputPin(GPIOC, GPIO_PIN_4);
     }
     if (usRegHoldingBuf[2]==1 || usRegHoldingBuf[4]==2) //команда вниз
     {
       GPIO_WriteHigh(GPIOD, GPIO_PIN_3);     
       POLfl=true;
       Delay(10000);
       GPIO_WriteHigh(GPIOD, GPIO_PIN_2);
     }
     if (usRegHoldingBuf[3]==1 || (usRegHoldingBuf[4]==1)) //команда вверх
     {
       GPIO_WriteLow(GPIOD, GPIO_PIN_3);     
       POLfl=false;
       Delay(10000);
       GPIO_WriteHigh(GPIOD, GPIO_PIN_2);
     }
     if (usRegHoldingBuf[2]==0 && usRegHoldingBuf[3]==0 && usRegHoldingBuf[4]==0) //стоп
     {
       GPIO_WriteLow(GPIOD, GPIO_PIN_2);
       usRegHoldingBuf[2]=0;
       usRegHoldingBuf[3]=0;
       Delay(5000);
     }
     if (POL != POLfl)
     {
       POL=POLfl;
       usRegHoldingBuf[5]=POL;
     }
///////////////////////////////////////////////////////
     if ((usRegHoldingBuf[0]==0) || (usRegHoldingBuf[0]>0xF7)) {
        usRegHoldingBuf[0]=ADR;
      }
     if (usRegHoldingBuf[1]>5) {
        usRegHoldingBuf[1]=BR;
      }
      if ((usRegHoldingBuf[0]!=ADR) || (usRegHoldingBuf[1]!=BR)) {
        FLASH_Unlock(FLASH_MEMTYPE_DATA); // Разблокируем флеш память
        ADR=usRegHoldingBuf[0];   // Записываем значение переменной
        BR=usRegHoldingBuf[1];
        FLASH_Lock(FLASH_MEMTYPE_DATA);   // Блокируем флеш память
        Delay(5000);
        eStatus = eMBInit( MB_RTU, usRegHoldingBuf[0], 1, (usRegHoldingBuf[1]+1)*9600, MB_PAR_NONE );
        eStatus = eMBEnable(  );
      }
     if (k==255) {
        GPIO_WriteReverse(GPIOC, GPIO_PIN_7);
        k=0;
     }
     else k++;
  }
}

Re: STM8S время выполнения цикла...

Вт май 14, 2019 21:33:07

(Для бОльшей убедительности я убрал эти задержки из кода программы - ничего не изменилось).

Убери задержки из второго проекта, где 254.

Re: STM8S время выполнения цикла...

Вт май 14, 2019 23:56:14

(Для бОльшей убедительности я убрал эти задержки из кода программы - ничего не изменилось).

Убери задержки из второго проекта, где 254.


Странно... Я вроде бы по русски написал: я убрал эти задержки из кода программы - ничего не изменилось, а Вы мне опять советуете их убрать...

Re: STM8S время выполнения цикла...

Ср май 15, 2019 00:17:45

Странно... Я вроде бы по русски написал: я убрал эти задержки из кода программы - ничего не изменилось, а Вы мне опять советуете их убрать...

Т.е. у тебя такой код мигает с периодом 1.5 сек?
Код:
while(1)
{
   if (k > 254)
   {
        GPIO_WriteReverse(GPIOC, GPIO_PIN_7);
        k=0;
   }
   else k++;
}

Re: STM8S время выполнения цикла...

Ср май 15, 2019 08:04:48

Reflector писал(а):Т.е. у тебя такой код мигает с периодом 1.5 сек?


Нет, я убрал только обращения к функции Delay() (хотя из кода понятно, что они не должны влиять на выполнение цикла на холостом ходу), остальное не трогал. Т.е. операторы if и поллинг Modbus остался в коде. Мигает с периодом 1,5сек.
Вечером попробую методом постепенного исключения найти виновника задержки...

Re: STM8S время выполнения цикла...

Ср май 15, 2019 09:03:47

Так, что-то и я уже начал тупить :) В общем изначально понятно, что если второй цикл выполняется в 1600 раз медленнее, а делает практически то же самое, значит где-то выполняются дополнительные операции и Delay был наиболее вероятным кандидатом. Тем более для 1.5с нужна пауза ~6ms, а они там по 5-10ms.

Re: STM8S время выполнения цикла...

Ср май 15, 2019 19:28:10

В общем изначально понятно, что если второй цикл выполняется в 1600 раз медленнее, а делает практически то же самое, значит где-то выполняются дополнительные операции и Delay был наиболее вероятным кандидатом. Тем более для 1.5с нужна пауза ~6ms, а они там по 5-10ms.


Да, Вы оказались правы отчасти. Я нашёл виновника задержки. Вчера я убрал только Delay(10000), но они действительно не обрабатываются в холостом цикле и не влияли на время исполнения, но я не убрал Delay(5000)... Эта задержка обрабатывается в холостом цикле. Убрал её - цикл ускорился. Но как оказалось всё равно опрос датчика получается происходит быстрее, чем опрос двух цифровых входов. Чтобы добиться приблизительно одинакового мигания - на устройстве, где датчик температуры прописано 400000 циклов, на устройстве опроса двух входов - 180000. Т.е. скорость отличается в 2,2 раза.

Добавлено after 9 minutes 23 seconds:
Теперь бы разобраться ещё с тактированием... Устройство с опросом цифровых входов имеет внешний резонатор на 8000Мгц. Для этого устройства портировал FreeModbus по инструкции, но там используется внутренний генератор 16Мгц. Задержки на таймере соответственно рассчитаны. Пробую запустить внешний кварц, при этом меняю коэфициент задержки по прилагаемой формуле - хрен - не работает modbus... Так и оставил пока работу на внутреннем генераторе...

Вот код для настройки таймера с формулой расчёта:

Код:
/* TIM4 configuration:
   - TIM4CLK is set to 16 MHz, the TIM4 Prescaler is equal to 128 so the TIM1 counter
   clock used is 16 MHz / 128 = 125 000 Hz
  - With 125 000 Hz we can generate time base:
      max time base is 2.048 ms if TIM4_PERIOD = 255 --> (255 + 1) / 125000 = 2.048 ms
      min time base is 0.016 ms if TIM4_PERIOD = 1   --> (  1 + 1) / 125000 = 0.016 ms
                                                           --> 16us
  - In this example we need to generate a time base equal to 50us
   so TIM4_PERIOD = (0.00005 * 125000 - 1) = 5 */
    /* Time base configuration */
  TIM4_TimeBaseInit(TIM4_PRESCALER_128, (5*usTim1Timerout50us));


Для 8Мгц меняю коэфициент с 5 на 2.
Ответить