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 of “iostm8s103.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