Ассемблер (ASM) для AVR в вопросах и ответах
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Единственное что понял так это УМВР = "У Меня Всё Работает". Остальное, кажется, написано в ответ не на эту тему...
-
forfrends
- Вымогатель припоя
- Сообщения: 546
- Зарегистрирован: Вс дек 30, 2012 00:32:06
- Откуда: Николаев / Украина
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Всем добрый день!
Пытаюсь освоить Ассемблер, проэкты тестирую на Атини2313.
Вот захотелось мне понять как сделать плавное включение/выключение светодиода. Ну, для примера, собрать простенькую схему: тинька, к порту PB0 подключен светодиод, другой контакт светодиода, через резистор, к "минусу". Вот так просто
А вот с прошивкой - у меня полный "0".
Точнее не представляю как устроить это самое "возгорание/затухание"
Поискал по форуму, наиболее похожую тему нашел здесь: http://radiokot.ru/forum/viewtopic.php?f=3&t=48068&start=60
Там был выложен код прошивки для МК:
Вот только я в этом коде запутался. Можете помочь отделить только то что отвечает за зажигание/гашение?
Пытаюсь освоить Ассемблер, проэкты тестирую на Атини2313.
Вот захотелось мне понять как сделать плавное включение/выключение светодиода. Ну, для примера, собрать простенькую схему: тинька, к порту PB0 подключен светодиод, другой контакт светодиода, через резистор, к "минусу". Вот так просто
А вот с прошивкой - у меня полный "0".
Точнее не представляю как устроить это самое "возгорание/затухание"
Поискал по форуму, наиболее похожую тему нашел здесь: http://radiokot.ru/forum/viewtopic.php?f=3&t=48068&start=60
Там был выложен код прошивки для МК:
Спойлер
Код: Выделить всё
;=========================
; Плавное зажигание 10 светодиодов
;
;=========================
;
; 10led.asm
;
; Copyright 2011 ploop <ploopgm@gmail.com>
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
; MA 02110-1301, USA.
;
;=========================
.device ATtiny2313
;----------
; Определения портов
;----------
.equ led0_port = PORTB
.equ led1_port = PORTB
.equ led2_port = PORTB
.equ led3_port = PORTB
.equ led4_port = PORTB
.equ led5_port = PORTB
.equ led6_port = PORTB
.equ led7_port = PORTB
.equ led8_port = PORTD
.equ led9_port = PORTD
.equ led0_bit = 7
.equ led1_bit = 6
.equ led2_bit = 5
.equ led3_bit = 4
.equ led4_bit = 3
.equ led5_bit = 2
.equ led6_bit = 1
.equ led7_bit = 0
.equ led8_bit = 6
.equ led9_bit = 5
.equ btn_pause_inc_port = PORTD
.equ btn_pause_inc_pin = PIND
.equ btn_pause_inc_bit = 1
.equ btn_pause_dec_port = PORTD
.equ btn_pause_dec_pin = PIND
.equ btn_pause_dec_bit = 0
.equ btn_pow_inc_port = PORTA
.equ btn_pow_inc_pin = PINA
.equ btn_pow_inc_bit = 1
.equ btn_pow_dec_port = PORTA
.equ btn_pow_dec_pin = PINA
.equ btn_pow_dec_bit = 0
; Для gavrasm
.def XH = R27
.def XL = R26
.def YH = R29
.def YL = R28
.def ZH = R31
.def ZL = R30
.def counter = r25 ; счетчик
.def max_l = r24 ; максимальная яркость
.def null = r23 ; ноль
.def delay = r22 ; задержка
.def btn_tsk = R8 ; регистр задач по нажатию кнопок.
;|7|6|5|4|3|2|1|0|
;| | 3-0 действие по нажатию
;|7-4 действие по отпусканию
.def btn_press = R7 ; регистр состояния кнопок (3-0 нажаты)
;
.equ btn_pause_inc = 3
.equ btn_pause_dec = 2
.equ btn_pow_inc = 1
.equ btn_pow_dec = 0
;=========================
; EEPROM
;=========================
.ESEG ; Хранение настроек
.org 0
e_bright:
.db 0 ; яркость
e_delay:
.db 1 ; задержка
;=========================
; RAM
;=========================
.DSEG
del_buf: .byte 10 ; буфер переменных сравнения для 10 каналов
;----------
.cseg
;----------
; Векторы прерываний
;----------
.org 0x0000
rjmp RESET ; Reset Handler
.org 0x0001
reti ;rjmp INT0 ; External Interrupt0 Handler
.org 0x0002
reti ;rjmp INT1 ; External Interrupt1 Handler
.org 0x0003
reti ;rjmp TIM1_CAPT ; Timer1 Capture Handler
.org 0x0004
reti ; Timer1 CompareA Handler
.org 0x0005
reti ;rjmp TIM1_OVF ; Timer1 Overflow Handler
.org 0x0006
reti ;rjmp TIM0_OVF ;rjmp TIM0_OVF ; Timer0 Overflow Handler
.org 0x0007
reti ; USART0 RX Complete Handler
.org 0x0008
reti ;rjmp USART0_DRE ; USART0,UDR Empty Handler
.org 0x0009
reti ;rjmp USART0_TXC ; USART0 TX Complete Handler
.org 0x000A
reti ;rjmp ANA_COMP ; Analog Comparator Handler
.org 0x000B
reti ;rjmp PCINT ; Pin Change Interrupt
.org 0x000C
reti ;rjmp TIMER1_COMPB ; Timer1 Compare B Handler
.org 0x000D
rjmp TIMER0_COMPA ; Timer0 Compare A Handler
.org 0x000E
reti ;rjmp TIMER0_COMPB ; Timer0 Compare B Handler
.org 0x000F
reti ;rjmp USI_START ; Usi Start Handler
.org 0x0010
reti ;rjmp USI_OVERFLOW ; USI Overflow Handler
.org 0x0011
reti ;rjmp EE_READY ; EEPROM Ready Handler
.org 0x0012
reti ;rjmp rjmp WDT_OVERFLOW ; Watchdog Overflow Handler
.org 0x0013
;----------
; Прерывание по переполнению
;----------
TIMER0_COMPA:
set ; устанавливаем флаг срабатывания таймера
reti
;----------
; Инициализация
;----------
reset:
ldi null,0
ldi max_l,0
ldi r16,low(RAMEND)
out spl,r16
ldi r16,$FF
out DDRB,r16
out PORTB,null
ldi r16,0b01100000
out DDRD,R16
ldi r16,0b00000011
out PORTD,R16
ldi r16,0b00000000
out DDRA,r16
ldi r16,0b00000011
out PORTA,r16
;-------- таймер ---------
ldi r16,(1<<WGM01)
out TCCR0A,r16
ldi r16,250
out OCR0A,r16
ldi r16,(1<<OCIE0A) ; прерывание по совпадению
out TIMSK,r16
ldi r16,(1<<CS00)|(1<<CS02) ; 1/1024
out TCCR0B,r16
;=========================
; Старт программы
;=========================
start:
rcall upd_max_light ; заполняем буфер минимальными значениями
ldi r17,e_bright ; Чтение настроек яркости и задержки
rcall EERead
mov max_l,r16
ldi r17,e_delay
rcall EERead
mov delay,r16
rcall big_delay ; задержка
;----------
; основной цикл
clr counter
clr r17 ; В r17 указатель на текущий светодиод
clt
sei
ldi r19,15 ; счетчик проходов,
main_loop: ; чтобы скорость не зависила от яркости
brtc no_timer ; Если флаг T не установлен, значит таймер не сработал
clt ; иначе сбрасываем его
dec r19
breq next_diode ; Если счетчик циклов =0 - следующий диод
cp r19,max_l ; проверим, не меньнше ли счетчик проходов максимального
brcs no_timer ; если меньше - зацикливаем
ldi YH,high(del_buf) ; берём значение яркости
ldi YL,low(del_buf)
add YL,r17
adc YH,null
ld r18,Y
dec r18 ; уменьшаем (увеличиваем яркость)
st Y,r18
rjmp no_timer
next_diode:
ldi r19,15
inc r17 ; если максимальная, увеличиваем счетчик светодиодов
cpi r17,10 ; если светодиод последний - выходим
breq exit_loop
no_timer:
rcall pwm
rjmp main_loop
;----------
; простой цикл после прохода эффекта
;----------
exit_loop:
rcall pwm ; ШИМ
rcall btn_test ; Опрос кнопок
rcall btn_set ; Реакция на кнопки
rjmp exit_loop
;=========================
; цикл прохода ШИМ по 10 каналам
;=========================
pwm:
ldi XH,high(del_buf)
ldi XL,low(del_buf)
ld r16,X+ ; загружаем значение сравнения 0-го канала
cp r16,counter ; сравниваем со счетчиком
brne pwm_1
sbi led0_port,led0_bit ; если равны - включаем канал
pwm_1:
ld r16,X+
cp r16,counter
brne pwm_2
sbi led1_port,led1_bit
pwm_2:
ld r16,X+
cp r16,counter
brne pwm_3
sbi led2_port,led2_bit
pwm_3:
ld r16,X+
cp r16,counter
brne pwm_4
sbi led3_port,led3_bit
pwm_4:
ld r16,X+
cp r16,counter
brne pwm_5
sbi led4_port,led4_bit
pwm_5:
ld r16,X+
cp r16,counter
brne pwm_6
sbi led5_port,led5_bit
pwm_6:
ld r16,X+
cp r16,counter
brne pwm_7
sbi led6_port,led6_bit
pwm_7:
ld r16,X+
cp r16,counter
brne pwm_8
sbi led7_port,led7_bit
pwm_8:
ld r16,X+
cp r16,counter
brne pwm_9
sbi led8_port,led8_bit
pwm_9:
ld r16,X+
cp r16,counter
brne pwm_x
sbi led9_port,led9_bit
pwm_x:
inc counter ; инкрементируем счетчик
sbrc counter,4 ; и проверяем на переполнение
rjmp ch_off
ret
ch_off: ; если переполнился - сбравываем счетчик и все порты
clr counter
out PORTB,null
cbi PORTD,6
cbi PORTD,5
ret
;=========================
; заполнение буфера значениями яркости
;=========================
upd_max_light:
ldi XL,low(del_buf)
ldi XH,high(del_buf)
ldi r16,10
ldi r17,16
l0:
st X+,r17
dec r16
brne l0
ret
upd_light:
ldi XL,low(del_buf)
ldi XH,high(del_buf)
ldi r17,10
l1:
st X+,r16
dec r17
brne l1
ret
;=========================
; Подпрограмма опроса кнопок
;=========================
btn_test:
mov r16,btn_press
mov r17,btn_tsk
sbic btn_pause_inc_pin,btn_pause_inc_bit
rjmp bt01 ; если кнопка нажата
sbrc r16,3 ; проверяем, была ли она нажата ранее
rjmp bt02 ; если да - выходим
ori r17,(1<<3) ; если нет - устанавливаем действие по нажатию
ori r16,(1<<3) ; и факт нажатия
rjmp bt02
bt01: ; если не нажата
sbrs r16,3 ; и не была нажата ранее
rjmp bt02 ; выходим
andi r16,~(1<<3) ; иначе сбрасываем факт нажатия
ori r17,(1<<7) ; ставим действие по отпусканию
bt02:
;----------
sbic btn_pause_dec_pin,btn_pause_dec_bit
rjmp bt03 ; если кнопка нажата
sbrc r16,2 ; проверяем, была ли она нажата ранее
rjmp bt04 ; если да - выходим
ori r17,(1<<2) ; если нет - устанавливаем действие по нажатию
ori r16,(1<<2) ; и факт нажатия
rjmp bt04
bt03: ; если не нажата
sbrs r16,2 ; и не была нажата ранее
rjmp bt04 ; выходим
andi r16,~(1<<2) ; иначе сбрасываем факт нажатия
ori r17,(1<<6) ; ставим действие по отпусканию
bt04:
;----------
sbic btn_pow_inc_pin,btn_pow_inc_bit
rjmp bt05 ; если кнопка нажата
sbrc r16,1 ; проверяем, была ли она нажата ранее
rjmp bt06 ; если да - выходим
ori r17,(1<<1) ; если нет - устанавливаем действие по нажатию
ori r16,(1<<1) ; и факт нажатия
rjmp bt06
bt05: ; если не нажата
sbrs r16,1 ; и не была нажата ранее
rjmp bt06 ; выходим
andi r16,~(1<<1) ; иначе сбрасываем факт нажатия
ori r17,(1<<5) ; ставим действие по отпусканию
bt06:
;----------
sbic btn_pow_dec_pin,btn_pow_dec_bit
rjmp bt07 ; если кнопка нажата
sbrc r16,0 ; проверяем, была ли она нажата ранее
rjmp bt08 ; если да - выходим
ori r17,(1<<0) ; если нет - устанавливаем действие по нажатию
ori r16,(1<<0) ; и факт нажатия
rjmp bt08
bt07: ; если не нажата
sbrs r16,0 ; и не была нажата ранее
rjmp bt08 ; выходим
andi r16,~(1<<0) ; иначе сбрасываем факт нажатия
andi r16,~(1<<0) ; иначе сбрасываем факт нажатия
ori r17,(1<<4) ; ставим действие по отпусканию
bt08:
;----------
mov btn_press,r16
mov btn_tsk,r17
ret
;=========================
; Действия при нажатии кнопок
;=========================
btn_set:
mov r20,btn_tsk
; сбросим все биты
mov r17,btn_tsk
andi r17,0b11110000
mov btn_tsk,r17
; условные переходы
sbrc r20,btn_pause_inc
rcall pause_inc
sbrc r20,btn_pause_dec
rcall pause_dec
sbrc r20,btn_pow_inc
rcall pow_inc
sbrc r20,btn_pow_dec
rcall pow_dec
ret
;=========================
; Подпрограмма записи в EEPROM (r17 - адрес, r16 - данные)
;=========================
EEWrite:
sbic EECR,EEWE ; Ждем готовности памяти к записи. Крутимся в цикле
rjmp EEWrite
cli ; запрещаем прерывания.
out EEAR,r17 ; Загружаем адрес нужной ячейки
out EEDR,r16 ; и сами данные из rx1
sbi EECR,EEMWE ; взводим предохранитель
sbi EECR,EEWE ; записываем байт
sei ; разрешаем прерывания
ret
;=========================
; Подпрограмма чтения в EEPROM (r17 - адреса, r16 - данные)
;=========================
EERead:
sbic EECR,EEWE ; Ждем пока будет завершена прошлая запись.
rjmp EERead
out EEAR, r17 ; загружаем адрес нужной ячейки
sbi EECR,EERE ; Выставляем бит чтения
in r16,EEDR ; Грузим из регистра данных результат
ret
;=========================
; увеличение задержки
;=========================
pause_inc:
cpi delay,251 ; проверка на максимум
breq exit_pause_inc
subi delay,-10 ; увеличение задержки и запись в EEPROM
mov r16,delay
ldi r17,e_delay
rcall EEWrite
rjmp reset
exit_pause_inc:
ret
;=========================
; уменьшение задержки
;=========================
pause_dec:
cpi delay,1 ; проверка на минимум
breq exit_pause_dec
subi delay,10 ; уменьшение задержки и запись в EEPROM
mov r16,delay
ldi r17,e_delay
rcall EEWrite
rjmp reset
exit_pause_dec:
ret
;=========================
; увеличение яркости
;=========================
pow_inc:
cpi max_l,0 ; проверка на ноль. 0 - максимальная яркость
breq exit_pow_inc
dec max_l ; увеличение яркости и запись в EEPROM
mov r16,max_l
ldi r17,e_bright
rcall EEWrite
rcall upd_light
exit_pow_inc:
ret
;=========================
; уменьшение яркости
;=========================
pow_dec:
cpi max_l,14 ; проверка на 15. 15 - минимальная яркость
breq exit_pow_dec
inc max_l ; увеличение яркости и запись в EEPROM
mov r16,max_l
ldi r17,e_bright
rcall EEWrite
rcall upd_light
exit_pow_dec:
ret
;=========================
; задержка
;=========================
big_delay:
ldi r16,0
ldi r17,0
mov r18,delay
del_loop:
dec r16
brne del_loop
dec r17
brne del_loop
dec r18
brne del_loop
ret
Вот только я в этом коде запутался. Можете помочь отделить только то что отвечает за зажигание/гашение?
Сделать своими руками всегда интересней чем просто купить и пользоваться
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
За это отвечает подпрограмма PWM.
Код вы слишком сложный взяли для "начинания". Очень тяжелый код, без коментариев, неочевидный и т.д.
Вся бодяга затеяна из-за 10 диодов. А тебе нужен ОДИН - для этого достаточно один канал ШИМ одного таймера. Переключаешь таймер в режим PWM разрешаешь аппаратный выход по сравнению, регистром сравнения задаешь скважность... осталось только в программе с задержкой наращивать значение скважности - это будет единственное что делает программа.
Код вы слишком сложный взяли для "начинания". Очень тяжелый код, без коментариев, неочевидный и т.д.
Вся бодяга затеяна из-за 10 диодов. А тебе нужен ОДИН - для этого достаточно один канал ШИМ одного таймера. Переключаешь таймер в режим PWM разрешаешь аппаратный выход по сравнению, регистром сравнения задаешь скважность... осталось только в программе с задержкой наращивать значение скважности - это будет единственное что делает программа.
-
forfrends
- Вымогатель припоя
- Сообщения: 546
- Зарегистрирован: Вс дек 30, 2012 00:32:06
- Откуда: Николаев / Украина
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Да, код для меня тяжелый...
Просто ничего другого не нашел. Да, я так и подумал что PWM отвечает за плавное включение/отключение, но не смог в ней разобраться.
Alexeyslav, можете показать пример кода где просто загорается светодиод, без всего лишнего, просто линейный алгоритм, без прыжков туда-сюда? Что бы PWM не было функцией, а основным кодом программы. То есть, включился контроллер, светодиод плавно загорелся, и на этом все.
Помогите в этом разобраться.
Просто ничего другого не нашел. Да, я так и подумал что PWM отвечает за плавное включение/отключение, но не смог в ней разобраться.
Alexeyslav, можете показать пример кода где просто загорается светодиод, без всего лишнего, просто линейный алгоритм, без прыжков туда-сюда? Что бы PWM не было функцией, а основным кодом программы. То есть, включился контроллер, светодиод плавно загорелся, и на этом все.
Помогите в этом разобраться.
Сделать своими руками всегда интересней чем просто купить и пользоваться
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Вот собственно: [ATTINY13]
Конфигурация таймера:
Данная конфигурация делает прямой вывод OC0A, и инверсный для OC0B, если для второго выхода надо прямой - почитай даташит, по поводу регистра TCCR0A.
Макрос установка ШИМа: (оба канала получают одно и то же значение, но их можно устанавливать раздельно)
Оба ШИМ устанавливаются в значение из регистра R16.
для плавного нарастания и спада я использую такой набор подпрограмм:
Вызывается переход яркости простым алгоритмом:
"trans_light 0x00, 0xFF" - до значения "0" со скоростью 255 т.е. каждую задержку ШИМ будет изменять значение на "1" если указать скорость 128 - каждые две задержки, указать 1 - каждые 256 задержек на 1 единицу, таким образом при скорости "1" от 0 до 255 пройдет времени на 65536 заданных интервалов. При заданном интервале 1мс это будет 65 секунд. при скорости 255 - 255 милисекунд.
Защиты от скорости равной нулю нет! Поэтому осторожней - при нулевой скорости из алгоритма выхода никогда не будет.
Конфигурация таймера:
Код: Выделить всё
set_io SPL, low(RAMEND)
; установить порты ввода-вывода
set_io DDRB, 0b00011111 ; 1 - выход, 0 - вход.
; настройка таймера
;прескалер выставить на 8, Fast PWM частота будет 4.8Мгц/(8*512) ~ 1.1кГц
set_io TCCR0A, 0b10110001 ; режим таймера 01 - PWM(Phase Correct). Clear OC0A on Compare Match when up-counting.
; Set OC0A on Compare Match when down-counting.
; Set OC0B on Compare Match when up-counting.
; Clear OC0B on Compare Match when down-counting.
set_io TCCR0B, 0b00000010 ; Счетчик работает c предделителем = 8.Данная конфигурация делает прямой вывод OC0A, и инверсный для OC0B, если для второго выхода надо прямой - почитай даташит, по поводу регистра TCCR0A.
Макрос установка ШИМа: (оба канала получают одно и то же значение, но их можно устанавливать раздельно)
Код: Выделить всё
.macro set_led
set_reg ledv, R16 ; Копия в текущее значение, для последующих плавных переходов.
OUT OCR0A, R16
OUT OCR0B, R16
.endmacroОба ШИМ устанавливаются в значение из регистра R16.
для плавного нарастания и спада я использую такой набор подпрограмм:
Код: Выделить всё
.DEF LEDV = R1 ; Текущая Яркость
.DEF tmp = R11
; Счетчики в регистрах
.DEF cyclecount = R16
.DEF target = R17
.DEF speed = R18
.macro trans_light
LDI target, @0
LDI speed, @1
rcall tr_light
.endmacro
.macro actualize_led
mov accum, ledv
OUT OCR0A, ACCUM
OUT OCR0B, ACCUM
.endmacro
tr_light:
clr tmp // будет выполнять роль суб-счетчика, который будет наполнятся speed
// и по переполнению выполнятся инкремент/декремент главного значения.
tr_loop:
CP ledv, target
BREQ tr_end // значение уже равно необходимому, выходим наф
BRLO tr_inc // target оказался больше чем ledv, нужен инкремент.
tr_dec: // остался только вариант ledv > target, нужен декремент
add tmp, speed
BRCC tr_no // нет переполнения субсчетчика - не меняем яркость
DEC ledv
actualize_led
rjmp tr_no
tr_inc:
add tmp, speed
BRCC tr_no
INC ledv
actualize_led
tr_no:
rcall delay_step
rjmp tr_loop
tr_end:
RET
Вызывается переход яркости простым алгоритмом:
"trans_light 0x00, 0xFF" - до значения "0" со скоростью 255 т.е. каждую задержку ШИМ будет изменять значение на "1" если указать скорость 128 - каждые две задержки, указать 1 - каждые 256 задержек на 1 единицу, таким образом при скорости "1" от 0 до 255 пройдет времени на 65536 заданных интервалов. При заданном интервале 1мс это будет 65 секунд. при скорости 255 - 255 милисекунд.
Защиты от скорости равной нулю нет! Поэтому осторожней - при нулевой скорости из алгоритма выхода никогда не будет.
-
forfrends
- Вымогатель припоя
- Сообщения: 546
- Зарегистрирован: Вс дек 30, 2012 00:32:06
- Откуда: Николаев / Украина
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Спасибо. Буду пробовать во всем этом разобраться
Сделать своими руками всегда интересней чем просто купить и пользоваться
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Вот еще небольшой примерчик:
Здесь яркость задает переменная "Vout_mV", остальсь только вставить в главный цикл алгоритм её изменения от 0 до Vpwr_mV и загрузки в регистр OCR1A.
Спойлер
Код: Выделить всё
.include "tn2313def.inc" ; Используем ATtiny2313
.equ Vpwr_mV = 5000 ; Питание = 5000 mV
.equ Vout_mV = 3000 ; Выход = 0 - 5000 mV
; ROM ===============
.CSEG ; ROM
.org $000
rjmp RESET ; External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
reti ; INT0 Внешнее прерывание 0
reti ; INT1 Внешнее прерывание 1
reti ; TIMER1 CAPT Захват таймера/счетчика Т1
reti ; TIMER1 COMPA Совпадение «А» таймера/счетчика Т1
reti ; TIMER1 OVF Переполнение таймера/счетчика Т1
reti ; TIMER0 OVF Переполнение таймера/счетчика Т0
reti ; USART,RX USART, прием завершен
reti ; USART,UDRE Регистр данных USART пуст
reti ; USART,TX USART, передача завершена
reti ; ANA_COMP Аналоговый компаратор
reti ; PCINT Pin Change Interrupt
reti ; TIMER1 COMPB Совпадение «В» таймера/счетчика Т1
reti ; TIMER0 COMPA Timer/Counter0 Compare Match A
reti ; TIMER0 COMPB Timer/Counter0 Compare Match B
reti ; USI START USI Start Condition
reti ; USI OVERFLOW USI Overflow
reti ; EE READY EEPROM, готово
reti ; WDT OVERFLOW Watchdog Timer Overflow
; ---------- R E S E T ----------
.ORG INT_VECTORS_SIZE ; Конец таблицы прерываний
RESET:
cli
ldi r16, RAMEND ; Set Stack Pointer to top of RAM
out SPL, r16 ;
; ---------- M A I N P R O G R A M M ----------
PORTS_Init:
ldi r16, 0b00001000
out DDRB, r16
PWM_16_A_Init:
ldi r16, low(Vout_mV) ;
ldi r17,high(Vout_mV) ;
out OCR1AH, r17 ;
out OCR1AL, r16
ldi r16, low(Vpwr_mV) ;
ldi r17,high(Vpwr_mV) ;
out ICR1H, r17 ;
out ICR1L, r16
ldi r16, (0b10<<WGM10) ; Set PWM, Phase Correct mode with resolution ICR1.
ldi r17, (0b10<<WGM12) ; Set PWM, Phase Correct mode with resolution ICR1.
ori r16, (0b10<<COM1A0); Clear OC1A on Compare Match, set OC1A at ICR1
ori r17, (0b001<<CS10) ; Prescaler 001=1:1
out TCCR1A, r16 ;
out TCCR1B, r17 ; Enable TCNT1
sei
MAIN_loop:
in r16,MCUCR
ori r16, (1<<SE)
out MCUCR, r16
sleep ; Отдыхаем пока не началось
rjmp MAIN_loop ; Go again
Здесь яркость задает переменная "Vout_mV", остальсь только вставить в главный цикл алгоритм её изменения от 0 до Vpwr_mV и загрузки в регистр OCR1A.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Это конечно интересная штука, но для светодиода достаточно 8-битного ШИМа, а 16-битные таймеры всегда дефицит. Правда, там всеравно оговорок много, в частности яркость светодиода зависит нелинейно от скважности - примерно до 30% яркость меняется быстро, а дальше - едва заметно. нужна какая-то хотя-бы табличная коррекция по 16 опорным точкам.
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Экспериментальный код из заначек, написан не для светодиода, но тоже пойдет, его плюсы в том, что можно плавно менять не только скважность, но и частоту ШИМа.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Подскажите, почему моя первая простейшая программа не работает?
ATMega16, программа должна зажигать светодиод при нажатой кнопке и гасить при отпущенной.
Гоняю в AVR Studio, там всё вроде нормально, но вот в контролере тупо зажигает светодиод и всё.
Разобрался, ёклмн!
ATMega16, программа должна зажигать светодиод при нажатой кнопке и гасить при отпущенной.
Код: Выделить всё
ldi r17, 0b11111111
out ddrb, r17 ; Порт В на выход
ldi r16, 0b00000000
out ddrc, r16 ; Порт С на вход
out PortC, r17 ; Подтяжка порта С
Main:
sbic pinc, 4 ; Проверим состояние входа кнопки РС4
rjmp LEDOff ; Переход, если не нажата (на РС4 высокий уровень)
out PortB, r17 ; Включим светодиод
RJMP Main
LEDOff:
out PortB, r16 ; Выключим светодиод
rjmp MainГоняю в AVR Studio, там всё вроде нормально, но вот в контролере тупо зажигает светодиод и всё.
Разобрался, ёклмн!
Классические вилы. Порт С по дефолту работает на жтаг и потому те выводы его , что служат жтагу (TDI TDO ЕСЛ TMS) не могут использоваться как порт. Жтаг можно отключить либо фуз битами. Либо поправив регистр MCUCSR поставив там бит JTD
Последний раз редактировалось BlYur Пт июл 19, 2013 19:06:27, всего редактировалось 3 раза.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Живьем проверяете, или в симуляторе? Казалось бы, в AVR Studio несложно выявить проблему. Сходу кажется, что все хорошо.
- dr.doc
- Это не хвост, это антенна
- Сообщения: 1368
- Зарегистрирован: Вс мар 28, 2010 12:52:22
- Откуда: Беларусь
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Доброго времени суток, уважаемые коты!
Разбираясь с кодом Игоря Чешко (если правильно прочел по чешски), столкнулся со следующим:
Регистр bitcount - R21, 8-ми битный, а переменная - 16-ти. При компиляции в АВР студио 6.0 выпадает ошибка:
Error 5 Operand(s) out of range in 'ldi r21,0x8005' - на 3-ю строку
Вопрос: Как мне изменить запись, чтобы ее (ошибку) обойти. Разбивать константу не очень хочется - код ведь чужой! И почему у автора в 4-й проект компилировался?
Разбираясь с кодом Игоря Чешко (если правильно прочел по чешски), столкнулся со следующим:
ldi bitcount,CRC16poly>>8 ;do bitcount CRC polynom - vrchny byte
eor temp1,bitcount ;a urob XOR zo zvyskom a CRC polynomom - vrchny byte
ldi bitcount,CRC16poly ;do bitcount CRC polynom - spodny byte
eor temp0,bitcount ;a urob XOR zo zvyskom a CRC polynomom - spodny byte
Регистр bitcount - R21, 8-ми битный, а переменная - 16-ти. При компиляции в АВР студио 6.0 выпадает ошибка:
Error 5 Operand(s) out of range in 'ldi r21,0x8005' - на 3-ю строку
Вопрос: Как мне изменить запись, чтобы ее (ошибку) обойти. Разбивать константу не очень хочется - код ведь чужой! И почему у автора в 4-й проект компилировался?
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
ldi r21,low(0x8005)
Или high, или byte1/2/3/4 - как задумано. Полностью 16 бит в 8 не влезут ну никак.
Компилятор имеет право обрезать лишнее молча. Или обрезать с предупреждением и продолжить. Или грязно выругаться и остановиться. На усмотрение компилятора.
К.О.
Или high, или byte1/2/3/4 - как задумано. Полностью 16 бит в 8 не влезут ну никак.
Компилятор имеет право обрезать лишнее молча. Или обрезать с предупреждением и продолжить. Или грязно выругаться и остановиться. На усмотрение компилятора.
К.О.
- dr.doc
- Это не хвост, это антенна
- Сообщения: 1368
- Зарегистрирован: Вс мар 28, 2010 12:52:22
- Откуда: Беларусь
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Спасибо огромное! Уже не ругается, добавил low(CRC16poly) и все стало нормально компилироваться. Про такой прием не знал (просто начинал с PIC контроллеров).
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Просто компилятор у него был молчаливый, на самом деле обработка-то идет 16 бит, но при помощи 8-битных регистров.
CRC16poly>>8 заменить на high(CRC16poly)
а там где просто CRC16poly заменить на low(CRC16poly) это будет правильней.
CRC16poly>>8 заменить на high(CRC16poly)
а там где просто CRC16poly заменить на low(CRC16poly) это будет правильней.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Всем привет. Такой вот вопрос.
Пишу программу на асемблере для атмега88
так работает
ldi temp,0b00000001
out EIMSK,temp
а так нет
ldi temp,0b00000001
sts EIMSK,temp
почему?
Спасибо
Пишу программу на асемблере для атмега88
так работает
ldi temp,0b00000001
out EIMSK,temp
а так нет
ldi temp,0b00000001
sts EIMSK,temp
почему?
Спасибо
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Потому что когда OUT, то EIMSK=0x1d
а когда используете STS, то EIMSK должен быть 0x3d, т.е. +0x20.
а когда используете STS, то EIMSK должен быть 0x3d, т.е. +0x20.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
zero648 писал(а):Потому что когда OUT, то EIMSK=0x1d
а когда используете STS, то EIMSK должен быть 0x3d, т.е. +0x20.
а почему так происходит? я запутался в етих out и sts. если не сложно обясните пжл. если нет, даите хотсябы ссылку где детально про это написано. спасибо
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Dessp писал(а):а почему так происходит?
Потому что младшие 32 байта области данных выделены под РОН, за ними идут РВВ, за ними — SRAM.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Потому что OUT работает только с УВВ со своим диапазоном адресов, а STS работает со всей областью доступной памяти, в которую входит регистры, адреса устройств ввода-вывода, RAM. Смотри как эти адреса распределяются в общей адресации. а OUT просто адресует внутри конкретного кусочка адресов, и все УВВ с адресами меньше 0x3F объявлены в инклуднике под команду OUT, можно изменить соответствующим образом инклуд на конкретный контроллер и пользоваться только командой STS. Выигрыша в тактах - никакого.