Обчислення і перетворення чисел BASCOM-8051

Bascom дозволяє виробляти арифметичні обчислення (додавання, віднімання, множення і деле-ня) над цілими числами (одно-, двох і четирехбайтний) і числами у форматі з плаваючою точкою У слідую- щей таблиці показане розташування байтів змінних в памяті

Тип

змінної

Розташування в памяті

Перший байт

(Adr*)

Другий байт

(Adr+1)

Третій байт

(Adr+2)

Четвертий байт

(Adr+3)

Однобайтового пе-

ремінна (Byte)

Байт

Двухбайтовая

(Word, Integer)

Молодший байт

Старший байт

Чотирьохбайтового

(Long)

1-й байт

(Молодший)

2-й байт

3-байт

4-й байт

(Старший)

У форматі з пла-

вающей точкою

(Single)_

1-й байт

(Молодший)

2-й байт

3-байт

(Старший)

Байт

порядку Обчислюється як 127 + p, де p-порядок з ви-Ражнів:

2 ^ p + Мантиса

Знак

Нормалізована мантасса, що приймає значення від 1 до 2,

старший біт мантиси відкидається (тільки увазі-

ся наявність завжди рівного 1)

Приклади коду 00 00 80 3F = 1 чисел в порядку, 00 00 00 40 = 2 розташування в 00 00 80 40 = 4 памяті 00 00 00 41 = 8

00 00 80 41 = 16

00 00 00 42 = 32

00 00 80 42 = 64

00 00 00 43 = 128

00 00 20 C1 = -10

00 00 20 C0 = -25

0 –

плюс 1 – мі-

нус

* Adr – адреса змінної певний при компіляції

Bascom з цілими двухбайтного числами може виконувати знакові (з змінними типу Integer і Long) і беззнакові (з змінними типу Byte і Word) арифметичні операції Арифметичні операції з четирехбайтний числами завжди проводяться з урахуванням знака При цілочисельних обчисленнях довжина результа-та, не може перевищувати довжини вихідних числових змінних Навіть при множенні 8-розрядних чисел резуль-тат буде теж 8-розрядних Аналогічно для 16-розрядних і 32-розрядних чисел Змішані твори дають результат, рівний по довжині, довшою змінної Головна прикрість цієї особливості компілятора полягає в тому, що при переповненні (можливе при додаванні і особливо множенні) губляться старші розряди Ця помилка не показується компілятором тому, що вважається помилкою програміста Щоб цього не відбувалося, додавання та множення при наявності ймовірності переповнення потрібно виконувати з використанням ням змінних подвійної довжини, а це значно збільшує час операції, або застосовувати швидку ас-семблерную програму з власною програмою додавання і множення Нижче наведена одна така програм-мало

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

Нижче наведена програма, в якій є приклади обчислення і перетворення чисел, виконуваних

мие компілятором Bascom

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

‘Перетворення числових змінних і обчислення

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

$large

Dim Cnt As Const 5 число 5

Dim Bt As Bit визначимо по парі всіх типів змінних

Dim Byt As Byte , Byt1 As Byte Dim Wrd As Word , Wrd1 As Word

Dim Intg As Integer , Intg1 As Integer Dim Lng As Long , Lng1 As Long

Dim Sng As Single , Sng1 As Single

‘————————————————- — Set Bt встановити біт

‘————————————————- — перетворення змінних

Byt = Bt значення біта поміщається в молодший розряд

Byt = Cnt записати число (константу)

Wrd = Byt в молодший байт дані, в старший байт 00

Intg = Wrd перемістити дані без змін

Intg = Not Intg інвертувати

Wrd = Intg назад без змін

Sng = Wrd: Print Sng перетворити в плаваючу Sng = 655500

Sng = Intg: Print Sng перетворити в плаваючу Sng = -60 ———————————– —————–

‘Цілочисельні обчислення

Intg = Intg * 5: Print Intg результат Intg = -30

Intg = Intg / 5: Print Intg рузультате Intg = -6

Intg1 = 1000

Intg = Intg1 / Intg: Print Intgрезультат Intg = -166

Intg = Intg * -1 зміна знака Це повільний варіант

Intg = Not Intg: Intg = Intg + 1 аналогічно, але працює набагато швидше

Intg = Not Intg: Incr Intg теж працює швидко

