Деякі поради щодо створення великих програм BASCOM-8051

Як будь-яка мова високого рівня, Bascom орієнтований на отримання якомога більше дій у виконуваному коді при мінімальному обсязі вихідного тексту І насправді, Bascom є підходящим інструментом для створення великих програм Тепер визначимо поняття «велика програма» Такий варто вважати програму, що використовує велику кількість ресурсів (памяті, вбудованої і зовнішньої периферії), що працює з великою кількістю програмних і фізичних обєктів, що має кілька незалежних станів або функцій і виконує безліч дій Велика програма, як правило, відрізняється розміром коду, не поміщається в память команд стандартних моделей мікроконтролерів (8051 і 8052) Нижче будуть приведені поради щодо створення оптимального коду «великих програм», оптимального з точки зору економії ресурсом мікроконтролера Ці поради будуть не менш корисні і при розробці коду для «маленьких» процесорів, наприклад AT89C2051

Приблизний розмір коду можна визначити за обсягом вихідного тексту Починаючи з третього-четвертого кілобайти кожні 50 рядків вихідного тексту (близько 70 операторів), не рахуючи порожніх рядків і рядків з мітками і коментарями, дають один кілобайт виконуваного коду

11 Приступаючи до розробки великої програми необхідно оцінити можливість створення такої

програми в рамках наявних апаратних ресурсів Може бути, потрібно створити резерв памяті – передбачити можливість використання «старшої» моделі мікроконтролера з більшою програмної памяттю або додатковою памяттю даних

12 Не використовуйте унікальних моделей мікроконтролерів або їх унікальних властивостей Переробка великої програми під інший процесор нікому не потрібна

13 Для формування тимчасових інтервалів максимально застосовуйте таймер, а не час виконання операторів (команд) конкретним мікроконтролером в даному проекті У іншому випадку ви отримаєте програму, яку без переробки не можна буде використати в іншому проекті

14 Подумайте як будете налагоджувати – без емулятора не обійтися Може бути схема не дозволить

застосувати наявний емулятор – краще змінити схему

Другий рада (про економії часу)Оцініть, скільки часу знадобиться на програмування і налагодження програму, може бути, ви їм не володієте Коли обєм вихідного тексту «вилізе» за 1000 рядків (це 6 – 8 кБ коду) робота почне сповільнюватися Таким чином середня швидкість розробки програми 1 – 15 кБ на місяць може стати реальною Для прискорення роботи програму можна розділити на незалежні модулі (великі програми ділити набагато простіше) і писати їх паралельно

Третій рада (про напрацювання) Використовуйте у великій програмі відпрацьовані модулі інших програм або розробляти і налагоджувати їх заздалегідь Розробити велику програму в розумні (або плановані) терміни без заділів НЕМОЖЛИВО Це правило можна сформулювати інакше – якщо все написане вами раніше не перевищує потроєного обсягу того, що ви збираєтеся написати, то, швидше за все, ви з роботою не впораєтеся

41 Пишіть якомога простіше Поменше вигадливих конструкцій і хитрощів Головне надійність роботи, а складнощів і так вистачить

42 Ретельно і детально коментуйте програму, а оформляйте акуратно Це, в підсумку, заощаджує

час Пишіть кожен програмний модуль так, щоб його можна було використовувати багаторазово –

наступні програми будуть писатися все простіше і простіше

43 Делите вихідний текст програми на частини як тільки він досягне 1000 рядків Так зручніше працювати

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

44 Менше використовуйте асемблерні вставки Вони не настільки ефективні (для скорочення коду) як в маленьких програмах

45 Не використовуйте виняткових особливостей даної версії компілятора Якщо якусь проблему вам вдалося подолати неординарним способом, то швидше за все, в наступній версії інша проблема

виникне в цьому ж місці знову

Пятий рада (коли думати)Перед початком роботи ретельно продумайте, що і коли писати Розробіть структуру програми і план використання ресурсів Інакше можна довго працювати на корзину Якщо немає бачення загальної картини, починайте з модулів програми, які напевно знадобляться (зараз або, в крайньому випадку, коли-небудь)

Шоста порада (сумісність з AVR) Поменше використовуйте унікальних можливостей ядра 8051 і Bascom-8051. Не захоплюйтеся без необхідності асемблерними вставками Це, в результаті, не дає великого виграшу Може бути програму доведеться перенести на AVR-ядро і компілювати BasAVR, який сумісний на 95% з Bascom-8051, але працює більш ніж на порядок швидше

71 Чим більше програма, тим краще вона повинна бути структурована

72 Кожна функція або дія має бути оформлене у вигляді окремого незалежного і повністю автономно функціонуючого модуля

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

74 Строго виконуйте принцип – кожна дія або використання одиниці апаратного ресурсу виконується тільки в одному місці програми або тільки одним програмним модулем Тільки таким чином

можна швидко налагодити і перевірити роботу програми При цьому правильне функціонування одного

пристрою або правильне виконання операції означає правильну роботу програми, що відповідає за це

75 Як можна ширше використовуйте табличні методи запису безпосередніх даних Для цього нумеруйте режими роботи, обєкти, послідовно виконувані операції та стану програми Вводите для цього спеціальні змінні, що приймають значення номера всього того, що пронумеровано Дані про стан портів, числові константи, текстові повідомлення, адреси переходів, знакогенератора тощо, залежні від номера режиму програми (стану або тп) оформляйте у вигляді таблиць В результаті прискорюється робота програми і дотримується принцип єдиності опису даних Дуже зручно, що дані, які застосовуються до одного обєкту, сконцентровані в одному місці і описуються один раз Нижче наведено типовий приклад табличній програми

‘————————————-

‘Взяти номінальне значення рівня калібрування в Ub

‘Ub (Single) – приймає значення, Ranga (Byte) – нумерація кроків калібрування

Get_nom_sc:

Ub = Lookup(ranga , Tab_nom_sc) : Return ————————————-

‘Таблиця номінального значення напруги на кроках калібрування в вольтах

Tab_nom_sc:

Data 00003 0 – Межа 02mv Data 00005 1 – Межа 05mv Data 0001 2 – Межа 1mv Data 0003 3 – Межа 2mv Data 0005 4 – Межа 5mv Data 001 5 – Межа 10mv Data 003 6 – Межа 20mv Data 005 7 – Межа 50mv Data 01 8 – Межа 100mv Data 03 9 – Межа 200mv Data 05 10 – Межа 500mv Data 1 11 – Межа 1v

‘————————————-

Наступний приклад програми організація табличних переходів Для цього в найбільшою мірою підходить оператор ON var GOTO .., .., … Ми бачимо, що залежно від значення змінної Ranga відбувається перехід до мітці одного з варіантів дій Головна особливість цієї конструкції в порівнянні з схожою конструкцією SELECT CASE var …….., яка також може бути використана для створення таблиці переходів, є можливість отримання дуже компактного коду А запис довгих рядків, починаючи з версії 120, перестала бути непереборною перешкодою Тепер довгі рядки з мітками прекрасно переносяться за допомогою символу _.

‘————————————-

‘Програма запису константи залежно від кроку калібрування з Flda Wr_c_sc:

On Ranga Goto Ws0 , Ws1 , Ws2 , Ws3 , Ws4 , Ws5 , Ws6 , Ws7 , _ Ws8 , Ws9 , Ws10 , Ws11 , Ws12 , Ws13 , Ws14

‘Встановити адресу запису і підготувати дані для запису

Ws0:   Wadr = Varptr(dc  2mv): Goto Wsend масштаб межі 02 мВ Ws1: Wadr = Varptr (dc  5mv): Goto Wsend масштаб межі 05 мВ Ws2: Wadr = Varptr (dc_1mv): Goto Wsend масштаб межі 1 мВ Ws3: Wadr = Varptr (dc_2mv): Goto Wsend масштаб межі 2 мВ Ws4: Wadr = Varptr (dc_5mv) : Goto Wsend масштаб межі 5 мВ Ws5: Wadr = Varptr (dc_10mv): Goto Wsend масштаб межі 10 мВ Ws6: Wadr = Varptr (dc_20mv): Goto Wsend масштаб межі 20 мВ Ws7: Wadr = Varptr (dc_50mv) : Goto Wsend масштаб межі 50 мВ

Ws8: Wadr = Varptr (dc_100mv): Goto Wsend масштаб межі 100 мВ Ws9: Wadr = Varptr (dc_200mv): Goto Wsend масштаб межі 200 мВ Ws10: Wadr = Varptr (dc_500mv): Goto Wsend масштаб межі 500 мВ Ws11: Wadr = Varptr (dc_1v) масштаб межі 1 У Wsend: Flda = Rscl: Goto Wr_cal_c

‘————————————-

Іншою особливістю наведеного прикладу є те, що він показує яким чином записати в таблицю і використовувати в програмі адресу змінної певної Bascom Змінної Wadr передається значення адреси іншої змінної за допомогою оператора Varptr () Спроба це ж дію записати в більш звичному вигляді (приклад нижче) буде невдалою, оскільки Bascom не може поміщати в поля даних значення символьних визначень

