
Справочник по программированию «Bascom-AVR» (М.Л. Кулиш)
.pdf===================================== Справочник по программированию «Bascom-AVR» ==
Search_pin: |
'повторять пока регистр Tmpb не станет равным нулю |
While Tmpb <> 0 |
|
Shift Tmpb , Right : Incr Num_port |
|
Wend |
|
Return |
|
'---------------------------------------------------------------------------------- |
|
Обработчик прерывания, написанный без применения ассемблера, не может иметь оптимального кода. Это показывает дисассемблированный текст (пример 6). Мы видим, что обработчик с одной стороны не выполняет недопустимых действий, а с другой – имеет явную избыточность и расточителен.
Пример 6 - Ассемблерный текст обработчика прерывания (листинг) из программы примера 5, получаемый при компиляции Bascom-AVR
'---------------------------------------------------------------------------------- |
|
|
Pc_int0: |
|
|
;сохранение регистрового блока |
|
|
push |
r0 |
|
push |
r1 |
|
push |
r2 |
|
push |
r3 |
|
push |
r4 |
|
push |
r5 |
|
push |
r7 |
|
push |
r10 |
|
push |
r11 |
|
push |
r16 |
|
push |
r17 |
|
push |
r18 |
|
push |
r19 |
|
push |
r20 |
|
push |
r21 |
|
push |
r22 |
|
push |
r23 |
|
push |
r24 |
|
push |
r25 |
|
push |
r26 |
|
push |
r27 |
|
push |
r28 |
|
push |
r29 |
|
push |
r30 |
|
push |
r31 |
|
in |
r24,$3F |
|
push |
r24 |
|
;Tmpb = Pina Xor Pcamsk |
|
|
in |
r16,$0 |
|
ldi |
r20,#255 |
|
eor |
r16,r20 |
|
ldi |
r26,#5 |
|
ldi |
r27,#1 |
|
st |
x,r16 |
|
;Tmpb = Pina Xor Dub_pa |
|
|
in |
r16,$0 |
|
lds |
r20,$101 |
|
eor |
r16,r20 |
|
ldi |
r26,#5 |
|
ldi |
r27,#1 |
|
st |
x,r16 |
|
;Num_port = 0 |
r24,#0 |
|
ldi |
|
|
sts |
$100,r24 |
'добавить в Num_port номер позиции единицы |
;Gosub Search_pin |
||
call |
0000036A |
|
;восстановление регистрового блока |
|
|
pop |
r24 |
|
out |
$3F,r24 |
|
pop |
r31 |
|
pop |
r30 |
|
pop |
r29 |
|
pop |
r28 |
|
pop |
r27 |
|
pop |
r26 |
|
pop |
r25 |
|
pop |
r24 |
|
pop |
r23 |
|
pop |
r22 |
|
pop |
r21 |
|
============================================================================= 31
===================================== Справочник по программированию «Bascom-AVR» ==
pop |
r20 |
|
pop |
r19 |
|
pop |
r18 |
|
pop |
r17 |
|
pop |
r16 |
|
pop |
r11 |
|
pop |
r10 |
|
pop |
r7 |
|
pop |
r5 |
|
pop |
r4 |
|
pop |
r3 |
|
pop |
r2 |
|
pop |
r1 |
|
pop |
r0 |
|
;Return |
|
|
Reti |
|
|
;------ |
|
|
;подпрограмма Search_pin: |
|
|
0000036A: |
|
'повторять пока регистр Tmpb не станет равным нулю |
While Tmpb <> 0 |
r16,$105 |
|
lds |
|
|
cpi |
r16,#0 |
|
brne |
00000376 |
|
jmp |
0000038E |
|
00000376: |
|
|
;Shift Tmpb , Right |
|
|
ldi |
r25,#1 |
|
ldi |
r26,#5 |
|
ldi |
r27,#1 |
;вызов библиотечной программы |
call |
000003C6 |
|
;Incr Num_port |
r26,#0 |
|
ldi |
|
|
ldi |
r27,#1 |
|
ld |
r24,x |
|
subi |
r24,#255 |
|
st |
x,r24 |
|
;Wend |
0000036A |
|
jmp |
|
|
0000038E: |
|
|
ret |
|
|
;------ |
|
|
;библиотечная подпрограмма сдвига вправо на число в R25 |
||
000003C6: |
r25,#0 |
|
cpi |
|
|
breq |
000003D4 |
|
ld |
r24,x |
|
000003CC: |
r24 |
|
lsr |
|
|
dec |
r25 |
|
brne |
000003CC |
|
st |
x,r24 |
|
000003D4: |
|
|
ret |
|
|
'---------------------------------------------------------------------------------- |
|
|
============================================================================= 32
===================================== Справочник по программированию «Bascom-AVR» ==
Вопросы и ответы (1-10)
---------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 1
Но вот не могу понять только одного, почему в такой короткой программе, как эта:
Dim A As Byte
For A=1 to 30
Print A
Next A
End
…при компиляции размер кода составляет более 300 байт?? Абсурд! Баском конечно кушает память, но чтобы так!.. Может я в чём не прав?
Ответ 1
1 Насчет размера вашего примера. Такой же будет для любого компилятора. В этот размер входит:
-заголовок программы, включаемый в код автоматически (по умолчанию) и содержащий место под все вектора прерывания по 4 байт на вектор, очистку памяти 20-30 байт и инициализацию оборудования 30 - 100 байт;
-библиотека используемой функции и плюс 2-3 стандартных - около 100 байт;
-и собственно код вашей программы. Т.е. все сходится. Зато еще один вызов данной функции приводит к добавлению всего 20 - 30 байт.
---------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 2
Да и вообще, здесь много подводных камней, про которые даже в pdf-файле не найдешь…Я изучал когда-то давно Бейсик, сейчас плохо помню, приходиться заново учить. К какому Бейсику ближе Баском?
Ответ 2
Синтаксис и мнемоника, в принципе, отвечают стандарту Basic для DOS с учетом особенностей, ограничений и дополнительных возможностей. Лучше на стандартный Basic не ориентироваться. Слишком много ограничений, обусловленных различными возможностями процессоров. Главное отличие в том, что нужно определить тип переменных заранее, не допускать скрытого преобразования типов и не применять больше одного действия в одном операторе.) Лучше ориентироваться на оригинальное описание Bascom-AVR – оно отличное. На русском имеется только описание Bascom-8051. И еще на примеры - их очень много.
--------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 3
Я сначала ничего не подозревал. Пытался спокойно делать себе программки в Баскоме, как вдруг понял, что реализация протокола I2C(TWI) в любом микроконтроллере происходит программно, независимо от того, есть ли в нём аппаратная поддержка данного протокола или нет. Я бы ничего этого не заметил, если бы не наткнулся на проблему нехватки памяти микроконтроллера. В конечном итоге выяснилось, что реализация аппаратного протокола возможна только в лицензионной версии Баскома, так как в демо-версии нет соответствующей библиотеки.
Ответ 3
По моему наблюдению, использование аппаратного контроллера с точки зрения размера кода совершенно неэффективно. При программной реализации размер кода получается равноценным. Потому, что работа с аппаратным портом конечно проще, но при этом требуется организовать обработку соответствующего прерывания. Преимущество аппаратного I2C только в возможности осуществлять "прозрачную" работу одновременно с другими процессами и при наличии очень медленных устройств. Когда, например, в фоновом режиме нужно постоянно считывать или дописывать данные. При этом в коде "весит" именно программа организации МАССИВА записываемых или считываемых данных, а не сам драйвер. Вот пример работающей программы на BAS и на ASM. В основной программе применяются готовые функции. В прерывании используется ассемблерная программа (а ее размер минимален). Если устройство более медленное - нужно вместо NOP-ов добавить в программу подпрограммы более продолжительной задержки. Не забывать, что когда работаешь с I2C, нужно бы запретить прерывания. Если длительность импульса SCL превысит 10 мкс устройство может само отключится! В последующем примере переключение уровней делается изменение направления порта. Это важно. Так можно манипулировать с им намного быстрее.
'--------------------------------------------------------------
============================================================================= 33
===================================== Справочник по программированию «Bascom-AVR» ==
' Программы обслуживания АЦП типа ADS1110 (Burr-Broun) '--------------------------------------------------------------
' результаты ' 1 смещение входа имеется и весьма заметно 1-2 мВ. Зависит от включенного коэффициента усиления
' 2 При усилении К=1 шум меньше 1 дискрета, что делает усреднение бесполезным ' 3 При максимальном усилении К=8 шум составляет около 20-30 мкВ пик-пик
'-------------------------------------------------------------- |
|
|
'линия данных |
Config Sda = Portc.1 |
|||
Config Scl = Portc.0 |
'линия синхронизации |
||
Config I2cdelay = 1 |
'наивысшая скорость |
||
'----------------------------- |
|
|
|
'АВТООПРЕДЕЛЕНИЕ АДРЕСА АЦП |
|
||
Find_adr: |
|
'АДРЕС НУЛЕВОЙ ПРОШИВКИ(90h -2) |
|
|
Adradc = 142 |
|
|
Disable Interrupts |
'запретить прерывания |
||
Findadr1: |
|
'АДРЕС ДЛЯ ЧТЕНИЯ + 2 |
|
|
Adradc = Adradc + 2 |
||
|
If Adradc <> 160 Then |
'ПРОВЕРИМ НА МАКСИМУМ(90h + 16) |
|
|
Goto Findadr2 |
||
|
End If |
|
'АДРЕС НУЛЕВОЙ ПРОШИВКИ (90h) |
|
Adradc = 144 |
|
|
|
Goto En_intr |
|
'НА ВЫХОД ЕСЛИ ВСЕ АДРЕСА ПРОЙДЕНЫ |
Findadr2: |
|
|
|
$asm |
Lds R31 , {Adradc} |
'АДРЕС ДЛЯ ЧТЕНИЯ |
|
|
Inc R31 |
|
'СТАРТ, ДАННЫЕ И ЖДЕМ ПОДТВЕРЖДЕНИЯ |
' |
Rcall Start_bit |
||
Rcall R_byte |
|
'ПРИМЕМ СТАРШИЙ БАЙТ |
|
|
|
||
|
Rcall Mstr_ack |
'ВЫДАЧА СИГНАЛА ПОДТВЕРЖДЕНИЯ |
|
|
Rcall R_byte |
|
'ПРИМЕМ МЛАДШИЙ БАЙТ |
|
Rcall Mstr_ack |
'ВЫДАЧА СИГНАЛА ПОДТВЕРЖДЕНИЯ |
|
|
Rcall R_byte |
|
'ПРИМЕМ СТАТУС |
|
Rcall No_ack |
|
'ДА - БЕЗ ПОДТВЕРЖДЕНИЯ И СФОРМИРУЕМ СТОП-БИТ |
|
Andi R31 , &B01100000 |
'АНАЛИЗИРУЕМ D5 И D6. ВСЕГДА Д.Б. = 0 |
|
|
Brne Findadr1 |
|
'ЕСЛИ НЕ НУЛЬ - ПОВТОРИТЬ |
$end Asm |
|
'НА ВЫХОД ЕСЛИ АДРЕС НАЙДЕН |
|
' |
Goto En_intr |
|
|
|
|
|
|
'п/п записи статуса АЦП ADS1110 (нормальный медленный режим) 15 изм/с. Шкала 1.024 В |
|||
Slow_adc: |
|
Запуск преобразования: 1 только в одиночном |
|
' |
|------------ |
|
|
' |
|--------- |
Запуск: 0 - автоматический, 1 - одиночное |
|
' |
| |
Скорость: 00 - 240 SPS, 01 - 60 SPS |
|
' |
| |
| ------- |
|
' |
| |
| | |
10 - 30 SPS, 11 - 15 SPS |
' |
| |
| | |
|
' |
| |
| | ----- Усиление: 00 - 1 , 01 - 2 |
|
' |
| | | | |
10 - 4 , 11 - 8 |
|
' |
| |
| | | |
|
' |
| |
||||| |
|
|
Value = &B00001101 |
|
|
Wr_adc: |
|
'запретить прерывания |
|
Disable Interrupts |
|||
|
I2cstart |
|
'старт |
|
I2cwbyte Adradc |
'байт адреса |
|
|
I2cwbyte Value |
'байт режима |
|
|
I2cstop |
|
'стоп |
$asm
'подготовить порты к дальнейшему использованию ассемблерной программой
|
Cbi Ddrc , 0 |
|
'установим на Scl плавающую "1" |
|
Cbi Portc , 0 |
|
'подготовим "0" для вывода |
|
Cbi Ddrc , 1 |
|
'установим на Sda плавающую "1" |
|
Cbi Portc , 1 |
|
'подготовим "0" для вывода |
$end Asm |
|
|
|
En_intr: |
|
'разрешить прерывания |
|
Enable Interrupts |
|
||
Return |
|
|
|
' |
------------------------------------------ |
|
|
'п/п записи статуса АЦП ADS1110 (быстрый режим) 240 изм/с. Шкала 1.024 В |
|||
Speed_adc: |
|
Запуск преобразования: 1 только в одиночном |
|
' ------------ |
| |
|
|
' --------- |
| |
Запуск: 0 - автоматический, 1 - одиночное |
|
' |
| |
Скорость: 00 - 240 SPS, 01 - 60 SPS |
|
' ------- |
| |
| |
|
' |
| |
| | |
10 - 30 SPS, 11 - 15 SPS |
' |
| |
| | |
----- Усиление: 00 - 1 , 01 - 2 |
' |
| |
| | |
|
' |
| | | | |
10 - 4 , 11 - 8 |
============================================================================= 34
===================================== Справочник по программированию «Bascom-AVR» ==
' |
| |
| | | |
|
|
|
|
|
|
|
' |
| |
||||| |
|
|
|
|
|
|
|
|
Value = &B00000001 |
|
|
|
|
|
|
|
|
' |
Goto Wr_adc |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'п/п записи статуса АЦП ADS1110 (нормальный режим) 15 изм/с. Шкала 2.048 В |
|||||||||
Wide_adc: |
|
Запуск преобразования: 1 только в одиночном |
|||||||
' |
|------------ |
|
|||||||
' |
|--------- |
Запуск: 0 - |
автоматический, 1 - одиночное |
|
|||||
' |
| |
Скорость: 00 - 240 SPS, 01 - 60 SPS |
|
|
|||||
' |
| |
| ------- |
|
|
|||||
' |
| |
| | |
10 - 30 SPS, |
11 - 15 SPS |
|
|
|||
' |
| |
| | |
----- Усиление: 00 - 1 , 01 - 2 |
|
|
|
|||
' |
| |
| | |
|
|
|
||||
' |
| | | | |
10 - 4 , 11 - 8 |
|
|
|
||||
' |
| |
| | | |
|
|
|
|
|
|
|
' |
| |
||||| |
|
|
|
|
|
|
|
|
Value = &B00001100 |
|
|
|
|
|
|
|
|
' |
Goto Wr_adc |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'ЧТЕНИЕ ДАННЫХ ИЗ АЦП В R27(ст), R26(мл), статус в R31 |
|
|
|
||||||
Rd_adc: |
|
|
|
|
|
|
|
|
|
$asm |
Cbi Ddrc , 0 |
|
|
'установим на Scl плавающую "1" |
|||||
' |
|
|
|||||||
' |
Cbi Portc , 0 |
|
'подготовим "0" для вывода |
|
|||||
' |
Cbi Ddrc , 1 |
|
|
'установим на Sda плавающую "1" |
|||||
' |
Cbi Portc , 1 |
|
'подготовим "0" для вывода |
|
|||||
|
Lds R31 , {Adradc} |
|
'АДРЕС ДЛЯ ЧТЕНИЯ |
|
|
||||
|
Inc R31 |
|
|
'СТАРТ, ДАННЫЕ И ЖДЕМ ПОДТВЕРЖДЕНИЯ |
|||||
' |
Rcall Start_bit |
|
|||||||
Rcall R_byte |
|
|
'ПРИМЕМ СТАРШИЙ БАЙТ |
|
|
||||
|
|
|
|
|
|||||
|
Mov R29 , R31 |
|
|
'ЗАПИШЕМ ДАННЫЕ В ОЗУ |
|
|
|||
|
Rcall Mstr_ack |
|
'ВЫДАЧА СИГНАЛА ПОДТВЕРЖДЕНИЯ |
|
|||||
|
Rcall R_byte |
|
|
'ПРИМЕМ МЛАДШИЙ БАЙТ |
|
|
|||
|
Mov R28 , R31 |
|
|
'ЗАПИШЕМ ДАННЫЕ В ОЗУ |
|
|
|||
|
Rcall Mstr_ack |
|
'ВЫДАЧА СИГНАЛА ПОДТВЕРЖДЕНИЯ |
|
|||||
|
Rcall R_byte |
|
|
'ПРИМЕМ СТАТУС |
|
|
|
||
' |
Rjmp No_ack |
|
|
'ДА - БЕЗ ПОДТВЕРЖДЕНИЯ И СФОРМИРУЕМ СТОП-БИТ |
|||||
|
|
|
|
|
|
|
|
|
|
'порты PC.0, PC1 инициализированы на ввод (исходно DDRC.0 = 0, DDRC.1 = 0), |
|||||||||
'а в порты PORTC.0 PORTC.1 записывается |
"0". Таким образом на линиях устанавливается "1". |
||||||||
'воспроизведение "0" производися переключением направления |
|
|
|||||||
'------------------------------------------ |
|
|
|
|
|
|
|
|
|
' Portc.0 - Scl, Portc.1 - Sda |
|
|
|
|
|
|
|||
'------------------------------------------ |
|
|
|
|
|
|
|
|
|
'ФОРМИРОВАНИЕ СТАРТ-БИТА И ЕЩЕ ДВЕ ОПЕРАЦИИ |
|
|
|
|
|
||||
Start_bit: |
|
|
'УСТАНОВКА И ОЖИДАНИЯ ОТПУСКАНИЯ ЛИНИИ Scl_l |
||||||
|
Cbi Ddrc , 0 |
|
|
||||||
|
Nop |
|
|
'------------------ |
¦ |
|
¦ |
|
|
|
Nop |
|
|
' |
|
|
|
||
|
Cbi Ddrc , 1 |
|
|
'--- |
|
|
- |
|
|
|
Nop |
|
|
'Scl |
----------------- |
|
|
|
|
|
Nop |
|
|
' |
|
|
|
|
|
|
Sbi Ddrc , 1 |
|
|
'------------- |
¦ |
|
¦ |
|
|
|
Nop |
|
|
' |
|
|
|
||
|
Nop |
|
|
'------- |
|
|
------ |
|
|
' |
Sbi Ddrc , 0 |
|
|
'Sda |
----------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'ВЫДАЧА НА ЛИНИЮ БАЙТА ДАННЫХ ЗАПИСАННЫХ В R31 |
|
|
|
|
|||||
T_byte: |
|
|
'ЧИСЛО БИТ |
|
|
|
|
||
|
Ldi R30 , 8 |
|
|
|
|
|
|
||
T_by0: |
|
|
'ЦИКЛ ПЕРЕДАЧИ |
|
|
|
|||
|
Sbi Ddrc , 0 |
|
|
|
|
|
|||
|
Rol R31 |
|
|
'СДВИГ |
|
|
|
|
|
|
Brcc T_by1 |
|
|
'порт в "1" |
|
|
|
|
|
|
Cbi Ddrc , 1 |
|
|
|
|
|
|
||
|
Rjmp T_by2 |
|
|
|
|
|
|
|
|
T_by1: |
|
|
'порт в "0" |
|
|
|
|
||
|
Sbi Ddrc , 1 |
|
|
|
|
|
|
||
T_by2: |
|
|
'УСТАНОВКА И ОЖИДАНИЯ ОТПУСКАНИЯ ЛИНИИ Scl_l |
||||||
|
Cbi Ddrc , 0 |
|
|
||||||
|
|
|
'- |
----- |
- - -- |
¦ |
----- |
||
|
Dec R30 |
|
|
' ¦ |
¦ |
¦ |
¦ |
¦ |
|
|
Brne T_by0 |
|
|
'------ |
|
|
---- |
---- |
|
|
|
|
|
'Scl |
-------------------------------- |
|
|
|
|
|
|
|
|
' |
|
|
|
|
|
|
|
|
|
'---- |
|---------- |
|
|--- - - |
---|------- |
|
|
|
|
|
' |
|
|
============================================================================= 35
===================================== Справочник по программированию «Bascom-AVR» ==
|
|
'---- |
---------- |
|
--- |
- - |
--- |
------- |
' |
|
'Sda-------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'СОСТОЯНИЕ ОЖИДАНИЯ БИТА ОТВЕТА (ПОДТВЕРЖДЕНИЕ) |
|
|
|
|
|
|||
Slave_ack: |
'УСТАНОВКА И ОЖИДАНИЯ ОТПУСКАНИЯ ЛИНИИ Scl_l |
|||||||
Sbi |
Ddrc , 0 |
|||||||
Nop |
Ddrc , 1 |
' |
|
---- |
¦ |
|
|
|
Cbi |
'¦ |
|
¦ |
|
|
|
||
Nop |
Ddrc , 0 |
' ------ |
|
|
--- |
|
|
|
Cbi |
'Scl------------- |
|
|
|
|
|
|
|
Nop |
|
' |
|
|
|
|
|
|
Nop |
Ddrc , 0 |
'---------------- |
¦ | |
|
| |
|
|
|
Sbi |
' |
|
|
|
|
|||
Ret |
|
'----- |
|
------ |
|
|
|
|
' |
|
'Sda------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'БЕЗ ВЫДАЧИ СИГНАЛА ПОДТВЕРЖДЕНИЯ И ЕЩЕ ОДНА ОПЕРАЦИЯ |
|
|
|
|
||||
No_ack: |
Ddrc , 1 |
'УСТАНОВКА И ОЖИДАНИЯ ОТПУСКАНИЯ ЛИНИИ Scl_l |
||||||
Cbi |
||||||||
Cbi |
Ddrc , 0 |
' |
¦------ |
¦ |
|
|
|
|
' |
---- |
|
|
|
||||
Nop |
|
'---- |
|
|
|
|
|
|
Nop |
Ddrc , 0 |
'Scl------------- |
|
|
|
|
|
|
Sbi |
'---------------- |
|
|
|
|
|
|
|
|
|
'¦ |
|
|
|
|
|
|
|
|
'- |
|
|
|
|
|
|
' |
|
'Sda------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'ФОРМИРОВАНИЕ СТОП-БИТА |
|
|
|
|
|
|
|
|
Stop_bit: |
' |
|
|
|
|
|
|
|
Sbi |
Ddrc , 1 |
¦--------- |
|
|
|
|
|
|
|
|
' |
|
|
|
|
|
|
Cbi |
Ddrc , 0 |
'----- |
|
|
|
|
|
|
'Scl------------ |
|
---- |
|
|
|
|||
Nop |
Ddrc , 1 |
' |
|
|
|
|
||
Cbi |
'¦ |
|
¦ |
|
|
|
|
|
Ret |
|
' --------- |
|
|
|
|
|
|
' |
|
'Sda------------ |
|
|
|
|
|
|
С ЛИНИИ БАЙТА ДАННЫХ В R31 |
|
|
|
|
|
|
|
|
'ЧТЕНИЕ |
|
|
|
|
|
|
|
|
R_byte: |
Ddrc , 1 |
'НА ВСЯКИЙ СЛУЧАЙ |
|
|
|
|||
Cbi |
|
|
|
|||||
Ldi |
R30 , 8 |
'ЧИСЛО СЧИТЫВАЕМЫХ БИТ |
|
|
||||
R_by0: |
Ddrc , 0 |
'ЦИКЛ СЧИТЫВАНИЯ |
|
|
|
|||
Cbi |
|
|
|
|||||
Sec |
|
'УСТАНОВКА И ОЖИДАНИЯ ОТПУСКАНИЯ ЛИНИИ SCL |
||||||
Nop |
|
'------- |
|
¦ |
--- -- |
¦ |
---- |
|
Sbis Pinc , 1 |
' ¦ |
|
¦ |
¦ |
¦ |
|||
'-- |
|
---- |
|
---- |
|
----- |
||
Clc |
Ddrc , 0 |
'SCL-------------------------------- |
|
|
|
|
|
|
Sbi |
'---------------- |
| R |
|
| R |
- ---------------- |
|
| R |
|
Rol |
R31 |
'¦ |
|
|
|
|||
Dec |
R30 |
'¦ |
| D |
|
| D |
|
|
| D |
Brne R_by0 |
' |
--------- |
|
- |
- ------- |
|
-------- |
|
Ret |
|
'SDA-------------------------------- |
|
|
|
|
|
|
'-------------------------- |
СИГНАЛА ПОДТВЕРЖДЕНИЯ |
|
|
|
|
|
|
|
'ВЫДАЧА |
|
|
|
|
|
|
|
|
Mstr_ack: |
|
|
|
|
|
|
|
|
Sbi |
Ddrc , 0 |
'УСТАНОВКА И ОЖИДАНИЯ ОТПУСКАНИЯ ЛИНИИ SCL |
||||||
Nop |
Ddrc , 1 |
|||||||
Sbi |
' |
|
¦------ |
¦ |
|
|
|
|
Nop |
Ddrc , 0 |
'¦ |
|
----- |
|
|
||
Cbi |
' -------- |
|
|
|
|
|
||
Nop |
Ddrc , 0 |
'SCL------------------- |
|
|
|
-- |
|
|
Sbi |
'---- |
¦ |
|
|
|
|
||
Nop |
Ddrc , 1 |
' |
|
|
¦ |
|
|
|
Cbi |
' |
-------------- |
|
|
|
|
|
|
Ret |
|
'SDA------------------- |
|
|
|
|
|
|
'------------------------------------------ |
|
|
|
|
|
|
|
|
$end Asm |
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 4
Я читал, что Bascom дает громоздкий и неоптимальный код. Это правда? Тогда какие выгоды дает применение этого компилятора?
============================================================================= 36

