Архів блогу

вівторок, 27 жовтня 2020 р.

Конспект №1 по мікроконтролерам STM8

Hello world - Вітання світу світлодіодом, або зустрічайте чергового мегапрогера.

Після встановлення та налаштування IDE http://ipasoft.info/index.php/blog/8-stm8-ustanovka-sredy-razrabotki-st-visual-develop-cxstm8 можна спробувати посмикати лапкою STM8. На моїй платі з STM8S103F3P6  


   світлодіод є під’єднаний до
PB5. Варто звернути увагу на характеристики виводів мікроконтролера перед тим, як щось робити з ними. Згідно документації виводи можуть бути 3 видів: T = True open drain, OD = Open drain, PP = Push pull. Опису різниці між T та OD  не знайшов.

Дивимось таблицю Table 17. Current characteristics в даташиті STM8S103F3 де вказаний максимальний струм, як втікаючий?впадаючий так і витікаючий, котрий становить 20мА на кожен пін, 100мА загалом на чіп по лінії VDD, ну і ще допустимо 80мА по VSS. Варто зауважити, що HS (high sink capability)  виводии можуть бути тільки з Push pull виходом. Наскільки мені зрозуміло то HS виводи це ті, які можуть пропустити через себе значний струм, певно цілих 20мА,на землю, того може таблиця трохи перебільшує про Output current sunk by any I/O and control pin   20 mA. Але це не точно.

В цій же таблиці вказано допустимий інжектований струм +-4мА на пін та +-20мА не весь чіп. Інжектований стум з’являється тоді коли напруга на лапці контролера є більшою VDD, або ж навпаки меншою за VSS на +-0,3 вольта. Така історія станеться коли живлення мк буде 3.3В (нагадаю, що STM8S можна живити напругою 2.95 to 5.5 V operating voltage), а живлення якогось датчика підключеного до мк буде 5В і коли датчик почне передавати свої 5В в контролер то йому стане фігово, якщо струм буде більшим за 4мА.

Є дуже класна реалізація з виводами True open drain, які згідно Table 16. Voltage characteristics можуть працювати від-0,3В до +6,5В (максимальні значення), незалежно від того скільки вольтів живлення контролера, чи 3В, чи 5В, що є неймовірно зручним для узгодження рівнів по напрузі з різними пристроями. В STM8S103F3 на пінах з True open drain знаходиться інтерфейс I2C, що є просто гіганським + в карму розробників!  Але, схоже, що для UART-а потрібно ставити резистори, або узгоджувачі рівнів при підключенні пристроїв з більшою напругою живлення ніж мк, як і для SPI, а це вже значний мінусL.

Логічні рівні описані в таблицях 39-41 того самого даташиту.  Наскільки я розумію то рівні спрацювання логіки відрізняються в залежності від напруги живлення, конфігурації виходу , та кількості задіяних виводів  4 чи 8 одного порта, на sunk (затоплені?)  чи sourced (оджерелені?).  Схоже словом sunk обзивають виводи котрі налаштовані виходом з низьким рівнем напруги на виході, тобто 0, при цьому нижній транзистор пуш-пула відкритий і навантаження через нього підключається на землю. Sourced - це виводи налаштовані на вихід, але з високим рівнем напруги на виході, тобто нижній транзистор закритий, а відкритий верхній.

Проаналізувавши все вище написане  дивимось Table 6. STM8S103F2 and STM8S103F3 pin descriptions для PB5 котрим хочемо посмикати. Наш PB5 являється True open drain виходом, піни PB5, PB4 заточені під I2C інтерфейс. Саме тому світлодіод на PB5 підключений до плюса живлення, на виході PB5 один транзистора з відкритим витоком, а не пара пуш-пула!!!

Яким струмом можна навантажити дану лапку? Пропоную обирати струм в 5 мА максимум на пін, щоби довго не думатиJ і поміститись в гарантований режим роботи.  Хоча все одно розробники плати вже подумали за мене і навіть зробили J встановивши резистор 1,8кОм послідовно зі світлодіодом, який при 5В живленні мк пропустить струм через лапку в 2,8мА, а при 3В – 1,7мА.

