Если нужно максимально быстро, можно использовать вставки на ASM AVR (ассемблер)
Вставки на ASM AVR (ассемблер)
Сообщений 1 страница 30 из 39
Поделиться22014-10-24 13:24:54
Поставить флажок в прерывании:
силами Bascom
on int0 обработка_прерывания_int0
dim флаг as byte
.....
....
обработка_прерывания_int0:
флаг=1
return
Итого, уложимся в:
заход в прерывание = 8 тактов
сохранение всех регистров = 32 (регистра) * 2 такта + SREG(3 такта) = 67 тактов
поднятие флага = 3 такта
восстановление всех регистров = 32 (регистра) * 2 такта + SREG(3 такта) = 67 тактов
выход из прерывания = 4 такта
8 + 67 + 3 + 67 + 4 = 149 тактов, из которых полезных всего 3 такта процессора
силами ASM AVR
on int0 обработка_прерывания_int0 nosave
dim флаг as byte
.....
....
обработка_прерывания_int0:
$asm
push R16
ldi R16 , 1
sts {флаг} , R16
pop R16
reti
$end asm
return
Итого, уложимся в:
заход в прерывание = 8 тактов
сохранение всех регистров = 1 (регистр) * 2 такта = 2 такта
поднятие флага = 3 такта
восстановление всех регистров = 1 (регистр) * 2 такта = 2 такта
выход из прерывания = 4 такта
8 + 2 + 3 + 2 + 4 = 19 тактов
Поделиться32014-10-24 13:25:19
' Аналог команды "Incr Переменная_byte"
lds R16 , {Переменная_byte}
inc R16
sts {Переменная_byte} , R16
' Аналог команды "Decr Переменная_byte"
lds R16 , {Переменная_byte}
dec R16
sts {Переменная_byte} , R16
' Аналог команды "Decr Переменная_word"
Loadadr Переменная_word , X ' Загрузка адреса переменной в регистровую пару R26:R27, 2 такта
ld R30 , X+ ' Косвенная загрузка с пост-инкрементом, 2 такта
ld R31 , X ' Косвенная загрузка, 2 такта
subi R30 , &H01 ' Вычитание константы, 1 такт
sbci R31 , &H00 ' Вычитание константы с переносом, 1 такт
st X , R31 ' Косвенное сохранение, 2 такта
St -x , R30 ' Косвенное сохранение с пре-декрементом, 2 такта
' Аналог команды "Incr Переменная_word"
Loadadr Переменная_word , X ' Загрузка адреса переменной в регистровую пару R26:R27, 2 такта
ld R30 , X+ ' Косвенная загрузка с пост-инкрементом, 2 такта
ld R31 , X ' Косвенная загрузка, 2 такта
subi R30 , &HFF ' Вычитание константы, 1 такт
sbci R31 , &HFF ' Вычитание константы с переносом, 1 такт
st X , R31 ' Косвенное сохранение, 2 такта
St -x , R30 ' Косвенное сохранение с пре-декрементом, 2 такта
'Аналог команды "Переменная_word + 1"
'Узнаём адрес переменной
Loadadr Переменная_word , X
' Грузим из переменной в регистры
ld R16 , X+ ' Косвенная загрузка с пост-инкрементом, 2 такта
ld R17 , X ' Косвенная загрузка, 2 такта
'Загружаем нужное число (BIN; DEC; HEX)
ldi R20 , &H01 ' число 1 Загрузить константу, 1 такт
ldi R21 , &H00 ' число 0 Загрузить константу, 1 такт
'Плюсуем к тому, что было в переменной
add R16 , R20 ' Суммирование без переноса, 1 такт
adc R17 , R21 ' Суммирование с переносом, 1 такт
'Узнаём адрес переменной
Loadadr Переменная_word , X
'Грузим обратно в переменную
St X+ , R16 ' Косвенное сохранение, 2 такта
st X , R17 ' Косвенное сохранение с пре-декрементом, 2 такта
$asm
'Аналог команды "Переменная_word - 1"
'Узнаём адрес переменной
Loadadr Переменная_word , X
' Грузим из переменной в регистры
ld R16 , X+ ' Косвенная загрузка с пост-инкрементом, 2 такта
ld R17 , X ' Косвенная загрузка, 2 такта
'Загружаем нужное число (BIN; DEC; HEX)
ldi R20 , &H01 ' число 1 Загрузить константу, 1 такт
ldi R21 , &H00 ' число 0 Загрузить константу, 1 такт
'Плюсуем к тому, что было в переменной
Sub R16 , R20 ' Вычитание без переноса, 1 такт
sbc R17 , R21 ' Вычитание с переносом, 1 такт
'Узнаём адрес переменной
Loadadr Переменная_word , X
'Грузим обратно в переменную
St X+ , R16 ' Косвенное сохранение, 2 такта
st X , R17 ' Косвенное сохранение с пре-декрементом, 2 такта
$end Asm
Может кому пригодится!
Incr переменная типа "Long" (только положительные значения) или "Dword" в прерывании.
Используется один регистр!
'===============================================================================
Обработка_прерывания_timer0:
'-------------------------------------------------------------------------------
' Incr Переменная_long_0
!push R16 ' Время выполнения инструкции 2 такта
!in R16 , sreg ' Время выполнения инструкции 1 такт
!push R16 ' Время выполнения инструкции 2 такта
!lds R16 , {Переменная_long_0} ' Время выполнения инструкции 2 такта
!SUBI R16 , (-1) ' Время выполнения инструкции 1 такт
!sts {Переменная_long_0} , R16 ' Время выполнения инструкции 2 такта
!lds R16 , {Переменная_long_0 + 1} ' Время выполнения инструкции 2 такта
!SBcI R16 , (-1) ' Время выполнения инструкции 1 такт
!sts {Переменная_long_0 + 1} , R16 ' Время выполнения инструкции 2 такта
!lds R16 , {Переменная_long_0 + 2} ' Время выполнения инструкции 2 такта
!SBcI R16 , (-1) ' Время выполнения инструкции 1 такт
!sts {Переменная_long_0 + 2} , R16 ' Время выполнения инструкции 2 такта
!lds R16 , {Переменная_long_0 + 3} ' Время выполнения инструкции 2 такта
!SBcI R16 , (-1) ' Время выполнения инструкции 1 такт
!sts {Переменная_long_0 + 3} , R16 ' Время выполнения инструкции 2 такта
!pop R16 ' Время выполнения инструкции 2 такта
!out sreg , R16 ' Время выполнения инструкции 1 такт
!pop R16 ' Время выполнения инструкции 2 такта
'-------------------------------------------------------------------------------
Return
'===============================================================================
Поделиться42014-10-24 13:25:34
' Если проворачивать битики один раз, аналог (Rotate переменная типа "Word" , Right , 1)
Rotate_right_word:
lds R18 , {Переменная_word} ' Забираем переменную в регистры
lds R19 , {Переменная_word + 1} ' Забираем переменную в регистры
lsr R19 ' Логический сдвиг вправо
Ror R18 ' Циклический сдвиг вправо через C
brcc Rotate_right_word_1 ' Перейти если перенос очищен
ori R19 , &B_1000_0000 ' Логическое ИЛИ с константой
Rotate_right_word_1:
' Сохраняем результат вращения битов в переменную
sts {Переменная_word} , R18 ' Сохраняем регистры в переменную
sts {Переменная_word + 1} , R19 ' Сохраняем регистры в переменную
ret
' Крутим биты в переменной типа "Word" направо, аналог команды на Bascom - ( Rotate переменная типа "Word" , Right , число проворотов )
Rotate_right_word:
ldi R21 , 1 ' На сколько бит смещаем переменную типа "Word" (число проворотов)
lds R18 , {Переменная_word} ' Забираем переменную в регистры
lds R19 , {Переменная_wordd + 1} ' Забираем переменную в регистры
cpi R21 , 0 ' Если 0, выходим
breq Выход_rotate_Right_word ' Перейти если равно
Rotate_right_word_1:
lsr R19 ' Логический сдвиг вправо
Ror R18 ' Циклический сдвиг вправо через C
brcc Rotate_right_word_2 ' Перейти если перенос очищен
ori R19 , &B_1000_0000 ' Логическое ИЛИ с константой
Rotate_right_word_2:
dec R21 ' Декрементировать значение регистра
brne Rotate_right_word_1 ' Если не 0, крутим битики ещё
' Сохраняем результат вращения битов в переменную
sts {Переменная_word} , R18 ' Сохраняем регистры в переменную
sts {Переменная_word + 1} , R19 ' Сохраняем регистры в переменную
Выход_rotate_right_word:
ret
' Если проворачивать битики один раз, аналог (Rotate переменная типа "Word" , Left , 1)
Rotate_left_word:
clr R20 ' Получаем нолик
lds R18 , {Переменная_word} ' Забираем переменную в регистры
lds R19 , {Переменная_word + 1} ' Забираем переменную в регистры
lsl R18 ' Логический сдвиг влево
Rol R19 ' Циклический сдвиг влево через C
adc R18 , R20 ' Суммирование с переносом
'Сохраняем результат вращения битов в переменную
sts {Переменная_word} , R18 ' Сохраняем регистры в переменную
sts {Переменная_word + 1} , R19 ' Сохраняем регистры в переменную
ret
' Крутим биты в переменной типа "Word" влево, аналог команды на Bascom - ( Rotate переменная типа "Word" , Left , число проворотов )
Rotate_left_word:
clr R20
ldi R21 , 1 ' На сколько бит смещаем переменную типа "Word"
lds R18 , {Переменная_word} ' Забираем переменную в регистры
lds R19 , {Переменная_word + 1} ' Забираем переменную в регистры
Rotate_left_word_1:
cpi R21 , 0 ' Если 0, выходим
breq Выход_rotate_left_word
lsl R18 ' Логический сдвиг влево
Rol R19 ' Циклический сдвиг влево через C
adc R18 , R20 ' Суммирование с переносом
dec R21 ' Декрементировать значение регистра
brne Rotate_left_word_1 ' Если не 0, крутим битики ещё
'Сохраняем результат вращения битов в переменную
sts {Переменная_word} , R18 ' Сохраняем регистры в переменную
sts {Переменная_word + 1} , R19 ' Сохраняем регистры в переменную
Выход_rotate_left_word:
ret
Поделиться52014-10-24 13:25:47
' Аналог команды: переменная_long = переменная_long + переменная_word
!lds R26 , {переменная_long} ' Время выполнения инструкции 2 такта
!lds R27 , {переменная_word} ' Время выполнения инструкции 2 такта
!add R26 , R27 ' Время выполнения инструкции 1 такт
!sts {переменная_long} , R26 ' Время выполнения инструкции 2 такта
!lds R26 , {переменная_long + 1} ' Время выполнения инструкции 2 такта
!lds R27 , {переменная_word + 1} ' Время выполнения инструкции 2 такта
!adc R26 , R27 ' Время выполнения инструкции 1 такт
!sts {переменная_long + 1} , R26 ' Время выполнения инструкции 2 такта
!lds R26 , {переменная_long + 2} ' Время выполнения инструкции 2 такта
!clr R27 ' Время выполнения инструкции 1 такт
!adc R26 , R27 ' Время выполнения инструкции 1 такт
!sts {переменная_long + 2} , R26 ' Время выполнения инструкции 2 такта
!lds R26 , {переменная_long + 3} ' Время выполнения инструкции 2 такта
!clr R27 ' Время выполнения инструкции 1 такт
!adc R26 , R27 ' Время выполнения инструкции 1 такт
!sts {переменная_long + 3} , R26 ' Время выполнения инструкции 2 такта
Поделиться62014-10-24 20:26:37
Исполнение на Bascom
' Время выполнения команд 39 тактов, если меньше или равно, иначе 43 такта
Переменная_word_3 = Переменная_word_1 + Переменная_word_2
If Переменная_word_3 > 1024 Then
Переменная_word_3 = 1024
End If
Исполнение на ASM AVR
' Время выполнения команд 19 тактов, если меньше или равно, иначе 21 такт
lds R16 , {Переменная_word_1} ' 2 такта
lds R17 , {Переменная_word_2} ' 2 такта
add R16 , R17 ' 1 такт
lds R17 , {Переменная_word_1 + 1} ' 2 такта
lds R18 , {Переменная_word_2 + 1} ' 2 такта
adc R17 , R18 ' 1 такт
cpi R16 , &H00 'Значение (пример &H00) ' 1 такт Младший разряд сравниваемого значения, больше которого оно-же и остаётся
ldi R18 , &H04 'Значение (пример &H04 (1024)) ' 1 такт Старший разряд сравниваемого значения, больше которого оно-же и остаётся
cpc R17 , R18 ' 1 такт
brcs Запись_в_переменную_word_3 ' 2 такта если переход, иначе 1 такт
breq Запись_в_переменную_word_3 ' 2 такта если переход, иначе 1 такт
ldi R16 , &H00 ' Значение (пример &H00) ' Младший разряд сравниваемого значения, больше которого оно-же и остаётся
ldi R17 , &H04 ' Значение (пример &H04 (1024)) ' Старший разряд сравниваемого значения, больше которого оно-же и остаётся
Запись_в_переменную_word_3:
STS {Переменная_word_3} , R16 ' 2 такта
sts {Переменная_word_3 + 1} , R17 ' 2 такта
Поделиться72014-11-14 16:15:45
Переход из прерывания на метки, без последствий для стека.
В архиве 2 симуляции, с "Terminal" и "COMPIM" (связь через виртуальный ComPort с железом).
У кого не настроены виртуальные порты - отключите "COMPIM" и подключите "Terminal". ! ВНИМАНИЕ ! Вместе работать не будут !
Симуляция Протеус 7.10 + мсходник Bascom 2.0.7.1 + программа терминал + бонус для работы "COMPIM" (пароль в личку) -- скачать
Поделиться82014-11-19 10:55:33
Раскидываем значение переменной типа "Long" или "Dword" по разрядам 7-seg Led индикаторов
Вариант на ASM AVR - 738 тактов процессора на 6 разрядов Led индикации
Вариант силами Bascom - 9755 тактов процессора на 6 разрядов Led индикации
Разница скорости ~ 13 раз !
Обсуждение темы --- здесь
Симуляция Протеус 7.10 + исходники Bascom 2.0.7.1 (варианты на ASM AVR и силами Bascom) -- скачать
Поделиться92014-11-28 15:41:49
Раскидываем значение переменной типа "Word" по разрядам 7-seg Led индикаторов
Вариант на ASM AVR - 409 тактов процессора на 5 разрядов Led индикации
Симуляция Протеус 7.10 + исходники Bascom 2.0.7.1 (варианты на ASM AVR и силами Bascom) -- скачать
Поделиться102014-11-28 16:51:02
Раскидываем значение переменной типа "Byte" по разрядам 7-seg Led индикаторов
Вариант на ASM AVR - 210 тактов процессора на 3 разряда Led индикации
Симуляция Протеус 7.10 + исходники Bascom 2.0.7.1 (варианты на ASM AVR и силами Bascom) -- скачать
Поделиться112014-11-28 17:45:17
Раскидываем значения двух переменных типа "Word" по разрядам 7-seg Led индикаторов
Вариант на ASM AVR - 978 тактов процессора на 8 разрядов Led индикации
Симуляция Протеус 7.10 + исходники Bascom 2.0.7.1 (варианты на ASM AVR и силами Bascom) -- скачать
Поделиться122014-11-29 09:31:14
----------------------------------------------------
Работа с 7-seg Led индикаторами на ASM AVR
8 разрядов
Выводы МК, которые обслуживают индикаторы, можно переназначить в исходнике
Симуляция Протеус 7.10 + исходники Bascom 2.0.7.1 (варианты на ASM AVR и силами Bascom) -- скачать
Поделиться132014-12-26 16:35:18
Выборка из 128 измерений АЦП, запущенного в режиме "Free", с последующим делением на 128 (так называемое усреднение), написано на ASM AVR
$map ' Получаем карту распределения памяти в отчёте компиляции
$regfile = "m328pdef.dat" ' Используемый контроллер
$crystal = 8000000 ' Частота работы контроллера
$framesize = 32 ' Размер области используемой для преобразований
$hwstack = 40 ' Размер аппаратного стека
$swstack = 16 ' Размер программного стека'------------- Настройка USART -----------------------------------------------
$baud = 38400
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0'------------- Настройка АЦП -------------------------------------------------
Config Adc = Free , Prescaler = 128 , Reference = Avcc ' Источник опорного напряжения Reference может быть: Aref – внешний источник, Avcc – напряжение питания схемы и Internal – внутренний
On Adc Обработка_прерывания_ацп_asm NosaveAdmux.mux0 = 1 ' Используем ADC3
Admux.mux1 = 1 ' Используем ADC3
Admux.adlar = 1 ' Берём 8 бит из 10, считываем только ADCHDim Фоторезистор As Byte
Dim Флаг_данные_ацп As Byte
Dim Temp_фоторезистор As Byte
Dim Сумма_измерений_ацп_word As Word
Dim Счетчик_измерений_ацп As Byte'\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
'-------------- Разрешаем работу необходимых прерываний ----------------------
Enable Adc : Start Adc'------------ Разрешаем работу всех включенных прерываний --------------------
Enable Interrupts'-------------------------------------------------------------------------------
'Ждём первой выборки замеров АЦП
Ждем_первый_замер_ацп:
Idle
If Флаг_данные_ацп = 0 Then
Goto Ждем_первый_замер_ацп
End If
Флаг_данные_ацп = 0'===============================================================================
' Г Л А В Н Ы Й Ц И К Л
Главный_цикл:
'===============================================================================If Флаг_данные_ацп <> 0 Then
Print Фоторезистор
Флаг_данные_ацп = 0
Goto Главный_цикл
End IfIdle ' Отправляем МК на тихий час
'===============================================================================
Goto Главный_цикл
End
'===============================================================================
' П О Д К Л Ю Ч Е Н И Е Р А Б О Ч И Х М О Д У Л Е Й
'==============================================================================='===============================================================================
Обработка_прерывания_ацп_asm:
'-------------------------------------------------------------------------------
'Сохраняем регистры, которые будем использовать и SREG
!push R16
!in R16 , sreg
!push R16
!push R30
!push R31'Забираем 8 бит АЦП
!in R16 , adch'Суммируем 128 измерений, для последующего усреднения
!lds R30 ,{Сумма_измерений_ацп_word}
!lds R31 ,{Сумма_измерений_ацп_word + 1}
!add R30 , R16
!ldi R16 , 0
!adc R31 , R16
!sts {Сумма_измерений_ацп_word} , R30
!sts {Сумма_измерений_ацп_word + 1} , R31
!lds R16 , {Счетчик_измерений_ацп}
!inc R16 ' Считаем выборку из 128 измерений
!cpi R16 , 128
!BRNE Выход_прерывания_ацп'Деление на 128 (сдвиг вправо на 7)
!ldi R16 , 7
Сдвиг_вправо:
!lsr R31
!ror R30
!dec R16
!brne Сдвиг_вправо
'Забираем готовые усреднённые по 128 выборкам, 8 бит данные
!sts {Фоторезистор} , R30'Поднимаем флаг сигнализирующий о готовности результата измерения АЦП
!ldi R16 , 1
!sts {Флаг_данные_ацп} , R16'Готовимся к следующей выборке измерений
!ldi R16 , 0
!sts {Сумма_измерений_ацп_word} , R16
!sts {Сумма_измерений_ацп_word + 1} , R16Выход_прерывания_ацп:
!sts {Счетчик_измерений_ацп} , R16'Восстанавливаем регистры и SREG
!pop R31
!pop R30
!pop R16
!out sreg , R16
!pop R16
'-------------------------------------------------------------------------------
Return
'===============================================================================
Поделиться142015-08-27 06:10:14
Dim D(12) As Integer
Dim W(12) As Integer
'Время выполнения фрагмента 565 тактов МК
For I = 1 To 12
D(i) = W(i)
Next I
!clr R18 , 0
!clr R19 , 0Next_i:
Loadadr W(1) , X
!add R26 , R18
!adc R27 , R19
!ld R17 , X+
!ld R16 , XLoadadr D(1) , X
!add R26 , R18
!adc R27 , R19
!st X+ , R17
!st X , R16!subi R18 , -2
!cpi R18 , 24
!BRSH Exit_next_i
!rjmp Next_iExit_next_i:
Но так быстрее
'Время выполнения фрагмента 554 тактов МК
For I = 12 To 1 step -1
D(i) = W(i)
Next I
'Время выполнения фрагмента 230 тактов МК
!ldi R18 , 24 ' Т.к., используются двухбайтовые переменные, смещение считается по 2 байта
!ldi r19 , 0Next_i:
Loadadr W(1) , X ' Получаем адрес первой переменной в массиве
!add R26 , R18 ' Высчитываем смещение в массиве
!adc R27 , R19 ' Высчитываем смещение в массиве
!ld R16 , -X ' Забираем данные из массива
!ld R17 , -X ' Забираем данные из массиваLoadadr D(1) , X ' Получаем адрес первой переменной в массиве
!add R26 , R18 ' Высчитываем смещение в массиве
!adc R27 , R19 ' Высчитываем смещение в массиве
!st -X , R16 ' Сохраняем данные в массив
!st -X , R17 ' Сохраняем данные в массив!subi R18 , 2 ' Считаем смещение адреса переменных массива. Одна переменная = 2 байта
!brne Next_i ' Если не "0", повторяемExit_next_i:
!push R16
!in R16 , sreg
!push R16
!push R17
!push R18
!push R19
!push R26
!push R27'Время выполнения фрагмента 230 тактов МК
!ldi R18 , 24 ' Т.к., используются двухбайтовые переменные, смещение считается по 2 байта
!ldi r19 , 0Next_i:
Loadadr W(1) , X ' Получаем адрес первой переменной в массиве
!add R26 , R18 ' Высчитываем смещение в массиве
!adc R27 , R19 ' Высчитываем смещение в массиве
!ld R16 , -X ' Забираем данные из массива
!ld R17 , -X ' Забираем данные из массиваLoadadr D(1) , X ' Получаем адрес первой переменной в массиве
!add R26 , R18 ' Высчитываем смещение в массиве
!adc R27 , R19 ' Высчитываем смещение в массиве
!st -X , R16 ' Сохраняем данные в массив
!st -X , R17 ' Сохраняем данные в массив!subi R18 , 2 ' Считаем смещение адреса переменных массива. Одна переменная = 2 байта
!brne Next_i ' Если не "0", повторяемExit_next_i:
!pop R27
!pop R26
!pop R19
!pop R18
!pop R17
!pop R16
!out sreg , R16
!pop R16
Если фрагмент используется в теле программы, сохраняться нет необходимости.
Поделиться152015-09-03 04:40:35
'Считаем 4096, 2 байтовых счётчика, так быстрее
Считаем_256:
!lds R26 , {Счетчик_256}
!inc R26
!sts {Счетчик_256} , R26
'Если = 256
!cpi R26 , 0
!BREQ Считаем_4096
!rjmp Выход_прерыванияСчитаем_4096:
!lds R26 , {Счетчик_4096}
!inc R26
!sts {Счетчик_4096} , R26
'Если =16, почему 16 (16 * 256 = 4096)
!cpi R26 , 16
!BREQ Реакция_на_совпадение_счетчика
!rjmp Выход_прерыванияРеакция_на_совпадение_счетчика:
'......
'......
'......Выход_прерывания:
'......
'......
'......'Считаем 65536, 2 байтовых счётчика, так быстрее
Считаем_256:
!lds R26 , {Счетчик_256}
!inc R26
!sts {Счетчик_256} , R26
'Если =256
!cpi R26 , 0
!BREQ Считаем_65536
!rjmp Выход_прерыванияСчитаем_65536:
!lds R26 , {Счетчик_65536}
!inc R26
!sts {Счетчик_65536} , R26
'Если = 256, почему 256 (256 * 256 = 65536)
!cpi R26 , 0
!BREQ Реакция_на_совпадение_счетчика
!rjmp Выход_прерыванияРеакция_на_совпадение_счетчика:
'......
'......
'......Выход_прерывания:
'......
'......
'......
Поделиться162015-09-03 05:17:32
'Incr Переменная_word
!lds R26 , {Переменная_word}
!lds R27 , {Переменная_word + 1}
!ADIW R26 , 1 ' плюс (вместо 1) нужное значение
!sts {Переменная_word} , R26
!sts {Переменная_word + 1} , R27
'Decr Переменная_word
!lds R26 , {Переменная_word}
!lds R27 , {Переменная_word + 1}
!sbIW R26 , 1 ' минус (вместо 1) нужное значение
!sts {Переменная_word} , R26
!sts {Переменная_word + 1} , R27
Поделиться172015-09-03 05:36:40
Select Case Переменная_byte
Case 0:
Case 1:
Case 2:
Case 3:
Case 4:
Case 5:
End SelectАналог на Bascom:
On Переменная_byte Goto Обработка_0 , Обработка_1 , Обработка_2 , Обработка_3 , Обработка_4 , Обработка_5
Обработка_0:
'.....
'.....
Goto ВыходОбработка_1:
'.....
'.....
Goto ВыходОбработка_2:
'.....
'.....
Goto ВыходОбработка_3:
'.....
'.....
Goto ВыходОбработка_4:
'.....
'.....
Goto ВыходВыход:
Аналог на ASM:
!lds R16 , {Переменная_byte}
!cpi R16 , 0
!BREQ Обработка_0 ' Перейти если равно!cpi R16 , 1
!BREQ Обработка_1 ' Перейти если равно!cpi R16 , 2
!BREQ Обработка_2 ' Перейти если равно!cpi R16 , 3
!BREQ Обработка_3 ' Перейти если равно!cpi R16 , 4
!BREQ Обработка_4 ' Перейти если равно!cpi R16 , 5
!BREQ Обработка_5 ' Перейти если равноОбработка_0:
'.....
'.....
!rjmp ВыходОбработка_1:
'.....
'.....
!rjmp ВыходОбработка_2:
'.....
'.....
!rjmp ВыходОбработка_3:
'.....
'.....
!rjmp ВыходОбработка_4:
'.....
'.....
!rjmp ВыходВыход:
Поделиться182016-10-17 04:47:05
$map
$loadersize = 1024$regfile = "m328pdef.dat"
$crystal = 8000000
$framesize = 64
$hwstack = 64
$swstack = 64'===============================================================================
'Настройка USART
'===============================================================================
$baud = 38400 '38400
Config Com1 = Baud , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
' Ucsr0a.1 = 1 ' Двойная скорость работы USART, скорость трансляции = $baud * 2'===============================================================================
'Настройка TIMER0 для отсчёта временных интервалов
'===============================================================================
Config Timer0 = Counter , Prescale = 64 , Compare A = Disconnect , Clear Timer = 1On Compare0a Обработка_прерывания_compare0a Nosave
Stop Timer0
Timer0 = 0
Compare0a = 124 '1 ms
Dim Счетчик_ms As Word
'-------------- Разрешаем работу необходимых прерываний ----------------------
Enable Compare0a
Start Timer0
'------------ Разрешаем работу всех включенных прерываний --------------------
Enable Interrupts
'===============================================================================' Г Л А В Н Ы Й Ц И К Л
Главный_цикл:
'===============================================================================nop
Power Idle ' Отправляем МК на тихий час
'===============================================================================
Goto Главный_цикл
End
'===============================================================================
' П О Д К Л Ю Ч Е Н И Е Р А Б О Ч И Х М О Д У Л Е Й
'==============================================================================='===============================================================================
Обработка_прерывания_compare0a:
'-------------------------------------------------------------------------------
!push R16
!in R16 , sreg
!push R16!lds R16 , {Счетчик_ms}
!SUBI R16 , -1
!sts {Счетчик_ms} , R16
!lds R16 , {Счетчик_ms + 1}
!SBCI R16 , -1
!sts {Счетчик_ms + 1} , R16!pop R16
!out sreg , R16
!pop R16!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Поделиться192017-09-22 06:21:03
Продолжение этого
Всё конечно работает и даже устраивает, но, чем больше ветка переходов, тем дольше обработка.
Пришлось искать решение проблемки. Результат = 11 тактов МК независимо от количества меток
$map ' Получаем карту распределения памяти компилятором Bascom
$regfile = "m328pdef.dat"
$crystal = 1000000
$framesize = 128 ' Размер области используемой и необходимой для преобразований
$hwstack = 128 ' Размер аппаратного стека
$swstack = 128 ' Размер программного стекаDim Переход As Byte
Do
Incr Переход
If Переход > 7 Then Переход = 0
'11 тактов МК
!lds R26 , {Переход}
!clr R27
!ldi R30 , low(s_0)
!ldi R31 , high(s_0)
!add R30 , R26
!adc R31 , R27
!ijmp 'Для МК < 128 kb
!eijmp 'Для МК => 128 kbS_0:
!rjmp Save_0
S_1:
!rjmp Save_1
S_2:
!rjmp Save_2
S_3:
!rjmp Save_3
S_4:
!rjmp Save_4
S_5:
!rjmp Save_5
S_6:
!rjmp Save_6
S_7:
!rjmp Save_7Save_0:
'Делаем, что надо
!rjmp Save_endSave_1:
'Делаем, что надо
!rjmp Save_endSave_2:
'Делаем, что надо
rjmp Save_endSave_3:
'Делаем, что надо
rjmp Save_endSave_4:
'Делаем, что надо
rjmp Save_endSave_5:
'Делаем, что надо
!rjmp Save_endSave_6:
'Делаем, что надо
!rjmp Save_endSave_7:
'Делаем, что надо
rjmp Save_endSave_end:
Loop
End
Поделиться202019-03-10 07:28:00
Как быстрее, брать данные из байтового массива в оперативке МК или таблицы во флеше ?
Если силами Bascom, то данные из массива забирать быстрее в ~3 раза
Если силами ASM, то разницы практически нет, 11 тактов из массива, 12 тактов из таблицы.
'=================================
'41 такт МК
'---------------------------------
1_val_byte = Lookup(count , Data_test)
'=================================аналог на ASM
'=================================
'12 тактов МК
'---------------------------------
!lds R16 , {count}
!clr R17
!ldi R30 , Low(Data_test * 2)
!ldi R31 , High(Data_test * 2)!add R30 , R16
!adc R31 , R17!lpm R18 , Z
!sts {1_val_byte} , R18
'=================================
'=================================
'13 тактов МК
'---------------------------------
Val_byte = 2_val_byte(count)
'=================================аналог на ASM
'=================================
'11 тактов МК
'---------------------------------
!lds R16 , {count}
!clr R17
Loadadr 2_val_byte(0) , Z!add R30 , R16
!adc R31 , R17!ld R18 , Z
!sts {Val_byte} , R18
'=================================
Поделиться212021-11-30 03:33:29
Если переменная Word > 0 Decr переменная Word
'===============================================================================
Interrupt_compare0a:
'-------------------------------------------------------------------------------
'Время выполнения 149 тактов (romsize < 128 kb), с заходом и выходом из прерывания
'Время выполнения 160 тактов (romsize = 128 kb), с заходом и выходом из прерывания
'Время выполнения 163 такта (romsize = 256 kb), с заходом и выходом из прерывания
' If Count_ms > 0 Then
' Decr Count_ms
' End If'Время выполнения 46 тактов (romsize < 128 kb), с заходом и выходом из прерывания
'Время выполнения 55 тактов (romsize = 128 kb), с заходом и выходом из прерывания
'Время выполнения 56 такта (romsize = 256 kb), с заходом и выходом из прерывания!Push R16
!In R16 , Sreg
!Push R16#if _romsize > 65535
!in R16 , RAMPZ
!Push R16
!clr R16
!out RAMPZ , R16
#endif!push R30
!push R31!clr R17
!lds R30 , {Count_ms}
!lds R31 , {Count_ms + 1}!cpi R31 , 0
!cpc R30 , R16
!brcs Exit_interrupt_compare0a
!breq Exit_interrupt_compare0a
!rjmp Decr_count_ms
!rjmp Exit_interrupt_compare0aDecr_count_ms:
!SBIW R30 , 1Save_count_ms:
!sts {Count_ms} , R30
!sts {Count_ms + 1} , R31Exit_interrupt_compare0a:
!pop R31
!pop R30#if _romsize > 65535
!pop R16
!out RAMPZ , R16
#endif!pop R16
!Out Sreg , R16
!Pop R16!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Поделиться222022-01-05 05:34:25
Умножение байтовых чисел без знака (0...255)
Dim A As Byte
Dim B As Byte
Dim Result As Word
Result = A * B '40 тактов
11 тактов МК
!lds R16 , {A}
!lds R17 , {B}
!Mul R16 , R17
!movw R16 , R0
!sts {Result} , R16
!sts {Result + 1} , R17
10 тактов МК, запись из переменных в регистровую пару R0:R1 возможна только для оператора MUL
!lds R0 , {A}
!lds R1 , {B}
!Mul R0 , R1
!sts {Result} , R0
!sts {Result + 1} , R1
Поделиться232022-01-05 15:35:57
Dim A As Integer : A = 32767
Dim B As Integer : B = -32767
Dim Results As Long
Results = A * B '91 такт
'Умножение переменных типа Integer (-32767...32767) 35 тактов
!lds R20 , {A}
!lds R21 , {A + 1}
!lds R22 , {B}
!lds R23 , {B + 1}
!clr R2
!muls R23 , R21
!movw R18 , R0
!mul R22 , R20
!movw R16 , R0
!mulsu R23 , R20
!sbc R19 , R2
!add R17 , R0
!adc R18 , R1
!adc R19 , R2
!mulsu R21 , R22
!sbc R19 , R2
!add R17 , R0
!adc R18 , R1
!adc R19 , R2
!sts {Results} , R16
!sts {Results + 1} , R17
!sts {Results + 2} , R18
!sts {Results + 3} , R19
Поделиться242022-01-05 15:36:53
Dim A As Word : A = 65535
Dim B As Word : B = 65535
Dim Results As Dword
Results = A * B '84 такта
'Умножение переменных типа 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
!sts {Results} , R16
!sts {Results + 1} , R17
!sts {Results + 2} , R18
!sts {Results + 3} , R19
Поделиться252022-01-09 23:37:07
'Забираем данные из "Val_word"
!ldS R20 , {Val_word}
!ldS R21 , {Val_word + 1}
'Забираем данные из "Val_byte"
!lds R22 , {Val_byte}
!clr R23
'Умножение переменных Word * Byte, время выполнения 28 тактов МК
!mul R23 , R21
!mov R18 , R0
!mul R22 , R20
!movw R16 , R0
!mul R23 , R20
!add R17 , R0
!adc R18 , R1
!mul R21 , R22
!add R17 , R0
!adc R18 , R1
Dim Itog As Long
Dim Itog As Double
'Забираем в переменную типа "Long" или "Double"
!sts {itog} , R16
!sts {itog + 1} , R17
!sts {itog + 2} , R18
!clr R19
!sts {itog + 3} , R19
Поделиться262022-05-08 07:54:03
'===============================================================================
Interrupt_handling: '34 такта (счёт); 40 тактов (счёт + реакция на сравнение)
'-------------------------------------------------------------------------------
'If Val_word = 0 Then
'Stop Timer1
'Led = On_led
'Else
'Decr Val_word
'End If
!push R16
!in R16 , sreg
!push R16
!push R30
!push R31
!lds R30 , {Val_word}
!lds R31 , {Val_word + 1}
'If Val_word = 0 Then
!clr R16
!cpi R30 , 0
!cpc R31 , R16
!breq Reaction_compare_variables
!rjmp Decrement_variable
Reaction_compare_variables:
'Stop Timer1
!lds R16 , tccr1b
!andi R16 , &B_1111_1000
!sts tccr1b , R16
'Set Led
Led = On_led
!rjmp Exit_isr_compare1a
'Else
Decrement_variable:
'Decr Val_word
!sbiw R30 , 1 ' Вычесть константу из слова
Exit_interrupt_handling:
!sts {Val_word} , R30
!sts {Val_word + 1} , R31
'End If
!pop R31
!pop R30
!pop R16
!out sreg , R16
!pop R16
!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
'===============================================================================
Interrupt_handling: '41 такт (счёт); 49 тактов (счёт + реакция на сравнение)
'-------------------------------------------------------------------------------
'Incr Переменная_word
'If Переменная_word = Count Then
'Stop Timer1
'Переменная_word = 0
'Set Led
'End If
!push R26
!in R26 , sreg
!push R26
!push R27
!push R30
!push R31
'Incr Val_word
!lds R30 , {Val_word}
!lds R31 , {Val_word + 1}
!adiw R30 , 1 'Сложить константу и слово
!lds R26 , {Count_word}
!lds R27 , {Count_word + 1}
'If Val_word = Count Then
!cp R30 , R26
!cpc R31 , R27
!breq Reaction_compare_variables
!rjmp Exit_isr_compare1a
Reaction_compare_variables:
'Stop Timer1
!lds R30 , tccr1b
!andi R30 , &B_1111_1000
!sts tccr1b , R30
'Val_word = 0
!clr R30
!clr R31
'Set Led
Led = On_led
'End If
Exit_interrupt_handling:
!sts {Val_word} , R30
!sts {Val_word + 1} , R31
!pop R31
!pop R30
!pop R27
!pop R26
!out sreg , R26
!pop R26
!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Поделиться272023-12-01 02:08:27
Dim A As Integer : A = -32767
Dim B As Integer : B = 32767
Dim Results As LongDo
Gosub 16_muls_16_32
Loop
End'=====================================
16_muls_16_32: '509 тактов
'-------------------------------------
!lds R16 , {A}
!lds R17 , {A + 1}!bst R17 , 7 'Проверка на "-"
!brtc 16_muls_16_32_1 'BRTC k Перейти если флаг T очищен!ldi R18 , 255 '$ff
!ldi R19 , 255 '$ff
!rjmp 16_muls_16_32_216_muls_16_32_1:
!clr R18
!clr R1916_muls_16_32_2:
!lds R20 , {B}
!lds R21 , {B + 1}!bst R21 , 7 'Проверка на "-"
!brtc 16_muls_16_32_416_muls_16_32_3:
!ldi R22 , 255 '$ff
!ldi R23 , 255 '$ff
!rjmp 16_muls_16_32_516_muls_16_32_4:
!clr R22
!clr R2316_muls_16_32_5:
!rcall 16_muls_16_32_6!sts {Results} , R16
!sts {Results + 1} , R17
!sts {Results + 2} , R18
!sts {Results + 3} , R19!ret
'=====================================
16_muls_16_32_6:
!rcall 16_muls_16_32_12
!rcall 16_muls_16_32_8
!sbrc R0 , 0 '$00
!rcall 16_muls_16_32_7
!ret16_muls_16_32_7:
!rcall 16_muls_16_32_14
!rcall 16_muls_16_32_16
!ret16_muls_16_32_8:
!mov R24 , R20
!mov R25 , R21
!mov R26 , R22
!mov R27 , R23!clr R20
!clr R21
!clr R22
!clr R23!ldi R31 , 33 '$21
!clc
!rjmp 16_muls_16_32_1116_muls_16_32_9:
!brcc 16_muls_16_32_10!add R20 , R24
!adc R21 , R25
!adc R22 , R26
!adc R23 , R2716_muls_16_32_10:
!lsr R23
!ror R22
!ror R21
!ror R20
!ror R19
!ror R18
!ror R17
!ror R16!dec R31
!brne 16_muls_16_32_9!ret
16_muls_16_32_11:
!ror R19
!ror R18
!ror R17
!ror R16!dec R31
!brne 16_muls_16_32_9
!ret16_muls_16_32_12:
!clr R0
!clt
!sbrs R23 , 7 '$07
!rjmp 16_muls_16_32_13
!rcall 16_muls_16_32_14
!set16_muls_16_32_13:
!bld R0 , 0
!rcall 16_muls_16_32_15
!bld R1 , 0
!eor R0 , R1
!ret16_muls_16_32_14:
!rcall 16_muls_16_32_17
!subi R20 , 255 '$ff
!sbci R21 , 255 '$ff
!sbci R22 , 255 '$ff
!sbci R23 , 255 '$ff
!ret16_muls_16_32_15:
!clt
!sbrs R19 , 7 '$07
!ret16_muls_16_32_16:
!com R16
!com R17
!com R18
!com R19
!subi R16 , 255 '$ff
!sbci R17 , 255 '$ff
!sbci R18 , 255 '$ff
!sbci R19 , 255 '$ff
!set
!ret16_muls_16_32_17:
!com R20
!com R21
!com R22
!com R23
!ret
'==========================================================
Поделиться282023-12-01 02:13:47
Dim A As Word : A = 32767
Dim B As Word : B = 65535
Dim Results As DwordDim C As String * 10
Do
'513 тактов
Gosub Word_mul_word!nop
C = Str(results)
Loop
End'=====================================
Word_mul_word: '509 тактов
'-------------------------------------
!lds R16 , {A}
!lds R17 , {A + 1}
!clr R18
!clr R19!lds R20 , {B}
!lds R21 , {B + 1}
!clr R22
!clr R23!rcall Word_mul_word_1
!sts {Results} , R16
!sts {Results + 1} , R17
!sts {Results + 2} , R18
!sts {Results + 3} , R19
'=====================================
!ret
'=====================================
Word_mul_word_1:
!mov R24 , R20
!mov R25 , R21
!mov R26 , R22
!mov R27 , R23
!clr R20
!clr R21
!clr R22
!clr R23
!ldi R31 , 33 '$21
!clc
!rjmp Word_mul_word_4
Word_mul_word_2:
!brcc Word_mul_word_3
!add R20 , R24
!adc R21 , R25
!adc R22 , R26
!adc R23 , R27
Word_mul_word_3:
!lsr R23
!ror R22
!ror R21
!ror R20
!ror R19
!ror R18
!ror R17
!ror R16
!dec R31
!brne Word_mul_word_2
!ret
Word_mul_word_4:
!ror R19
!ror R18
!ror R17
!ror R16
!dec R31
!brne Word_mul_word_2
!ret
'=====================================
Поделиться292024-05-11 04:00:02
Не смог найти на форуме преобразование в ассемблер двойного FOR NEXT.
Есть код, часть которого уже преобразована. Помогите полностью перевести на ассеблер.
Dim Page_counter As Byte
Dim Page_offset As Word
Dim M_red(mem_size) , M_green(mem_size) , M_blue(mem_size) As Byte
Dim Nn1 , Nn2 , Nn3 As Word
Nn1 = 32
Nn2 = 64
Nn3 = 4
Display_refresh:
Load Timer0 , Timer0reload
$asm
lds R31 , {Page_counter} ' Прямая загрузка из переменной в регистр время выполнения 2 такта
cpi R31 , 7 ' Сравнить регистр и константу "Количество_подсчетов" 1 такт
BRCS Cnt_Plus ' Перейти если меньше чем "Количество_подсчетов + 1 " если переход на метку тогда 2 такта иначе 1 такт
SBI PORTd,5 ' Очистить регистр 1 такт
lds R31 , 0
sts {Page_counter} , R31
Cnt_plus:
inc R31 ' Инкрементировать содержимое регистра 1 такт
sts {Page_counter} , R31 ' Прямая загрузка из регистра в переменную 2 такта
!lds R0 , {Page_counter}
!lds R1 , {nn3}
!Mul R0 , R1
!sts {Page_offset} , R0
!sts {Page_offset + 1} , R1
lds R17 , {Page_offset}
lds R18 , {Nn1}
add R17 , R18
STS {L1} , R17
lds R17 , {L1}
lds R18 , {Nn2}
add R17 , R18
STS {L2} , R17
$end Asm
For K = 1 To 2
For B_1 = 1 To 4
R18 = M_red(l1)
R19 = M_green(l1)
R20 = M_blue(l1)
R21 = M_red(l2)
R22 = M_green(l2)
R23 = M_blue(l2)
$asm
LDI r17,8
Loop_shift2:
in R16, dout_port
BST r18,7
BLD r16,Dout_pin_r1
BST r19,7
bld r16,Dout_pin_g1
BST r20,7
bld r16,Dout_pin_b1
BST r21,7
BLD r16,Dout_pin_r2
BST r22,7
bld r16,Dout_pin_g2
BST r23,7
bld r16,Dout_pin_b2
LSl r18
LSl r19
lsl r20
lsl r21
lsl r22
lsl r23
Out Dout_port , R16
SBI shift_clock_Port, shift_clock_Pin
dec r17
CBI shift_clock_Port, shift_clock_Pin
BRnE loop_shift2
lds R16 , {L1}
lds R17 , {L2}
inc R16
inc R17
sts {L1} , R16
sts {L2} , R17
$end Asm
Next B_1
$asm
lds R16 , {Page_offset}
sts {L1} , R16
lds R17 , {L1 }
lds R18 , {Nn2}
add R17 , R18
STS {L2} , R17
$end Asm
Next
Pwm1b = 0
Waitus 20
$asm
sbi PORTb,3 ' установить на выводе "1"
Cbi Portb,3 ' установить на выводе "0"
sbi PORTd,3
Cbi Portd,3
Cbi Portd,5
$end Asm
Pwm1b = Br
Return