===================================== Справочник по программированию «Bascom-AVR» ==
Ответ 4
Не нужно паниковать о том, что Bascom дает некомпактный код. Размер кода полностью соответствует классу компиляторов с языков высокого уровня. Уступает только CodeVision на малых проектах, а с другими компиляторами Си успешно конкурирует. Bascom особенно хорош в больших проектах, когда мелочная оптимизация уже не приносит заметного выигрыша, а важнее структурированность исходного текста.
Размер кода в громадной степени зависит от стиля написания. Нужно применять тоже приемы, что и при программировании на ассемблере:
- похожие программы оформлять в подпрограммы. Различия формировать ветвлением и дроблением участ-
ков;
-применять простые конструкции, минимум вложенности (от вложенности код становится еще больше). Лучше больше ветвится по тексту программы, чем применять вложенные проверки условий. Чем длиннее текст и применяются более мелкие операторы, тем короче код и он быстрее работает;
-программы прерывания писать на ассемблере, осуществляя минимум действий. Запрещать автоматически сохранять регистры;
-применять больше переменных (на каждый чих свою, обычно ресурсов хватает), чтобы было меньше "заморочек", чтобы не вспоминать лишний раз о возможности одновременного использования;
-применять конструкцию On … Goto с таблицей переходов даже избыточной, а не любимую многими
Select Case;
-применять табличные методы установки и выбора параметров Lookup(offset,Table);
-программа должна построена таким образом, чтобы обращение к каждому элементу периферии встречалось в программе только один раз;
-также как и задание числовых данных нужно делать один раз.
Не рекомендуется применять экзотические методы передачи параметров (через стек). Просто советы:
-не вставлять Return внутрь закрытых конструкций (типа if.. do.. for..) , а применять переход Goto на выходную метку;
-не располагать переменные (Single, массивы и строковые) на границе страниц памяти. Поступать так - скомпилить и посмотреть. При необходимости определить распределение памяти для Single и String самостоятельно вручную. Например:
Dim Kzr0 As Single At 1024 Dim Kzr1 As Single At 1028
или набить промежутки на границе страниц пустыми неиспользуемыми переменными;
-не забывать один оператор - одно действие (это не Си).
--------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 5
При преобразовании демоверсии 1.11.8.1 в полную, добавление dll-файлов библиотека не расширяется. Как
быть?
Ответ 5
Неполность библиотек не имеет большого значения. Большинство из них просто не представлено в виде исходного текста, который можно править и добавлять. За 10 лет использования Bascom ни разу в исходном она мне понадобилась. На самом деле, отсутствуют только утилиты уникального оборудования, которое, все равно, приходится описывать "вручную", чтобы не потерять критичные свойства. Во-вторых, имеющиеся библиотеки часто не обеспечивают совместную (параллельную) работу с другим оборудованием (параллельными задачами). В-третьих, со сложной периферией МК приходится работать напрямую - просто пишешь и читаешь регистры, анализируешь биты. Так вернее и полезней - иначе нельзя использовать все возможности и не будешь отчетливо представлять ее работу. Если лень читать, можно применять утилиту CodeVizard компилятора CodeVision. Сделано очень точно.
--------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 6
Не могу понять, как правильно использовать эту настройку. 1. По поводу настройки ТАЙМЕРА1.В оригинальном описании написано:
CONFIG TIMER1 = COUNTER | TIMER | PWM , EDGE=RISING | FALLING , PRESCALE= 1|8|64|256|1024 , NOISE CANCEL=0 |1, CAPTURE EDGE = RISING | FALLING , CLEAR TIMER = 1|0,
COMPARE A = CLEAR | SET | TOGGLE I DISCONNECT ,
COMPARE B = CLEAR | SET | TOGGLE I DISCONNECT
============================================================================= 37
===================================== Справочник по программированию «Bascom-AVR» ==
Ответ 6
Не пользуйтесь для настройки конфигурации ключевыми словами Баскома. Забыть их! Ведь кристаллы разные, расположение битов и регистров различное, очень велика вероятность, что вы или компилятор ошибется. Например, в Bascom-8051 кристаллы совместимы по периферии и все поэтому работает надежно. В Bascom-AVR такие настройки оставлены для совместимости. Читайте Datasheet на процессоры и записывайте необходимые настройки сами. Причем лучше пользоваться оригинальными документами. В переводных много ошибок. Их ценность только в возможности быстрее изучить интересующий вопрос.
--------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 7
Как записать значение в регистр совпадения OCR1A, причём так, чтобы это можно было сделать в любом месте программы? Как записать в значение в сам таймер-счётчик (регистр TCNT1)?
Ответ 7
'Да. Например, число 12345. Преобразуем в калькуляторе в HEX 12345=3039h OCR1AH=&H30 : OCR1AL=&H39 'при записи обязательно старший байт первым
'-----------------------------
TCNT1H=&h11:TCNT1H=&hFF 'по записи первым старший потом младший Byte1=TCNT1H:Byte2=TCNT1H 'при чтении первым младший потом старший
'-----------------------------
TCNT1H=High(word):TCNT1H=low(word) 'так записывается двухбайтное число
TEMPh=TCNT1H : TEMPl=TCNT1H : Word=Makeint(Temph,Templ) 'так читается в двухбайтовое число '-----------------------------
'и как это выглядит на ассемблере
'-----------------------------
'считать значение, полученное в счетчике таймера 1
Rd_tim1: |
|
$asm |
'СЧИТАТЬ ДАННЫЕ |
In R30 , Tcnt1l |
|
In R31 , Tcnt1h |
'из таймера |
Sts {r_bd} , R30 |
|
Sts {r_bd + 1} , R31 |
|
Lds R30 , {c_msb} |
|
'--------- |
'проверим бит переполнения таймера 1 |
In R31 , Tifr |
|
Sbrs R31 , 2 |
'этой операцией мы учтем еще не обработанное переполнение таймера |
Rjmp Rdtim_1 |
'если бит переполнения таймера 1 установлен, |
Inc R30 |
'добавим единицу в счетчик старших разрядов |
'--------- |
|
Rdtim_1: |
|
Sts {r_bd + 2} , R30 |
|
Clr R31 |
|
Sts {r_bd + 3} , R31 |
|
$end Asm |
|
Return |
|
'---------------------------------------------- |
|
'оформление прерывания на ассемблере |
|
'---------------------------------------------- |
|
'обработка прерывания от таймера 1 |
|
Timer1_int: |
|
$asm |
'сохраним регистры |
Push R31 |
|
In R31 , Sreg |
|
Push R31 |
|
'--------------------- |
|
Lds R31 , {c_msb} |
|
Inc R31 |
'добавить единицу в счетчик старших разрядов |
Sts {c_msb} , R31 |
|
'--------------------- |
'восстановим регистры |
Pop R31 |
|
Out Sreg , R31 |
|
Pop R31 |
|
Reti |
|
$end Asm |
|
Return |
|
'---------------------------------------------- |
|
--------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 8
============================================================================= 38