На демонстраційній платі живлення мк 3,3В!!!

Отож запускаємо STVD, створюємо новий проект і починаємо.

http://ipasoft.info/index.php/blog/9-stm8-stvd-cxstm8-konfiguratsiya-gpio-ili-hello-led

Як показала практика, а може я просто ще не дістався тих функцій, вибір мікроконтролера в налаштуваннях проекту не критичний, коли грався з STM8S103F3 та STM8S001 по черзі, то часто забував переобирати мк у властивостях і не помічав ніякої разниці.

А от починати програму потрібно з підключення необхідного файлу, саме для використовуваного мк.

#include "iostm8s103.h"    -  це файл в якому названі всі регістри контролера та вказана область пам’яті де вони саме розміщуються, вміст файлу виглядає так :

/*           Port A

 */

volatile char PA_ODR        @0x5000;        /* Data Output Latch reg */

volatile char PA_IDR        @0x5001;          /* Input Pin Value reg */

volatile char PA_DDR        @0x5002;        /* Data Direction */

volatile char PA_CR1        @0x5003;         /* Control register 1 */

volatile char PA_CR2        @0x5004;         /* Control register 2 */

 

Все прописано згідно даташиту і не вимагає ламання мізків непідготовленого потерпілого конструкціями типу :

#ifdef __IAR_SYSTEMS_ICC__

typedef struct

{

  unsigned char ODR0        : 1;

  unsigned char ODR1        : 1;

  unsigned char ODR2        : 1;

  unsigned char ODR3        : 1;

  unsigned char ODR4        : 1;

  unsigned char ODR5        : 1;

  unsigned char ODR6        : 1;

  unsigned char ODR7        : 1;

} __BITS_PA_ODR;

#endif

__IO_REG8_BIT(PA_ODR,      0x5000, __READ_WRITE, __BITS_PA_ODR);

Які забезпечують роботу з окремими бітами регістрів наступним зверненням до бітів регістра: PA_DDR_bit.DDR0 =1. 

Схожі структури використовуються і в бібліотеках для AVR мікроконтролерів:  out->pin = pin;.

Операції -> та . використовуються для доступу до елементів структур, по ним і можна визначити наявність додаткових надбудов, які використовуються для спрощення, більш наглядної роботи з окремим бітами регістрів.

Файл «iostm8s103.h» являється файлом компілятора Cosmic  і знаходиться в глибинах папок куди компілятор встановлено …COSMIC\FSE_Compilers\CXSTM8\Hstm8\iostm8s103.h. Там же розміщені, так звані, стандартні бібліотеки мови Сі типу math.h, stdio.h

Відповідно в цей файл можна підглядати для правильного написання імен регістрів. Відкривається файл прямо у новій вкладці редактора коду, для цього потрібно виділити ім’я файла та через праву кнопку миші вибрати пункт Go to definition ofiostm8s103.h”. Така дія можлива тільки після компіляції проекту, а щоб проект скомпілювався потрібно написати деякий мінімум у вигляді функції main (void){}.

#include "iostm8s103.h"

main(void) {}

Мінімальна програма готова, хоча вона й нічого не робить за те збирається і компілюється J.

Є один момент! В пункті 5.1.2.2.1 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf пишуть, що main() це головна функція, яка має щось повертати, тому її треба обзивати int main() хоча й Cosmic пише просто main(), але int main() пишеться і у використаних прикладах.

Додамо трохи коду по мотивам http://ipasoft.info/index.php/blog/10-stm8-stvd-cxstm8-konfiguratsiya-gpio-ili-hello-led-ob-yasnenie-teoreticheskoj-chasti

#include "iostm8s103.h"

void delay(unsigned int it)

                {

                while(it--);

                } 

int main()

{

PB_DDR |= (1<<5);

PB_CR1 = 0x00;

PB_CR2 = 0xff;

PB_ODR = 0x00; 

                while (1)

                {

                PB_ODR |= (1<<5);

                delay(50000);

                PB_ODR &= ~(1<<5);

                delay(50000);

                } 

}

