Свежие обсуждения
Микроконтроллеры

TEX учится

1 7

Tadas: А какого черта у Вас закоментирована команда бесконечного цикла ?

А она нужна только для отладки, эмулятора, которые не умеет спать. Перед ней стоит команда перевода МК в ждущий режим: mov PCON, #001h
(установка бита IDL). МК встает с сохранением всех состояний, а таймер молотит. Дальше, происходит прерывание, МК просыпается, выполняет немного развесистый обработчик прерывания, заталкивает в стек адрес программы перезапуска таймера, и опять спать.

 

TEX: Она нормально работает

Где ж нормально?
1) Вы загрузили в таймер константу "timer", перешли к метке cskip и вернулись (через RETI) к метке "timer_reload", опять перегрузили таймер той же константой, таймер ещё до переноса не досчитал, где тут нормально?

2) Вы загружаете в R7 константу сс (mov R7,#cc), потом перегружаете в R7 константу #high(timer_reload) (mov A,#high(timer_reload)). После метки tmr0_isr вы вычитаете 1 из R7, но это всегда одно и тоже число, которое вы выводите в порт Р0. Ну и зачем всё это?

3) Вы не выходите из подпрограммы прерываний, поскольку в конце подпрограммы переходите на её начало, разве это нормально? Сделайте обычный цикл в конце концов, и не морочьте всем голову, что х8051 не так работают.

4) Ну чего вы упираетесь, настройте стек на 0х09, да проверьте, как будет программа работать на всех МС.

TEX: Просто не знаю как по другому поменять адрес возврата.

Просто напишите sjmp timer_reload, поскольку эта инструкция полный функциональный эквивалент вашему нагромождению
cskip: pop ACC
pop ACC
mov A,#low(timer_reload)
push ACC
mov A,#high(timer_reload)
push ACC
setb EA
reti

 

Я так уже пробовал. Так программы не работают нормально. Пока не выполнено RETI, МК находится в обработке прерывания, и через несколько итераций программы (сколько там позволено вложенных прерываний) программу заклинивает.
Мне самому не нравятся эти костыли.
Таймер не может не досчитать до конца, потому что после запуска таймера следует команда остановки процессора. Выйти из этого состояния можно только по прерыванию. Ну, или по сбросу.
Указатель стека - сменю. Щас не могу, на работе.

Я не упираюсь. Я удивляюсь. Программа по шагам прохоженная в эмуле, а тут мне говорят что она нерабочая
P.S только что опять прошагал программу в эмуляторе. Стек ползет в сторону увеличения адреса, на R7 повлиять не может.

 

1) Ну, вам ещё удивляться и удивляться . Проверьте стек после первого РОР, ну и второго тоже. А потом можете проверить после PUSH

2) Формально в программе нет каких-то косяков, ну кроме стека, формально программа рабочая, но вот какие чудеса она при своём выполнении вытворяет...и, главное, за каким шутом? Или чем чудней написана программа, тем модней ?

 

Только что проверил. На метке cskip, SP - 09 После первого POP - 08, после второго - 07. Первый PUSH - 08, второй - 09

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

 

Хотя бы так

timer equ 65536-62500
cc equ 008h
ldport0 equ P1

org 0h
jmp main
org 0Bh
jmp tmr0_isr
main: clr A ; clear acc
mov R1,#000h ; clear reg
mov TMOD,#001h ;wind up timer
setb ET0
setb PT0
mov R7,#cc ;Load repeat counter
setb EA
timer_reload:
mov PCON,#001h ;sleep, sweet prince
sjmp timer_reload ;

tmr0_isr: clr TR0
clr EA
djnz R7,cskip
mov R7,#cc
mov A,R1
inc A
mov R1,A
cpl A
mov P0,A
cskip: mov TL0,#low(timer)
mov TH0,#high(timer)
setb TR0
setb EA
reti

 

Короче, чего-то с питанием МК (или с моими блоками питания) не т-е. Запитал МК от лития 18650 через самодельную платку преобразователя на 5В, все работает.

 

А кто нибудь может объяснить про сегменты, желательно - популярно. Зачем они нужны (то что память МК делится на виды - память программ (FLASH), оперативная - регистровые банки, бит-адресумая, доступная прямо, доступная косвенно и без этого знаю, и могу это использовать), зачем их объявлять, и как вообще пользоваться этими объявлениями. Зачем писать CSEG AT 0, если можно просто написать ORG 0? Зачем мне BSEG, если я могу просто указать нужный мне адрес и номер бита?

 

Это так, пока Ваши программы состоят из одного единственного модуля.
Если собирать программу из нескольких модулей, надо будет линкеру указать что и куда помещать.
Он и будет помещать данные по сегментам самым компактным способом автоматически.
Если не использовать этот механизм, придется вручную подсчитывать адреса кода и данных для каждого модуля. напр. имеем два програмных модуля: main.asm и foo.asm. В начале кода первого модуля написали ORG 0.
Для того, чтобы расположить код второго модуля впритык к окончанию кода первого, Вы должны будете сосчитать объём кода первого модуля.
А где ещё межмодульные переходы, адресация данных, описанных в другом модуле и т.п. ? В ручную всё это состыковать адский труд. И при каждом редактировании программы алреса будут меняться и пересчитывать придётся заново. Такого и врагу не пожелаешь
С использованием сегментов памяти связка ассемблер-линкер или С транслятор-линкер всё это будет делать автоматически.

 
1 7