Ассемблер (ASM) для AVR в вопросах и ответах
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Первое что нужно. Читать ВНИМАТЕЛЬНО соответствующий раздел архитектуры. На каждый камень дополнительно читать даташит. Это базис. Отталкиваемся только от ЭТОГО. Если в студии соответствующий элемент периферии ведёт себя некорректно, учитывать это, и если требуется, ставить тестовые программные затычки. И да, если требуется, вручную делать телодвижения, где порт, где регистры ввода-вывода.
- Реклама
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Своё скромное мнение выскажу: добившись корректной работы в симуляторах можно не запустить в железе.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
ГЛАВНЫЙ СИМУЛЯТОР - МАКЕТ.

-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Господа оппоненты. Я с AVR работаю с 2007 года. Не буду очередной срач поднимать про протеус. Его убираем. Кто желает, пусть протеус использует. Все эти годы я отлаживаю все свои проекты в студии. И я знаю о чем говорю. Так же я знаю, о чем я говорю, когда говорю: RTFM, мать вашу. Вы, новички теряете время, когда бежите на форумы, вместо того, чтобы прочитать книги по архитектуре МК AVR.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
[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
- Реклама
- afz
- Опытный кот
- Сообщения: 744
- Зарегистрирован: Сб дек 22, 2012 08:17:42
- Откуда: Караганда, Казахстан
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Вообще-то непонятно. В ДШ про этот 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)
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Djonny. Добро пожаловать.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
[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Спасибо, учту.Да, еще момент. То, что ты взял код под спойлер - это правиоьно, однако код под спойлером надо еще взять в, тогда более-менее сохранится форматирование исходника, не будет той кучи, в которую и смотреть не хочется...Код: Выделить всё
-
Wladimir_TS
- Друг Кота
- Сообщения: 5066
- Зарегистрирован: Вс фев 15, 2009 01:04:58
- Откуда: Kaluga
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Неоднократно замечал что при старте проекта в студии имеет место быть 1 холостое прерывание от внешних источников если они разрешены и если настроено на фронт или спад сразу после SEI. В железе его нет, но я делаю свои подпрограммы такими, что-б им это было до светодиода....
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Это говорит о том, что всегда нужно сначала настроить режим работы, и только потом включать прерывания. И сбрасывать флаги, если требуется. А на устройстве всегда учитывать такие особенности.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Djonny Попробуйте в студии simulator, который более приближён к железу, вместо simulator 2.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Да, но в нем не все МК.
-
Wladimir_TS
- Друг Кота
- Сообщения: 5066
- Зарегистрирован: Вс фев 15, 2009 01:04:58
- Откуда: Kaluga
Re: Ассемблер (ASM) для AVR в вопросах и ответах
[uquote="Demiurg",url="/forum/viewtopic.php?p=3886177#p3886177"]Это говорит о том, что всегда нужно сначала настроить режим работы, и только потом включать прерывания. И сбрасывать флаги, если требуется. А на устройстве всегда учитывать такие особенности.[/uquote]
Я всегда так делал - однако факт остается фактом. Версию студии не помню уже. Но на симуляторе.
Я всегда так делал - однако факт остается фактом. Версию студии не помню уже. Но на симуляторе.
- Starichok51
- Модератор
- Сообщения: 19055
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
когда ты в студии запустил симуляцию и курсор встал на нулевой адрес, сначала пины соответствующих входов нужно поставить в нужное состояние. тогда не будет возникать ложного запуска прерывания.Wladimir_TS писал(а):Неоднократно замечал что при старте проекта в студии имеет место быть 1 холостое прерывание от внешних источников если они разрешены и если настроено на фронт или спад сразу после SEI. В железе его нет
изначально студия на всех пинах всех портов ставит нули.
а в железе пины при запуске стоят в нужном состоянии, потому в железе ложного запуска прерывания при старте не происходит.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
-
Wladimir_TS
- Друг Кота
- Сообщения: 5066
- Зарегистрирован: Вс фев 15, 2009 01:04:58
- Откуда: Kaluga
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Видимо так оно и есть.
- a1000
- Первый раз сказал Мяу!
- Сообщения: 31
- Зарегистрирован: Вс окт 18, 2020 19:01:52
- Откуда: Харьковская область
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Всем привет!
В ходе изучения ASM в учебных целях решил сделать частотомер на 50 Гц. Принцип работы - измерение периода. Камень - atmega8, частота 8 МГц. Напяжение через диод и резисторный делитель подаю на ICP1. Для начала был написан такой код.
Подключенный к PD0 логический анализатор выдал красивую картинку

Следующий этап - получение данных с регистра захвата. В качестве индикатора применил модуль из 4 семисегментных индикаторов на TM1637. Что-бы число импульсов влазило в индикатор, решил ограничится 1 байтом. По сему коэфициент предделителя выбрал 1024, должно получаться что-то около 156. Вывод на TM1637 уже давно отработан и в коде не приводится.
В кратце логика такая. До первого прерывания ничего не делаем. По первому прерыванию сбрасываем TCNT1 в ноль, по второму забираем в Temp1 младший байт регистра захвата и разрешаем его вывод на индикатор. Перед выводом запрещаем прерывания, выводим значение Temp1. Задержка 1 сек. Разрешаем прерывания и всё по новой. В теории красиво, а на деле на индикаторе бегают цифры от 3 до 200.
Где косяк?
В ходе изучения ASM в учебных целях решил сделать частотомер на 50 Гц. Принцип работы - измерение периода. Камень - atmega8, частота 8 МГц. Напяжение через диод и резисторный делитель подаю на ICP1. Для начала был написан такой код.
Спойлер
Код: Выделить всё
;=============
; Сегмент FLASH памяти
.CSEG
;=============
; Таблица прерываний
.ORG 0x00 RJMP RESET
.ORG 0x05 RJMP TIM1_CAPT
;=============
; Прерывание по сбросу, стартовая инициализация
RESET:
; Инициализация стека
LDI Temp1, LOW(RAMEND)
OUT SPL, Temp1
LDI Temp1, HIGH(RAMEND)
OUT SPH, Temp1
; Очистка ОЗУ и регистров R0-R31
LDI ZL, LOW(SRAM_START) ; Адрес начала ОЗУ в индекс
LDI ZH, HIGH(SRAM_START)
CLR Temp1 ; Очищаем R16
RAM_Flush:
ST Z+, Temp1
CPI ZH, HIGH(RAMEND + 1)
BRNE RAM_Flush
CPI ZL, LOW(RAMEND + 1)
BRNE RAM_Flush
LDI ZL, (0x1F-2) ; Адрес регистра R29
CLR ZH
Reg_Flush:
ST Z, ZH
DEC ZL
BRNE Reg_Flush
CLR ZL
CLR ZH
; Регистры и SRAM полностью очищены (обнулены)
; Но регистры ввода-вывода (IO) НЕОБХОДИМО очищать
; Глобальный запрет прерываний
CLI
;настройка порта D
ldi Temp1, 0xFF // порт D на выход
out DDRD, Temp1
;настройка порта B
cbi DDRB,0 ; ICP1 на вход
;настройка таймера1
ldi Temp1, 0b00000000
out TCCR1A, Temp1
ldi Temp1, 0b01000011
out TCCR1B, Temp1
ldi Temp1, 0b00100000
out TIMSK, Temp1
out TIFR, Temp1
SEI ;разрешаем прерывания
;***************************************************
LOOP:
rjmp LOOP
;==============
TIM1_CAPT: ;обработчик прерывания по захвату таймера 1
SBIC PORTD,EXT
rjmp metka
SBI PORTD,EXT ;установить бит
rjmp EXIT
metka:
CBI PORTD,EXT ;установить бит
EXIT:
RETI

Следующий этап - получение данных с регистра захвата. В качестве индикатора применил модуль из 4 семисегментных индикаторов на TM1637. Что-бы число импульсов влазило в индикатор, решил ограничится 1 байтом. По сему коэфициент предделителя выбрал 1024, должно получаться что-то около 156. Вывод на TM1637 уже давно отработан и в коде не приводится.
Спойлер
Код: Выделить всё
;=============
; Сегмент FLASH памяти
.CSEG
;=============
; Таблица прерываний
.ORG 0x00 RJMP RESET
.ORG 0x05 RJMP TIM1_CAPT
;=============
; Прерывание по сбросу, стартовая инициализация
RESET:
; Инициализация стека
LDI Temp1, LOW(RAMEND)
OUT SPL, Temp1
LDI Temp1, HIGH(RAMEND)
OUT SPH, Temp1
; Очистка ОЗУ и регистров R0-R31
LDI ZL, LOW(SRAM_START) ; Адрес начала ОЗУ в индекс
LDI ZH, HIGH(SRAM_START)
CLR Temp1 ; Очищаем R16
RAM_Flush:
ST Z+, Temp1
CPI ZH, HIGH(RAMEND + 1)
BRNE RAM_Flush
CPI ZL, LOW(RAMEND + 1)
BRNE RAM_Flush
LDI ZL, (0x1F-2) ; Адрес регистра R29
CLR ZH
Reg_Flush:
ST Z, ZH
DEC ZL
BRNE Reg_Flush
CLR ZL
CLR ZH
; Регистры и SRAM полностью очищены (обнулены)
; Но регистры ввода-вывода (IO) НЕОБХОДИМО очищать
; Глобальный запрет прерываний
CLI
;настройка порта D
ldi Temp1, 0xFF // Порт D на выход
out DDRD, Temp1
;настройка порта B
cbi DDRB,0 ; ICP1 на вход
;настройка таймера1
ldi Temp1, 0b00000000
out TCCR1A, Temp1
ldi Temp1, 0b01000101
out TCCR1B, Temp1
ldi Temp1, 0b00100000
out TIMSK, Temp1
out TIFR, Temp1
; ===========
CLT ;сбрасываем бит Т
ORI R30, 0b00000001 ;устанасливаем бит 0 R30 в 1
SEI ;разрешаем прерывания
;***************************************************
LOOP:
BRTC LOOP ;если Т=0 не делаем ничего
CLI ;запрещаем прерывания
;***************************************************
; вывод значения Temp1 на TM1637
;***************************************************
; ===========
; delay loop generator
; 8000000 cycles:
; -----------------------------
; delaying 7999992 cycles:
ldi R17, $48
WGLOOP00: ldi R18, $BC
WGLOOP1: ldi R19, $C4
WGLOOP2: dec R19
brne WGLOOP2
dec R18
brne WGLOOP1
dec R17
brne WGLOOP00
; -----------------------------
; delaying 6 cycles:
ldi R17, $02
WGLOOP3: dec R17
brne WGLOOP3
; -----------------------------
; delaying 2 cycles:
nop
nop
; ===========
SEI ;разрешаем прерывания
CLT ;сбрасываем бит Т
rjmp LOOP
;==============
TIM1_CAPT: ;обработчик прерывания по захвату таймера 1
SBRS R30,0
rjmp ZAHVAT
CLR Temp1 ;обнуляем счётчмк
out TCNT1H,Temp1
out TCNT1L,Temp1
ANDI R30, 0b11111110 ;устанасливаем бит 0 R30 в 0
rjmp EXT
ZAHVAT:
in Temp1,ICR1L ;копируем значение регистра захвата
in Temp2,ICR1H
ORI R30, 0b00000001 ;устанасливаем бит 0 R30 в 1
SET ;устанавливаем бит Т
EXT:
RETI
Где косяк?
Это Спарта! В смысле, ассемблер. Все ручками.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Неполная очистка таймера, т.к. задействован предделитель
Таймер при выходе из прерывания по окончании измерения не останавливается. За время вывода на индикацию и задержки входной сигнал на PB0/ICP1 установит флаг ICF1, т.е. при переходе на LOOP прерывание вызовется сразу, а не по фронту входного сигнала.
Код: Выделить всё
TIM1_CAPT: ;обработчик прерывания по захвату таймера 1
SBRS R30,0
rjmp ZAHVAT
CLR Temp1 ;обнуляем счётчмк
out TCNT1H,Temp1
out TCNT1L,Temp1
;================
LDI R16,1<<PSR10
OUT SFIOR,R16 ; обнулить предделитель таймера
;================
ANDI R30, 0b11111110 ;устанасливаем бит 0 R30 в 0
rjmp EXT
ZAHVAT:
in Temp1,ICR1L ;копируем значение регистра захвата
in Temp2,ICR1H
ORI R30, 0b00000001 ;устанасливаем бит 0 R30 в 1
SET ;устанавливаем бит Т
EXT:
RETIСпойлер
Код: Выделить всё
.include "m8def.inc" ; ATMega8
.equ Fo=8000000
.def temp1=R16
.def temp2=R17
;=============
; Сегмент FLASH памяти
.CSEG
;=============
; Таблица прерываний
.ORG 0x00
RJMP RESET
.ORG 0x05 ; RJMP TIM1_CAPT
TIM1_CAPT: ;обработчик прерывания по захвату таймера 1
SBRS R30,0
rjmp ZAHVAT
OUT TCCR1B,R22
; CLR Temp1 ;обнуляем счётчмк
; out TCNT1H,Temp1
; out TCNT1L,Temp1
CBR R30,1<<0
; ANDI R30, 0b11111110 ;устанасливаем бит 0 R30 в 0
rjmp EXT
ZAHVAT:
in Temp1,ICR1L ;копируем значение регистра захвата
in Temp2,ICR1H
SBR R30,1<<0
; ORI R30, 0b00000001 ;устанасливаем бит 0 R30 в 1
ldi Temp1,0b01000000
out TCCR1B, Temp1
; ldi Temp1, 0b01000101
; out TCCR1B, Temp1
ldi Temp1, 0b00100000
out TIMSK, Temp1
out TIFR, Temp1
LDI R16,1<<PSR10
OUT SFIOR,R16
SET ;устанавливаем бит Т
EXT:
RETI
;=============
; Прерывание по сбросу, стартовая инициализация
RESET:
; Инициализация стека
LDI Temp1, LOW(RAMEND)
OUT SPL, Temp1
LDI Temp1, HIGH(RAMEND)
OUT SPH, Temp1
; Очистка ОЗУ и регистров R0-R31
CLI
;настройка порта D
ldi Temp1, 0xFF // Порт D на выход
out DDRD, Temp1
;настройка порта B
cbi DDRB,0 ; ICP1 на вход
;настройка таймера1
ldi Temp1, 0b00000000
out TCCR1A, Temp1
ldi Temp1,0b01000000
out TCCR1B, Temp1
; ldi Temp1, 0b01000101
; out TCCR1B, Temp1
ldi Temp1, 0b00100000
out TIMSK, Temp1
out TIFR, Temp1
LDI R16,1<<PSR10
OUT SFIOR,R16
; ===========
CLT ;сбрасываем бит Т
SBR R30,1<<0
; ORI R30, 0b00000001 ;устанасливаем бит 0 R30 в 1
LDI R22,0b01000101
SEI ;разрешаем прерывания
;***************************************************
LOOP:
BRTC LOOP ;если Т=0 не делаем ничего
CLI ;запрещаем прерывания
;***************************************************
; вывод значения Temp1 на TM1637
;***************************************************
; ===========
; delay loop generator
; 8000000 cycles:
; ----------
; delaying 7999992 cycles:
ldi R17, $48
WGLOOP00: ldi R18, $BC
WGLOOP1: ldi R19, $C4
WGLOOP2: dec R19
brne WGLOOP2
dec R18
brne WGLOOP1
dec R17
brne WGLOOP00
; ----------
; delaying 6 cycles:
ldi R17, $02
WGLOOP3: dec R17
brne WGLOOP3
; ----------
; delaying 2 cycles:
nop
nop
; ===========
; SEI ;разрешаем прерывания
; CLT ;сбрасываем бит Т
rjmp RESET
;rjmp LOOP
;==============
.EXIT
Последний раз редактировалось akl Пн окт 19, 2020 05:31:45, всего редактировалось 1 раз.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Замечание по комментариям. Комментарии должны быть информативными, нести смысловую нагрузку. А не информировать об очевидном.
Пример:
Это очевидно. Масло масляное. Указывайте в комментариях непростые, неочевидные вещи. Алгоритм, пояснения. То, о чем другим будет непонятно, и что вы забудете через месяц.
Пример:
Код: Выделить всё
sbi LED_PORT, LED // Включение светодиода
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Далеко не очевидно.
Например, светик подключен через резистор анодом на плюс. Или для камня с переключением состояния через PIN
Например, светик подключен через резистор анодом на плюс. Или для камня с переключением состояния через PIN
Код: Выделить всё
;.equ LED_PORT=PORTD
.equ LED_PORT=PIND
.equ LED=0
SER ZH
OUT DDRD,ZH
SBI LED_PORT,LED ; переключить состояние светика
- a1000
- Первый раз сказал Мяу!
- Сообщения: 31
- Зарегистрирован: Вс окт 18, 2020 19:01:52
- Откуда: Харьковская область
Re: Ассемблер (ASM) для AVR в вопросах и ответах
[uquote="akl",url="/forum/viewtopic.php?p=3909119#p3909119"]Неполная очистка таймера, т.к. задействован предделитель
...............
Таймер при выходе из прерывания по окончании измерения не останавливается. За время вывода на индикацию и задержки входной сигнал на PB0/ICP1 установит флаг ICF1, т.е. при переходе на LOOP прерывание вызовется сразу, а не по фронту входного сигнала.[/uquote]
Предделитель сильно не повлияет. Плюс-минус один такт. А по второму согласен на все сто. Пока будем выводить значения и висеть в задержке флаг ICF1 будет установлен и первое прерывание произойдёт не по фронту а в момент разрешения прерывания. Попробовал решить вопрос в лоб, сбрасывать ICF1 в конце LOOP перед установкой бита I. Показания немного стабилизировались. Буду разбираться с вашим кодом. Спасибо за совет.
Добавлено after 8 minutes 46 seconds:
Ещё вопрос в догонку. Установив биты предделителя CS12 – CS10 в "000" мы останавливаем таймер. При этом TCNT1 обнуляется? Если опять запустить счёт он продолжится со значения в момент остановки или начнётся с нуля?
...............
Таймер при выходе из прерывания по окончании измерения не останавливается. За время вывода на индикацию и задержки входной сигнал на PB0/ICP1 установит флаг ICF1, т.е. при переходе на LOOP прерывание вызовется сразу, а не по фронту входного сигнала.[/uquote]
Предделитель сильно не повлияет. Плюс-минус один такт. А по второму согласен на все сто. Пока будем выводить значения и висеть в задержке флаг ICF1 будет установлен и первое прерывание произойдёт не по фронту а в момент разрешения прерывания. Попробовал решить вопрос в лоб, сбрасывать ICF1 в конце LOOP перед установкой бита I. Показания немного стабилизировались. Буду разбираться с вашим кодом. Спасибо за совет.
Добавлено after 8 minutes 46 seconds:
Ещё вопрос в догонку. Установив биты предделителя CS12 – CS10 в "000" мы останавливаем таймер. При этом TCNT1 обнуляется? Если опять запустить счёт он продолжится со значения в момент остановки или начнётся с нуля?
Это Спарта! В смысле, ассемблер. Все ручками.


