Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » FAQ по Bascom AVR и МК » Скорость работы операторов Bascom


Скорость работы операторов Bascom

Сообщений 31 страница 52 из 52

31

Операторы сравнения If...Then и Select...Case для переменных типа String
=================================================
Во всех случаях, независимо от типа переменной, Dim S As String * 4
Во всех случаях использован "пустой" Gosub...Return

If S = "1" Then Gosub...               71 такт
If S <> "1" Then Gosub...             73 такта
If S > "1" Then Gosub...               75 тактов
If S < "1" Then Gosub...               73 такта

If S = "12" Then Gosub...             95 тактов
If S <> "12" Then Gosub...           97 тактов
If S > "12" Then Gosub...             99 тактов
If S < "12" Then Gosub...             97 тактов

На каждый последующий символ в переменной ("123", "1234" и т.д.) добавляется 24 такта.
Дальше даже копаться не стал - тенденция очевидна. ;)

=================================================

Select Case S                              результат - True
      Case "1" : Gosub...                71 такт
End Select

Select Case S                              результат - False
      Case "2" : Gosub...                47 тактов
End Select

Select Case S                              результат - True
      Case "12" : Gosub...              95 тактов
End Select

Select Case S                              результат - False
      Case "21" : Gosub...              65 тактов
End Select

На каждый последующий символ в переменной ("123", "1234" и т.д.) при результате True добавляется 24 такта.

Что занятно, но при увеличении количества символов более 2-х при результате False выполнение ускоряется - используется уже 47 тактов, а не 65.
Изначально подумал, это связано с тем, что использовались разные очередности символов - "12" и "21" и при различии уже в первом символе результат сравнения будет False, но пробы показали, что "12" или "123" ситуацию не меняют.

Отредактировано Nord (2021-09-13 20:06:54)

+3

32

Основные логические операции AND, NOT, OR, XOR

C = A AND B
Для переменных типа Byte              10 тактов
Для переменных типа Integer          21 такт
Для переменных типа Long              42 такта
Для переменных типа Single            операция не выполняется, Error : 392
Для переменных типа Double           операция не выполняется, Error : 392

C = NOT A
Для переменных типа Byte              10 тактов
Для переменных типа Integer          28 тактов
Для переменных типа Long              44 такта
Для переменных типа Single            операция не выполняется, Error : 31
Для переменных типа Double           операция не выполняется, Error : 31

C = A OR B
Для переменных типа Byte              10 тактов
Для переменных типа Integer          21 такт
Для переменных типа Long              42 такта
Для переменных типа Single            операция не выполняется, Error : 392
Для переменных типа Double           операция не выполняется, Error : 392

C = A XOR B
Для переменных типа Byte              10 тактов
Для переменных типа Integer          21 такт
Для переменных типа Long              42 такта
Для переменных типа Single            операция не выполняется, Error : 392
Для переменных типа Double           операция не выполняется, Error : 392

Отредактировано Nord (2021-09-13 21:08:38)

+5

33

Возникла необходимость подсчета CRC для 1-Wire устройств...
Решил проверить в свете данной темы...

B = Crc8(A(1) , 7)          575 тактов
:canthearyou:

CRC16 даже пробовать страшно... ;)

0

34

Не бойтесь! Всё зависит от Задачи. Где-то и Wait 30 -- нормально :)

0

35

Александр Д. написал(а):

Не бойтесь! Всё зависит от Задачи.

Неоспоримо. ;)
Понятно, что при расчете CRC "затратная арифметика", просто ожидалось хотя бы раза в три быстрее. ;)

0

36

Nord написал(а):

Каждый последующий результат True дает приращение в 5 тактов, а False - в 2 такта, например:

Без прироста тактов

+2

37

Nord написал(а):

Возникла необходимость подсчета CRC для 1-Wire устройств...
Решил проверить в свете данной темы...
B = Crc8(A(1) , 7)          575 тактов

Есть МК с аппаратным подсчетом CRC. Должно быть быстрее.

+1

38

Вот стандартный алгоритм CRC8. Он на Паскале, но думаю перевести на Бейсик нетрудно. Попробуйте, может быстрее будет.

Код:
//------------------ Подсчет CRC8 ------------------
function Crc8: Byte;
var
  m,j,k,x,Crc: Byte;