‘————————————- Це не працююча програма

Wadr = Lookup(ranga , Tab) Tab:

Data Dc_2mv% тут компілятор записує 0000h Data Dc_5mv%

Data Dc_10mv%

Data Dc_20mv% Data Dc_50mv% Data Dc_100mv% Data Dc_200mv% Data Dc_500mv% Data Dc_1v%

76 Конструкція ON var GOTO .., .., .. краще конструкції SELECT CASE var …….. (дає більш компактний код) навіть якщо ви використовуйте всього два-три із шістнадцяти-двадцяти можливих значень тестируемой змінної var Конструкцію SELECT CASE потрібно застосовувати тоді, коли вибір дійсно великий або число значень, що приймається змінної, не обмежена Нижче дається приклад використання конструкції ON .. GOTO при обробці кнопок У тих випадках, коли кнопку обробляти не потрібно, зазначений перехід на мітку-«заглушку» (Mcz_mes) Ще раз нагадаємо, в даному прикладі змінна Buf_kl може мати значення тільки від 0 до 16

‘————————————- Обробка кнопок при калібруванні нуля Comzkl:

On Buf_kl Goto Mcz_mes , Mcz_mes , To_next_step , To_prev_step , End_of_c , _

Mcz_mes

,

Mcz_mes

,

Mcz_mes

,

Mcz_mes , _

Mcz_mes

,

Mcz_mes

,

Mcz_mes

,

Mcz_mes , _

Mcz_mes

,

Mcz_mes

,

Mcz_mes

,

Mcz_mes

‘————————————-

77 Упаковуйте в підпрограми всі повторювані фрагменти навіть якщо це всього одна операції У

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

Ua = Ub + Uc або Ua = Ua + 10123

дає близько 50 байт коду Якщо цю операцію оформити підпрограмою, то кожен її виклик (не рахуючи опису

підпрограми) займатиме всього 3 байта Приклади ефективного використання цього прийому є в розділі, присвяченому обчислень В обчислювальних програмах ця міра дає найбільший виграш (до двох-трьох разів), а в середньому розмір всієї програми може скоротитися на чверть

81 Правильно розподіляйте змінні в памяті мікроконтролера Оцініть необхідну їх кількість Може бути, знадобиться розширити память, Для цього краще застосувати модель процесора з

додатковою памяттю – сьогодні їх дуже багато – це все моделі ряду 8xC51Rx з ОЗУ від 512 до 1280 байт

82 Якщо в системі є розширена память, розташовуйте в ній змінні, використовувані рідше або ті, які завжди адресуються за допомогою індексного регістра (рядкові та масиви) Змінні типу Single також можна розташовувати в зовнішній памяті – це не відібється на продуктивності (все одно їх обробка займає багато часу) Однак потрібно бути уважним при використанні цих змінних – напевно, маються оператори не працюють (або неправильно працюючі) з даними у зовнішній памяті Змінні типу Byte, Word, Integer і Long потрібно розташовувати в основній памяті і нижче 7fh

91 Залишайте більше місця для стека Великі програми завжди припускають велику вкладеність

підпрограм Мінімальний розмір стека 32 байта, а безпечний становить 48 байт (коли стек використовується

звичайним чином) Якщо застосовані переривання, додайте ще Перевіряйте після компіляції, скільки залишилося після розміщення всіх змінних

92 Включайте в програму операції відновлення стека Це підвищить надійність роботи тривало працюючих програм Відновлення можна проводити, наприклад, при перемиканні режиму роботи, коли оновлюються значення багатьох змінних Для цього в текст програми відразу після ініціалізації включите

наступний маленький фрагмент:

Clr_mem:

$asm

Mov R0 , #&amphff

Mov @ r0, Sp запамятати значення стека в самій верхній комірці

Dec R0

Clrmem:

Mov @ r0, # 0 очищення памяті

Djnz R0 , Clrmem

$end Asm

Тепер в потрібному місці завжди можна відновити значення стека, призначене компілятором:

$asm

Mov R0 , #&amphff

Mov Sp, @ r0 відновити значення стека

$end Asm

Обидві програми написані на асемблері, щоб повністю контролювати цей процес

101 Чи не застосовуйте складні конструкції перевірки умов По-перше, це не скорочує розмір коду

(Навпаки, збільшує в порівнянні з простими перевірками) Рекомендований максимум – конструкція If .. Then .. Else .. End If Краще нехай буде більше простих операторів перевірки умов – буде менше помилок ваших і компілятора

