Перейти к содержанию

Програмирование Ассемблер


Rusik05

Рекомендуемые сообщения

Вообще-то я про AVR, а ты? AVR сохраняет в стеке содержимое счетчика команд PC и загружает в него (PC) адрес вектора прерывания, а по возвращению команда RETI обеспечивает возвращение в основную программу и восстанавливает содержимое счетчика команд. Заметь, это он делает сам.

Изменено пользователем Геннадий
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

  • Ответов 54
  • Создана
  • Последний ответ

Топ авторов темы

Топ авторов темы

Изображения в теме

а по возвращению команда RETI

А если я составлю программу так, что не будет никакого RETI, и вернусь из подпрограммы по другому?

Разве у AVR такое не возможно?

Это все условности типа кто куда зашел или вышел. Просто AVR человек таким изобрел и вложил в него такой порядок выполнения инструкции (команды). Построят по другому и будет по другому.

Вообще-то я про AVR, а ты?

А я про то, что ВСЕ ЧТО ДЕЛАЕТ хоть AVR, хоть Z80, хоть К580 - это только выполняет программу человеком составленную. Просто я наблюдал не так давно как мой сын осваивал AVR и долго его убеждал начать составление программы своей не усевшись за компьютер, а спокойно с карандашем и на листе бумаги.

И процесс сразу сдвинулся с мертвой точки.

Сейчас переодически подглядываю за ним :) , начинает с рисования алгоритма на листе бумаги, а потом клавиши топчет.

Просто считаю, что вся эта процессорная тема ничего сама не делает, а делает только ВАШИ КОМАНДЫ и все проблемы (при отсутствии косяков аппаратных) это результат ВАШИХ КОМАНД.

Считаю, что если начинающий забъет себе в мозг эту идею то ему будет намного проще понимать тему программирования для процессора, а то, что память сегодня засовывают во внутрь маленькой микросхемы в принципе ничего не менят. Можно наверняка прямо в чип и микрофон вставить и программировать прямо голосом в этот микрофон.

Извиняйте за флуд. Больше не буду. :)

Изменено пользователем 131959G
Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Это не будет считаться возвратом. Процессор сохранит (как его учили) счетчик команд перед прерыванием, заняв ячейку стека. Если попытаться выйти из прерывания (как будет казаться) неординарным способом, то стек со временем будет переполнен и прога глюканет. А если "забыть" поднять флаг I в регистре состояния "руками", то и прерываний больше не будет. Нет, так нельзя.

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

А что "указатель стека" не доступен для программиста в AVR?

Установить то его хоть можно по новой или он жесткое аппаратное устройство?

Стек наверняка в области памяти лежит?

Программист может зайти в подпрограмму и переписать стек по своему усмотрению и изменить адреса возвратов?

Это в принципе "трюки" программные и они возможно не укладываются в стеретипы которые сложились, но все же?

Изменено пользователем 131959G
Ссылка на комментарий
Поделиться на другие сайты

Дело в том, что эти трюки могут привести к непредсказуемым последствиям, сделай программист хоть одну маленькую ошибку (например с уровнем стека). Вот для исключения этого, изготовители и "научили" камни некоторым моментам на аппаратном уровне. Ведь камень все-таки запоминает сам некоторые вещи, перед прерыванием. Да и адрес вектора прерывания он "выбирает" сам, на аппаратном уровне. А уж только потом (в прерывании или после его) ты можешь изменить стандартный ход событий. Все-таки что-то сам он делает.

Изменено пользователем Геннадий
Ссылка на комментарий
Поделиться на другие сайты

Как интересно! Все представляют один и тотже контроллер по разному!

Кто шкафом с ящичками, кто ещё как. :blink:

Вот бы составить выставку представлений в графическом виде! :rolleyes:

Не сочтите за оффтоп.

Изменено пользователем mazzi

Пока ты жив, надежда есть.

Ссылка на комментарий
Поделиться на другие сайты

Вот потому што уних представление об МК различаются, они и спорили. Как я понял они говорили чуть о разных вещах. Вот 131959G говорил что МК придумал человек и человек им управляет. Уже с момента проектирования МК. А вот Геннадий говорил уже о непосредственной работе МК, готового к пименению, любителями или профи. Жаль что Я немогу спорить свами на Вашем уровне.

