Ассемблер (ASM) для AVR в вопросах и ответах
Re: Ассемблер (ASM) для AVR в вопросах и ответах
[uquote="siimao",url="/forum/viewtopic.php?p=3293062#p3293062"]чОт фигня получается. Кварцы использовал.[/uquote]
Я про кварц в железе, а не в каком-то симуляторе. Какой МК используешь?
Я про кварц в железе, а не в каком-то симуляторе. Какой МК используешь?
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Со скоростями все нормально - проект модифицировался из рабочего.
MK = Attiny2313, 8MHz, скорость 19200
Зачем нужен байт окончания сообщения? Идет сообщение с N байт, выполняется N прерываний с записью во флеш в итоге имеем записанными N байт. Далее анализируем сообщение по символам... В текущей версии: .., выполняется N прерываний с записью только символов, приходящих после символа ','.
Ввел защиту от переполнения, при которой после принятых/записанных 15 символов я перевожу адрес на начало секции data.
На стороне принимающего МК после начала работы постоянно сыпятся ошибки "PC=0x0000. RETI address = 0x0000". Куда копать?
MK = Attiny2313, 8MHz, скорость 19200
Зачем нужен байт окончания сообщения? Идет сообщение с N байт, выполняется N прерываний с записью во флеш в итоге имеем записанными N байт. Далее анализируем сообщение по символам... В текущей версии: .., выполняется N прерываний с записью только символов, приходящих после символа ','.
Ввел защиту от переполнения, при которой после принятых/записанных 15 символов я перевожу адрес на начало секции data.
На стороне принимающего МК после начала работы постоянно сыпятся ошибки "PC=0x0000. RETI address = 0x0000". Куда копать?
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Приведите код.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Код для принимающего МК:
.nolist ;Suppress listing of include file
.include "tn2313def.inc" ;Define chip particulars
;.include "macro.inc"
.list
; RAM ====================
.dseg
RX_Count: .byte 1 ;Значение переменной RX_Count записывается в RamStart
.equ BAUD =25
;***************************************************************************
; for 19200 bps
; 8.00MHz - BAUD=25
;***************************************************************************
.equ RamStart =96
.def temp =R16 ;Temporary storage register
.def interrupt =R17
.def txbyte =R18 ;Data to be transmitted
.def rxbyte =R19 ;Received data
.def temp2 =R20
.def temp3 =R21
.def temp4 =R22
.def temp5 =R23
.def temp6 =R24
.def temp7 =R25
; ====== Начало программного кода ====================
.cseg ; Выбор сегмента программного кода
.org 0 ; Установка текущего адреса на ноль
; ***** INTERRUPT VECTORS ************************************************
rjmp reset
reti ;INT_0 ;INT0addr = 0x0001 ; External Interrupt Request 0
rjmp INT_1 ;INT1addr = 0x0002 ; External Interrupt Request 1
reti ;ICP1addr = 0x0003 ; Timer/Counter1 Capture Event
reti ;OC1Aaddr = 0x0004 ; Timer/Counter1 Compare Match A
reti ;OVF1addr = 0x0005 ; Timer/Counter1 Overflow
reti ;OVF_0 ;OVF0addr = 0x0006 ; Timer/Counter0 Overflow
rjmp RX_OK ;URXCaddr = 0x0007 ; USART, Rx Complete
reti ;UDREaddr = 0x0008 ; USART Data Register Empty
reti ;UTXCaddr = 0x0009 ; USART, Tx Complete
reti ;ACIaddr = 0x000a ; Analog Comparator
reti ;PCIaddr = 0x000b ; Pin Change Interrupt Request 0
reti ;OC1Baddr = 0x000c ; Timer/Counter1 Compare Match B
reti ;OC0Aaddr = 0x000d ; Timer/Counter0 Compare Match A
reti ;OC0Baddr = 0x000e ; Timer/Counter0 Compare Match B
reti ;USI_STARTaddr = 0x000f ; USI Start Condition
reti ;USI_OVFaddr = 0x0010 ; USI Overflow
reti ;ERDYaddr = 0x0011 ; EEPROM Ready
reti ;WDTaddr = 0x0012 ; Watchdog Timer Overflow
reti ;PCINT1addr = 0x0013 ; Pin Change Interrupt Request 1
reti ;PCINT2addr = 0x0014 ; Pin Change Interrupt Request 2
;.org INT_VECTORS_SIZE ; Конец таблицы прерываний. Активизируется при урезанной таблице векторов,
; для резервирования памяти под будущее расширение
; ***** END INTERRUPT VECTORS ************************************************
cmd1: .db "+CMTI: ",'"',"MT",'"',',',"3225",0x0d, 0
reset:
; Setup buffers and pointers
ldi temp,RAMEND
out SPL,temp ;Init Stack Pointer
ldi temp,0b11111111 ;Все выводы порта B - на выход
out DDRB,temp
ldi temp,0b11110010 ;Все выводы порта D - на выход,
out DDRD,temp
ldi temp,0b00001101 ;Вкл подтяжку на входных выводах
out portD,temp
ldi temp,(1<<CS02)+(0<<CS01)+(1<<CS00)
out TCCR0B,temp ;Set clock to count on CK/1024
;8000000/1024=7812,5 (делим тактовую частоту МК на выбранный предделитель). 8 разрядов таймера означает, что в нем 2 в 8 степени позиций = 256.
;7812,5/256=30,52 (считаем число переполнений). Значит потребуется примерно 30 переполнений всего таймера(с 0) для достижения 1 секунды.
ldi temp,(0<<TOIE0)
out TIMSK,temp ;Disable timer 0 overflow interrupt
;ldi temp,(1<<TOIE0)
;out TIMSK,temp ;Enable timer 0 overflow interrupt
ldi temp,(0<<U2X) ;Disable Double the USART Transmission Speed
out UCSRA,temp
ldi temp,(0<<UMSEL)+(0<<USBS)+(0<<UPM0)+(0<<UPM1)+(1<<UCSZ1)+(1<<UCSZ0) ;UMSEL:USART Mode Select=async, USBS:Stop Bit Select=1, UCSZ0/1:Character Size=8 bits
out UCSRC,temp
ldi temp,(0<<UCSZ2)+(1<<TXEN)+(1<<RXEN)|(1<<RXCIE);|(1<<TXCIE)|(0<<UDRIE) ;UCSZ2:Character Size=8bits + Enable UART Tx and Rx. ; Прерывания разрешены
out UCSRB,temp
;Используем все три прерывания. По приему, по опустошению буфера и по окончании передачи.
;Но пока разрешаем только два — по приему и по передаче. Иначе при старте мы сразу же ускачем на обработчик UDRIE — буфер то пуст!
ldi temp,BAUD
out UBRRL,temp ;Set baud rate generator=UBRR
ldi temp,(0<<ISC00)+(1<<ISC01)+(0<<ISC10)+(0<<ISC11) ;Set INT0 on the falling edge and INT1 on the rising edge
out MCUCR,temp
ldi temp,(1<<INT0)+(1<<INT1) ;Set INT0 and INT1 interrupt enable
out GIMSK,temp
ldi temp,(1<<INTF0)+(1<<INTF1) ;Clear external interrup flags
out EIFR,temp
; <<<<<<<<<<<<<<<<<<< End Internal Hardware Init >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Main =====================
Main:
sei
NOP ; Любой произвольный код главной программы
NOP
NOP
;После чего спокойно выполняем любой другой код.
rjmp Main
;========
; Подпрограмма прерываний по кнопке отправки смс
;========
INT_0: ;INT0 interrupt
ldi zl,low(cmd1*2)
ldi zh,high(cmd1*2)
rcall send_command ;Send +CMTI: "MT",3225
reti
;========
; Подпрограмма проверки сохранения смс
;========
INT_1: ;INT0 interrupt
;??????? Проверка факта записи ????????????????????????????????
ldi temp,4 ;Read 4 bytes of RAM
ldi YL,RamStart+1 ;It is the first byte of RAM
clr YH
Read_more:
ld txbyte,Y+ ;3225 from +CMTI: "MT",3225
rcall b_transmit
dec temp
brne Read_more
reti
;========
; Подпрограмма прерываний по приему байта в usart
;========
RX_OK:
cli
clr XH
ldi XL,RamStart+1 ;Адрес RAM куда складываем строку
lds temp,RX_Count ;Скопируем смещение
add XL,temp ;Прибавляем смещение к адресу RAM
ldi temp2,4 ;Write 4 bytes from UART (+CMTI: "MT",3225) to ram
again:
rcall receive
cpi rxbyte,',' ;Ignore all till comma
brne again
uart2ram:
rcall receive
st X,rxbyte
inc temp
cpi temp,15
brlo loop
ldi temp,0
loop:
sts RX_Count,temp
dec temp2 ;Is temp2 zero ?
brne uart2ram ;If not, read next byte
reti
;=======================
; Receiving routine
;=======================
receive:
sei ;Set Enable Interrupts. ALT:= sbi UCSRB, RXCIE
rec_loop:
sbis UCSRA,RXC
rjmp rec_loop
cli ;Clear Interrupts. ALT:= cbi UCSRB, RXCIE
in rxbyte,UDR
ret
;=======================
; Transmiting routine
;=======================
b_transmit:
sbis UCSRA,UDRE ;Is UART transmitter ready?
rjmp b_transmit
out UDR,txbyte ;Sent out char
ret
send_command:
cli
lpm
tst r0 ;Check if its the last character (the zero)
breq return ;If yes, return.
mov txbyte,r0
rcall b_transmit
adiw zl,1 ;Increase zl
rjmp send_command ;Read next character from flash memory
return:
ret
.nolist ;Suppress listing of include file
.include "tn2313def.inc" ;Define chip particulars
;.include "macro.inc"
.list
; RAM ====================
.dseg
RX_Count: .byte 1 ;Значение переменной RX_Count записывается в RamStart
.equ BAUD =25
;***************************************************************************
; for 19200 bps
; 8.00MHz - BAUD=25
;***************************************************************************
.equ RamStart =96
.def temp =R16 ;Temporary storage register
.def interrupt =R17
.def txbyte =R18 ;Data to be transmitted
.def rxbyte =R19 ;Received data
.def temp2 =R20
.def temp3 =R21
.def temp4 =R22
.def temp5 =R23
.def temp6 =R24
.def temp7 =R25
; ====== Начало программного кода ====================
.cseg ; Выбор сегмента программного кода
.org 0 ; Установка текущего адреса на ноль
; ***** INTERRUPT VECTORS ************************************************
rjmp reset
reti ;INT_0 ;INT0addr = 0x0001 ; External Interrupt Request 0
rjmp INT_1 ;INT1addr = 0x0002 ; External Interrupt Request 1
reti ;ICP1addr = 0x0003 ; Timer/Counter1 Capture Event
reti ;OC1Aaddr = 0x0004 ; Timer/Counter1 Compare Match A
reti ;OVF1addr = 0x0005 ; Timer/Counter1 Overflow
reti ;OVF_0 ;OVF0addr = 0x0006 ; Timer/Counter0 Overflow
rjmp RX_OK ;URXCaddr = 0x0007 ; USART, Rx Complete
reti ;UDREaddr = 0x0008 ; USART Data Register Empty
reti ;UTXCaddr = 0x0009 ; USART, Tx Complete
reti ;ACIaddr = 0x000a ; Analog Comparator
reti ;PCIaddr = 0x000b ; Pin Change Interrupt Request 0
reti ;OC1Baddr = 0x000c ; Timer/Counter1 Compare Match B
reti ;OC0Aaddr = 0x000d ; Timer/Counter0 Compare Match A
reti ;OC0Baddr = 0x000e ; Timer/Counter0 Compare Match B
reti ;USI_STARTaddr = 0x000f ; USI Start Condition
reti ;USI_OVFaddr = 0x0010 ; USI Overflow
reti ;ERDYaddr = 0x0011 ; EEPROM Ready
reti ;WDTaddr = 0x0012 ; Watchdog Timer Overflow
reti ;PCINT1addr = 0x0013 ; Pin Change Interrupt Request 1
reti ;PCINT2addr = 0x0014 ; Pin Change Interrupt Request 2
;.org INT_VECTORS_SIZE ; Конец таблицы прерываний. Активизируется при урезанной таблице векторов,
; для резервирования памяти под будущее расширение
; ***** END INTERRUPT VECTORS ************************************************
cmd1: .db "+CMTI: ",'"',"MT",'"',',',"3225",0x0d, 0
reset:
; Setup buffers and pointers
ldi temp,RAMEND
out SPL,temp ;Init Stack Pointer
ldi temp,0b11111111 ;Все выводы порта B - на выход
out DDRB,temp
ldi temp,0b11110010 ;Все выводы порта D - на выход,
out DDRD,temp
ldi temp,0b00001101 ;Вкл подтяжку на входных выводах
out portD,temp
ldi temp,(1<<CS02)+(0<<CS01)+(1<<CS00)
out TCCR0B,temp ;Set clock to count on CK/1024
;8000000/1024=7812,5 (делим тактовую частоту МК на выбранный предделитель). 8 разрядов таймера означает, что в нем 2 в 8 степени позиций = 256.
;7812,5/256=30,52 (считаем число переполнений). Значит потребуется примерно 30 переполнений всего таймера(с 0) для достижения 1 секунды.
ldi temp,(0<<TOIE0)
out TIMSK,temp ;Disable timer 0 overflow interrupt
;ldi temp,(1<<TOIE0)
;out TIMSK,temp ;Enable timer 0 overflow interrupt
ldi temp,(0<<U2X) ;Disable Double the USART Transmission Speed
out UCSRA,temp
ldi temp,(0<<UMSEL)+(0<<USBS)+(0<<UPM0)+(0<<UPM1)+(1<<UCSZ1)+(1<<UCSZ0) ;UMSEL:USART Mode Select=async, USBS:Stop Bit Select=1, UCSZ0/1:Character Size=8 bits
out UCSRC,temp
ldi temp,(0<<UCSZ2)+(1<<TXEN)+(1<<RXEN)|(1<<RXCIE);|(1<<TXCIE)|(0<<UDRIE) ;UCSZ2:Character Size=8bits + Enable UART Tx and Rx. ; Прерывания разрешены
out UCSRB,temp
;Используем все три прерывания. По приему, по опустошению буфера и по окончании передачи.
;Но пока разрешаем только два — по приему и по передаче. Иначе при старте мы сразу же ускачем на обработчик UDRIE — буфер то пуст!
ldi temp,BAUD
out UBRRL,temp ;Set baud rate generator=UBRR
ldi temp,(0<<ISC00)+(1<<ISC01)+(0<<ISC10)+(0<<ISC11) ;Set INT0 on the falling edge and INT1 on the rising edge
out MCUCR,temp
ldi temp,(1<<INT0)+(1<<INT1) ;Set INT0 and INT1 interrupt enable
out GIMSK,temp
ldi temp,(1<<INTF0)+(1<<INTF1) ;Clear external interrup flags
out EIFR,temp
; <<<<<<<<<<<<<<<<<<< End Internal Hardware Init >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Main =====================
Main:
sei
NOP ; Любой произвольный код главной программы
NOP
NOP
;После чего спокойно выполняем любой другой код.
rjmp Main
;========
; Подпрограмма прерываний по кнопке отправки смс
;========
INT_0: ;INT0 interrupt
ldi zl,low(cmd1*2)
ldi zh,high(cmd1*2)
rcall send_command ;Send +CMTI: "MT",3225
reti
;========
; Подпрограмма проверки сохранения смс
;========
INT_1: ;INT0 interrupt
;??????? Проверка факта записи ????????????????????????????????
ldi temp,4 ;Read 4 bytes of RAM
ldi YL,RamStart+1 ;It is the first byte of RAM
clr YH
Read_more:
ld txbyte,Y+ ;3225 from +CMTI: "MT",3225
rcall b_transmit
dec temp
brne Read_more
reti
;========
; Подпрограмма прерываний по приему байта в usart
;========
RX_OK:
cli
clr XH
ldi XL,RamStart+1 ;Адрес RAM куда складываем строку
lds temp,RX_Count ;Скопируем смещение
add XL,temp ;Прибавляем смещение к адресу RAM
ldi temp2,4 ;Write 4 bytes from UART (+CMTI: "MT",3225) to ram
again:
rcall receive
cpi rxbyte,',' ;Ignore all till comma
brne again
uart2ram:
rcall receive
st X,rxbyte
inc temp
cpi temp,15
brlo loop
ldi temp,0
loop:
sts RX_Count,temp
dec temp2 ;Is temp2 zero ?
brne uart2ram ;If not, read next byte
reti
;=======================
; Receiving routine
;=======================
receive:
sei ;Set Enable Interrupts. ALT:= sbi UCSRB, RXCIE
rec_loop:
sbis UCSRA,RXC
rjmp rec_loop
cli ;Clear Interrupts. ALT:= cbi UCSRB, RXCIE
in rxbyte,UDR
ret
;=======================
; Transmiting routine
;=======================
b_transmit:
sbis UCSRA,UDRE ;Is UART transmitter ready?
rjmp b_transmit
out UDR,txbyte ;Sent out char
ret
send_command:
cli
lpm
tst r0 ;Check if its the last character (the zero)
breq return ;If yes, return.
mov txbyte,r0
rcall b_transmit
adiw zl,1 ;Increase zl
rjmp send_command ;Read next character from flash memory
return:
ret
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Фактом приема байта по флагу RxC с одновременным сбросом оного является чтение UDR. Вы в обработчике зацикливаетесь, потому что флаг не сброшен чтением.
Код: Выделить всё
;========
; Подпрограмма прерываний по приему байта в usart
;========
RX_OK:
in rxbyte,UDR
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Уважаемый akl! наверное найду как это делать, но буду долго разбираться.. Можете парой слов подсказать?
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Как то так вижу прием.
Есть ещё несколько предложений по более строгой инициализации
Спойлер
Код: Выделить всё
;========
; Подпрограмма прерываний по приему байта в usart
;========
RX_OK:
again:
rcall receive
cpi rxbyte,',' ;0x2C Ignore all till comma
brne again
clr XH
ldi XL,RamStart+1 ;Адрес RAM куда складываем строку
lds temp,RX_Count ;Скопируем смещение
add XL,temp ;Прибавляем смещение к адресу RAM
ldi temp2,4 ;Write 4 bytes from UART (+CMTI: "MT",3225) to ram
uart2ram:
rcall receive
st X+,rxbyte
inc temp
cpi temp,15
brlo loop
ldi temp,0
loop:
sts RX_Count,temp
dec temp2 ;Is temp2 zero ?
brne uart2ram ;If not, read next byte
reti
;=======================
; Receiving routine
;=======================
receive:
;sei ;Set Enable Interrupts. ALT:= sbi UCSRB, RXCIE
rec_loop:
sbis UCSRA,RXC
rjmp rec_loop
;cli ;Clear Interrupts. ALT:= cbi UCSRB, RXCIE
in rxbyte,UDR
ret
;=======================
; Transmiting routineСпойлер
Код: Выделить всё
ldi temp,(1<<CS02)+(0<<CS01)+(1<<CS00)
out TCCR0B,temp ;Set clock to count on CK/1024
;8000000/1024=7812,5 (делим тактовую частоту МК на выбранный предделитель). 8 разрядов таймера означает, что в нем 2 в 8 степени позиций = 256.
;7812,5/256=30,52 (считаем число переполнений). Значит потребуется примерно 30 переполнений всего таймера(с 0) для достижения 1 секунды.
;ldi temp,(0<<TOIE0)
;out TIMSK,temp ;Disable timer 0 overflow interrupt
LDI R16,0
STS RX_Count,R16
OUT UBRRH,R16
ldi temp,BAUD
out UBRRL,temp ;Set baud rate generator=UBRR
;ldi temp,(1<<TOIE0)
;out TIMSK,temp ;Enable timer 0 overflow interrupt
;ldi temp,(0<<U2X) ;Disable Double the USART Transmission Speed
;out UCSRA,temp
;ldi temp,(0<<UMSEL)+(0<<USBS)+(0<<UPM0)+(0<<UPM1)+(1<<UCSZ1)+(1<<UCSZ0) ;UMSEL:USART Mode Select=async, USBS:Stop Bit Select=1, UCSZ0/1:Character Size=8 bits
;out UCSRC,temp
ldi temp,(0<<UCSZ2)+(1<<TXEN)+(1<<RXEN)|(1<<RXCIE);|(1<<TXCIE)|(0<<UDRIE) ;UCSZ2:Character Size=8bits + Enable UART Tx and Rx. ; Прерывания разрешены
out UCSRB,temp
NOP
IN R0,UDR ; псевдочтение для сброса флага приёма
SBI UCSRB,TxC ; сброс флага передатчика
;Используем все три прерывания. По приему, по опустошению буфера и по окончании передачи.
;Но пока разрешаем только два — по приему и по передаче.
; Иначе при старте мы сразу же ускачем на обработчик UDRIE — буфер то пуст!
ldi temp,(0<<ISC00)+(1<<ISC01)+(0<<ISC10)+(0<<ISC11) ;Set INT0 on the falling edge and INT1 on the rising edge
out MCUCR,tempRe: Ассемблер (ASM) для AVR в вопросах и ответах
akl, спасибо тебе огромное!!!!!!
Работает (пока проверял первый вариант), но как-то не так как хотелось. Для формулирования надо набрать статистику... Но результату отпишу. Хороших выходных!!!
Добавлено after 55 minutes 1 second:
Первый вариант в протеус работает след.образом:
Независимо от количества ПЕРЕДАЧ сообщений из U3-GENERATOR (по прерыванию по кнопке 1), на U1-RECEIVER могу проверить запись ЧТЕНИЕМ символов отправкой сообщения по усарт (по прерыванию по кнопке 2) только в таком порядке:
Нажатие кнопок Кн1->Кн2->Кн1.
Причем триггером является переход Кн2 -> Кн1 и тогда передается от U1-RECIVER четыре символа. Т.е. не зависимо от количества нажатий первый раз кнопки Кн1 и кнопки Кн2.
NxКн1->MxКн2->Кн1.
Работает (пока проверял первый вариант), но как-то не так как хотелось. Для формулирования надо набрать статистику... Но результату отпишу. Хороших выходных!!!
Добавлено after 55 minutes 1 second:
Первый вариант в протеус работает след.образом:
Независимо от количества ПЕРЕДАЧ сообщений из U3-GENERATOR (по прерыванию по кнопке 1), на U1-RECEIVER могу проверить запись ЧТЕНИЕМ символов отправкой сообщения по усарт (по прерыванию по кнопке 2) только в таком порядке:
Нажатие кнопок Кн1->Кн2->Кн1.
Причем триггером является переход Кн2 -> Кн1 и тогда передается от U1-RECIVER четыре символа. Т.е. не зависимо от количества нажатий первый раз кнопки Кн1 и кнопки Кн2.
NxКн1->MxКн2->Кн1.
- Вложения
-
- ПРОТЕУС.png
- (110.8 КБ) 435 скачиваний
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Обоги... эту программу уже НИЧТО не спасёт. В прерывании кто будет сохранять регистры и регистр статуса? ВАМ ТОЧНО нужно разрешать прерывания в прерывании? У вас сами обработчики не реентерабельные, поэтому вообще плохая идея в прерывании разрешать другие прерывания. Это не для начинающих магия. А уж темболее чего-то ждать в прерывании.
Классическое "RETI address = 0x0000" означает с 99% вероятностью разрушение/переполнение стека, и что-то мне подсказывает что это из-за разрешения прерываний в прерывании. На живом контроллере это будет равносильно его сбросу.
Советую пересмотреть подход к программе и переписать её, иначе удивительные открытия у вас ещё в переди. Изменение регистров, а темболее регистра статуса в прерывании это очен коварная штука. Поскольку прерывание может возникнуть в любой момент у вас программа бует странным образом глючить то там то там, выполняться "невозможные" ветки кода и т.п. Главное что это будет носить довольно таки случайный характер и выловить истинную проблему будет очень сложно.
Классическое "RETI address = 0x0000" означает с 99% вероятностью разрушение/переполнение стека, и что-то мне подсказывает что это из-за разрешения прерываний в прерывании. На живом контроллере это будет равносильно его сбросу.
Советую пересмотреть подход к программе и переписать её, иначе удивительные открытия у вас ещё в переди. Изменение регистров, а темболее регистра статуса в прерывании это очен коварная штука. Поскольку прерывание может возникнуть в любой момент у вас программа бует странным образом глючить то там то там, выполняться "невозможные" ветки кода и т.п. Главное что это будет носить довольно таки случайный характер и выловить истинную проблему будет очень сложно.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
попытался завести на аттини 2313 два таймера, и не могу понять что у меня получилось. Один работает нормально: Т0 в норм режиме и прерывание по переполнению (канал А), а второй должен тикать 2 раза в сек а осцилограф выдает какую то фигню (канал Б)
код:
; Main.asm file generated by New Project wizard
;
; Created: Чт апр 20 2017
; Processor: ATtiny2313
; Compiler: AVRASM (Proteus)
;==============
;==============
; DEFINITIONS
;==============
.def Temp=R16
.def Temp1=R17
.def Temp2=R18
.def second=R19
.def count=R20 ;
.def flags=R21 ;0-флаг прерывания,1-нажата кнопка
.def shift=R22 ;данные для вывода в послед порт
.def shift1=R23 ;
.def shift2=R24 ;
.dseg
Key: .byte 4
Time: .byte 2
Day: .byte 1
Data: .byte 1
Month: .byte 1
Digit: .byte 4
.cseg
.org 0
rjmp Reset ;вектора прерываний
rjmp INT_0
rjmp INT_1
rjmp Timer1_capt1
rjmp Timer1_comp1
rjmp Timer1_OVF1
rjmp Timer0_OVF0
rjmp UART_RX
rjmp UART_UDRE
rjmp UART_TX
rjmp ANA_COMP
;Reset:
INT_0:
INT_1:
Timer1_capt1:
;Timer1_comp1:
Timer1_OVF1:
;Timer0_OVF0:
UART_RX:
UART_UDRE:
UART_TX:
ANA_COMP:
reti
;****************************************************
; ИНИЦИАЛИЗАЦИЯ
;****************************************************
Reset: ldi Temp,0b11111111 ;настройка портов
out DDRB,Temp
ldi Temp,0b11111111
out DDRD,Temp
ldi Temp,0b01000010 ;разрешить прерывание компаратора таймера 1
out TIMSK,Temp ;и переполнение таймера 0
ldi Temp,0b00000010 ;таймер 0 запускаем
out TCCR0B,Temp ;с делитетлем на 8
ldi Temp,0b00000010 ;инициализация таймера 1
out TCCR1B,Temp ;с делителем на 8
ldi Temp,0x7A ;инициализация компаратора
out OCR1AH,Temp
ldi Temp,0x12
out OCR1AL,Temp
ldi Temp,RamEnd ;установка указателя стека
out SPL,Temp
ldi Temp,0 ;обнуление таймера
out TCNT1H,Temp
out TCNT1L,Temp
clr Count
sts Time,Temp
sts Time+1,Temp
sts Key,Temp
sts Key+1,Temp
sei ;разрешить прерывания
rjmp main
;****************************************************
; Обработчик прерывания
;****************************************************
Timer1_comp1: in R15,sreg ;
cli
ldi Temp,0 ;обнуление таймера
out TCNT1H,Temp
out TCNT1L,Temp
com temp1
sbrc temp1,1
cbi pind,1
sbrs temp1,1
sbi pind,1
exit_comp:
out sreg,R15
sei
reti
;==============
; Прерывание по переполнению
;==============
Timer0_OVF0: in R15,sreg ;что бы их не изменить в ходе обработки прерывания
cli
com temp2
sbrc temp2,0
cbi pind,0
sbrs temp2,0
sbi pind,0
exit_ovf:
out sreg,R15
sei
reti
;==============
; Основной цыкл программы
;==============
main:
rjmp main
Спойлер
;==============; Main.asm file generated by New Project wizard
;
; Created: Чт апр 20 2017
; Processor: ATtiny2313
; Compiler: AVRASM (Proteus)
;==============
;==============
; DEFINITIONS
;==============
.def Temp=R16
.def Temp1=R17
.def Temp2=R18
.def second=R19
.def count=R20 ;
.def flags=R21 ;0-флаг прерывания,1-нажата кнопка
.def shift=R22 ;данные для вывода в послед порт
.def shift1=R23 ;
.def shift2=R24 ;
.dseg
Key: .byte 4
Time: .byte 2
Day: .byte 1
Data: .byte 1
Month: .byte 1
Digit: .byte 4
.cseg
.org 0
rjmp Reset ;вектора прерываний
rjmp INT_0
rjmp INT_1
rjmp Timer1_capt1
rjmp Timer1_comp1
rjmp Timer1_OVF1
rjmp Timer0_OVF0
rjmp UART_RX
rjmp UART_UDRE
rjmp UART_TX
rjmp ANA_COMP
;Reset:
INT_0:
INT_1:
Timer1_capt1:
;Timer1_comp1:
Timer1_OVF1:
;Timer0_OVF0:
UART_RX:
UART_UDRE:
UART_TX:
ANA_COMP:
reti
;****************************************************
; ИНИЦИАЛИЗАЦИЯ
;****************************************************
Reset: ldi Temp,0b11111111 ;настройка портов
out DDRB,Temp
ldi Temp,0b11111111
out DDRD,Temp
ldi Temp,0b01000010 ;разрешить прерывание компаратора таймера 1
out TIMSK,Temp ;и переполнение таймера 0
ldi Temp,0b00000010 ;таймер 0 запускаем
out TCCR0B,Temp ;с делитетлем на 8
ldi Temp,0b00000010 ;инициализация таймера 1
out TCCR1B,Temp ;с делителем на 8
ldi Temp,0x7A ;инициализация компаратора
out OCR1AH,Temp
ldi Temp,0x12
out OCR1AL,Temp
ldi Temp,RamEnd ;установка указателя стека
out SPL,Temp
ldi Temp,0 ;обнуление таймера
out TCNT1H,Temp
out TCNT1L,Temp
clr Count
sts Time,Temp
sts Time+1,Temp
sts Key,Temp
sts Key+1,Temp
sei ;разрешить прерывания
rjmp main
;****************************************************
; Обработчик прерывания
;****************************************************
Timer1_comp1: in R15,sreg ;
cli
ldi Temp,0 ;обнуление таймера
out TCNT1H,Temp
out TCNT1L,Temp
com temp1
sbrc temp1,1
cbi pind,1
sbrs temp1,1
sbi pind,1
exit_comp:
out sreg,R15
sei
reti
;==============
; Прерывание по переполнению
;==============
Timer0_OVF0: in R15,sreg ;что бы их не изменить в ходе обработки прерывания
cli
com temp2
sbrc temp2,0
cbi pind,0
sbrs temp2,0
sbi pind,0
exit_ovf:
out sreg,R15
sei
reti
;==============
; Основной цыкл программы
;==============
main:
rjmp main
Если я чего-то не знаю, это не говорит о моем невежестве, а только о том, что раньше этот вопрос лежал вне сферы моих интересов.
- dr.doc
- Это не хвост, это антенна
- Сообщения: 1368
- Зарегистрирован: Вс мар 28, 2010 12:52:22
- Откуда: Беларусь
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Канал Б измеряет переменную составляющую. Именно так и должен выглядеть НЧ прямоугольный сигнал.
Запрет прерываний происходит АППАРАТНО при входе на вектор прерываний, поэтому в векторе их запрещать не надо. Тоже самое происходит при выходе (разрешение прерываний).
Запрет прерываний происходит АППАРАТНО при входе на вектор прерываний, поэтому в векторе их запрещать не надо. Тоже самое происходит при выходе (разрешение прерываний).
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Jetetex Выберите входы A и B DC. 2 раза в секунду прерывания OC1A будут при частоте тактирования 500кГц.
[uquote="dr.doc",url="/forum/viewtopic.php?p=3295150#p3295150"]Запрет прерываний происходит АППАРАТНО при входе на вектор прерываний, поэтому в векторе их запрещать не надо. Тоже самое происходит при выходе (разрешение прерываний).[/uquote]Уточню. При выходе по RETI да.
[uquote="dr.doc",url="/forum/viewtopic.php?p=3295150#p3295150"]Запрет прерываний происходит АППАРАТНО при входе на вектор прерываний, поэтому в векторе их запрещать не надо. Тоже самое происходит при выходе (разрешение прерываний).[/uquote]Уточню. При выходе по RETI да.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
[uquote="akl",url="/forum/viewtopic.php?p=3293298#p3293298"]Как то так вижу прием.[/uquote]
Уважаемый akl, проверено в протеусе с отсылкой команды через терминал. Первый вариант работоспособен. При работе двух МК в протеус глюки, наверное, объясняются проблемой в протеус.
Второй пока не проверял.
Спасибо прЕОгромное!!!!
Уважаемый akl, проверено в протеусе с отсылкой команды через терминал. Первый вариант работоспособен. При работе двух МК в протеус глюки, наверное, объясняются проблемой в протеус.
Второй пока не проверял.
Спасибо прЕОгромное!!!!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
это только у меня gavrasm (свежий, v.37) не видит XH,XL,YH,YL,ZH,ZL ?
странно, что более ранние версии нормально понимали, например v.25
а в добавок -
свистопляска прописи ворда - и R25:R24, и R25:24, и даже тупо R24
З.Ы.ну когда уже весна нафик
странно, что более ранние версии нормально понимали, например v.25
а в добавок -
свистопляска прописи ворда - и R25:R24, и R25:24, и даже тупо R24
З.Ы.ну когда уже весна нафик
..всего две 6Ф1П, включенные последовательно,
высушат обое ваших сапог даже в автомобиле..
высушат обое ваших сапог даже в автомобиле..
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Чем AVR-Studio не нравится? Или IAR. Зачем вам экзотика?
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Ассемблер видит то, что прописано в *.inc файлах.
Возможно в новой версии где-то "очепятались".
Или используется файл от старых версий (проблемы совместимости).

