Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
yura02
0 / 0 / 0
Регистрация: 19.12.2013
Сообщений: 5
1

Сдвиги по прерываниям ASM

18.05.2015, 17:24. Просмотров 601. Ответов 6
Метки нет (Все метки)

Дано восьмибитное число 10000110 (бит7-должен быть всегда 1, бит0- должен быть всегда 0).
При вызове прерывания INT0 сдвигать содержимое влево, не меняя биты 7 и 0.
При вызове прерывания INT1 сброс в начальные условия(10000110)
При вызове прерывания INT2 сдвигать содержимое вправо, не меняя биты 7 и 0.
есть код со сдвигами, но в нем меняются и биты 7 и 0
(код для STK500)
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
.include "m16def.inc" ;Подключение файла для м.к. ATmega16
.dseg
 
.cseg  ;Переход в сегмент программного кода
.org $0000  ;Установка адреса
  jmp  Start  ;Переход на начало основной программы
 
.org $0002
  jmp  ExtInt0
.org $0004
  jmp  ExtInt1
.org $0024
  jmp  ExtInt2
;
.org INT_VECTORS_SIZE
Start: ;Основноя программа
 
  cli  ;Глобальное запрещение прерываний!
;Отмена работы сторожевого таймера:
  wdr
  ldi  R16, 0b00011000
  out  WDTCR, R16 ;Установка битов WDTOE и WDE в рег. WDTCR
  ldi  R16, 0b00010000   
  out  WDTCR, R16 ;Очистка бита WDE в рег. WDTCR
;Установка указателя стека:
  ldi  R16, Low (RamEnd)  ;Константа RamEnd определена в m16def.inc
  ldi  R17, High(RamEnd)
  out  SPL, R16   ;SPL и SPH - регистры указателя стека. 
  out  SPH, R17   ;Адреса SPL и SPH определены в m16def.inc.
;Отмена работы сторожевого таймера и установка указателя стека
;необходимы для всех последующих программ!
 
.def Var = R20
 
 
;Настройка порта C на вывод данных
  ldi  R16, 0b11111111  ;вывод первоначальных данных
  out  PortC, R16
  ldi  R16, 0b11111111  ;настройка на вывод
  out  DDRC, R16
 
ldi R16, 0b00000110
mov Var, R16
 
 
ldi R16,0b10001111
out MCUCR, r16
 
 
LDI r16, 0b00001111
out MCUCSR, R16
 
 
ldi R16, 0b11100000
out GIFR, R16
 
ldi R16, 0b11100000
out GICR, R16
 
 
 
  sei  ;Глобальное разрешение прерываний!
Cycle: ;Бесконечный цикл:
  nop
  nop
  rjmp Cycle
;
;Подпрограммы внешних прерываний INT0,INT1 и INT2:
ExtInt0:
  lsl  Var
  brcc NoSetBitFire
  ori  Var, 0b00000001
 NoSetBitFire:
   mov R16, Var
   com R16
ori R16, 0b10000000
   out  PortC, R16
  reti
ExtInt1:
  ldi  R16,0b10000110
mov Var, R16
com R16
ori R16, 0b10000000
out PortC, R16
  reti
ExtInt2:
  lsr  Var
  brcc NoSetBitFire
  ori  Var, 0b10000000
 NoSetBitFire:
   mov R16, Var
   com R16
ori R16, 0b10000000
   out  PortC, R16
  reti
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.05.2015, 17:24
Ответы с готовыми решениями:

Вопрос по прерываниям
При использовании одновременно нескольких из PCINT5..0 пинов в ATtiny13, можно-ли узнать, от какого...

Соответствие портов вв внешним прерываниям - где это документировано?
Привет всем! В общем, столкнулся с программированием МК чисто по академическим причинам. И вот,...

ASM atmega написать программу на ASM
Нужна помощь в написании программы с объяснениями.. Проверить свою программу Вашу работу. ...

Вопрос по прерываниям
У меня на stm32f3 стоит два прерывания (помимо стандартного SysTick_Homdler), одно вызывается с...

можно ли while() и for() отнести к прерываниям?
сабж...

6
pyzhman
795 / 488 / 67
Регистрация: 15.05.2012
Сообщений: 2,770
18.05.2015, 17:59 2
Жаль, что меняются. Бида-пичалька.
А вы делайте по заданию -
бит7-должен быть всегда 1, бит0- должен быть всегда 0
То бишь двигайте куда надо, а потом взведите старший и сбросьте младший биты.
0
yura02
0 / 0 / 0
Регистрация: 19.12.2013
Сообщений: 5
18.05.2015, 19:45  [ТС] 3
Если я правильно вас понял, то должно получиться так? То есть после самого сдвига просто поставить значения битов 7=0, 0=1
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
ExtInt0:
  lsl  Var
  brcc NoSetBitFire
  ori  Var, 0b00000001
 NoSetBitFire:
   mov R16, Var
   com R16
ori R16, 0b10000000
   out  PortC, R16
cbi PortC, 7
sbi PortC, 0
  reti