Наступна частина програми це функція чи може процедура??? «void delay».

void delay(unsigned int it)

                {

                while(it--);

                }

Чому процедура? Та от наприклад тому http://itrobo.ru/programmirovanie/osnovy-si/procedury-i-funkcii-v-si.html,  http://kpolyakov.spb.ru/school/c.htm -тут також в першому конспекті автор вирізняє функції від процедур. Коротко то пишуть, що процедура від функції  наявністю слова void і тим, що вона не повертає ніяких значень, вона просто виконалась і програма повернулась до подальшого виконання. Функція оголошується не void, а наприклад int checksum (int x),  int це тип значення яке функція має повернути після виконання свого завдання, int x – це значення яке функція приймає для обчислень, їх може бути багато.

А тут http://easyelectronics.ru/file/yazyk-programmirovaniya-s-spravochnik/151-2 кажуть, що в Сі процедур немає. Тут https://learnc.info/c/functions.html, тут  http://www.c-cpp.ru/books/funkcii також не згадують процедури.  

ГМ, виходить якась НІНЗЯ_ЧЕБУРАШКА (непорозуміння) з цими функціями-процедурами.

В цьому документі http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf слово procedure зустрічається лиш один раз і цей раз не вирізняє функцію від процедури. А йому певно варто повірити і назвати все функціями, які, або повертають значення, або не повертають.

Якщо хто знає краще то виправляйте!!!

Так от назвали функцію void delay далі в дужках вказали параметр функції – значення, яке вона приймає для обробки і виконання.  (unsigned int it) параметр it (об’явили чи оголосили?? ІНІЦІАЛІЗУВАЛИ –О!!!) ініціалізували і відразу присвоїли тип unsigned int.

Далі цикл while(it--); починає декрементувати змінну it, яка є параметром функції void delay, як тільки it стане більше нуля, тобто в дужках утвориться логічна істина. Цикл while буде повторюватись поки в дужках буде істина, а завдяки особливостям мови Сі можна скоротити запис