Такой вопрос. Я тут прочёл, что регистры ввода вывода I/O служат для связи центрального процессора с переферийными устройствами самой микросхемы, таймеры, компараторы, шим и тд.

А порты (PD0, PD1, PD3 итд ) не относятся кним?

Ссылка на комментарий
Поделиться на другие сайты

Мы с Генычем и не спорили вовсе. Так, мило беседовали, "выискивая" истину, можно сказать.

Кстати, mazzi, все началось с твоего оригинального представления  МК (см. пост 17). :)

Ссылка на комментарий
Поделиться на другие сайты

Иногда нестандартный взгляд на привычные вещи открывает такое, что просто ... нет слов... :blink:

Такой вопрос. Я тут прочёл, что регистры ввода вывода I/O служат для связи центрального процессора с переферийными устройствами самой микросхемы, таймеры, компараторы, шим и тд.

А порты (PD0, PD1, PD3 итд ) не относятся кним?

Указанные вами порты(PD0, PD1, PD3) служат для связи центрального процессора с внешними устройствами(вне микросхемы).

Пока ты жив, надежда есть.

Ссылка на комментарий
Поделиться на другие сайты

А порты (PD0, PD1, PD3 итд ) не относятся кним?

Порты являются для контроллера регистрами, не более. Т.е. регистры служат для связи ядра контроллера с портом, а порт - контроллера с внешним миром.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Программа должна выполнять следующие действия

1)Сканировать состояние порта PD0 и считать количество нажатий.

2)Выводить соответствуюшую нажатию цифру, используя все порты PB для вывода на семисегментный индикатор, соответствующего числа.

3)После подщёте десяти нажатий, на одинадцатом нажатии подать 0 на PB7 что соответствует h в индикаторе. То есть загарается точка.

4)Следующее нажатие возвращает процесс и высвечивает цифру 1 и т.д.

post-57989-1256763136_thumb.jpg

Такой вопрос. Как вывести семисегментный код через порт PB ?

А вот мой вариант Например: создаем рабочие регистры тоесть, подразумеваем что каждый регистр соответствует цифре от 0 до 9 (0=R16, 1=R17, 2=R18 и т.д)

и назначаем для каждого регистра в соответствующем разряде (в бите) соответствующий уровень 0 или 1. Комбинация которого соответствует цифре. Например R16=0b00000011 т.е цифра один в семисегментном индикаторе. И соответствено дальше оперируем ими. Думаю что алгоритм я смогу составит, а вот написать программу потребуется помощь позже.

Может это приметивно для вас но я пока учусь, поэтому такая прозьба, не раскрывайте все карты, а просто направляйте. Благодорю за содействие.

Изменено пользователем Rusik05
Ссылка на комментарий
Поделиться на другие сайты

;Здесь необходимо табличное преобразование

table1: .db 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90

;digit 0 1 2 3 4 5 6 7 8 9

.db 0x88,0x83,0xc6,0xa1,0x86,0x8e,0x87,0xef,0xeb,0xAF,0xFF,0x00

;digit a b c d e f t 1 2 r ____

cif_out_port_b:

lds r16,cifra

clr r17

ldi r31,high(table1<<1)

ldi r30,low(table1<<1)

add r30,r16

adc r31,r17

lpm r16,Z

out portb,r16

ret

Ссылка на комментарий
Поделиться на другие сайты

terminal немоглибы добавить коментарии, ато непонятны некоторы строки.

А мой вариант не подходит?

Изменено пользователем Rusik05
Ссылка на комментарий
Поделиться на другие сайты

terminal немоглибы добавить коментарии, ато непонятны некоторы строки.

А мой вариант не подходит?

Ваш нет.

table1: .db 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 ;таблица в памяти программ для семисегментного индикатора, бит 0-сегмент включен, бит в 1 выключен

; к примеру 0= 0xC0 что соответствует 0В11000000 или выключенной точке и средней линии и включенным остальным сегментам тобиш выводится 0.

;digit 0 1 2 3 4 5 6 7 8 9

.db 0x88,0x83,0xc6,0xa1,0x86,0x8e,0x87,0xef,0xeb,0xAF,0xFF,0x00