Добавлено через 1 час 25 минут
помощь все так же требуется, не могу понять как сделать чтобы сдвиг происходил среди битов 1-6
0
Ethereal
5495 / 1947 / 255
Регистрация: 17.02.2013
Сообщений: 2,894
18.05.2015, 20:09 4
;Пусть число в r16
ldi r17, 0b10000001
and r17, r16 ;Сохранили биты 0 7, остальные нули
add r16, r16 ;Сдвинули влево
andi r16, 0b01111100b ;Обнулили биты 0 1 7
or r16, r17 ;Вставили биты 0 7 обратно
0
pyzhman
795 / 488 / 67
Регистрация: 15.05.2012
Сообщений: 2,770
18.05.2015, 20:16 5
Да вот же оно -
Assembler
1
2
cbi PortC, 7
sbi PortC, 0
Только наоборот.
Не вижу смысла применять тут маску. Не сказано же, что нужно оставлять биты в таком-то состоянии. Русским по белому - седьмой д/б 1, нулевой - 0.
Двигайте всё, весь байт, а потом установите седьмой и сбросьте нулевой.
0
yura02
0 / 0 / 0
Регистрация: 19.12.2013
Сообщений: 5
18.05.2015, 20:37  [ТС] 6
С этим я понял, но нужно чтоб сдвигались только биты с 1 по 6.Возможно ли такое сделать?
Вот еще похожий вопрос
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
Порт C (линии PC0...PC5 на вывод данных):
;
;Необходимо использовать 6 сигнальных линий PC0...PC5.
  in   R16, PortC      ;0bxxxxxxxx ;Предварительная установка выходных сигналов PC0...PC5.
  ori  R16, 0b00111111 ;0b11111111 ;Отключаем светодиоды запиью лог."1" (для STK500)
  out  PortC, R16                 
  in   R16, DDRC       ;0bxxxxxxxx ;Настройка линий PC0...PC5 порта C на вывод
  ori  R16, 0b00111111 ;0b00111111
  out  DDRC, R16
;
;Порт D (линия PD0 на вывод данных):
  in   R16, PortD      ;0bxxxxxxxx ;Предварительная установка выходного сигнала PD0.
  ori  R16, 0b00000001 ;0bxxxxxxx1 ;Отключаем светодиод запиью лог."1" (для STK500)
  out  PortD, R16
  in   R16, DDRD       ;0bxxxxxxxx ;Настройка линии PD0 порта D на вывод
  ldi  R16, 0b00000001 ;0bxxxxxxx1
  out  DDRD, R16
;
;--------------------------------------
;Настройка работы модуля аналого-цифрового преобразователя (АЦП):
;Опорное напряжение: внешний контакт AREF  REFS1..0 = 0b00
;Выравнивание по левому краю: ADLAR=1
;Аналоговый входной сигнал на линии PA2(ADC2):  MUX4..0 = 0b00010
  ldi  R16, 0b00100010; ;(0<<REFS1)|(0<<REFS0)|(1<<ADLAR)|(0<<MUX4)|(0<<MUX3)|(0<<MUX2)|
;(1<<MUX1)|(0<<MUX0)
  out  ADMUX, R16
;
;Включение АЦП: ADEN=1
;Запуск АЦП выполним позднее, поэтому ADSC=0
;АЦП в режиме одиночного преобразования: ADATE=0
;Прерывание не используем: ADIF <- 0(т.е. запись лог."1"), ADIE=0
;Предделитель АЦП: /32 [0b110]  (4000000/32 = 125000Гц) 50кГц..200кГц
  ldi  R16, 0b10010110;
;(1<<ADEN)|(0<<ADSC)|(0<<ADATE)|(1<<ADIF)|(0<<ADIE)|(1<<ADPS2)|
;(1<<ADPS1)|(1<<ADPS0)
  out  ADCSRA, R16
;
;--------------------------------------
;Настройка таймера/счетчика TC1:
;Полная остановка таймера/счетчика1 (сброс всех бит регистров управления):
  ldi  R16, 0b00000000
  out  TCCR1A, R16
  out  TCCR1B, R16
;Сброс счетных регистров TC1:
  ldi  R16, $00
  out  TCNT1H, R16 ;
  out  TCNT1L, R16 ;
;Установка регистров сравнения:
;4000000такт./сек. * 0.02сек. = 80000 тактов (длительность интервала между измерениями АЦП)
;Выберем предделитель для TC1 равнам 8, тогда период прерывания TC1(A) будет 80000/8 = 10000
  ldi  R16, Low (10000-1) ;Для обеспечения интервала времени 0.02сек.
  ldi  R17, High(10000-1) ;при тактовой частоте 4МГц.
  out  OCR1AH, R17
  out  OCR1AL, R16
  ldi  R16, $FF
  out  OCR1BH, R16
  out  OCR1BL, R16