while(it>0

{

it=it-1;

}

до запису while(it--);.

Далі починається основна програма main(). В ній же проводиться конфігурування регістрів, вводиться цикл while (1), який просто постійно крутиться і де в свою чергу написана програма блимання світлодіодом.  

В новому мікроконтролері STM8S всі порти знаходяться у високоімпедансному стані, налаштовані по замовчуванню на вхід без підтяжок, такий же стан по ідеї має бути коли записати в мк пусту програму. В документації написано, що це дефолтний стан і контролер повертається в нього після reset-a. Тут потрібно уточнити, що саме означає слово reset, а воно означає по підтексту явно не просте перезавантаження мк, а повне стирання користувацької програми з налаштуваннями.

Для смикання лапками потрібно 4 регістра:

 DDR  (data direction register) – 0 –вхід, 1 - вихід.

CR1 (control register 1) – 0- open drain - відкритий стік (відкритий колектор), 1-пуш-пул, якщо DDR=1;

                                               -  0- плаваючий(диференційний) вхід, 1- вхід з підтяжкою до +(pull-up) при DDR=0;

CR2 (control register 2) – 0- зовнішні переривання заборонені, 1- переривання дозволені при DDR=0;

0-      вихідна частота до 2МГц, 1- вихідна частота до 10Мгц, при DDR=1;

ODR (output data register) – тут встановлюється вихідний рівень лапки, 0 або 1. 

Більше для блимати світлодіодом не потрібно, бо в STM8S по замовчуванню увімкнене тактування периферії, а ще контролер «з заводу» працює від внутрішнього тактового генератора на частоті 2МГц, частота генератора 16МГц поділена до 2Мгц відповідними регістрами. 

Після налаштувань програма переходить у цикл while (1), де прописано зміну 5-го біту в регістрі вихідних даних ODR.

 PB_ODR |= (1<<5); - тут записується одиничка.

 delay(50000); - тут передається значення 50000 для функція delay, яка в свою чергу рахує від 50000 до 0 і коли дійде до нуля її виконання зупиниться, а програма перейде до наступного кроку.

 PB_ODR &= ~(1<<5); - тут записується нулик на вихід PB5.

delay(50000); - знову чекаємо поки функція дорахує до нуля, після чого програма перейде знову до першого кроку в бескінечному while (1) і виконає  PB_ODR |= (1<<5);.

 Добре, пора чіпляти кнопку.

#include "iostm8s103.h" 

void delay(unsigned int it) //функція затримки

      {

         while(it--); 

      } 

int main()                                                                                                   {

      PB_DDR |= (1<<5);         //PB5 налаштовується виходом

      PB_CR1 = 0x00;                                // для PB4,PB5 режим може бути тільки "open drain"

      PB_CR2 = 0xff;                 // частота перемикання виходу до 10МГц

      PB_ODR |= (1<<5);        // записуємо 1 в PB5, щоби світлодіод не світився,бо він підключений до + 

      PC_DDR = 0x00;              // порт С налаштовується виходом

      PC_CR1 |= (1<<3);          // підключається підтяжка РС3 до плюса, до РС3 підключимо кнопку

      PC_CR2 = 0x00;              // переривання відключені 

      while (1)                              //бескінечний цикл

      {                     

      if (!(PC_IDR&(1<<3)))   // перевіряється чи натиснута кнопка, так як на РС3 одниця, то у випадку 0,

      {

      PB_ODR ^= (1<<5);        //тобто при натисканні кнопки, інвертується біт PB5 і світолодіод засвічується //(гасне)

      delay(10000);                    //після того як світлодіод засвітився(погас), чекаємо 10000 папуг, після чого //програма

      }                                                             // перевіряє умову натиснення кнопки і повторює інверсію PB5, поки //кнопка натиснена

      else

      {

      PB_ODR |= (1<<5);   // в іншому випадку в PB5 записується одиничка щоби світлодіод не світив

      }     

   } 

}

 

В програмі додалось налаштування для PC3, а безкінечний цикл скоротився.

Якщо в безкінечний цикл накидати ще завдань, змінити частоту такування, використати «більші» змінні типу long, double, то час виконання програми зміниться. Світлодіод змінить частоту блимання, контролер може «не побачити» натискання кнопки, або опрацювати її з затримкою. Значить треба вдосконалювати програму.

x

субота, 10 жовтня 2020 р.

Конспект №0 по мікроконтролерам STM8


Творчі пориви в напрямку створення електронних пристроїв змушують зосереджувати увагу на мікроконтролерах та програмуванні.  Для більш якісного засвоєння матеріалу вирішив писати такий собі конспект. Це не буде інструкцією, закликом до чого небудь чи хизування. Має бути просто конспект зі своїми спостереженнями і висновками, які мій мозок вивів на основі опрацьованої інформації з інтернету, або іншими словами результат самонавчання. Не факт, правда, що отримана інформація була вірною чи висновки зроблені з неї є вірними.

Загалом для роботи з мікроконтролерами потрібно знати 3 предмета:

-         англійська мова, благо є гугл;

-         програмування, є повно уроків в інтеренеті;

-         радіоелектроніка, гадаю свої 20 років дружби з паяльником можна врахувати в орієнтовне знайомство з предметом.

До списку не входить багато чого з таких речей як: користування комп’ютером, читання, писання, використання, налаштовування  програмних та апаратних засобів розробки.

Для роботи з сімейством STM8 обраний набір STVD +Cosmic C compiler. Програми робочі, безкоштовні, без обмежень в кількості коду.  ST Visual develop https://www.st.com/en/development-tools/stvd-stm8.html  - фірмове IDE (інтегроване середовище розробки) від STM, але в ньому можна працювати лиш з Асемблером, тому в якості зовнішнього модуля підключається Cosmic C compiler, щоб мати змогу писати-компілювати програми на мові Сі. Cosmic надає безкоштовну ліцензію на використання свого програмного забезпечення для мікроконтролерів  STM8 після реєстрації на їх сайті http://www.cosmicsoftware.com/, також там вказано, що всі продукти  Cosmic включають один рік технічної підтримки та оновлень, як буде після року користування то побачимо...

В якості піддослідних чіпів обрались STM8S103F3P6 на платі та STM8S001, STM8L001 в якості дрібних і дешевих  восьмилапок.

В мікроконтролері є така штука як регістри і якщо ми хочемо чогось від контролера то потрібно спілкуватись з регістрами:  записувати або читати дані, які знаходяться в комірках(розрядах) регістрів. Коли регістр 8-ми бітний в ньому є 8 комірок пам’яті котрі можуть записувати 1 біт інформації тобто 0 або 1. Відповідно для запису – читання бітів регістра використовуються логічні операції з бітами. Бітові операції в мові програмування Сі потрібно знати, як 2+2 з першого класу школи. Особисто мені не завадить нагадування, що є що і куди саме його впихнути потрібно, тому алгебра логіки та бітові операції в Сі:

https://folkprog.net/pobitovie-operatsii-v-c/

https://ph0en1x.net/81-howto-work-with-ports-register-bits-in-microcontroller.html

https://pikabu.ru/story/nemnogo_o_portakh_i_bitovyikh_operatsiyakh_4316272

http://www.atmega8.ru/wiki/view/doc.20.html

https://diodov.net/logicheskie-operatsii-programmirovanie-mikrokontrollerov-avr/

https://diodov.net/pobitovye-operatsii-programmirovanie-mikrokontrollerov-avr-na-c/

https://habr.com/ru/post/406889/

 

Символ

назва

дія (приклад)

&

Побітове логічне «І»

AND», множення)