Lng = Intg щоб отримати 32-розр результат множення, Lng = Lng * Intg хоча б один з операндів має бути 32-розр Lng = 1000000: Lng = Not Lng інверсія для зміни знака

Incr Lng                        -1000001 + 1 = -1000000

Print Lng результат Lng = -1000000

Lng = Lng / 1000 ділення на константу

Print Lng результат Lng = -1000

Wrd = Lng / 1000 так неправильно, хоча компілятор помилку не покаже

Lng = Lng / 1000: Wrd = Lng а це правильно

Intg1 = -10

Lng = Lng / Intg1 ділення на змінну іншої розмірності

Print Lng результат Lng = 100

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

‘Обчислення з плав точкою

Sng = Sng * Lng множення цілого числа на плаваюче

Print Sng результату Sng = -6000

Sng1 = 015: Sng = Sng * Sng1 множення плаваючих чисел

Print Sng результату Sng = -900

Sng = Sng / -10 ділення на константу

Print Sng результату Sng = 90

$asm

Xrl {Sng +3}, # & h80 миттєва зміна знака числа з плав точкою

Anl {Sng +3}, # & h7f або установка позитивної полярності

Prl {Sng +3}, # & h80 або установка негативної полярності

$end asm

‘————————————————- — демонстрація неправильного множення

Byt = 10: Byt1 = 15: Wrd = & H1234 призначимо числа

Wrd = Byt * Byt1 твір відразу запишемо в двухбайтное число

Printhex Wrd результат Wrd = 1296h – тільки в молодших розрядах

Byt = Byt * Byt1 проробляємо це ж інакше, а потім

Wrd = Byt переписуємо з очищенням старших розрядів

Byt1 = Wrd назад беруться лише молодші розряди і Print Byt Byt1 Wrd тепер результат скрізь однаковий = 150 —————————————– ———–

‘Визначимо час виконання арифметичних операцій

Byt = 50: Byt1 = 10 призначимо числа

Byt = Byt + Byt1 додавання – 11 тактів

Byt = 50: Byt1 = 10 числа

Byt = Byt – Byt1 віднімання – 12 тактів

Byt = 20: Byt1 = 10 числа

Byt = Byt * Byt1 умножніе – 10 тактів

Byt = 50: Byt1 = 10 числа

Byt = Byt / Byt1 ділення – 10 тактів

‘————————————————- — Wrd = 500: Wrd1 = 100 числа

Wrd = Wrd + Wrd1 додавання – 20 тактів

Wrd = 500: Wrd1 = 100 числа

Wrd = Wrd – Wrd1 віднімання – 21 такт

Wrd = 200: Wrd1 = 100 числа

Wrd = Wrd * Wrd1 умножніе – 63 такту

Wrd = 500: Wrd1 = 100 числа

Wrd = Wrd / Wrd1 ділення – 560 тактів ————————————— ————- Intg = 500: Intg1 = -100 числа

Intg = Intg + Intg1 додавання – 20 тактів

Intg = 500: Intg1 = -100 числа

Intg = Intg – Intg1 віднімання – 21 тактів

Intg = 200: Intg1 = -100 числа

Intg = Intg * Intg1 умножніе – 95 тактів

Intg = 500: Intg1 = -100 числа

Intg = Intg / Intg1 ділення – 620 тактів ————————————— ————- Lng = -5000: Lng1 = 1000 числа

Lng = Lng + Lng1 додавання – 74 такту

Lng = -5000: Lng1 = 1000 числа

Lng = Lng – Lng1 віднімання – 74 такту

Lng = -2000: Lng1 = 1000 числа

Lng = Lng * Lng1 умножніе – 2500 тактів

Lng = -5000: Lng1 = 1000 числа

Lng = Lng / Lng1 ділення – 3200 тактів

‘————————————————- — Sng = 50: Sng1 = 10 числа

Sng = Sng + Sng1 додавання – 240 тактів

Sng = 50: Sng1 = 10 числа

Sng = Sng – Sng1 віднімання – 290 тактів

Sng = 20: Sng1 = 10 числа

Sng = Sng * Sng1 множення – 2000 тактів

Sng = 50: Sng1 = 10 числа

Sng = Sng / Sng1 ділення – 2300 тактів ————————————— ————- визначимо час виконання перетворень

Byt = 100: Sng = Byt байт в плаваючу – 490 тактів

‘Назад перетворення не виробляється

Wrd = 10000: Sng = Wrd слово в плаваючу -370 тактів

Wrd = Sng назад -340 тактів

Intg = -1000: Sng = Intg знакова слово в плав – 470 тактів

Intg = Sng назад – 420 тактів

Lng = 1000000: Sng = Lng подвійне слово в плав – 280 тактів

Lng = Sng назад – 250 тактів —————————————– ———– End

У демонстраційній програмі є відповіді майже на всі питання застосування операцій перетворень-

ня та використання в обчисленнях числових змінних Потрібно зауважити, що виміряні значення вироб-

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

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

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

Нижче дається приклад швидкої ассемблерной програми беззнакового множення 16-розрядних чисел,

дає 32-розрядний результат

;———————————————-

; Множення двухбайтного ЧИСЛА НА двухбайтного ЧИСЛО

; ЧАС ВИКОНАННЯ 52 ТАКТ

; ВИХІДНІ ЧИСЛА: В R3-СТ, R2-МЛ І R1-СТ, R0-МЛ РЕЗУЛЬТАТ В R7-СТ, R6, R5, R4

;———-

MUL2B: множення молодшими ЦИФР ПЕРШОГО І ДРУГОГО ЧИСЛА

MOV     A,R2

MOV     B,R0

MUL     AB MOV     R4,A MOV     R5,B

; Множення молодшими ЦИФРИ ПЕРШОГО ЧИСЛА на старших ДРУГОГО ЧИСЛА

MOV     A,R2

MOV     B,R1

MUL     AB

; Скласти із попереднім РЕЗУЛЬТАТОМ

ADD     A,R5

MOV     R5,A CLR     A ADDC    A,B MOV     R6,A

; Множення молодшими ЦИФРИ ДРУГОГО ЧИСЛА на старших ПЕРШОГО ЧИСЛА

MOV     A,R3

MOV     B,R0

MUL     AB

; Скласти із попереднім РЕЗУЛЬТАТОМ

ADD     A,R5

MOV     R5,A

MOV     A,R6

ADDC    A,B

MOV     R6,A

CLR     A

RLC     A

MOV     R7,A

; Множення СТАРШИХ ЦИФР ПЕРШОГО І ДРУГОГО ЧИСЛА

MOV     A,R3

MOV     B,R1

MUL     AB

; Скласти із попереднім РЕЗУЛЬТАТОМ

ADD     A,R6

MOV     R6,A

MOV     A,R7

ADDC    A,B

MOV     R7,A

;—————————————————-

Bascom дозволяє виробляти дуже складні обчислення, завдяки короткій формі записи виробляй-

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

‘————————————————- — тестування програми обчислення квадратного кореня

Dim X As Single, Y As Single, Z As Single тимчасові значення

Do

Input &quotx=&quot , X

X = X + 000001 щоб ніколи не було нульового значення, яке

‘Викликає переповнення при обчисленні квадратного кореня

Gosub Sqr тепер обчислимо квадратний корінь (час обчислення 50 мс) Print Y подивимося результат

Loop

‘—————————–

‘Підпрограма обчислення квадратного кореня за формулою Ньютона

‘Обчислення проводиться методом послідовних наближень: Yi +1 = (X / Yi + Yi) * 5

‘Початкове (вихідне) значення обчислюється за формулою: Y0 = X / 200 + 2

Sqr:

‘Обчислимо початкове значення, з якого почнемо іттерацію

Y = X * 0005 : Y = Y + 2

Do

‘Обчислимо чергове значення кореня Y = (X / Y + Y) * 5

Z = Y : Y = X / Y : Y = Y + Z : Y = Y * 05

‘Перевіримо IF ABS (Y1 – Y)> Y / 1000 GOTO srq_1

‘В Bascom функція ABS не працює з числами у форматі з плаваючою точкою

Z = Z – Y: Z = Z / Y обчислюємо відношення між остан і предпосл значення

$asm

Anl {z + 3}, # & H7f робимо абсолютне значення стиранням знака

$end Asm

Loop Until Z < 0.001 'якщо необхідна точність досягнута (0.1%) Return' виходимо

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

Далі наведено ще кілька підпрограм для обчислення функцій методом розкладання в степеневий ряд У цих програмах для скорочення розміру коду застосована упаковка повторюваних операцій в підпрограм грами, що значно скорочує розмір коду (2 – 3 рази)