;Запуск TC1 (Режим CTC, предделитель /1 [CS12..0 = 0b010]):
  ldi  R16, (0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|(0<<FOC1A)|(0<<FOC1B)|(0<<WGM11)|(0<<WGM10)
  out  TCCR1A, R16 ;0b00000000
  ldi  R16, (0<<ICNC1)|(0<<ICES1)|(0<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10)
  out  TCCR1B, R16 ;0b00001010
;Отмена ложных прерываний (Сброс всех флагов событий для TC1):
  ldi  R16, 0b11111111
  out  TIFR, R16
;Разрешение прерывания TC1 при выходе сравнения A:
  in   R16, TIMSK                                         ;0bxxxxxxxx
  cbr  R16, (1<TICIE1)|(1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1) ;0bxx0000xx
  sbr  R16,  1<<OCIE1A                                    ;0bxx0100xx
  out  TIMSK, R16
;
;--------------------------------------
  sei  ;I(SREG) <- 1  ;Глобальное разрешение прерываний!
MainCycle: ;Бесконечный пустой цикл!!!
  nop
  nop
  rjmp MainCycle
;
;/- Подпрограмма прерывания для TC1 выхода сравнения A  -------/
fInterrupt_TC1_OC1A:
;Обработка нового результата измерения положения потенциометра:
  sbi  ADCSRA, ADSC ;Запуск преобразования АЦП:
WaitReadyADC:       ;Ожидание завершения преобразования АЦП
  sbic ADCSRA, ADSC
    rjmp WaitReadyADC
;Считываем новые данные из регистра ADCH:
  in  RdataL, ADCL ;!
  in  RdataH, ADCH ;!
;
;Запись полученного результата в память данных SRAM:
;Вчисление адреса для сохранения результата АЦП:
  mov  R16, Rpoint
  ldi  R17, $00
  lsl  R16 ;При сдвиге влево на один бит число умножается на два
  rol  R17 ;
  ldi  XL, Low (DataADC) ;Записываем в регистры XL/XH стартовый адрес
  ldi  XH, High(DataADC) ;зарезервированной области
  add  XL, R16   ;Складываем стартовый адрес массива DataADC и смещение!
  adc  XH, R17   ;В регистрах XL/XH получен необходимый адрес!
;Теперь в регистровой паре XL и XH находится адрес для записи очередного результата!
  st   X+, RdataL  ;Сохранение результата измерения 
  st   X+, RdataH  ;положения потенциометрического датчика SPI18
;
;Увеличение указателя Rpoint на 1:
  ldi  R16, 1
  add  Rpoint, R16
;Проверка на переполнение Rpoint:
  cpi  Rpoint, 150  ;Сравниваем с 150
  brcs NoResetPoint ;Если флаг C=1 (т.е. Rpoint<150), то пропускаем сброс
    ldi  Rpoint, $00 ;Сброс Rpoint (При C(SREG)=0)
  NoResetPoint:
;
;Перевод полученного результата АЦП в миллиметры:
  ldi  R16, 60
  mul  RdataH, R16 ;Результат умножения RdataH*R16 находится в R1 и R0.
;Округление результата:
  ldi  R16, 0b10000000
  ldi  R17, 0b00000000
  add  R0, R16
  adc  R1, R17
;Теперь в R1 находится значение положения потенциометрического датчика в мм.
;
;Вывод данных на порт C для внешнего устройства:
  mov  R16, R1
  com  R16  ;(для STK500)
  out  PortC, R16
;
;Переключение сигнала для светодиода на линии PD0:
;(Для проверки правильности интервала времени 0,02сек.):
  ldi  R16, Low (50)
  ldi  R17, High(50)
  cp   YL, R16
  cpc  YH, R17
  brcs NoBlinkLampPD0
  ;Сброс регистровой пары Y:
    ldi  YL, 0
    ldi  YH, 0
  ;Переключение сигнала линии PD0 порта D:
    in   R16, PortD
    ldi  R17, 0b00000001
    eor  R16, R17
    out  PortD, R16
  NoBlinkLampPD0:
;Увеличение значения регистровой пары Y на единицу:
  adiw YH:YL, 1
;
  reti  ;Выход из прерывания
        ;+ глобальное разрешение прерываний! (I(SREG)<-1)
то есть на порту С настроены на выход 6 линий, а на порту D - одна, нужно очистить порт D и перенести на порт С на линию 8(7 бит)
нужно сделать чтоб в этом отрывке
Assembler
1
2
3
4
Вывод данных на порт C для внешнего устройства:
  mov  R16, R1
  com  R16  ;(для STK500)
  out  PortC, R16
выводился не весь порт С а лишь биты с 0 по 5
0
pyzhman
795 / 488 / 67
Регистрация: 15.05.2012
Сообщений: 2,770
19.05.2015, 06:33 7
Цитата Сообщение от yura02 Посмотреть сообщение
биты с 0 по 5
Есть такая чУдная конструкция:
Assembler
1
2
3
xor 1_op,2_op
and maska
xor 1_op,2_op
0
19.05.2015, 06:33
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.05.2015, 06:33

Справочник по прерываниям Intel x86
Нужен справочник, в котором было бы написано примерно следующее: interrupt 10: принимает...

Delphi и ASM - не работает вызов функции Invoke через asm
В Delphi не работает вызов функции Invoke через asm. часть кода: asm invoke...

Создание проекта с участием c++ и asm модулей. Ошибка asm модуля
Доброго времени суток! Подскажите, пожалуйста, как исправить данную ошибку (А2008)?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru