Ассемблер (ASM) для AVR в вопросах и ответах
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
GP1 писал(а):В R0 грузится не адрес а содержимое байта памяти по адресу, который содержится в ZH:ZL
Вот это я протупил !!! Теперь все встало на свои места. И написано же "Загружает один байт, адресованный регистром Z, в регистр 0 (R0)..." Спасибо огромное, можно ехать дальше.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
edm2007 писал(а):Про множитель понятно, и про загрузку в регистровую пару тоже. Адрес ПЗУ 16-ти битный, так? И все это в пару грузится нормально (два регистра). А вот как этот адрес в R0 загружается я не понимаю.
В r0 загружается не адрес слова в ПЗУ, а значение этого слова, а точнее полуслова. Рассказываю
Когда вы грузите в пару Z адрес слова в ПЗУ, умноженный на 2, то младший бит получившегося числа будет равен 0, значит в r0 считывается значение младшего байта слова по адресу(здесь уже считайте что адрес не умножен на 2), загруженному в Z. Когда младший бит числа, соответсвующего адресу, будет равен 1, то в r0 загрузится старший байт слова.
Мое объяснение несколько сумбурно, лучше всего Вы найдите на сайте атмел документ AVR Instruction Set и в почитайте, там в начале расписаны все способы адресации с картинками, на мой взгляд очень доходчиво, после этого почитайте описание команды lpm, тогда думаю вообще неясностей не останется.
Попробую на всякий случай по-другому объяснить (для лучшего понимания см присоединенный рисунок):
пятнадцать старших бит, загруженных в Z определяют адрес по которому в r0 будет загружаться младший или старший байт слова, расположенного в памяти программ по этому адресу. Младший байт слова загружается в r0, если младший бит в Z равен 0, старший байт - если младший бит в Z равен 1.
- Вложения
-
- lpm.tif
- (70.48 КБ) 450 скачиваний
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
smac писал(а):В r0 загружается не адрес слова в ПЗУ, а значение этого слова, а точнее полуслова. Рассказываю
Когда вы грузите в пару Z адрес слова в ПЗУ, умноженный на 2, то младший бит получившегося числа будет равен 0, значит в r0 считывается значение младшего байта слова по адресу(здесь уже считайте что адрес не умножен на 2), загруженному в Z. Когда младший бит числа, соответсвующего адресу, будет равен 1, то в r0 загрузится старший байт слова.
И Вам спасибо огромное. Разумеется я перед тем как спросить проштудировал информацию про адресацию. И про то что младший значащий разряд указателя выбирает младший или старший байт слова тоже. Просто на адресе зациклился и завис... Теперь вопросов по-этому поводу нет, можно двигаться дальше.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
Внешние прерывания
Добрый день.
Разобравшись с переключением массивов по прерыванию reset решил добить проект бегущих огней до простенького автомата световых эффектов (пока без ШИМ). На внешние прерывания МК Attiny2313 повесил две кнопки (выбор режима и изменение скорости). С настройкой внешних прерываний вроде проблем не возникло, все заработало сразу. Правда возникли неясности. GIMSK я собственно разрешил внешние прерывания а MCUCR настроил на работу по низкому уровню. Теперь вопросы:
1. Осталось непонятным PCIE в GIMSK. Вроде как разрешение прерывания по изменению состояния выводов. Когда оно используется я не понимаю. При чем пишут что прерывание возникает при ЛЮБОМ изменении сигнала на ЛЮБОМ входе.
2. Та же история с флагами прерываний EIFR
3. Даже не вопрос а скорее небольшая просьба. Я прикрепил исходник этих огней, не могли бы вы посмотреть на предмет замечаний. Структура программы, может какие-то ошибки... Не хотелось бы с самого начала эти ошибки допускать.
4. И там же. Не могли бы вы натолкнуть на мысль, каким образом можно реализовать изменение скорости выполнения эффектов. По кольцу одной кнопкой.
Заранее благодарен.
Разобравшись с переключением массивов по прерыванию reset решил добить проект бегущих огней до простенького автомата световых эффектов (пока без ШИМ). На внешние прерывания МК Attiny2313 повесил две кнопки (выбор режима и изменение скорости). С настройкой внешних прерываний вроде проблем не возникло, все заработало сразу. Правда возникли неясности. GIMSK я собственно разрешил внешние прерывания а MCUCR настроил на работу по низкому уровню. Теперь вопросы:
1. Осталось непонятным PCIE в GIMSK. Вроде как разрешение прерывания по изменению состояния выводов. Когда оно используется я не понимаю. При чем пишут что прерывание возникает при ЛЮБОМ изменении сигнала на ЛЮБОМ входе.
2. Та же история с флагами прерываний EIFR
3. Даже не вопрос а скорее небольшая просьба. Я прикрепил исходник этих огней, не могли бы вы посмотреть на предмет замечаний. Структура программы, может какие-то ошибки... Не хотелось бы с самого начала эти ошибки допускать.
4. И там же. Не могли бы вы натолкнуть на мысль, каким образом можно реализовать изменение скорости выполнения эффектов. По кольцу одной кнопкой.
Заранее благодарен.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
- GP1
- Поставщик валерьянки для Кота
- Сообщения: 2401
- Зарегистрирован: Пт май 23, 2008 19:32:22
- Откуда: Россия, Волгоград
- Контактная информация:
использовать массивы для бегущих огней - это круто, гораздо проще реализовать на командах циклического сдвига, а обработку сдвига производить по прерыванию таймера.
добавте переменную которую будете увеличивать/уменьшать (без разницы) от мин до макс (или от макс до мин) значения при нажатии на кнопку, это будет коэф.пересчета дальше делайте с ним что хотите
добавте переменную которую будете увеличивать/уменьшать (без разницы) от мин до макс (или от макс до мин) значения при нажатии на кнопку, это будет коэф.пересчета дальше делайте с ним что хотите
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
GP1 писал(а):использовать массивы для бегущих огней - это круто, гораздо проще реализовать на командах циклического сдвига, а обработку сдвига производить по прерыванию таймера.
добавте переменную которую будете увеличивать/уменьшать (без разницы) от мин до макс (или от макс до мин) значения при нажатии на кнопку, это будет коэф.пересчета дальше делайте с ним что хотите
Из обучалки так пошло.
А обработка сдвига и так по прерыванию таймера происходит. Можно увеличивать переменную и затем грузить ее в компаратор? Или проще можно?
Последний раз редактировалось edm2007 Пт май 08, 2009 23:07:38, всего редактировалось 1 раз.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
- GP1
- Поставщик валерьянки для Кота
- Сообщения: 2401
- Зарегистрирован: Пт май 23, 2008 19:32:22
- Откуда: Россия, Волгоград
- Контактная информация:
Собственно я не вижу смысла в применении компаратора, для чего он здесь вообще, у вас же нет отслеживания какой-то аналоговой величины на входе или я не прав?
переменную можно использовать для изменения коэф.пересчета основного счетчика, определяющего время переключения между каналами.
зы: для изучения работы с массивами согласен.
переменную можно использовать для изменения коэф.пересчета основного счетчика, определяющего время переключения между каналами.
зы: для изучения работы с массивами согласен.
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
GP1 писал(а):Собственно я не вижу смысла в применении компаратора, для чего он здесь вообще, у вас же нет отслеживания какой-то аналоговой величины на входе или я не прав?
переменную можно использовать для изменения коэф.пересчета основного счетчика, определяющего время переключения между каналами.
зы: для изучения работы с массивами согласен.
Так не про аналоговой компаратор речь.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
Pooher писал(а):А вот как этот адрес в R0 загружается я не понимаю.
А по чему, если не секрет, это Вас так интересует? Ну грузится, и слава Богу
Такой уж я человек. Если что-то изучаю, то стараюсь это делать осмысленно и досконально. Предела совершенству нет, но стремиться к нему все же стоит.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Доброго времени суток!
Дамы и Господа !
Обьясните новичку, почему в блоке «Переключение светодиода» в первой строчке PINB а не PORTB? Ведь порт Б настроен на вывод
И …
Для каких целей в блоке «подпрограмма задержки» сохраняем в стек, а потом извлекаем из стека содержимое регистра loop ??? я так понимаю во время этой операции он вообще пустой, то есть забит нулями. Операция декремента, как я понимаю, производится не над содержимым стека ? а над реальным содержимым регистра
Бред имхо …
Программа :
;---------- Псевдокоманды управления
.include "tn2313def.inc" ; Присоединение файла описаний
.list ; Включение листинга
;---------- Начало программного кода
.cseg ; Выбор сегмента программного кода
.org 0 ; Устанеовка текущего адреса на ноль
.def temp = r16 ; Определение главного рабочего регистра
.def loop = r17 ; Определение регистра организации цикла
;---------- Инициализация стека
ldi temp, 0x7F ; Выбор адреса вершины стека
out SPL, temp ; Запись его в регистр стека
;---------- Инициализация Главного предделителя
ldi temp, 0x80 ; Записываем число $80 в регистр temp
out CLKPR, temp ; Записываем в регистр CLKPR
ldi temp, 0 ; Записываем 0 в регистр temp
out CLKPR, temp ; Записываем этот ноль в CLKPR
;---------- Инициализация портов ВВ
out DDRD, temp ; Записываем этот ноль в DDRD (порт PD на ввод)
ldi temp, 0xFF ; Записываем число $FF в регистр temp
out DDRB, temp ; Записываем это число в DDRB (порт PB на вывод)
out PORTB, temp ; Записываем то же число в PORTB (потушить светодиод)
out PORTD, temp ; Записываем его же в PORTD (включаем внутр. резисторы)
;---------- Инициализация компаратора
ldi temp, 0x80 ; Выключение компаратора
out ACSR, temp
;---------- Начало основного цикла
main:
in temp, PIND ; Читаем содержимое порта PD
sbrc temp, 0 ; Проверка младшего разряда
rjmp main ; Если не ноль, переходим в начало
rcall wait ; Вызов подпрограммы задержки
;---------- Переключение светодиода
in temp, PINB ; Читаем содержимое порта PB
sbrc temp, 0 ; Проверка младшего разряда
rjmp m1
sbi PORTB, 0 ; Установка выход PB0 в единицу
rjmp m2
m1: cbi PORTB, 0 ; Сброс PB0 в ноль
;---------- Цикл ожидания отпускания кнопки
m2: in temp, PIND ; Читаем содержимое порта PD
sbrs temp, 0 ; Проверка младшего разряда
rjmp m2 ; Продолжить ожидание отпускания кнопки
rcall wait ; Вызов подпрограммы задержки
rjmp main ; К началу цикла
;---------- Подпрограмма задержки
wait: push loop ; Сохраняем содержимое регистра loop
ldi loop, 200 ; Помещаем в loop константу задержки
; Цикл задержки
wt1: dec loop ; Уменьшаем значение регистра loop
brne wt1 ; Если не ноль, продолжаем цикл
pop loop ; Восстанавливаем значение регистра loop
ret ; Выход из подпрограммы
Дамы и Господа !
Обьясните новичку, почему в блоке «Переключение светодиода» в первой строчке PINB а не PORTB? Ведь порт Б настроен на вывод
И …
Для каких целей в блоке «подпрограмма задержки» сохраняем в стек, а потом извлекаем из стека содержимое регистра loop ??? я так понимаю во время этой операции он вообще пустой, то есть забит нулями. Операция декремента, как я понимаю, производится не над содержимым стека ? а над реальным содержимым регистра
Бред имхо …
Программа :
;---------- Псевдокоманды управления
.include "tn2313def.inc" ; Присоединение файла описаний
.list ; Включение листинга
;---------- Начало программного кода
.cseg ; Выбор сегмента программного кода
.org 0 ; Устанеовка текущего адреса на ноль
.def temp = r16 ; Определение главного рабочего регистра
.def loop = r17 ; Определение регистра организации цикла
;---------- Инициализация стека
ldi temp, 0x7F ; Выбор адреса вершины стека
out SPL, temp ; Запись его в регистр стека
;---------- Инициализация Главного предделителя
ldi temp, 0x80 ; Записываем число $80 в регистр temp
out CLKPR, temp ; Записываем в регистр CLKPR
ldi temp, 0 ; Записываем 0 в регистр temp
out CLKPR, temp ; Записываем этот ноль в CLKPR
;---------- Инициализация портов ВВ
out DDRD, temp ; Записываем этот ноль в DDRD (порт PD на ввод)
ldi temp, 0xFF ; Записываем число $FF в регистр temp
out DDRB, temp ; Записываем это число в DDRB (порт PB на вывод)
out PORTB, temp ; Записываем то же число в PORTB (потушить светодиод)
out PORTD, temp ; Записываем его же в PORTD (включаем внутр. резисторы)
;---------- Инициализация компаратора
ldi temp, 0x80 ; Выключение компаратора
out ACSR, temp
;---------- Начало основного цикла
main:
in temp, PIND ; Читаем содержимое порта PD
sbrc temp, 0 ; Проверка младшего разряда
rjmp main ; Если не ноль, переходим в начало
rcall wait ; Вызов подпрограммы задержки
;---------- Переключение светодиода
in temp, PINB ; Читаем содержимое порта PB
sbrc temp, 0 ; Проверка младшего разряда
rjmp m1
sbi PORTB, 0 ; Установка выход PB0 в единицу
rjmp m2
m1: cbi PORTB, 0 ; Сброс PB0 в ноль
;---------- Цикл ожидания отпускания кнопки
m2: in temp, PIND ; Читаем содержимое порта PD
sbrs temp, 0 ; Проверка младшего разряда
rjmp m2 ; Продолжить ожидание отпускания кнопки
rcall wait ; Вызов подпрограммы задержки
rjmp main ; К началу цикла
;---------- Подпрограмма задержки
wait: push loop ; Сохраняем содержимое регистра loop
ldi loop, 200 ; Помещаем в loop константу задержки
; Цикл задержки
wt1: dec loop ; Уменьшаем значение регистра loop
brne wt1 ; Если не ноль, продолжаем цикл
pop loop ; Восстанавливаем значение регистра loop
ret ; Выход из подпрограммы
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
MeL$ писал(а):Доброго времени суток!
Дамы и Господа !
Обьясните новичку, почему в блоке «Переключение светодиода» в первой строчке PINB а не PORTB? Ведь порт Б настроен на вывод
И …
Для каких целей в блоке «подпрограмма задержки» сохраняем в стек, а потом извлекаем из стека содержимое регистра loop ???
Привет. Так все правильно, мы сначала загружаем содержимое порта B в temp, а потом командой sbrc проверяем младший разряд порта (куда подключен светодиод). Нам же нужно знать, горит он в данный момент или нет. Команда sbrc вызывает пропуск следующей за ней команды, если проверяемый регистр РОН сброшен (0). У команды два параметра, имя регистра общего назначения, и номер проверяемого бита. Вот мы и проверяем младший разряд. Если он равен нулю (я не знаю как светодиод подключен, ну допустим он не горит), мы пропускаем команду rjmp m1 а сразу переходим к установке 1 в порт B0 (зажигаем светодиод), если же он не равен нулю (светодиод горит), команду rjmp m1 не пропускаем, и переходим к сбросу порта B0 (гасим светодиод). Таким образом в зависимости от того что имеется на порту к которому подключен светодиод мы принимаем решение как действовать дальше. Либо менять 0 на 1, либо 1 на 0.
А по-поводу стека... В данном случае оно смысла не имеет, хотя подобная процедура - штука полезная. Ибо по окончанию подпрограммы задержки, значения всех регистров МК остаются без изменений. Полезно тогда, когда та же переменная используется в основном цикле. Какую взяли - такую и вернули.
Запутал наверное еще больше, но вроде так... Я сам недавно начал изучать asm, так что сильно не бейте.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
- GP1
- Поставщик валерьянки для Кота
- Сообщения: 2401
- Зарегистрирован: Пт май 23, 2008 19:32:22
- Откуда: Россия, Волгоград
- Контактная информация:
to MeL$
ИМХО
Некоторые замечания по оформлению текста программы,
для данной программы это не существенно, но когда перейдете к более менее серьезным проектам дурная привычка скажется.
- описывайте переменные до кодового сегмента
- оставляйте место под вектора прерываний, только в простейших примерах не используются разлиные прервания :
- пользуйтесть опредлениями из файла хххххdef.inc. так для верхней границы ОЗУ лучше использовать "RAMEND"
меньше вариантов допустить ошибку
- сохраняйте в стеке регистры используемые для промежуточных операций в подпрограммах, поверьте эта привычка съэкономит кучу времени и нервов, не надо будет искать - почему это программа выдает "цену на дрова в прошлом году" вместо того что надо
В общем не наступайте на грабли по которым уже прошлись другие, приучите себя сразу писать "красиво", ведь "красота спасет мир" (и программистов
)
ИМХО
Некоторые замечания по оформлению текста программы,
для данной программы это не существенно, но когда перейдете к более менее серьезным проектам дурная привычка скажется.
- описывайте переменные до кодового сегмента
- оставляйте место под вектора прерываний, только в простейших примерах не используются разлиные прервания :
Код: Выделить всё
.org 0
jmp(или rjmp для младших процессоров) start
...
(таблица векторов прерываний)
...
start: ; начало основной программы
- пользуйтесть опредлениями из файла хххххdef.inc. так для верхней границы ОЗУ лучше использовать "RAMEND"
Код: Выделить всё
ldi temp,low(RAMEND)
out SPL,temp
меньше вариантов допустить ошибку
- сохраняйте в стеке регистры используемые для промежуточных операций в подпрограммах, поверьте эта привычка съэкономит кучу времени и нервов, не надо будет искать - почему это программа выдает "цену на дрова в прошлом году" вместо того что надо
В общем не наступайте на грабли по которым уже прошлись другие, приучите себя сразу писать "красиво", ведь "красота спасет мир" (и программистов
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
А вот мне, к сожалению, никто помочь не хочет.
Не могу я понять как изменить скорость бегущих огней. Задержка между переключением светодиодов через прерывание таймера по совпадению. Ну введу я переменную скорости, буду ее в обработчике прерывания увеличивать / уменьшать, а вот как все это в компаратор записать я не соображу никак. 
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
- GP1
- Поставщик валерьянки для Кота
- Сообщения: 2401
- Зарегистрирован: Пт май 23, 2008 19:32:22
- Откуда: Россия, Волгоград
- Контактная информация:
У вас же есть строки:
Это и есть загрузка компаратора таймера
ИМХО я бы сделал так:
1. организал бы счетчик Т1 на формирование какого-нибудь определенного промежутка времени
2. с помощью клавы изменял коеэф. пересчета кратный заданным интервалам Т1 (не забывать при вводе коэф блокировать Т1 а то получится бред)
3. по каждому "сбросу по совпадению" Т1 уменьшал коэф на 1, пока не станет равным нулю
4. изменяем состояние порта управления светиками
5. восстанавливаем значение коэф.
6. переход на п.3 и так по кругу.
Код: Выделить всё
ldi temp, 0x3d ; инициализация компаратора (загружаем число, с которым сравниваем таймер)
out ocr1ah, temp
ldi temp, 0x09
out ocr1al, temp
Это и есть загрузка компаратора таймера
ИМХО я бы сделал так:
1. организал бы счетчик Т1 на формирование какого-нибудь определенного промежутка времени
2. с помощью клавы изменял коеэф. пересчета кратный заданным интервалам Т1 (не забывать при вводе коэф блокировать Т1 а то получится бред)
3. по каждому "сбросу по совпадению" Т1 уменьшал коэф на 1, пока не станет равным нулю
4. изменяем состояние порта управления светиками
5. восстанавливаем значение коэф.
6. переход на п.3 и так по кругу.
edm2007 писал(а):MeL$ писал(а):Доброго времени суток!
Дамы и Господа !
Обьясните новичку, почему в блоке «Переключение светодиода» в первой строчке PINB а не PORTB? Ведь порт Б настроен на вывод
И …
Для каких целей в блоке «подпрограмма задержки» сохраняем в стек, а потом извлекаем из стека содержимое регистра loop ???
Привет. Так все правильно, мы сначала загружаем содержимое порта B в temp, а потом командой sbrc проверяем младший разряд порта (куда подключен светодиод). Нам же нужно знать, горит он в данный момент или нет. Команда sbrc вызывает пропуск следующей за ней команды, если проверяемый регистр РОН сброшен (0). У команды два параметра, имя регистра общего назначения, и номер проверяемого бита. Вот мы и проверяем младший разряд. Если он равен нулю (я не знаю как светодиод подключен, ну допустим он не горит), мы пропускаем команду rjmp m1 а сразу переходим к установке 1 в порт B0 (зажигаем светодиод), если же он не равен нулю (светодиод горит), команду rjmp m1 не пропускаем, и переходим к сбросу порта B0 (гасим светодиод). Таким образом в зависимости от того что имеется на порту к которому подключен светодиод мы принимаем решение как действовать дальше. Либо менять 0 на 1, либо 1 на 0.
А по-поводу стека... В данном случае оно смысла не имеет, хотя подобная процедура - штука полезная. Ибо по окончанию подпрограммы задержки, значения всех регистров МК остаются без изменений. Полезно тогда, когда та же переменная используется в основном цикле. Какую взяли - такую и вернули.
Запутал наверное еще больше, но вроде так... Я сам недавно начал изучать asm, так что сильно не бейте.
ага всем спасибо за ответы/советы, но наверное вопрос не поняли (((
или я его непонятно сформулировал ...
меня интересует почему используется именно PINB , а не PORTB ???
мы же для порта Б ddr установили, тоесть порт Б работает на вывод
почему тогда используется PINB
ведь PINB - это ввод , а у нас вывод
имхо ...
ту GP1
по культуре оформления программы замечания учту - спасибо!
просто я пока только начинаю заниматься и всех тонкостей просто не понимаю ...
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
MeL$ писал(а):ага всем спасибо за ответы/советы, но наверное вопрос не поняли (((
или я его непонятно сформулировал ...
меня интересует почему используется именно PINB , а не PORTB ???
мы же для порта Б ddr установили, тоесть порт Б работает на вывод
почему тогда используется PINB
ведь PINB - это ввод , а у нас вывод
имхо ...
ту GP1
по культуре оформления программы замечания учту - спасибо!
просто я пока только начинаю заниматься и всех тонкостей просто не понимаю ...
Потому что PORTB не соединен электрически внутри МК со схемой входа, он может работать только в режиме «выход».
Если необходимо считать состояние вывода порта, то это надо делать из PINB, так как именно через него осуществляется считывание данных в МК.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
-
YurkaM
- Нашел транзистор. Понюхал.
- Сообщения: 151
- Зарегистрирован: Пн сен 01, 2008 14:49:03
- Откуда: Казахстан
MeL$, PORTB доступен и для записи, и для чтения, так же как и PINB. Но при чтении с PINB мы получим реальное состояние на ноге порта, а при чтении PORTB то значение, которое записано в этот регистр. И в общем случае эти значения не обязаны совпадать - например во время переходных процессов, или когда нагрузка на ногу слишком большая. Всё это сказано к случаю, когда порт настроен на вывод, т.е. в DDRB записаны единицы. Я к сожалению, плохо объясняю, посмотри на схему вывода порта по даташиту или в книжке какой, - и всё будет ясно.
ps: кстати в данной программе правильней будет читать всё-таки с PORTB, а не с PINB.
ps2: И вообще, что бы проверить состояние одного бита порта, совсем не обязательно его читать полностью. Для этого есть команды sbic, sbis.
ps3: Да, а если бы МК был класса Мега, то было бы ещё проще:
И всё!!
ps: кстати в данной программе правильней будет читать всё-таки с PORTB, а не с PINB.
ps2: И вообще, что бы проверить состояние одного бита порта, совсем не обязательно его читать полностью. Для этого есть команды sbic, sbis.
Код: Выделить всё
;---------- Переключение светодиода
sbic PORTB, 0 ; Проверка младшего разряда
rjmp m1
sbi PORTB, 0 ; Установка выход PB0 в единицу
rjmp m2
m1: cbi PORTB, 0 ; Сброс PB0 в нольps3: Да, а если бы МК был класса Мега, то было бы ещё проще:
Код: Выделить всё
;---------- Переключение светодиода
sbi PINB,0 ;инверсия PB0И всё!!