begin
Crc:=0;
For m:=1 To 7 do begin
 x:=D[m];
  For k:=0 To 7 do begin
   j:=1 And (x Xor crc);
   crc:=Trunc(crc / 2) And $FF;
   x:=Trunc(x / 2) And $FF;
   If j <> 0 Then crc:=crc Xor $8C;
  end;
end;
Crc8:=Crc;
end;

+2

39

Спасибо всем откликнувшимся ! ;)
Возьму на заметку сказанное, ускориться никогда не лишне.

0

40

Вот тут опять распроверялся...  :blush:
Сразу оговорюсь - не ради приращения скорости, а просто ради интереса ! ;)
На этот раз RND без предварительных указателей.

Dim A As Byte
A = Rnd(255)          292 такта

Dim A As Integer
A = Rnd(32767)      296 тактов

Dim A As Word
A = Rnd(65535)      298 тактов

Честно, ожидалось более ощутимой разницы...

Дальше проверять не стал, т.к. Справка гласит:

Функция RND() возвращает целое число/слово и нуждается во внутреннем хранилище объемом 2 байта.

Чуток апну... ;)
Попробовал с использованием CONFIG RND = 32...
Приращение есть, но оно незначительное - 5 тактов. Что для DWORD, что для LONG.

Отредактировано Nord (2022-01-04 00:19:42)

+3

41

Добрался до тригонометрии... ;)

Во всех случаях:
Dim A As Single
Dim B As Single

B = 45

A = COS(B)              1509 тактов
A = ACOS(B)              222 такта

A = SIN(B)               1806 тактов
A = ASIN(B)               133 такта

A = TAN(B)               2753 такта
A = ATN(B)               2714 тактов

B = 45
A = DEG2RAD(B)       231 такт
B = 0.8
A = RAD2DEG(B)       218 тактов

Независимо от значения В (от 0 до 90) скорости не меняются.
:canthearyou: (выделено)
С тригонометрией после обеда надо завязывать... ;)

+3

42

Сравнил упомянутую здесь Операторы работы со строками функцию

sasha_1973 написал(а):

Insertchar  -  крайне полезная функция, чтобы не использовать очень прожорливую Fusing

... с "прожорливой" ;) Скорость работы операторов Bascom
170 тактов против 6ххх - это неоспоримо !

Только есть одно "но"...
Insertchar работает уже с готовой строковой переменной.
Следовательно, в строке до использования этой функции не должно быть разделителей в виде "." или ",".
Иначе можно получить что-то типа "12.3.45"... ;)
А это значит, что для использования Insertchar в преобразовании "число" > "строка" использовать целое число или проверять строку на наличие разделителей.

Думаю, что даже второй ход не наберет в сумме 6ххх тактов... ;)

+1

43

Использование Insertchar подразумевает предварительную подготовку данных, а именно, приведение к целому значению с учётом необходимого количества знаков после запятой.

+1

44

sasha_1973 написал(а):

Использование Insertchar подразумевает предварительную подготовку данных

    A = Getadc(0)
   '3 строчки 7155 тактов
    Result_sin = A * 0.0488
    Data_str = Fusing(result_sin , "&.&")
    Data_str = Format(data_str , "   0")

    A = Getadc(0)
   '9 строчек 3517 тактов
    Result = A * 500
    !lds R16 , {Result + 1}
    !lds R17 , {Result + 2}
    !sts {C} , R16
    !sts {C + 1} , R17
    Shift C , Right , 2
    Data_str = Str(c)
    Data_str = Format(data_str , " 00")
    Insertchar Data_str , 3 , "."

0

45

А можно вообще так, ускорение >27 раз по сравнению с Fusing + Format

259 тактов

$regfile = "m328pdef.dat"
  $crystal = 1000000
  $hwstack = 40
  $swstack = 16
  $framesize = 32

'Одиночные измерения с частотой АЦП = f_МК / Prescaler (8 МГц / 128 = 62 500)
  Config Adc = Single , Prescaler = 128 , Reference = Avcc

  Dim A As Word
  Dim B As Word : B = 500
  Dim Count_sumbol As Byte
  Dim Data_byte(10) As Byte
  Dim Data_str As String * 10 At Data_byte(1) Overlay

Do

    A = Getadc(0)

   'подпрограмма 259 тактов
    Gosub Format_string

    Locate 2 , 1
    Lcd Data_str

