Страница 118 из 130

Re: Программирование STM8

Добавлено: Ср авг 23, 2023 21:46:02
Pjatruha@mail.ru
Спасибо за наводку.
Саму книгу скачать не удалось, но нашел где ее можно почитать. Правда для этого пришлось зарегистрироваться. Попутно нашел еще и лабораторный практикум того же автора.

Re: Программирование STM8

Добавлено: Вт авг 29, 2023 18:49:58
Pjatruha@mail.ru
Подскажите, пожалуйста, а как избавиться от дребезга контактов программно? Знаю, что можно задержку добавить после опроса кнопки, но это не лучшее решение, вроде. А как же тогда борются с этим явлением? В электронике для этого используют триггер. Наверное что-то подобное можно программно реализовать?

Re: Программирование STM8

Добавлено: Вт авг 29, 2023 19:11:18
Martian
Задержка. Только не глобальная, которая останавливает всю программу, а задержка на реакцию следующего события кнопки. Реализации могут быть всякие, с таймерами и без, для работы по прерываниям или нет...

Re: Программирование STM8

Добавлено: Вт авг 29, 2023 20:51:11
Pjatruha@mail.ru
Написал я вот такую програмку

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

#include "IOSTM8S103F3.h"
 
int main (void) 
{ 
    
   PD_DDR_bit.DDR3 = 0; // Активируем порт PD3 в качестве "входа"
   PD_CR1_bit.C13 = 0; //  переключаем порт в качестве Дифф. входа 
   PD_CR2_bit.C23 = 0; // Прерывания запрещены
   
   PB_DDR_bit.DDR5 = 1; // Настраиваем PB5 в качестве "вывода".
   PB_CR1_bit.C15 = 1; // Переключение порта в режим push-pull. 
   PB_CR2_bit.C25 = 1; // Скорость переключения до 2 МГц
   
   int n = 2;
  while(1)
  {
    if (PD_IDR_bit.IDR3!=1) // Проверка нажатия кнопки. Кнопка NO замыкает PD3 на землю. PD3 через резистор подтянут к плюсу.
    {
      for  (unsigned long i=0;  i<20000;  i++);
      if (PD_IDR_bit.IDR3!=1)
      {
        n++;
      }
    }
    switch(n)
    {
      case 1:
        PB_ODR_bit.ODR5 = 0; // Включение светодиода. 
        break;			
      case 2:
        PB_ODR_bit.ODR5 = 1; // Отключение светодиода.
        break;			
      default:
        n=1;
         }
  }
   
}
Задержка на нажатие кнопки в этой программе глобальная, правильно? А как будет выглядеть локальная задержка?
Не нравится мне как работает кнопка. Переключения не очень четкие. Оно конечно гораздо лучше чем без задержки, но все равно не то. Подскажите, в какую сторону копать?

Re: Программирование STM8

Добавлено: Вт авг 29, 2023 21:21:06
Martian

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

 
int main (void)
{
   i = 0;
   ....
  while(1)
  {
     if (i > 0) 
     {
        i--;
     }

     if (PD_IDR_bit.IDR3!=1) // Проверка нажатия кнопки. Кнопка NO замыкает PD3 на землю. PD3 через резистор подтянут к плюсу.
     {
       if (i == 0)
       { 
         i = 20000;
         n++;
       }
     }

   .....
  }// while
}
фактически, это тоже самое, только теперь i меняется в глобальном цикле, не препятствуя выполнению основной программы. При первом нажатии происходит обработка (n++;) и инициализируется счётчик (i = 20000;). И пока i не станет равным нулю, последующие состояния кнопки игнорируются. Минус такого решения: в зависимости от ветвления основной программы длительность игнорирования может сильно отличаться. Использование таймера позволит сделать более точное время антидребезга.

И ещё: кнопка может генерировать три события: KeyUp, KeyDown и Click. Вариант подобного кода их не различает, то есть, как только счетчик обнулится и кнопка при этом не отпустится, она снова обработается.

Re: Программирование STM8

Добавлено: Вт авг 29, 2023 22:25:01
Pjatruha@mail.ru
[uquote="Martian",url="/forum/viewtopic.php?p=4470112#p4470112"]только теперь i меняется в глобальном цикле, не препятствуя выполнению основной программы.[/uquote]
Ах вот как это делается... А я всю голову себе сломал... Все оказывается лежит на поверхности. :)
[uquote="Martian",url="/forum/viewtopic.php?p=4470112#p4470112"]И ещё: кнопка может генерировать три события: KeyUp, KeyDown и Click.[/uquote]
Навереное KeyUp/KeyDown будет выглядеть вот так, с учетом ваших рекомендаций:

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