‘————————————————- ————————- обчислення десяткового логарифма Log (x) функція в Ua від аргументу Ua

‘————————————————————————–

Log:

‘Виділимо порядок (двійковий вихідного числа), а залишок зробимо

‘Числом в діапазоні від 1 до 2

$asm

Mov R0 , #{ua + 2}

Mov A , @R0

Mov C , Acc7

Clr Acc7

Mov @R0, A Inc R0

Mov A , @r0

Rlc A

Mov {tmpb} , A Mov @R0 , #&ampH40

$end Asm

‘Числа для довідки:

‘ln(2)= 0,69314718, 1/ln(2)=1442695, ln(10)=23025851, 1/ln(10)=04342945

Gosub Ln обчислимо натуральний логарифм залишку

Ua = Ua * 1442695 перетворимо в двійковий логарифм залишку

Ub = Tmpb: Ub = Ub – 128: Ua = Ua + Ub обєднаємо порядок і логарифм залишку

‘І отримаємо двійковий логарифм числа

Ua = Ua * 030103001 перетворимо в десятковий логарифм

Return

‘————————————————- ————————- обчислення натурального логарифма Ln (x) функція в Ua від аргументу Ua дуже хороша точність тільки від x = 1 до x = 3 (близько 0003 %)

‘При x = 5 похибка близько 002%, а при x = 10 – 07%

‘               3   5   7   9   11   13     n

‘              p   p   p   p   p    p      p             x-1

‘Ln (x) = 2 * [p + – + – + – + – + – + – .. + -] де p = —– 3 5 7 9 11 13 n x +1

‘————————————————————————– Ln:

Ub = Ua – 1 : Ua = Ua + 1

Ua = Ub / Ua

Ub = Ua * Ua : Uc = Ub * Ua : Ud = Uc * 03333333 : Gosub Add_aad Gosub Mul_cbc : Ud = Uc * 02 : Gosub Add_aad

Gosub Mul_cbc : Ud = Uc * 014285714 : Gosub Add_aad

Gosub Mul_cbc : Ud = Uc * 01111111111 : Gosub Add_aad Gosub Mul_cbc : Ud = Uc * 009090909 : Gosub Add_aad

Gosub Mul_cbc: Ud = Uc * 007692308: Gosub Add_aad точність 0003% Gosub Mul_cbc: Ud = Uc * 006666667: Gosub Add_aad

‘    Gosub Mul_cbc : Ud = Uc * 005882353 : Gosub Add_aad

‘    Gosub Mul_cbc : Ud = Uc * 005263158 : Gosub Add_aad Ua = Ua + Ua : Return

‘———————

‘Для скорочення розміру коду повторювані програми виділимо

Mul_cbc:

Uc = Ub * Uc : Return ——————— Add_aad:

Ua = Ua + Ud : Return ———————

‘————————————————- ————————- синусна функція в Ua від аргументу Ua в радіанах

‘Хороша точність тільки до 90 град (близько 00002%) при 180 град похибка досягає 4%

Sin:

Ub = Ua : Ua = Ua * Ua Uc = Ua

Ua = Ua * 0013888889                   1/72

Gosub Sub_aa1

Gosub Mul_aac

Ua = Ua * 00238095243                  1/42

Gosub Add_aa1

Gosub Mul_aac

Ua = Ua * 05                           1/20

Gosub Sub_aa1

Gosub Mul_aac

Ua = Ua * 016666667                    1/6

Gosub Add_aa1

Gosub Mul_aab

Return

‘——————— Add_aa1:

Ua = Ua + 1

Return

‘———————

Sub_aa1:

Ua = Ua –  1

Return

‘——————— Mul_aac:

Ua = Ua * Uc Return

‘———————

Mul_aab:

Ua = Ua * Ub Return

‘————————————————————————–

‘Косинусна функція в Ua від аргументу Ua в радіанах

‘Хороша точність тільки до 90 град (близько 0003% від максимального значення) при 180 град похибка досягає 3%

Cos:

Ua = Ua * Ua                            angle squared

Ub = Ua                                 save Ua = Ua * 0017857144                   1/56

Gosub Sub_aa1

Gosub Mul_aab

Ua = Ua * 0033333333                   1/30

Gosub Add_aa1

Gosub Mul_aab

Ua = Ua * 0083333333                   1/12

Gosub Sub_aa1

Gosub Mul_aab