;digit a b c d e f t 1 2 r ____

cif_out_port_b: ;указатель на программу (метка)

lds r16,cifra ;загружаем в регистр r16 значение числа,если 0 выведет 0, если 1 то выведет 1 и.т.д.

clr r17 ;очищаем регистр r17 загружаем в него 0.

ldi r31,high(table1<<1) ;загружаем в регистр Z адрес таблицы в памяти программ

ldi r30,low(table1<<1)

add r30,r16 ;складываем наше число с адресом таблицы, тем самым смещаемся на количество ячеек соответствующее нашей цифре

adc r31,r17

lpm r16,Z ;загружаем число из таблицы

out portb,r16 ;выводим его в порт, тем самым зажигая нужные сегменты

ret ;возвращаемся из программы

Надеюсь понятно ;)

Ссылка на комментарий
Поделиться на другие сайты

  • 2 недели спустя...

Уважаемый terminal Вы говорили что мой вариант не подходит. Но Я всетаки решил зделать по своему, толька для того чтобы закрепить прочитаное. Вроде чтота получилось, хоть логически не имеет смысла решать эту задачу таким способом, но для обучения, самодеятельность думаю лучще чем копирование. Незнаю как оценить свою программу учитывая что это мая первая программа

поэтому выслущаю все ваши замечания.

Вот файл дла симуляции в Протеус 7.5PrN1.rar

; проект Щёт нажатий
;
;

;------Псевдо команды управления
.include "tn2313def.inc"
.list
.def	temp1=r16
.def	temp2=r17
.def	temp3=r18
;------Начало програмного кода
.cseg
.org	0
;------Инициализация стека
ldi	temp1,RAMEND
out	SPL,temp1	
;------Инициализация портов ВВ	
ldi	temp1,0
out	DDRD,temp1
ldi	temp1,0xFF
out	DDRB,temp1
out	PORTB,temp1
out	PORTD,temp1
;------Инициализация компаратора
ldi	temp1,0x80
out	ACSR,temp1
;------Начало основного цикла		
main:	ldi	temp1,0b01000000	;0
out	PORTB,temp1
in	temp3,PIND
sbrc	temp3,0
rjmp	main
ldi	temp2,0b01111001	;1
out	PORTB,temp2
rjmp	pauza1
m1:	in	temp3,PIND
sbrc	temp3,0
rjmp	m1
ldi	temp2,0b00100100	;2
out	PORTB,temp2
rjmp	pauza2
m2:	in	temp3,PIND
sbrc	temp3,0
rjmp	m2
ldi	temp2,0b00110000	;3		
out	PORTB,temp2
rjmp	pauza3
m3:	in	temp3,PIND
sbrc	temp3,0
rjmp	m3
ldi	temp2,0b00011001	;4		
out	PORTB,temp2
rjmp	pauza4
m4:	in	temp3,PIND
sbrc	temp3,0
rjmp	m4
ldi	temp2,0b00010010	;5		
out	PORTB,temp2
rjmp	pauza5
m5:	in	temp3,PIND
sbrc	temp3,0
rjmp	m5
ldi	temp2,0b00000010	;6		
out	PORTB,temp2
rjmp	pauza6
m6:	in	temp3,PIND
sbrc	temp3,0
rjmp	m6
ldi	temp2,0b01111000	;7		
out	PORTB,temp2
rjmp	pauza7
m7:	in	temp3,PIND
sbrc	temp3,0
rjmp	m7
ldi	temp2,0b00000000	;8		
out	PORTB,temp2
rjmp	pauza8
m8:	in	temp3,PIND
sbrc	temp3,0
rjmp	m8
ldi	temp2,0b00010000	;9		
out	PORTB,temp2
rjmp	pauza9
m9:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza9
rjmp	main					
;------Процедура задержки1	
pauza1:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza1
rjmp	m1	
pauza2:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza2
rjmp	m2		
pauza3:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza3
rjmp	m3	
pauza4:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza4
rjmp	m4
pauza5:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza5
rjmp	m5	
pauza6:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza6
rjmp	m6
pauza7:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza7
rjmp	m7
pauza8:	in	temp3,PIND
sbrs	temp3,0
rjmp	pauza8
rjmp	m8
pauza9:	in	temp3,PIND
sbrc	temp3,0
rjmp	m9
rjmp	m8	