int main (void)
{
   i = 0;
   ....
  while(PD_IDR_bit.IDR3!=1) // KeyUp - 0, KeyDown - 1
  {
     if (i > 0)
     {
        i--;
     }   
       if (i == 0)
       {
         i = 20000;
         n++;
       }
     
   .....
  }// while
}
А Click будет выглядеть вот так:

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

int main (void)
{
   i = 0;
   ....
  while(1)
  {
     if (i > 0)
     {
        i--;
     }

     if (PD_IDR_bit.IDR3!=1) 
     {
       if (i == 0)
       {
         if (PD_IDR_bit.IDR3!=0)
          {
            i = 20000;
            n++;
          }
       }
     }

   .....
  }// while
}

Re: Программирование STM8

Добавлено: Вт авг 29, 2023 23:06:15
Martian
во втором случае проверка на отжатие сработает в момент дребезга и сделает ложный клик. Отжатие в свою очередь тоже вызывает дребезг, поэтому надо немного больше заморочиться.

Re: Программирование STM8

Добавлено: Ср авг 30, 2023 17:53:40
Pjatruha@mail.ru
[uquote="Martian",url="/forum/viewtopic.php?p=4470141#p4470141"]поэтому надо немного больше заморочиться.[/uquote]
Тогда Click будет выглядеть так:

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

int main (void)
{
   i = 0;
   j = 0;
     ....
  while(1)
  {
     if (i > 0)
     {
        i--;
     }
     if (PD_IDR_bit.IDR3!=1 & i == 0)
     {
       if (j == 0 )
       {
         j = 1;
       }
     }
     if (PD_IDR_bit.IDR3!=0 & j == 1)
       {
           if (i == 0)
            {
              i = 20000;
              j = 0;
              n++;
            }
       }
   .....
  }// while
}
Дополнение
Нет, не будет это работать. Надо еще подумать...

Все, придумал. Проверил. Четкие переключения без ложных срабатываний. Теперь мне нравится работа кнопки.

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

int n = 2, i=0, j=0;
  while(1)
  {
    if (i > 0)
     {
        i--;
     }

     if (PD_IDR_bit.IDR3!=1 & i == 0)
     {
       if (j == 0 )
       {
         j = 1;
         i = 2000;
       }
     }
     if (PD_IDR_bit.IDR3!=0 & j == 1)
       {
           if (i == 0)
            {
              i = 2000;
              j = 0;
              n++;
            }
       }
}

Re: Программирование STM8

Добавлено: Ср авг 30, 2023 23:31:37
Martian
Ну, надо просто нарисовать алгоритм, примерно так:
произошло событие кнопки, например, замыкание, которое мы отловили и теперь должны переждать дребезг.
пока идет дребезг, мы не реагируем ни на что.
дребезг закончился, смотрим состояние кнопки, если она всё ещё нажата - запускаем/инкрементируем счётчик, как долго нажата кнопка, если хотим отловить удержание, для, например, входа в меню, если не хотим - продолжаем игнорировать.
если не нажата - считаем, что кнопка была отпущена, надо снова переждать дребезг.
пока идет дребезг, мы не реагируем ни на что.

То есть, у нас видится как одинаковое что-то, так и разное что-то. Одинаковое - это пережидание дребезга, изменение состояния кнопки (неважно, на какое) и отсутствие реакции:

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

int main (void)
{
   drebezg_count = 0;
   button_status = 0; // 0 - не нажата, 1 - нажата
     ....
  while(1)
  {
     if (drebezg_count > 0)
     {
       drebezg_count--;  // пережидаем дребезг
     }
     else
     { 
// а здесь пишем обработку кнопок
        if ((PD_IDR_bit.IDR3 == button_status) // кнопка изменила состояние
        {
           drebezg_count = 20000;
           button_status != button_status; //меняем статус кнопки
          // здесь можно вызвать функцию обработки события кнопки или написать код
     }

// продолжение программы
  }
}
Я не проверял строго, писал прям здесь, но вот как-то так, попроще (чем проще - тем меньше риск ошибок). Мы теперь можем ловить изменение любого состояния кнопки, минуя оба дребезга и строить дальше уже логику исходя из какое именно изменение (по фронту или спаду) кнопки произошло

Re: Программирование STM8

Добавлено: Чт авг 31, 2023 19:19:14
Pjatruha@mail.ru
Суть вашей идеи я уловил, как мне кажется, но отдельные моменты мне остались не понятны.
[uquote="Martian",url="/forum/viewtopic.php?p=4470548#p4470548"]// а здесь пишем обработку кнопок[/uquote]
Поясните этот момент. Не понял, что за обработка.



А тут вы хотели сделать инверсию?
[uquote="Martian",url="/forum/viewtopic.php?p=4470548#p4470548"]button_status ^= button_status;[/uquote]
Если да, то 0^0=1, но и 1^1=1. Может вот так: button_status = !button_status ? Или так нельзя?

Re: Программирование STM8

Добавлено: Чт авг 31, 2023 19:55:28
Martian
Да, блин, ошибся, думал и об бите, и о буле ) спасибо за замечание.

Обработка кнопок - здесь это часть программы, которая опрашивает кнопки и что-то изменяет от действий кнопки, у Вас, например, n++

Re: Программирование STM8

Добавлено: Чт авг 31, 2023 20:00:36
Pjatruha@mail.ru
Тогда что вы имели ввиду тут?
[uquote="Martian",url="/forum/viewtopic.php?p=4470548#p4470548"]// здесь можно вызвать функцию обработки события кнопки или написать код[/uquote]
Честно говоря, в этих двух строчках я и запутался. :)

Re: Программирование STM8

Добавлено: Чт авг 31, 2023 20:15:51
Martian
Просто я как-то неверно выразил мысль.
Она была как-то так - обработка кнопок - это то, что касается опроса состояния портов, где подключены кнопки и то, что меняет что-то в программе в зависимости от результата опроса портов. Вызов функции обработки события кнопки - это как раз последняя часть, то самое инкрементирование n++. Просто работа с кнопками может быть гораздо большей, чем просто инкрементирование, раздувать главный цикл неудобно, поэтому, я бы написал так:

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

void KeyChange(unsigned char btn_status);
...

int main (void)
{
   drebezg_count = 0;
   button_status = 0; // 0 - не нажата, 1 - нажата
     ....
  while(1)
  {
     if (drebezg_count > 0)
     {
       drebezg_count--;  // пережидаем дребезг
     }
     else
     {
// а здесь пишем обработку кнопок
        if ((PD_IDR_bit.IDR3 == button_status) // кнопка изменила состояние
        {
           drebezg_count = 20000;
           button_status != button_status; //меняем статус кнопки
          KeyChange(button_status);
        }
     }

// продолжение программы
  }
}

void KeyChange(unsigned char btn_status)
{
   if (btn_status == 1) // проверка, что произошло событие отпускания кнопки
   {
      n++;
   }
}

Конечно, ради одного условия и инкремента нет смысла и сожрет больше ресурсов на вызов, если оптимизатор не соптимизирует, но зато удобно и минимизирует ошибки: если антидребезг и опрос портов отлажены, то там уже ничего не трогается, работаем только с KeyChange

Re: Программирование STM8

Добавлено: Чт авг 31, 2023 21:03:42
Pjatruha@mail.ru
[uquote="Martian",url="/forum/viewtopic.php?p=4470993#p4470993"]если антидребезг и опрос портов отлажены, то там уже ничего не трогается, работаем только с KeyChange[/uquote]
Сразу видно, что не один десяток программ написали :) Мыслите глобально с заделом на будущее. Я пока так не умею, но буду к этому стремиться.

Re: Программирование STM8

Добавлено: Чт авг 31, 2023 23:18:07
valentinovich
Pjatruha@mail.ru писал(а):Я пока так не умею, но буду к этому стремиться.
Ничего, ничего, как говорят "лиха беда начало". :)
Стремиться к чему-то - это хорошо и нужно.
Но главное всё же во всём этом уловить, что основное есть выбор правильного алгоритма для решения задуманного вами процесса!
И только второе - это его та или иная (но желательно всё же оптимальная :roll: ) реализация на выбранном вами языке.
Удачи в освоении программирования. :beer:

Re: Программирование STM8

Добавлено: Пт сен 01, 2023 17:27:52
Pjatruha@mail.ru
[uquote="valentinovich",url="/forum/viewtopic.php?p=4471080#p4471080"]Но главное всё же во всём этом уловить, что основное есть выбор правильного алгоритма для решения задуманного вами процесса![/uquote]
Да, полностью с вами согласен. Это я еще со школьной скамьи знаю. :lol:(давно это было...) Мы тогда паскаль изучали. Сам язык и не помню, но алгоритмы составлять нас научили(я так думаю :) ).

Добавлено after 9 hours 30 minutes 46 seconds:
Подскажите, пожалуйста, а как мне посчитать частоту моргания светодиода в этой программе:

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

#include "IOSTM8S103F3.h"

int main( void )
{
  int k=0;
   PB_DDR_bit.DDR5 = 1; //
   PB_CR1_bit.C15 = 1; //
   PB_CR2_bit.C25 = 1; //
   while(1)
  {
   if ( k > 0)
  {
    k++;
  }
  if (k == 0)
        {
     PB_ODR_bit.ODR5 = 0;
     k++;
        }
  if (k == 200)
  {
     PB_ODR_bit.ODR5 = 1;
  }
  if (k == 400)
  {
    k=0;
  }
  } 
}
Частота работы процессора по умолчанию 2МГц. Нужно 2000кГц/400? Что-то у меня другую частоту осциллограф показывает...

Re: Программирование STM8

Добавлено: Пт сен 01, 2023 19:41:55
Martian
Упростим до:

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

#include "IOSTM8S103F3.h"

int main( void )
{
   unsigned char k=0;
   PB_DDR_bit.DDR5 = 1; //
   PB_CR1_bit.C15 = 1; //
   PB_CR2_bit.C25 = 1; //
   while(1)
   {
     if (++k == 200)
     {
       PB_ODR_bit.ODR5 ^= 1; 
       k = 0;
     }
   }
}
теперь смотрим листинг ассемблера, как компилятор скомпилировал:

Изображение

Теперь надо сосчитать количество тактов процессора, которые потребуются для выполнения всех этих команд. И вот на это число и надо делить частоту работы процессора, а не на 400.

Наверное, пришло время изучить таймеры ;)

Re: Программирование STM8

Добавлено: Пт сен 01, 2023 21:51:47
Pjatruha@mail.ru
[uquote="Martian",url="/forum/viewtopic.php?p=4471482#p4471482"]теперь смотрим листинг ассемблера, как компилятор скомпилировал:[/uquote]
Большое спасибо за пояснение.

[uquote="Martian",url="/forum/viewtopic.php?p=4471482#p4471482"]Наверное, пришло время изучить таймеры ;)[/uquote]
Опять вы зрите в корень. :lol:
Уже начал изучать. А параллельно и прерывания. Пару дней уже не могу понять вот это

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

Обработчики прерываний определяются следующим образом: 
#pragma vector=<номер прерывания> (табл. 3.1) 
__interrupt void <имя прерывания>, 
<номер прерывания> – номер прерывания в hex формате. Берется 
значение  из  технической  документации  микроконтроллера  и  к  нему 
прибавляется 2. 
<имя  прерывания> –  имя,  которое  будет  именем  подпрограммы 
обработчика прерывания (определяется пользователем). 
__interrupt void Это функция, которая будет исполнятся при наступлении условия прерывания(вектора прерывания)?
Как указать значение вектора прерывания? Точнее сказать, какое значение должно стоять, например, для TIM1 захват/сравнение? Не могу разобраться как значение из таблицы перевести в шестнадцатеричный формат.

Re: Программирование STM8

Добавлено: Пт сен 01, 2023 23:24:11
Martian
Полагаю, проще прочитать здесь: https://we.easyelectronics.ru/STM8/8l-k ... -exti.html
а то писать очень много :)

Добавлено after 1 minute 34 seconds:
И обязательно читать учебник, прилагающийся к каждой среде разработки, так как есть различия.

Re: Программирование STM8

Добавлено: Сб сен 02, 2023 09:34:26
Pjatruha@mail.ru
Большое спасибо за статью. Мне очень понравилось. Написано простыми словами. Очень легко читать. Пожалуй прочитаю весь цикл статей этого автора по теме STM8. Но тут ответ на мой вопрос все же не полный. По сути можно не заморачиваться и пользоваться готовой таблицей из заголовочного файла IOSTM8S103F3.h(ведь не зря же он подключен :) ) , но мне все же хотелось бы разобраться до конца. Как получилась эта таблица в заголовочном файле?
Вот таблица из DataSheet
Изображение
Нужно брать номер вектора прерывания из первого столбца таблицы, прибавлять к нему 2, а затем переводить в шестнадцатеричный формат? Т.е. для TIM2 capture/compare это значение будет 14+2=16(dec)=10(hex),верно?