Loop
End

'===============================================================================
  Format_string:
'-------------------------------------------------------------------------------
  'Умножение переменных типа Word (0...65535)  33 такта
    !lds  R20 , {A}
    !lds  R21 , {A + 1}
    !lds  R22 , {B}
    !lds  R23 , {B + 1}

    !clr  R2
    !mul  R23 , R21
    !movw R18 , R0
    !mul  R22 , R20
    !movw R16 , R0
    !mul  R23 , R20
    !add  R17 , R0
    !adc  R18 , R1
    !adc  R19 , R2
    !mul  R21 , R22
    !add  R17 , R0
    !adc  R18 , R1
    !adc  R19 , R2

    !lsr R18
    !ror R17
    !lsr R18
    !ror R17

    !mov R16 , R17
    !mov R17 , R18

    !ldi  R19 , 3       ' Необходимое количество разрядов
    !sts {Count_sumbol} , R19

   Next_byte:
    !movw R4  , R16
    !lsr  R17
    !ror  R16
    !movw R0  , R16
    !lsr R1
    !ror  R0
    !add  R16 , R0
    !adc  R17 , R1
    !movw R0  , R16
    !lsr  R17
    !ror  R16
    !lsr  R17
    !ror  R16
    !lsr  R17
    !ror  R16
    !lsr  R17
    !ror  R16
    !add  R16 , R0
    !adc  R17 , R1
    !movw R0  , R16
    !clr  R0
    !add  R16 , R1
    !movw R0  , R16
    !clr  R0
    !movw R0  , R16
    !lsr  R1
    !ror  R0
    !lsr  R1
    !ror  R0
    !andi R16 , 248
    !add  R16 , R0
    !adc  R17 , R1
    !cbr  R16 , 1
    !Sub  R4  , R16
    !sbc  R5  , R17
    !lsr  R1
    !ror  R0
    !ldi  R16 , 9
    !cp   R16 , R4
    !brsh Exit_div
    !ldi  R16 , 10
    !sub  R4  , R16
    !ldi  R16 , 1
    !add  R0  , R16
    !ldi  R16 , 0
    !adc  R1  , R16
   Exit_div:
   'Можно забрать промежуточный результат делимого
    !mov  R16 , R0
    !mov  R17 , R1

'    Loadadr Переменная_byte(count_sumbol) , Z       ' Если надо, забираем текущий разряд
'    !st   Z   , R4       ' Если надо, забираем значение текущего разряда

' Если надо, забираем значение кода 7-SEG LED выводимой цифры, текущего разряда
    !ldi  R30 , low(Sumbol_ascii * 2)
    !ldi  R31 , high(Sumbol_ascii * 2)
    !add  R30 , R4
    !clr  R3
    !ADC  R31 , R3
    !lpm  R18 , Z
    Loadadr Data_byte(count_sumbol) , Z
    !st   Z   , R18

    !dec  R19
    !sts {Count_sumbol} , R19
    !BREQ ready_format_string
    !rjmp next_byte
   Ready_format_string:

    If Data_byte(1) = &H30 Then
        Data_byte(1) = &H20
    End If

    Data_byte(4) = Data_byte(3)
    Data_byte(3) = &H2E
'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
  Sumbol_ascii:
'-------------------------------------------------------------------------------
    Data &H30       ' 0   "0"
    Data &H31       ' 1   "1"
    Data &H32       ' 2   "2"
    Data &H33       ' 3   "3"
    Data &H34       ' 4   "4"
    Data &H35       ' 5   "5"
    Data &H36       ' 6   "6"
    Data &H37       ' 7   "7"
    Data &H38       ' 8   "8"
    Data &H39       ' 9   "9"
    Data &H20       ' 10  "Пустое место"
'===============================================================================



+3

46

Изменение порядка положения байтов для 4-байтовой переменной.

Начальные установки

Dim A As Dword

Dim ar(6) As Byte
Dim arr2 As Byte At A + 3 Overlay
Dim arr3 As Byte At A + 2 Overlay
Dim arr4 As Byte At A + 1 Overlay
Dim arr5 As Byte At A + 0 Overlay

A = &H01020304

17 тактов

ar(2) = arr2
ar(3) = arr3
ar(4) = arr4
ar(5) = arr5

19 тактов

SWAP A

+1

47