010 &  101 результат  000

 100 &  101 результат 100

Побітова операція логічного «І» відбувається з кожним розрядом (кожною цифрою)  чисел відповідно таблиці істинності

Х  У   &

0  0   0

0  1   0

1  0   0

1  1   1

&&

Логічне «І», “AND”

Використовується для перевірки умови істинності чи хиби

If( 101 && 010 ) – вираз дасть значення істини і код оператора умови if буде виконано.

x && y – буде істинним допоки один із операндів не стане 0, при чому кажуть якщо перший з операндів стане 0 то другий і наступні опранди до уваги не беруться і перевірятись не будуть в зв’язку з відсутнісю необхідності відповідно таблиці істинності логічного «І», тобто весь вираз прийме стане хибним.

&

отримання адреси

y = &xтака операція призначає адресу комірки пам’яті (номер квартири) де зберігається значення х (гроші) змінній Y, тобто  Y тепер знає номер квартири де лежать гроші і при зверненні до у залюбки каже його(номер).

*

звернення за адресою

z=*yвикористовується для доступу до грошей з квартири номер якої знає у. Враховуючи попередній приклад  вийде, що зет приймає значення ікс через звернення до ігрека  z == x.

|

побітове логічне  «АБО», “OR

(додавання)

101 | 010 буде 111 згідно таблиці істинності

х  у  |

0  0  0

0  1  1

1  0  1

1  1  1

||

логічне «АБО», “OR”

 001 || 000 дасть результаті  значення істини, якщо хоча б один з операндів не 0 то вираз буде істиною згідно таблиці істинності для логічного «АБО». Використовується у  if(001||000)

!

логічне заперечення «НІ», “NOT

(інверсія)

!0 дасть в результаті  1

!1 дасть в результаті  0

If(1!=0 ) – вираз істинний і читається, як -один не дорівнює нулю.

Операція використовується в порівняннях як і  &&, ||.

~

побітове логічне заперечення «НІ», “NOT

~ 010 буде дорівнювати  101. Дана операція - унарна, така, що  проводиться тільки  над одним числом.

^

побітове виключне «АБО»,XOR

х    у    ^    Одиниця в результаті виходить тільки тоді,

0    0    0    коли значення бітів в тих само розрядах

1    0    1    чисел різне. Тобто  1 «АБО» 0 дасть 1 в

