Ассемблер (ASM) для AVR в вопросах и ответах
- Сообщения: 473
- Зарегистрирован: Ср янв 11, 2012 18:20:26
У меня этот даташитовский код работает на ура. Лишь вместо r16 в цикле Wait_Transmit я r15 применяю.
- Реклама
- Сообщения: 1495
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Код: Выделить всё
.nolist
.include "m328pdef.inc"
.list
//==================
.equ SPIDIV4=0
.equ SPIDIV16=1
.equ SPIDIV64=2
.equ SPIDIV128=3
.equ hSPIE=1<<SPIE
.equ hSPE=1<<SPE
.equ hDORD=1<<DORD
.equ hMSTR=1<<MSTR
.equ hCPOL=1<<CPOL
.equ hCHAP=1<<CPHA
rjmp Reset
Reset:
sbi DDRB, 3
L0:ldi r16,hSPE | hMSTR | SPiDIV64
out SPCR,r16
ldi r17,10
L1:ldi r16,0xFF
out SPDR,r16
L2:in r16, SPSR
sbrs r16, SPIF
rjmp L2
in r16, SPDR // Сброс флага SPIF.
dec r17
brne L1
Main:
wdr
rjmp Main
//==================
Угу, косяк. Но в примере кода в ДШ этого тоже нет, так, что косяк не совсем мой. Но да, не до конца вник в это чудо - аппаратный SPI.Demiurg писал(а):1- А сбрасывать флаг SPIF кто будет?
Давно не программировал на асме, подзабыл, что там не так с флагами у команды DEC, разбираться еще и с этим поленился, а длина и количество тактов у DEC и SUBI одинаковы. Да, DEC работает со всеми регистрами, в отличие от SUBI, но "для попробовать" регистров и так выше крыши, а боевую программу все равно надо будет делать в прерываниях, т.е. писать заново...Demiurg писал(а):2 - Вы оригинал? На куа subi вместо dec?!
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
- Сообщения: 473
- Зарегистрирован: Ср янв 11, 2012 18:20:26
[uquote="Demiurg",url="/forum/viewtopic.php?p=3882329#p3882329"]1- А сбрасывать флаг SPIF кто будет?[/uquote]
Теперь мне ничего не понятно. Зачем его сбрасывать? Я не сбрасываю и всё работает.
И эту строку вообще не использую:
PS
И ещё в этой теме уже рассматривалось о сбросе флага:
https://radiokot.ru/forum/viewtopic.php?f=57&t=148266
"Отсутствие данных в SPDR"
Теперь мне ничего не понятно. Зачем его сбрасывать? Я не сбрасываю и всё работает.
И эту строку вообще не использую:
Код: Выделить всё
in r16, SPDR // Сброс флага SPIF..Сброс флага происходит аппаратно, при вызове подпрограммы обработки прерывания или после чтения регистра SPSR с последующим обращением к регистру данных SPDR
PS
И ещё в этой теме уже рассматривалось о сбросе флага:
https://radiokot.ru/forum/viewtopic.php?f=57&t=148266
"Отсутствие данных в SPDR"
- Сообщения: 3
- Зарегистрирован: Пт авг 28, 2020 23:07:01
Доброго времени суток!
Изучаю внешние прерывания. При прогоне программы в AVRStudio4 и эмуляции внешнего прерывания на выводе PB1(INT0) (прерывание настроено по изменению уровня) иногда программа уходит в прерывание и возвращается из прерывания однократно, а иногда прерывание обрабатывается два раза, при этом в дополнительно устанавливается бит INTF0 в активное состояние, который при первом заходе в прерывание не сбрасывается, а сбрасывается при втором заходе в прерывание. Подскажите, может у меня ошибка в коде где то? Что не так я делаю. Далее программа .Сама программа написана только для понимания работы прерывания
.INCLUDE "tn13def.inc"
.DSEG
.ESEG
.CSEG
;****** INTERRUPT VECTORS **************************************************
.ORG $000
RJMP RESET ; Reset Handler
.ORG $001
RJMP EXT_INT0 ; EXT_INT0 ; IRQ0 Handler
.ORG $002
RJMP PCINT_0 ; PCINT0 ; PCINT0 Handler
;****** INTERRUPTS **************************************************
;****** ВНЕШНЕЕ ПРЕРЫВАНИЕ **********************************
EXT_INT0:
NOP
RETI
PCINT_0:
NOP
RETI
RESET:
LDI R16, RAMEND
OUT SPL, R16
LDI R16, 0b00000001
OUT DDRB, R16
LDI R16, 0b00000001
OUT PORTB, R16
;***** ИНИЦИАЛИЗАЦИЯ ВНЕШНЕГО ПРЕРЫВАНИЯ *******************************************
;*** MCUCR – MCU Control Register Внешний регистр управления прерываниями A содержит биты управления для контроля значения прерываний
LDI R16, 0<<ISC01 | 1<<ISC00 ;00- прерывание по низкому уровню, 01- прерывание по логическому изменению, 10- прерывание по ниспадающему фронту, 11- прерывание по нарастающему фронту
OUT MCUCR, R16
;*** GIMSK– General Interrupt Mask Register Реестр масок прерываний
LDI R16, 1<<INT0 | 1<<PCIE ;- INT0: запрос внешнего прерывания 0 разрешен;- PCIE: разрешение прерывания при смене вывода
OUT GIMSK, R16
;*** GIFR – General Interrupt Flag Register Общий регистр флагов прерываний
LDI R16, 1<<INTF0 | 1<<PCIF ;INTF0: флаг внешнего прерывания; - PCIF: флаг прерывания смены вывода
OUT GIFR, R16
;*** PCMSK – Pin Change Mask Register
LDI R16, 0<<PCINT5 | 1<<PCINT4 | 1<<PCINT3| 1<<PCINT2| 0<<PCINT1| 0<<PCINT0
OUT PCMSK, R16
SEI ; глобально разрешаем прерывания
MAIN:
NOP
RJMP MAIN
Скриншот AVRStudio Спасибо
Изучаю внешние прерывания. При прогоне программы в AVRStudio4 и эмуляции внешнего прерывания на выводе PB1(INT0) (прерывание настроено по изменению уровня) иногда программа уходит в прерывание и возвращается из прерывания однократно, а иногда прерывание обрабатывается два раза, при этом в дополнительно устанавливается бит INTF0 в активное состояние, который при первом заходе в прерывание не сбрасывается, а сбрасывается при втором заходе в прерывание. Подскажите, может у меня ошибка в коде где то? Что не так я делаю. Далее программа .Сама программа написана только для понимания работы прерывания
Спойлер
.DEVICE ATtiny13.INCLUDE "tn13def.inc"
.DSEG
.ESEG
.CSEG
;****** INTERRUPT VECTORS **************************************************
.ORG $000
RJMP RESET ; Reset Handler
.ORG $001
RJMP EXT_INT0 ; EXT_INT0 ; IRQ0 Handler
.ORG $002
RJMP PCINT_0 ; PCINT0 ; PCINT0 Handler
;****** INTERRUPTS **************************************************
;****** ВНЕШНЕЕ ПРЕРЫВАНИЕ **********************************
EXT_INT0:
NOP
RETI
PCINT_0:
NOP
RETI
RESET:
LDI R16, RAMEND
OUT SPL, R16
LDI R16, 0b00000001
OUT DDRB, R16
LDI R16, 0b00000001
OUT PORTB, R16
;***** ИНИЦИАЛИЗАЦИЯ ВНЕШНЕГО ПРЕРЫВАНИЯ *******************************************
;*** MCUCR – MCU Control Register Внешний регистр управления прерываниями A содержит биты управления для контроля значения прерываний
LDI R16, 0<<ISC01 | 1<<ISC00 ;00- прерывание по низкому уровню, 01- прерывание по логическому изменению, 10- прерывание по ниспадающему фронту, 11- прерывание по нарастающему фронту
OUT MCUCR, R16
;*** GIMSK– General Interrupt Mask Register Реестр масок прерываний
LDI R16, 1<<INT0 | 1<<PCIE ;- INT0: запрос внешнего прерывания 0 разрешен;- PCIE: разрешение прерывания при смене вывода
OUT GIMSK, R16
;*** GIFR – General Interrupt Flag Register Общий регистр флагов прерываний
LDI R16, 1<<INTF0 | 1<<PCIF ;INTF0: флаг внешнего прерывания; - PCIF: флаг прерывания смены вывода
OUT GIFR, R16
;*** PCMSK – Pin Change Mask Register
LDI R16, 0<<PCINT5 | 1<<PCINT4 | 1<<PCINT3| 1<<PCINT2| 0<<PCINT1| 0<<PCINT0
OUT PCMSK, R16
SEI ; глобально разрешаем прерывания
MAIN:
NOP
RJMP MAIN
Скриншот AVRStudio Спасибо
- Реклама
- Сообщения: 1495
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Симулятор студии не всегда корректно отражает работу внутренней периферии мк. Поэтому нужно отталкиваться от знания архитектуры мк. Читайте толковые книги, даташиты.
Расставляем точки останова в критических местах ДО момента исполнения проверяемой команды и вручную меняем содержимое флажков во время останова исполнения симуляции.