===================================== Справочник по программированию «Bascom-AVR» ==
Как подключить таймер1 в режиме сравнения к выводу OC1A?(а так же OC1B)?
Ответ 8
'все назначения конфигурации записывать в основной программе так TCCR1A=&b01010000 'переключение выходов по совпадению OCR1A и OCR1B) TCCR1B=&b00001001 'считать с частотой Fкв, перезагрузка по OCR1A
'если конфигурация делается в теле прерывания оформлять так
'----------------------------------------------
'запретить прерывание таймера 1 |
|
Dis_timer1: |
|
$asm |
|
Ldi R31 , &b00000001 |
'сбросить бит разрешения прерывания таймера 1. |
Out Timsk , R31 |
|
Ldi R31 , &b00000100 |
'после запрещения сбросить флаг прерывания таймера 1 |
Out Tifr , R31 |
|
$end Asm |
|
Return |
|
'----------------------------- |
|
'запретить внешнее прерывание 1 |
|
Dis_int0: |
|
$asm |
'сбросить бит разрешения внешнего прерывания. |
Ldi R31 , &b00000000 |
|
Out Gimsk , R31 |
'по datasheet этот регистр называется Gicr |
Ldi R31 , &b01000000 |
'после запрещения сбросить флаг прерывания. |
Out Gifr , R31 |
|
$end Asm |
|
Return |
|
--------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 9
Могу ли я одновременно использовать COMPARE A и COMPARE В?
Ответ 9
'Да, но режим CTC (сброс по совпадению) возможен только от OCR1A 'или от OCR1B если не используется OCR1A
'вообще это "скользкое" место, плохо прописанное в оригинальной документации 'при этом коэффициент деления определяется OCR1A,
'а переключение выхода совпадением и с OCR1A и с OCR1B
--------------------------------------------------------------------------------------------------------------------------------------------------
Вопрос 10
Что означает Compare = Off(On) для компаратора? Я так понял, что это функция захвата таймера1, подключенного непосредственно к выходу компаратора.
'смотри регистр ACSR. Эта опция - фактически бит ACSR.2
'когда ACSR.2 = 1 по любому переключению компаратора значение TCNT1 запоминается в ICR1, 'как и по перепаду на входе CP1
Как можно в самой программе включить и выключить компаратор?
'это бит ACSR.7. По сбросу компаратор включен! ACSR=&B1xxxxxxxx 'выключить
ACSR=&B0xxxxxxxx 'включить, значение остальных битов смотри сам
============================================================================= 39