Nord написал(а):

ar(2) = arr2
ar(3) = arr3
ar(4) = arr4
ar(5) = arr5

!lds R16 , ar(x)  'прочитать данные из переменной, 2 такта
!sts ar(x) , R16    'записать данные в переменную, 2 такта

+2

48

спасибо

0

49

В одном из "Исследований" Александра Исследование Ds18b20 (датчик температуры) ("Короткий вариант работы с одним Ds18b20") обратил  внимание на способ получения конечного значения температуры:

Dim Температура As Single
.....
Температура = Temp_ds18b20       ' Забираем сырое значение температуры
Shift Температура , Right , 4          ' Получаем готовую температуру с знаком

Не знаю, кто как, а лично я применял уже известный способ:

Температура = Температура \ 16

Решил "померять", вот что получилось... ;)
Shift Температура , Right , 4              - 74 такта
Температура = Температура \ 16       - 584 такта   !!!

+1

50

Продолжил сравнение...
Здесь часть вопроса уже рассматривалась.

Вот что получилось:
А = A \ n
‘ ----------------------------------
Для  А = BYTE          ‘ Время выполнения – 112 тактов
Для  А = INTEGER    ‘ Время выполнения – 290 тактов
Для  А = SINGLE      ‘ Время выполнения – 584 такта

Время выполнения при n = 2 (8, 16) было практически одинаковым, разница в 2...4 такта

Shift A , Right , n
‘ ----------------------------------
Для  А = BYTE          ‘ Время выполнения – при n = 1 - 20 тактов
                                                                 при n = 2 - 24 такта
                                                                 при n = 4 - 32 такта
Для  А = INTEGER    ‘ Время выполнения – при n = 1 - 25 тактов
                                                                 при n = 2 - 30 тактов
                                                                 при n = 4 - 40 тактов
Для  А = SINGLE      ‘ Время выполнения – при всех n =... - 74 такта

Значение A во всех случаях было равно 128.

Хочется еще добавить такой подмеченный факт - разные размеры конечного файла после компиляции.

При использованном профиле ATMega48

$Regfile="m48pdef.dat"
$Crystal=1000000
$hwstack=16
$swstack=16
$framesize=16
$baud = 9600

'Dim B As Byte
'Dim B As Integer
Dim B As Single

B = 128

Do

'B = B \ 16
Shift B , Right , 4

Print B

Loop
End

А = A \ n
‘ ----------------------------------
Для  А = BYTE          - 11%
Для  А = INTEGER    - 14%
Для  А = SINGLE      - 26%

Shift A , Right , n
‘ ----------------------------------
Для  А = BYTE          - 10%
Для  А = INTEGER    - 11%
Для  А = SINGLE      - 19%

Получается, что Shift.... не только "быстрее", но и "компактнее"... ;)

+1

51

Деление на 16, если >0 то 28 тактов:

      !ldi R16 , 4
      !lds R17 , {Val_word}
      !lds R18 , {Val_word + 1}

     Еще_сдвиг:
      !lsr R18
      !ror R17
      !dec R16
     !brne Еще_сдвиг

      !sts {Val_word} , R17
      !sts {Val_word + 1} , R18

+2

52

Работа с EEPROM.

Запись и чтение одиночного байта:
Writeeeprom C, 0                      ' 41 такт
Readeeprom C, 0                      ' 32 такта

При использовании Ассемблера соответственно - 14 и 12 тактов (подсчитано вручную по примерам в даташите).
Предварительная работа с регистрами, связанными с EEPROM, не учитывалась.

Запись и чтение нескольких байтов:
For C = 0 To 7
Writeeeprom A, C
Next C

Время выполнения полного цикла - 476 тактов (0,476 ms)

For C = 0 To 7
Readeeprom A, C
Next C

Время выполнения полного цикла - 404 такта (0.404 ms)

В даташите на ATMega48 (используемый МК при симуляции) указано время доступа к EEPROM - 3,3 ms.
Возможно, речь идет о доступе ко всей EEPROM (256 байт), а не к отдельным адресам, что косвенно подтверждается "арифметикой" - 3300 тактов / 256 байт = 12 тактов (см. выше)...

+1

Похожие темы


Вы здесь » Программирование ATMEL в BASCOM. » FAQ по Bascom AVR и МК » Скорость работы операторов Bascom