Ссылка на комментарий
Поделиться на другие сайты

ой нимогу ... (это был коментарий кода) посмотри в справке по командам что такое CALL и RET думаю, алгоритм сразу упростится.

и от дребезга контакта это не спасет.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

ой нимогу ... (это был коментарий кода)

Последовал вашему совету что скажете наэтот раз (помните это моя вторая программа).Надеюсь для второй проги не слишком приметивно, хотя использую не тот способ что советовал terminal. Это я делою для лучщего запоминания, того что изучаю шаг за шагом чтобы не упустить основных понятий. Ведь упушение простого это непонимание сложного в дальнейшем.

.include "tn2313def.inc"
.list
.def	temp=R16
.def	loop=R18
;---Начало програмного кода
.cseg
.org	0
;---Инициализация стека	
ldi	temp,RAMEND
out	spl,temp
;---Инициализация портов ВВ	
ldi	temp,0
out	DDRD,temp
ldi	temp,0xFF
out	DDRB,temp
out	PORTB,temp
out	PORTD,temp
;---Инициализация компаратора	
ldi	temp,0x80
out	ACSR,temp
;---Начало основного цикла
main:	in	temp,PIND	
sbrc	temp,0
rjmp	main
ldi	loop,0xC0
rcall	wait
out	PORTB,loop
rcall	wait2
m1:	in	temp,PIND	
sbrc	temp,0
rjmp	m1
ldi	loop,0xF9
rcall	wait
out	PORTB,loop
rcall	wait2
m2:	in	temp,PIND	
sbrc	temp,0
rjmp	m2
ldi	loop,0xA4
rcall	wait
out	PORTB,loop
rcall	wait2
m3:	in	temp,PIND	
sbrc	temp,0
rjmp	m3
ldi	loop,0xB0
rcall	wait
out	PORTB,loop
rcall	wait2	
m4:	in	temp,PIND	
sbrc	temp,0
rjmp	m4
ldi	loop,0x99
rcall	wait
out	PORTB,loop
rcall	wait2	
m5:	in	temp,PIND	
sbrc	temp,0
rjmp	m5
ldi	loop,0x92
rcall	wait
out	PORTB,loop
rcall	wait2	
m6:	in	temp,PIND	
sbrc	temp,0
rjmp	m6
ldi	loop,0x82
rcall	wait
out	PORTB,loop
rcall	wait2	
m7:	in	temp,PIND	
sbrc	temp,0
rjmp	m7
ldi	loop,0xF8
rcall	wait
out	PORTB,loop
rcall	wait2							
m8:	in	temp,PIND	
sbrc	temp,0
rjmp	m8
ldi	loop,0x80
rcall	wait
out	PORTB,loop
rcall	wait2	
m9:	in	temp,PIND	
sbrc	temp,0
rjmp	m9
ldi	loop,0x90
rcall	wait
out	PORTB,loop
rcall	wait2
rjmp	main			
;Цикл ожидания отпускания кнопки
wait2:	push	loop
wt2:	in	loop,PIND
sbrs	loop,0
rjmp	wt2
pop	loop
ret	
;---Цикл задержки
wait:	push	loop
ldi	loop,200
wt1:	dec	loop
brne	wt1
pop	loop
ret	

Изменено пользователем Rusik05
Ссылка на комментарий
Поделиться на другие сайты

Что-то в такие дебри залезли ... смотрю в листинг и практически ничего не понимаю ... как-то это некрасиво для простейшей программки. Зря ты начал сразу в кодах писать, составь для начала алгоритм на бумажке или в электронном виде - графически. потом каждый ромбик и квадратик преобразуешь в ассемблерные команды, обычно так делается ВСЕГДА ... просто кому в голове это держится а кто-то через листик ...

Ну не понимаю я зачем для такой простейшей программы столько меток?

Наколько я понимаю, там достаточно организовать бесконечный цикл с опросом состояния конопки и когда это состояние изменяется с 0 на 1 прибавлять внутренний счетчик, преобразовать его в 7-сегментный код и вывести в порт. Даже не используя табличных преобразований код явно должен выглядеть иначе.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