102 Чи не застосовуйте вкладені конструкції перевірки умов Це також не скорочує розмір коду, а тільки завантажує стек Якщо дуже потрібно, застосовуйте конструкцію If .. Then .. Elseif … Then … End If)

103 Пишіть програму так, щоб все проверяемое було по можливості змінними типу Bit, Byte і

Single

104 Аналіз строкових змінних зводите до перевірки значення одного символу

105 Ніколи не перевіряйте значення числа, записаного в строкової змінної Перетворіть в число,

а потім перевіряйте

106 Ніколи не перевіряйте на рівність значення числа записаного у форматі з плаваючою точкою (типу Single) Числа в цьому форматі записані наближено Тому два однакових числа, отриманих різним способом, швидше за все не рівні

111 Чи не застосовуйте складних конструкцій Вони збереглися як приналежність перших версій Бейсика з нумерований рядками і, що не має міток для переходу Вони зручні для інтерпретує версій

Бейсика, так як скорочують розмір вихідного тексту У сучасній версії всі спеціальні конструкції легко

будуються за допомогою операторів перевірки умов і переходу Прості конструкції займають більше місця тільки в початковому тексті, а в коді вони коротші Крім того, менше використовується стек і додаткові внутрішні змінні, які займає компілятор Маються на увазі конструкції типу: Do .. Loop Until .., While .. Wend і навіть For .. Next Громіздкою код дає конструкція Select Case .., практично не поступається ланцюжка конструкцій типу If .. Then …

112 Уникайте вкладеності складних конструкцій і тим більше однакових конструкцій Можливі помилки компілятора Краще відразу зробити додаткову гілку програми, ніж довго шукати причину помилки

113 Намагайтеся, щоб у програмі застосовувалося якомога більше однакових конструкцій Всі вони будуть використовувати одну бібліотечну підпрограму А чим менше бібліотека, тим коротше програма

114 По можливості використовуйте перевірені і відпрацьовані конструкції з тими ж типами змінних Застосування нової конструкції, швидше за все, призведе до помилки і необхідності перевірки її

роботи

115 По можливості, використовуйте для управління програмою (вибору, розгалуження, індексації) тільки бітові і байтові змінні, навіть якщо число таких змінних доведеться збільшити Ви отримаєте дуже компактний і швидко працюючий код

Дванадцятий рада (про передачі значень адрес)Використовуйте оператор Restore і функцію Varptr ()

для зчитування значень адрес змінних і міток отриманих при компіляції

При програмуванні з використанням Bascom виникають труднощі записи в поля безпосередніх даних адрес, визначених при компіляції При записи мітки або символьного імені змінної в поле

даних (наприклад, при створенні таблиць) компілятор повертає в коді нульові значення Пропонований спосіб передачі програмі значень адрес, отриманих при компіляції, демонструє нижче наступна програма Dim X As Byte , Y As Byte , W As Word

$Ramstart = &ampH1000

Dim Var1 As XRAM Single

W = Varptr (Var1) вважаємо адресу змінної

Print W “4096 – адреса змінної

M1:

Restore M1 вважаємо адресу мітки

Gosub Read_restore

Print W “240 – адреса мітки M1

End

‘———–

‘Підпрограма зчитування адреси, записаного оператором Restore Read_restore:

X = Peek(&ampH47) : Y = Peek(&ampH48)    &amph47 = (SP)-2, &ampH48 = (SP)-1

W = Makeint(x , Y)

Return

Оператор Restore записує значення зазначеної мітки у внутрішню змінну (типу Word), розташування якої потрібно визначити в відладчик У компіляторі версії 2хх вона розташовується під стеком, обчисленим компілятором (її адресу = (SP) – 2) Це значення можна подивитися у файлі звіту про компіляції (викликається кнопками Ctrl + W) Можна спробувати застосовувати і наступну конструкцію

‘Варіант підпрограми зчитування адреси, записаного оператором Restore

$Asm

Pop Acc взяти під стека

Mov {W + 1} , A Pop Acc

Mov {W} , A Inc SP

Inc SP

$End Asm

Функція Varptr () відразу записує адресу змінної Обсяг одержуваного коду від подібних дій дуже малий (6-20 байт), тому їх можна застосовувати в програмі багато разів і, навіть створювати таблиці їх цих операторів

Джерело: МЛКуліш, ДОВІДНИК З ПРОГРАМУВАННЯ BASCOM-8051, Краснодар 2001

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*