0    1    1    результаті, а   1«АБО» 1 та 0 «АБО» 0 дадуть 

1    1    0    логічну хибу чи просто 0.

<< 

логічний зсув вліво

010<<1  дасть 100 

010<<3  дасть 000

Операція зміщує вліво  біти лівої частини (числа 010) на кількість позицій вказану справа виразу.

0b00000000 | (1<<5) – тут же одиниця встановлюється на 5-ту позицію 

0b00000000 | 0b00100000 ==  0b00100000

0b00000000 | (1<<0)   ==  0b00000001

Біти рахуються з 0 !!!!

Зсув числа вліво рівноцінно множенню на 2, на скільки позицій зсунули, на стільки двійок і множити:

2 == 0b00000010

0b00000010 <<  2 == 0b00001000 == 2 *2 *2 == 8

0b00000010 <<  5 == 0b01000000 == 2*2*2*2*2*2 == 64

>> 

логічний зсув вправо

010>>1 001

010>>2 000

Аналогічно зсуву вліво тільки в іншу сторону і при зсуві вправо відбувається ділення на 2  

64 == 0b01000000

 0b01000000 >>  4  ==  0b00000100 == 64/2/2/2/2 == 4

 

 

 

 











































































Оператори порівняння  >, <, >=, <=, ==, != разом з логічними операторами !, &&, || в якості результату завжди дають 0 або 1, істину або хибу, чисел не утворюють!!!

Бітові оператори  &, |, ~, ^, <<, >> в результаті використання можуть утворювати числа відповідно до своєї дії, тобто числа відмінні від просто логічної істини  чи логічної хиби.   

Це звісно не вся інформація по операціям в Сі, тому читаємо, наприклад :

http://www.c-cpp.ru/books

https://learnc.info/c/

https://narodstream.ru/programmirovanie_n_c/

«ВВЕДЕНИЕ В ЯЗЫК СИ» (c) Курсков С.Ю., составление, 2006-2012

Б.В. Керниган, Д.М. Ричи.  «Язык С». 

Оскільки Stm8 – мікроконтролери 8-ми бітні, то й регістри мають 8 бітів, або 8 комірок, є звісно виключення коли 2 8-ми бітні регістри поєднуються в один 16-ти бітний, як то лічильники в таймерах, але контролер від цього 16-ти бітним не стає.

Регістри, їх біти описані в даташИтаманУала  референс мануалі, а те які саме з них реалізовані в конкретному контролері вказано вже в даташиті на контролер.

Наприклад регістр DDR (data direction register-регістр напрямку даних) має 8 бітів кожен з яких відповідає лінії порта вводу-виводу даних. Портом можна, також, називати лапку (вивід, контакт) контролера, але краще не треба. Н випадку різних корпусів, різних серій, не всі порти можуть мати всі фізичні виводи, тобто порт B (PB) є весь в наявності, а виводи має тільки PB4 та PB5. В документах від СТМ є рекомендації переключати віртуальні виводи, які не використовуються(не мають фізичного виводу, лапки) в режим виводу даних (output), конфігурації  ПУШ-ПУЛЛ, та подати низький рівень сигналу на них. Цитата з даташити на STM8S001J3:

«The PA2, PB0, PB1, PB2, PB3, PB6, PB7, PC1, PC2, PC7, PD0, PD2, PD4, PD7, PE5 and PF4 GPIOs should be configured after device reset in output push-pull mode with output
low-state to reduce the devices consumption and to improve its EMC immunity. The GPIOs
mentioned above are not connected to pins, and they are in input-floating mode after a
device reset
»

За допомогою регістра ДДР можна сконфігурувати лапку порта на роботу входом чи виходом. Тут же на допомогу ДДР приходять регістри CR1 та CR2. При роботі входом лапка приймає високоімпедансний стан плаваючий, або притягнутий до плюса живлення, коли ж призначити її виходом то додатково потрібно вказати чи вихід буде відкритим колектором чи буде пуш пул.