;-----Начало основного цикла

main:	sbi	PORTB,0
in	temp,PIND
sbrc	temp,0
rjmp	main

;-----Мигание светодиода
cbi	PORTB,0
rcall	wait1

sbi	PORTB,0
rcall	wait1

rjmp	main

;-----Программа задержки

wait1:	push	loop1
push	loop2
push	loop3

ldi	loop3, 15
wt1:	dec	loop3
breq	wt4
ldi	loop2, 100					
wt2:	dec	loop2
breq	wt1 
ldi	loop1, 255
wt3:	dec	loop1
brne	wt3
rjmp	wt2
wt4:	pop	loop3
pop	loop2
pop	loop1
ret	

Как указано автором (Белов) Этот код должен обеспечить мигание сватодиола с частотой 5Гц, и для этог необходимо время задержки 0.2сек. Но уменя получается частота около 0.1-0.2Гц.

Как я понял принцип здесь такой (умножение) 255*100=25500 и 25500*15=382500 т.е 382500 тактов задержки. F=4MГц.

Если один такт можно принять за один периуд, то Т=1/4МГц=25*10^-8 (0.00000025), а для пяти герц Т=1/5=0.2 чтобы получить 0.2 секунды задержки необходимо 0.2/25*10^-8=800 000 тактов.

382500 тактов светодиод горит, 382500 такта диод негорит (+- другие такты), вроде все сходится.

Вопрос: есть вчемто ошибка автора или моя? как проще подшитывать ? Или может Протеус неможет симулировать вовсех случаях приближено к реальному.

Изменено пользователем Rusik05
Ссылка на комментарий
Поделиться на другие сайты

Немножко не так. Каждая команда вполняется за половину машинного цикла, а машинный цикл процессора определяется тактовой частотой деленной на 4. И только команды перехода выполняются за один машинный цикл, но т.к. они в задержке редки можно пренебречь.

а теперь посчитай сколько времени пройдет за 382500 такта при 4Мгц ...

ПРотеус вообще нельзя брать за эталон, кстати у него в строке статуса есть симулируемое время - по нему и ориентируйся, а так же по делениям осциллографа. Но лучше всего конечно это делать в MPlab, там можно замерять время выполнения между любыми участками кода в ходе симуляции.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Каждая команда вполняется за половину машинного цикла, а машинный цикл процессора определяется тактовой частотой деленной на 4.

Но ведь если делить тактовую частоту на четыре т.е. 4 000 000/4=1 000 000. если я правильнопонял то половина цикла это 500 000. Слишком долго

А как насчет 1мипс этоведь 1/4 000 000 тоесть 4 милиона опираций в секунду (или непонял) "Благодору за помощь"

Ссылка на комментарий
Поделиться на другие сайты

Половина цикла а не частоты.

За один машинный цикл в конвеере выполняется две команды - для одной команды происходит выборка, а для предыдущей в этот же момент происходит выполнение. Вобщем, гораздо проще это проиллюстрировано в даташите на контроллер, все фазы прохождения выполнения команд.

При этом следует оперировать не частотой а ВРЕМЕНЕМ выполнения машинного цикла.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Спасибо по датащиту понял все. И ешё вычетал на другом форуме-

(Ещё если быть более точным по выполнению команд, то у Atmelелов и PICах команды выполняются за один машинный цикл. Отличие в том, что у Atmelов машинный цикл равен одному периоду тактовой частоты, а у PICов тактовая частота делится на четыре такта, и за эти четыре такта выполняется комманда.

Посчитав, получается:

Atmel: при f=1МГц машинный цикл составляет 1/1000000Гц=1мкС

PIC: при f=1МГц машинный цикл составляет 1000000Гц/4=250000Гц => 1/250000Гц=4мкС => 4*4= 16 мкС

Получается, что при одинаковом кварце контроллер Atmel быстрее PICа в 16 раз, а это большой плюс для Atmelа.

Ну и с ценой конечно согласен. Почему PIC такой дорогой даже не знаю.)

Я изучаю AVR

Изменено пользователем Rusik05
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...