Ua = Ua * 05                           1/2

Gosub Add_aa1

Return

‘————————————————- ————————- показова функція e ^ x в Ua від аргументу Ua в радіанах

‘Хороша точність тільки до x = 3 (близько 0002%) точність при x = 4 (близько 007%), а при x = 10 – 4% Exp:

Ub = Ua + 1                                               1+x/1 Gosub Mul_cac : Ud = Uc * 05 : Gosub Add_bbd             +x^2/2 Gosub Mul_cac : Ud = Uc * 016666667 : Gosub Add_bbd      +x^3/3 Gosub Mul_cac : Ud = Uc * 0041666667 : Gosub Add_bbd     +x^4/4 Gosub Mul_cac : Ud = Uc * 0008333333 : Gosub Add_bbd     +x^5/5 Gosub Mul_cac : Ud = Uc * 00013888889 : Gosub Add_bbd    +x^6/6 Gosub Mul_cac : Ud = Uc * 00001984127 : Gosub Add_bbd    +x^7/7 Gosub Mul_cac : Ud = Uc * 0000024801587 : Gosub Add_bbd  +x^8/8 Gosub Mul_cac : Ud = Uc * 0000002755732 : Gosub Add_bbd  +x^9/9 Gosub Mul_cac : Ud = Uc * 00000002755732 : Gosub Add_bbd +x^10/10

Return

‘———————

Add_bbd:

Ub = Ub + Ud : Return ——————— Mul_cac:

Uc = Uc * Ua : Return

‘——————— Add_cad:

Ua = Ua + Ud : Return

‘————————————————————————–

Можливість застосування тих чи інших обчислювальних програм частот обумовлена ​​продуктивно-стю мікроконтролера Далі наведена програма цифрового фільтра нижніх частот третього порядку Для його реалізації з вказаною частотної характеристикою потрібно дуже висока продуктивність мікрокон-троллера – в десять разів вище стандартної (еквівалентно понад 120 МГц) Для цього можуть бути використані тільки поліпшені моделі W77E58, DS89C420) При використанні мікроконтролера з ядром AVR ця і всі наведені вище обчислювальні програми працюють швидше в середньому в 50 разів (компілюють BasAVR)

‘————————————————- ————————- фільтр з частотою зрізу близько 5-10 Гц при частоті вибірок 500 Гц

‘(Частоті виклику даної програми) Коефіцієнт передачі фільтра: 1 січня

‘К = ———————– * ——— 0006 * p ^ 2 + 0111 * p + 1 01 * p + 1

‘А це коефіцієнти цифрового фільтра

Const _a = 0013869625

Const _b = -083217753

Const _c = 18183079

Const _d = 009090909

Const _e = 09090909

‘———————

Dim Ux As Single вхідне значення

Dim Uy As Single вихідне значення першої ланки

Dim Uy1 As Single попереднє вихідне значення першої ланки

Dim Uy2 As Single предпредидущее вихідне значення першої ланки

Dim Uz As Single вихідне значення другої ланки

Dim Uz1 As Single попереднє вихідне значення другої ланки

‘————————

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

‘2-го і 1-го порядку:

‘Uy = Ux * a + Uy2 * b + Uy1 * c – формула ланки другого порядку

‘Uz = Uy * d + Uz1 * e – формула фільтра ланки першого порядку

‘—–

Filtr_3p:

Uy = Ux * _a: Uz = Uy2 * _b: Uy = Uy + Uz програма фільтра другого порядку

Uz = Uy1 * _c : Uy = Uy + Uz Uy2 = Uy1 : Uy1 = Uy

‘—–

Uz = Uy * _d: Uy = Uz1 * _e: Uz = Uy + Uz програма фільтра першого порядку

Uz1 = Uz : Return

‘——————————————

Bascom версій 2хх розширив діапазон можливих дій з бітовими змінними Тепер стала можливим операція з індексованими битами Причому в якості індексу може виступати інша змінна, і звичайно тільки байтовая Наприклад:

Dim X As Byte , Y As Byte

X3 = Y2: P21 = Y4 передача значень між бітами байтових змінних

For X = 0 To 7 індексування біта

Set P3X

Next

If P2X = 1 Then перевірка індексованого біта

P2X = 0

End If

Джерело: МЛКуліш, ДОВІДНИК З ПРОГРАМУВАННЯ 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>

*

*