Регістри можна представити, як дисковий кодовий замок в якому першим диском ми вибираємо регістр, іншими 8 –ма дисками(або 16-ма, чи 32-ма)  вибираємо код, тобто, функціонал який нам потрібен.

Писати в регістр можна так

PB_DDR = 0b11111111 //всі лінії порта Д встановлено виходом (всі 8 лапок)

PB_DDR =0xFF                // результат від такого запису буде ідентичним попередньому.

Наскільки я зрозумів простим присвоюванням (опрація «=») можна конфігурувати порт на початку програми, в процесі ж роботи програми, коли потрібно записати якісь біти в регістр порта використовуються логічні операції та логічний зсув бітів

PB_DDR |= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)

Так як нумерація бітів починається з нульового біту то відповідно для нього використовується зсув вліво на нульове положення.  Результат такої операції буде ідентичний попереднім двом.

 Хоча на перший погляд і не зрозуміло, чому б не писати через присвоєння завжди: PB_DDR= 0b00000001. Кажуть, що у випадку логічних операцій з конкретними бітами інші біти регістра не змінюються тому користуються таким способом. А ще, я собі думаю, що в процесі виконання програми не можна знати точно де яке значення знаходиться 0 чи 1 тому й використовується зсув разом з логічними операціями для отримання, так би мовити, гарантованого результату незалежно від вмісту регістра.

 Отож бітова магія!

Записуємо одиничку:

PB_DDR = 0b00000000;         // початкове значення порта, після скидання контролера всі виводи (лапки)

                       //  порта налаштовані,  як входи.

PB_DDR  = 0b00100000;        //  лапка PB5 налаштована на вихід.

PB_DDR = 0x20;                       // те саме.

PB_DDR = PB_DDR| (1<<5);  //знову те саме тільки за допомогою логічного «АБО» та логічного зсуву         

                                                      //одинички вліво на позицію з номером 5  (012345)

PB_DDR |= (1<<5);                  // те саме, але скороченим записом.

 

Записуємо нулик (стираємо одиничку обнуляємо ):

PB_DDR = 0b11111111;  // весь порт налаштовано виходом.

PB_DDR & = ~ (1<<7);      // скидаємо в 0 сьомий біт (вивід PB7 стає входом).

PB_DDR == 0b01111111; // результат попередньої дії.

 

Логіка тут наступна:  (1<<7) – робимо зсув одиниці вліво на сьому позицію. Стоп, нам же треба  НУЛЬ, добре чіпляємо хвостика логічного заперечення  ~ (1<<7)  і отримуємо НУЛЬ, але в нас на 7-му місці ОДИНИЦЯ і якщо один додати нуль отримаємо ОДИНИЦЮ,  а це означає необхідність виконати дію множення & = і в результаті отримаємо бажаний НУЛЬ в бажаномі місці.

Всі дії описано відповідно до пріоритету виконання операцій в Сі, спочатку круглі дужки, потім інверсія, потім складений оператор множення з присвоєнням.

 

Зміна стану біта на протилежний:

PB_DDR=0b00000000;     //початковий стан.

PB_DDR^= (1<<5);             // змінюємо  5-й біт порта на протилежний.

PB_DDR==0b00100000;   // результат операції.

PB_DDR^= (1<<5);              // повторно змінюємо.

PB_DDR==0b00000000;    // результат повторної зміни.

 

За пріоритетом спершу виконуються дужки, потім побітове «АБО» разом з присвоюванням. Коли змінюється нуль на одиницю то має бути типу такої дії 0^1 що в результаті дасть 1, яка в свою чергу має стати на 5-ту позицію (5-й розряд).  У випадку  наявної одиниці 1^1 буде 0 який і запишеться в 5-й розряд. Все чинно-ладно по таблиці істинності побітового виключного «АБО».

 

Дані дії треба прийняти, як є. Незважаючи на деяку нелогічність, яка може ЗДАТИСЬ з пріоритетами, діями та результатами.

 

Для зміни декількох, або всіх бітів, необхідно перечислити в правій частині операції всі зсуви потрібних бітів через побітове «АБО»