- Сообщения: 1495
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Первое что нужно. Читать ВНИМАТЕЛЬНО соответствующий раздел архитектуры. На каждый камень дополнительно читать даташит. Это базис. Отталкиваемся только от ЭТОГО. Если в студии соответствующий элемент периферии ведёт себя некорректно, учитывать это, и если требуется, ставить тестовые программные затычки. И да, если требуется, вручную делать телодвижения, где порт, где регистры ввода-вывода.
- Сообщения: 473
- Зарегистрирован: Ср янв 11, 2012 18:20:26
Своё скромное мнение выскажу: добившись корректной работы в симуляторах можно не запустить в железе.
- Сообщения: 1495
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Господа оппоненты. Я с AVR работаю с 2007 года. Не буду очередной срач поднимать про протеус. Его убираем. Кто желает, пусть протеус использует. Все эти годы я отлаживаю все свои проекты в студии. И я знаю о чем говорю. Так же я знаю, о чем я говорю, когда говорю: RTFM, мать вашу. Вы, новички теряете время, когда бежите на форумы, вместо того, чтобы прочитать книги по архитектуре МК AVR.
- Сообщения: 3
- Зарегистрирован: Пт авг 28, 2020 23:07:01
[uquote="Djonny",url="/forum/viewtopic.php?p=3885135#p3885135"]Доброго времени суток!
Изучаю внешние прерывания. При прогоне программы в AVRStudio4 и эмуляции внешнего прерывания на выводе PB1(INT0) (прерывание настроено по изменению уровня) иногда программа уходит в прерывание и возвращается из прерывания однократно, а иногда прерывание обрабатывается два раза, при этом в дополнительно устанавливается бит INTF0 в активное состояние, который при первом заходе в прерывание не сбрасывается, а сбрасывается при втором заходе в прерывание. Подскажите, может у меня ошибка в коде где то? Что не так я делаю. Далее программа .Сама программа написана только для понимания работы прерывания
.INCLUDE "tn13def.inc"
.DSEG
.ESEG
.CSEG
;****** INTERRUPT VECTORS **************************************************
.ORG $000
RJMP RESET ; Reset Handler
.ORG $001
RJMP EXT_INT0 ; EXT_INT0 ; IRQ0 Handler
.ORG $002
RJMP PCINT_0 ; PCINT0 ; PCINT0 Handler
;****** INTERRUPTS **************************************************
;****** ВНЕШНЕЕ ПРЕРЫВАНИЕ **********************************
EXT_INT0:
NOP
RETI
PCINT_0:
NOP
RETI
RESET:
LDI R16, RAMEND
OUT SPL, R16
LDI R16, 0b00000001
OUT DDRB, R16
LDI R16, 0b00000001
OUT PORTB, R16
;***** ИНИЦИАЛИЗАЦИЯ ВНЕШНЕГО ПРЕРЫВАНИЯ *******************************************
;*** MCUCR – MCU Control Register Внешний регистр управления прерываниями A содержит биты управления для контроля значения прерываний
LDI R16, 0<<ISC01 | 1<<ISC00 ;00- прерывание по низкому уровню, 01- прерывание по логическому изменению, 10- прерывание по ниспадающему фронту, 11- прерывание по нарастающему фронту
OUT MCUCR, R16
;*** GIMSK– General Interrupt Mask Register Реестр масок прерываний
LDI R16, 1<<INT0 | 1<<PCIE ;- INT0: запрос внешнего прерывания 0 разрешен;- PCIE: разрешение прерывания при смене вывода
OUT GIMSK, R16
;*** GIFR – General Interrupt Flag Register Общий регистр флагов прерываний
LDI R16, 1<<INTF0 | 1<<PCIF ;INTF0: флаг внешнего прерывания; - PCIF: флаг прерывания смены вывода
OUT GIFR, R16
;*** PCMSK – Pin Change Mask Register
LDI R16, 0<<PCINT5 | 1<<PCINT4 | 1<<PCINT3| 1<<PCINT2| 0<<PCINT1| 0<<PCINT0
OUT PCMSK, R16
SEI ; глобально разрешаем прерывания
MAIN:
NOP
RJMP MAIN
Скриншот AVRStudio Спасибо[/uquote]
При изучении внешних прерываний отталкивался исключительно от даташита и Евстифеева. Не думал что в Студии могут глюки появлятся при прогонке программы. А так как опыта у меня нет, то вновь и вновь искал косяк в коде и не находил.
Кстати проблему решил введением в обработчик прерывания сброса регистра INTF0 путем записи туда 1
Изучаю внешние прерывания. При прогоне программы в AVRStudio4 и эмуляции внешнего прерывания на выводе PB1(INT0) (прерывание настроено по изменению уровня) иногда программа уходит в прерывание и возвращается из прерывания однократно, а иногда прерывание обрабатывается два раза, при этом в дополнительно устанавливается бит INTF0 в активное состояние, который при первом заходе в прерывание не сбрасывается, а сбрасывается при втором заходе в прерывание. Подскажите, может у меня ошибка в коде где то? Что не так я делаю. Далее программа .Сама программа написана только для понимания работы прерывания
Спойлер
.DEVICE ATtiny13.INCLUDE "tn13def.inc"
.DSEG
.ESEG
.CSEG
;****** INTERRUPT VECTORS **************************************************
.ORG $000
RJMP RESET ; Reset Handler
.ORG $001
RJMP EXT_INT0 ; EXT_INT0 ; IRQ0 Handler
.ORG $002
RJMP PCINT_0 ; PCINT0 ; PCINT0 Handler
;****** INTERRUPTS **************************************************
;****** ВНЕШНЕЕ ПРЕРЫВАНИЕ **********************************
EXT_INT0:
NOP
RETI
PCINT_0:
NOP
RETI
RESET:
LDI R16, RAMEND
OUT SPL, R16
LDI R16, 0b00000001
OUT DDRB, R16
LDI R16, 0b00000001
OUT PORTB, R16
;***** ИНИЦИАЛИЗАЦИЯ ВНЕШНЕГО ПРЕРЫВАНИЯ *******************************************
;*** MCUCR – MCU Control Register Внешний регистр управления прерываниями A содержит биты управления для контроля значения прерываний
LDI R16, 0<<ISC01 | 1<<ISC00 ;00- прерывание по низкому уровню, 01- прерывание по логическому изменению, 10- прерывание по ниспадающему фронту, 11- прерывание по нарастающему фронту
OUT MCUCR, R16
;*** GIMSK– General Interrupt Mask Register Реестр масок прерываний
LDI R16, 1<<INT0 | 1<<PCIE ;- INT0: запрос внешнего прерывания 0 разрешен;- PCIE: разрешение прерывания при смене вывода
OUT GIMSK, R16
;*** GIFR – General Interrupt Flag Register Общий регистр флагов прерываний
LDI R16, 1<<INTF0 | 1<<PCIF ;INTF0: флаг внешнего прерывания; - PCIF: флаг прерывания смены вывода
OUT GIFR, R16
;*** PCMSK – Pin Change Mask Register
LDI R16, 0<<PCINT5 | 1<<PCINT4 | 1<<PCINT3| 1<<PCINT2| 0<<PCINT1| 0<<PCINT0
OUT PCMSK, R16
SEI ; глобально разрешаем прерывания
MAIN:
NOP
RJMP MAIN
Скриншот AVRStudio Спасибо[/uquote]
При изучении внешних прерываний отталкивался исключительно от даташита и Евстифеева. Не думал что в Студии могут глюки появлятся при прогонке программы. А так как опыта у меня нет, то вновь и вновь искал косяк в коде и не находил.
Кстати проблему решил введением в обработчик прерывания сброса регистра INTF0 путем записи туда 1
Вообще-то непонятно. В ДШ про этот INTF0 открытым текстом сказано
О! Посмотрел внимательнее. Djonny, ты же разрешил ОБА прерывания, и INT0, и PCINT1 от несчастной ножки PB1. Не знаю, как реальное железо, а симулятор из-за этого, похоже, сходит с ума, одно прерывание отработал, про второе забыл. Не удивлюсь, если железо тоже сойдет с ума...
Или отдельно исследуй PCINTn и INT0 (разными программами), или исключи из PCINTn ножку PCINT1 (PB1).
Добавлено after 4 minutes 7 seconds:
Да, еще момент. То, что ты взял код под спойлер - это правиоьно, однако код под спойлером надо еще взять в, тогда более-менее сохранится форматирование исходника, не будет той кучи, в которую и смотреть не хочется...
То же самое сказано про биты 0-5 регистра PCMSK.The flag is cleared when the interrupt routine is executed.
Alternatively, the flag can be cleared by writing a logical one to it. This flag is always cleared when INT0 is configured as a level interrupt.
О! Посмотрел внимательнее. Djonny, ты же разрешил ОБА прерывания, и INT0, и PCINT1 от несчастной ножки PB1. Не знаю, как реальное железо, а симулятор из-за этого, похоже, сходит с ума, одно прерывание отработал, про второе забыл. Не удивлюсь, если железо тоже сойдет с ума...
Или отдельно исследуй PCINTn и INT0 (разными программами), или исключи из PCINTn ножку PCINT1 (PB1).
Добавлено after 4 minutes 7 seconds:
Да, еще момент. То, что ты взял код под спойлер - это правиоьно, однако код под спойлером надо еще взять в
Код: Выделить всё
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
- Сообщения: 1495
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Djonny. Добро пожаловать.
- Сообщения: 3
- Зарегистрирован: Пт авг 28, 2020 23:07:01
[uquote="afz",url="/forum/viewtopic.php?p=3885372#p3885372"]Или отдельно исследуй PCINTn и INT0 (разными программами), или исключи из PCINTn ножку PCINT1 (PB1).[/uquote]
Добрый день,
Я бит PCINT1 (PB1) не задействовал, выставлен 0.
Добрый день,
Я бит PCINT1 (PB1) не задействовал, выставлен 0.
Код: Выделить всё
LDI R16, 0<<PCINT5 | 1<<PCINT4 | 1<<PCINT3| 1<<PCINT2| 0<<PCINT1| 0<<PCINT0Спасибо, учту.Да, еще момент. То, что ты взял код под спойлер - это правиоьно, однако код под спойлером надо еще взять в, тогда более-менее сохранится форматирование исходника, не будет той кучи, в которую и смотреть не хочется...Код: Выделить всё
Неоднократно замечал что при старте проекта в студии имеет место быть 1 холостое прерывание от внешних источников если они разрешены и если настроено на фронт или спад сразу после SEI. В железе его нет, но я делаю свои подпрограммы такими, что-б им это было до светодиода....
- Сообщения: 1495
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Это говорит о том, что всегда нужно сначала настроить режим работы, и только потом включать прерывания. И сбрасывать флаги, если требуется. А на устройстве всегда учитывать такие особенности.
Djonny Попробуйте в студии simulator, который более приближён к железу, вместо simulator 2.
- Сообщения: 1495
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Да, но в нем не все МК.
[uquote="Demiurg",url="/forum/viewtopic.php?p=3886177#p3886177"]Это говорит о том, что всегда нужно сначала настроить режим работы, и только потом включать прерывания. И сбрасывать флаги, если требуется. А на устройстве всегда учитывать такие особенности.[/uquote]
Я всегда так делал - однако факт остается фактом. Версию студии не помню уже. Но на симуляторе.
Я всегда так делал - однако факт остается фактом. Версию студии не помню уже. Но на симуляторе.