"ПОДАРКИ" от микрощип-атмел:
http://radiokot.ru/forum/viewtopic.php? ... 0#p3299980

Возможно в новой версии где-то "очепятались".
Или используется файл от старых версий (проблемы совместимости).
"ПОДАРКИ" от микрощип-атмел:
http://radiokot.ru/forum/viewtopic.php? ... 0#p3299980
Re: Ассемблер (ASM) для AVR в вопросах и ответах
не знаю... нравится когда открытые исходники,Demiurg писал(а):...Зачем вам экзотика?
да и список поддерживаемых микрух неплохой
Спойлер

..всего две 6Ф1П, включенные последовательно,
высушат обое ваших сапог даже в автомобиле..
высушат обое ваших сапог даже в автомобиле..
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Компилятор поддерживает базовую систему команд ядра.
Дополнительные особенности обеспечивают файлы с указанием/объявлением расширенного функционала.
Тот же результат можно получить написав собственный файлик с такими определениями.
Другое дело симулятор или программатор (софт-оболочка). В основном проблемы применения МК в них и упираются - программатор хош и можно самому сочинить, но ради единичного случая такое сооружать долго и накладно.
Переписывать/дополнять компилятор как-то... Лучше для начала досконально его изучить в том виде, который имеется, а уж потом чего мудрить (это относительно "открытых исходников").
Лучше хорошо построенное описание правил работы/синтаксиса компилятора... и предпочтительно владение несколькими "дружественно-подобными" для различных семейств...
Дык вроде как микрочип/атмел постарался немного над юзерс гвиде avrasm2 для народопользователя:
http://radiokot.ru/forum/download/file.php?id=303044