PB_DDR |= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)

PB_DDR &= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)

PB_DDR ^= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)

 

Потрібно не тільки писати, змінювати, а ще ж читати біти в розрядах портів. В STM8 є свої регістри які потрібно прочитати, щоб отримати інформацію про стан входів порта вводу-виводу даних. Читати потрібно регістри ODR (output data register, Px_ODR) та IDR (input data register, Px_IDR) З назви видно, що регістр  ODR потрібен коли пін працює, як вихід, а IDR коли пін є входом. При цьому в ODR можна писати і читати з нього дані (зручна штука коли, наприклад, програма щось виконала, але результат невідомий наперед, то його можна просто прочитати з регістра порта і зробити щось чи не робити, як то в генераторі випадкових чисел щось випало і треба зробити інтерпретацію вихідних даних, дати відповідь), а регістр IDR тільки читати, що в свою чергу дуже навіть логічно )).

  Як пишеться тут: https://diodov.net/pobitovye-operatsii-programmirovanie-mikrokontrollerov-avr-na-c/

https://obanracer.ru/chtenie-portov-avr-v-si-izuchenie-sistemy-komand-mikrokontrollera-avr.html

Перевірка, читання бітів в регістрі проводиться з операторами if-else, while.

            Перевірка на 0:

            if (0== (PB_ODR&( 1<<5)))                //порівнюємо 0 із п’ятим розрядом порта B, який в свою чергу

                        // перевіряється на 0 зсувом 1 на 5-ту позицію та побітовим  «І» з

                        //значенням, яке знаходиться в регістрі PB_ODR. Відповідно коли 

                        //там 1 то й результатом лог«І» буде одиниця, а коли одиницю      

                       //прирівняєм з 0 то отримаємо логічну брехню (хибу).

 if (~ (PB_ODR&( 1<<5)))     //інша форма запису того самого виразу.

     {

Some code                          // якийсь код

}

            else{

                     Other code                    // інший якийсь код

                    }


 

Особисте спостереження на основі користування ARDUINO при використанні if дуже доречним буде додавання else, для того, щоб програма випадково не потрапила в «незрозумілий стан» і подальший код гарненько виконувався.

Перевірка на 1:

if (0!= (PB_ODR&( 1<<5)))

{

Some code                          // якийсь код

}

            else{

                     Other code                    // інший якийсь код

                        }

if (PB_ODR&( 1<<5))            // інша форма запису того самого виразу.

 

Все те саме окрім порівняння 0!=, яке читається -нуль не дорівнює. Коли нуль не дорівнює одиниці значення істинне і виконується код   «Some code», коли ж в регістрі в п’ятому розряді знаходиться 0 то операція & в (PB_ODR&( 1<<5)) дасть 0, а 0!=0 це вже хибне ствердження, а тому буде виконуватись код «Other code».

 

Очікування 0:

while (PB_IDR & (1<<0))     //як видно операція порівняння не змінилась,

                                      // цикл while буде виконувати Some code до тих пір, допоки на PB0

                                                    //буде одиниця, як тільки порт отримає 0, цикл завершиться, якщо  

                                                    //програма має ще код після while то продовжиться його виконання.

{

Some code

}

Очікування 1:

while (!(PB_IDR & (1<<0)))   //while буде крутитись, а відповідно виконувати Some code допоки на PB0 буде 0.

{

Some code

}

while (~(PB_IDR & (1<<0)))    //те саме тільки для порівняння використовується операція побітового заперечення, тобто 

                                                       //поки PB0 буде 0 до тих пір вираз буде істинним, а відповідно цикл буде виконувати  Some code.

{

Some code

}

 

  Надалі не завадить література:

«Основы микропроцессорной техники: Микроконтроллеры STMС.Н. Торгаев. Томск 2014

«Начало работы с микроконтроллерами STM8» Матюшов Н.В.

RM0016, Reference manual STM8S Series and STM8AF Series 8-bit microcontrollers разом з даташитами на конкретний чіп.