Дополнительные особенности обеспечивают файлы с указанием/объявлением расширенного функционала.
Тот же результат можно получить написав собственный файлик с такими определениями.
Другое дело симулятор или программатор (софт-оболочка). В основном проблемы применения МК в них и упираются - программатор хош и можно самому сочинить, но ради единичного случая такое сооружать долго и накладно.
Переписывать/дополнять компилятор как-то... Лучше для начала досконально его изучить в том виде, который имеется, а уж потом чего мудрить (это относительно "открытых исходников").
Лучше хорошо построенное описание правил работы/синтаксиса компилятора... и предпочтительно владение несколькими "дружественно-подобными" для различных семейств...
Дык вроде как микрочип/атмел постарался немного над юзерс гвиде avrasm2 для народопользователя:
http://radiokot.ru/forum/download/file.php?id=303044
- Гефестион
- Поставщик валерьянки для Кота
- Сообщения: 2022
- Зарегистрирован: Вт фев 09, 2010 02:04:53
- Откуда: Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Продолжаю писать программу для бегущей строки. И столкнулся с каким-то непонятным глюком.
Есть вот такой простой кусок кода (это конец обработчика прерываний по таймеру)
Первая часть кода, которая увеличивает значение ArrCtrOffset, заработала сразу. Читаем из ОЗУ значение ArrCtrOffset в регистр R21, инкрементируем, сохраняем обратно в ОЗУ. Но как выяснилось позже, заработала только потому, что R21 больше нигде не используется. Если взять другой регистр (R16, R17, R18), то начинается какая-то хрень. Сначала взял R16 - значение ReadOffset вообще не инкрементируется (или не сохраняется в ОЗУ?), с R18 то же самое, с R17 вообще знакогенератор стал выдавать крякозябры вместо букв. Вторая половина этого кода, которая изменяет значение ReadOffset, сначала никак не хотела работать, поскольку я пробовал регистры R16, R17, R18. И только когда взял нигде больше не используемый R25, всё заработало (хотя и не совсем как надо).
На первый взгляд кажется, что проблема очевидна - я изменяю содержимое указанных регистров, а они ведь где-то используются. Да, используются, но в начале подпрограммы (обработчик прерываний по таймеру) идёт загрузка в эти регистры из ОЗУ
Переменные Read, ReadOffset, ArrCtrOffset объявлены в самом начале (до таблицы векторов прерываний) по 1 байту на каждую. BuffSize - константа, равная 32, тоже объявлена в начале.
Далее идёт работа с этими регистрами, но никакой записи обратно в ОЗУ! И только в самом конце подпрограммы надо инкрементировать их значения и сохранить в ОЗУ. Да и в любом случае, в начале обработчика прерываний R16, R17, R18 сохраняются в стек, а в конце извлекаются, т.е. это локальные переменные.
Такое ощущение, что запись регистров в ОЗУ и извлечение оттуда вообще не работает, а работа идёт только напрямую с регистрами. Не могу понять, почему так
Добавлено after 7 minutes 15 seconds:
При этом когда я изменял значения ReadOffset, ArrCtrOffset в обработчике другого прерывания - INT0 (при вращении энкодера), всё работало. Т.е. тогда прокрутка текста была вручную.
Есть вот такой простой кусок кода (это конец обработчика прерываний по таймеру)
Код: Выделить всё
lds R21,ArrCtrOffset
inc R21 ; Увеличиваем ArrayCounterOffset
cpi R21,6
brne Exit
clr R21
lds R25,ReadOffset
inc R25 ; Увеличиваем ReadOffset
cpi R25,BuffSize
brne Exit
clr R25
Exit: sts ArrCtrOffset,R21
sts ReadOffset,R25
pop XH
pop XL
pop R19
pop R18
pop R17
pop R16
out SREG,R16
pop R16На первый взгляд кажется, что проблема очевидна - я изменяю содержимое указанных регистров, а они ведь где-то используются. Да, используются, но в начале подпрограммы (обработчик прерываний по таймеру) идёт загрузка в эти регистры из ОЗУ
Код: Выделить всё
lds R18,Read ; Берём точку чтения
lds R16,ReadOffset ; Берём смещение точки чтения
lds R21,ArrCtrOffset ; Берём смещение счётчика массиваДалее идёт работа с этими регистрами, но никакой записи обратно в ОЗУ! И только в самом конце подпрограммы надо инкрементировать их значения и сохранить в ОЗУ. Да и в любом случае, в начале обработчика прерываний R16, R17, R18 сохраняются в стек, а в конце извлекаются, т.е. это локальные переменные.
Такое ощущение, что запись регистров в ОЗУ и извлечение оттуда вообще не работает, а работа идёт только напрямую с регистрами. Не могу понять, почему так
Добавлено after 7 minutes 15 seconds:
При этом когда я изменял значения ReadOffset, ArrCtrOffset в обработчике другого прерывания - INT0 (при вращении энкодера), всё работало. Т.е. тогда прокрутка текста была вручную.
Фак, кот грызёт провод! Сейчас его ударит либо током, либо тапком! ))
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Если хрень по вине куска кода в прерывании, то причины:
Не сохраняется SREG.
Не сохраняются регистры, используемые в прерывании.
В обработчике прерывания ошибка.
Основной код и обработчик не корректно работают по временным параметрам.
Пользуйтесь симулятором в студии для отладки программ.
Не сохраняется SREG.
Не сохраняются регистры, используемые в прерывании.
В обработчике прерывания ошибка.
Основной код и обработчик не корректно работают по временным параметрам.
Пользуйтесь симулятором в студии для отладки программ.