Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Понял лучше про логику работы лестницы. Если регистрировать только момент входа человека на лестницу и организации подсветки в направлении последнего входа, в случае с одной лестницей (2 датчика по одному на каждом конце) использование конечного автомата видится мне следующим образом. Представьте себе устройство с тремя состояниями S1, S2, S3. В состоянии S1 подсветка лестницы выключена, в S2 она производится бегущим огнем в направлении от конца А до Б, а в S3 - в направлении от Б до А. Переходы между состояниями производятся в результате детектирования одного из следующих трех событий: сигнал от датчика А, сигнал от датчика Б, и сигнал переполнения таймера по истечении 100-мсек интервала. В каждый момент времени обрабатывается одно событие - процессор-то у нас один.
В состоянии S1: таймер выключен. При сигнале от датчика А запускаем таймер, устанавливаем count=10, и переходим в состояние S2. Аналогично, при сигналe от датчика Б запускаем таймер, устанавливаем count=10, и переходим в состояние S3.
В состоянии S2: при переполнении таймера и count>0 поджигаем следующую лампу в направлении от А к Б, уменьшаем count на 1 и остаемся в состоянии S2. При переполнении таймера и count=0, выключаем таймер, лампы, и переходим в состояние S1. При сигнале от датчика А (на лестницу зашел человек вслед за первым) устанавливаем count=10, поджигаем первую лампу в направлении от А до Б и остаемся в этом состоянии. Наконец при сигнале от датчика Б (на лестницу зашел человек с другого конца и идет навстречу первому) устанавливаем count=10, поджигаем первую лампу в направлении от Б до А и переходим в состояние S3.
Аналогично в состоянии S3: при переполнении таймера и count>0 поджигаем следующую лампу в направлении от Б к A, уменьшаем count на 1 и остаемся в состоянии S3. При переполнении таймера и count=0, выключаем таймер, лампы, и переходим в состояние S1. При сигнале от датчика Б (на лестницу зашел человек вслед за первым) устанавливаем count=10, поджигаем первую лампу в направлении от Б до А и остаемся в этом состоянии. Наконец при сигнале от датчика А (на лестницу зашел человек с другого конца и идет навстречу первому) устанавливаем count=10, поджигаем первую лампу в направлении от А до Б и переходим в состояние S2.
Реализация: нужна будет переменная state хранящая номер текущего состояния. Она инициализируется в 1 до входа в основной цикл программы и переустанавливается каждый раз при переходе между состояниями. Основной цикл программы начинается с разрешения прерываний и помещения процессора в сон. Выход из сна производится по получению любого из сигналов после стабатывания обработчика его прерывания. Запрещаем прерывания глобально (запрет прерываний не мешает установке флагов прерываний, т.е. их аппаратному фиксированию), анализируем значение state и переходим в соответствующую ветку кода как указано выше. После отработки команд перехода из одного состояния в следующее переходим на начало цикла, и все повторяется. Таким образом, программа будет полностью "interrupt driven". В обработчике каждого прерывания сбрасываем флаг этого прерывания в регистре МК (если он не сбрасывается автоматом) и устанавливаем софтверный флаг события, который будет анализироваться для переходов между состояниями.
В случае двух лестниц для обработки событий от датчиков А2,Б2 второй лестницы проще всего добавить 3 состояния S4, S5, S6 - аналогов S1, S2 и S3 для первой лестницы - и задействовать еще один таймер МК для временных интервалов второй лестницы (путем некоторого усложнения программы можно обойтись и одним таймером). При независимой подсветки лестниц удобно для второй лестницы завести свою переменную state2 и инициализировать ее в 4. Таким образом, при получении события от датчиков первой лестницы и ее таймера переходы будут осуществляться между состояниями S1 - S3 в зависимости от значения state1. В случае получения события от датчиков второй лестницы и таймера_2 переходы будут осуществляться между состояниями S4 - S6 в зависимости от state2. Только я не понимаю зачем тянуть провода от датчиков и ламп обоих лестниц к централизованному контроллеру. Не проще-ли вблизи каждой лестницы поставить свое независимое устройство с копеечным МК. Если только лестницы не рядом находятся...
Насчет режимов сна МК: очень удобно задействовать таймер, тактируемый отдельным генератором отличным от генератора, тактирующего ЦПУ. В этом случае МК можно будет помешать в глубокий сон. Однако, в атмеловском х51 такого отдельного генератора нет. Поэтому при переходе в состояния S2/S3 придется помещать ЦПУ в режим неглубокого сна с работающим тактовым генератором. Вы писали, что токопотребление Вам неважно, но меня сильно нервирует если МК зря пожирает миллиамперы. В случае "нормального" МК все устройство контроля вообще можно от батареек запитать, которых хватит на несколько лет. Или от изредка подзаряжаемого аккума. Тогда можно будет подумать о коммутировании БП устройства, если он все-таки нужен для управления лампами, в моменты простоя (основное состояние). А то сетевой адаптер то там, то сям, еще один здесь - так и набегает.
В состоянии S1: таймер выключен. При сигнале от датчика А запускаем таймер, устанавливаем count=10, и переходим в состояние S2. Аналогично, при сигналe от датчика Б запускаем таймер, устанавливаем count=10, и переходим в состояние S3.
В состоянии S2: при переполнении таймера и count>0 поджигаем следующую лампу в направлении от А к Б, уменьшаем count на 1 и остаемся в состоянии S2. При переполнении таймера и count=0, выключаем таймер, лампы, и переходим в состояние S1. При сигнале от датчика А (на лестницу зашел человек вслед за первым) устанавливаем count=10, поджигаем первую лампу в направлении от А до Б и остаемся в этом состоянии. Наконец при сигнале от датчика Б (на лестницу зашел человек с другого конца и идет навстречу первому) устанавливаем count=10, поджигаем первую лампу в направлении от Б до А и переходим в состояние S3.
Аналогично в состоянии S3: при переполнении таймера и count>0 поджигаем следующую лампу в направлении от Б к A, уменьшаем count на 1 и остаемся в состоянии S3. При переполнении таймера и count=0, выключаем таймер, лампы, и переходим в состояние S1. При сигнале от датчика Б (на лестницу зашел человек вслед за первым) устанавливаем count=10, поджигаем первую лампу в направлении от Б до А и остаемся в этом состоянии. Наконец при сигнале от датчика А (на лестницу зашел человек с другого конца и идет навстречу первому) устанавливаем count=10, поджигаем первую лампу в направлении от А до Б и переходим в состояние S2.
Реализация: нужна будет переменная state хранящая номер текущего состояния. Она инициализируется в 1 до входа в основной цикл программы и переустанавливается каждый раз при переходе между состояниями. Основной цикл программы начинается с разрешения прерываний и помещения процессора в сон. Выход из сна производится по получению любого из сигналов после стабатывания обработчика его прерывания. Запрещаем прерывания глобально (запрет прерываний не мешает установке флагов прерываний, т.е. их аппаратному фиксированию), анализируем значение state и переходим в соответствующую ветку кода как указано выше. После отработки команд перехода из одного состояния в следующее переходим на начало цикла, и все повторяется. Таким образом, программа будет полностью "interrupt driven". В обработчике каждого прерывания сбрасываем флаг этого прерывания в регистре МК (если он не сбрасывается автоматом) и устанавливаем софтверный флаг события, который будет анализироваться для переходов между состояниями.
В случае двух лестниц для обработки событий от датчиков А2,Б2 второй лестницы проще всего добавить 3 состояния S4, S5, S6 - аналогов S1, S2 и S3 для первой лестницы - и задействовать еще один таймер МК для временных интервалов второй лестницы (путем некоторого усложнения программы можно обойтись и одним таймером). При независимой подсветки лестниц удобно для второй лестницы завести свою переменную state2 и инициализировать ее в 4. Таким образом, при получении события от датчиков первой лестницы и ее таймера переходы будут осуществляться между состояниями S1 - S3 в зависимости от значения state1. В случае получения события от датчиков второй лестницы и таймера_2 переходы будут осуществляться между состояниями S4 - S6 в зависимости от state2. Только я не понимаю зачем тянуть провода от датчиков и ламп обоих лестниц к централизованному контроллеру. Не проще-ли вблизи каждой лестницы поставить свое независимое устройство с копеечным МК. Если только лестницы не рядом находятся...
Насчет режимов сна МК: очень удобно задействовать таймер, тактируемый отдельным генератором отличным от генератора, тактирующего ЦПУ. В этом случае МК можно будет помешать в глубокий сон. Однако, в атмеловском х51 такого отдельного генератора нет. Поэтому при переходе в состояния S2/S3 придется помещать ЦПУ в режим неглубокого сна с работающим тактовым генератором. Вы писали, что токопотребление Вам неважно, но меня сильно нервирует если МК зря пожирает миллиамперы. В случае "нормального" МК все устройство контроля вообще можно от батареек запитать, которых хватит на несколько лет. Или от изредка подзаряжаемого аккума. Тогда можно будет подумать о коммутировании БП устройства, если он все-таки нужен для управления лампами, в моменты простоя (основное состояние). А то сетевой адаптер то там, то сям, еще один здесь - так и набегает.
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Спасибо за столь развернутую консультацию.
- FireProoF
- Мучитель микросхем
- Сообщения: 424
- Зарегистрирован: Чт май 14, 2015 15:11:39
- Откуда: Саратов
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Кто может расшифровать строку из Кеил о размере программы?
Program Size: data=63.3 xdata=0 code=2271
Желательно рассказать что где лежит)
Program Size: data=63.3 xdata=0 code=2271
Желательно рассказать что где лежит)
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Читать хелп по компилятору для кейла надоть.
А у атмелевского табличка несколько другая, но смысл одинаков:
вот только не пойму откуда дробное число в Вашем блоке data...
с51asm по описанию дает аналогию с кейлом - так битовая секция вроде отдельно печатается...

А у атмелевского табличка несколько другая, но смысл одинаков:
вот только не пойму откуда дробное число в Вашем блоке data...
с51asm по описанию дает аналогию с кейлом - так битовая секция вроде отдельно печатается...
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Доброго времени суток. С книжки переписана программка, которая должна играть мелодию. Но мелодии нет, есть тихое тиканье. Скорее всего я что-то не так переписал, но просто книжка стараю, и там есть нестандартные символы в коде, +программа написана так, как будто нотная запись Song размещена во внешней памяти данных. Так что наверное я что-то не так написал, когда разместил ее во внутренней памяти программ.
Спойлер
Код: Выделить всё
Buzzer equ P3.5
org 0
Song:
db 27h,27h,47h,27h,27h,47h,27h,27h
db 23h,25h,87h,28h,28h,28h,28h,28h
db 27h,27h,27h,27h,25h,25h,27h
db 45h,4Ah
db 27h,27h,47h,27h,27h,47h,27h,2Ah
db 23h,25h,87h,28h,28h,28h,28h,28h
db 27h,27h,27h
db 2Ah,28h,27h,27h,83h
db 00h ; Знак-терминатор "Конец текста"
Music:
mov DPTR,#Song ; Загрузка начального адреса Song
mov TMOD,#11h ; Инициализация T/C0 и T/C1
Main:
movx A,@DPTR ; Загрузка кода ноты
jz Exit_ ; Выход, если код равен 0
; Вычисление значений D и N
anl A,0Fh ; Выделение тетрады из байта
rl A ; Удвоение кода N
mov r6,A
movx A,@DPTR ; Повторная загрузка кода ноты
anl A,#0F0h ; Выделение тетрады D из байта
swap A
rl A ; Удвоение кода D
mov r7,A
Sound: ; Процедура генерации одной ноты
clr TCON.4 ; Остановим Timer0, инициализация
mov TL0,#low(not(62500)+1)
mov TH0,#high(not(62500)+1)
setb TCON.4 ; Запустим Timer0
S1:
cpl Buzzer ; Инвертируем звуковой выход
jbc TCON.5,S2 ; Проверка флага переполнения T/C0
; Задержка на 1/2 периода
clr TCON.6 ; Остановим Timer1
mov A,r6 ; Формируем в аккумуляторе разность адресов старшего байта полупериода ноты и команды обращения к таблице Tab
add A,#(Tab-$+2)
movc A,@A+PC ; Обращение к таблице Tab за старшим байтом поолупериода ноты
mov TH1,A ; Загрузка старшего байта в T/C1
mov A,r6
add A,#(Tab-$+2+1)
movc A,@A+PC ; Обращение к таблице Tab за младшим байтом поолупериода ноты
mov TL1,A ; Загрузка младшего байта в T/C1
setb TCON.6 ; Запустим Timer1
S0:
jbc TCON.7,S1 ; Проверка флага переполнения T/C1
jmp S0
S2: ; Декремент счетчика длительности звука
djnz r7,Sound ; Повторение D, пока не равно 0
inc DPTR ; Инкремент указателя кодов
jmp Main ; Переход к началу процедуры
Tab:
dw 1136-16 ; ля1
dw 1073-16 ; ля1#
dw 1012-16 ; си1
dw 956-16 ; до2
dw 902-16 ; до2#
dw 850-16 ; ре2
dw 804-16 ; ре2#
dw 758-16 ; ми2
dw 716-16 ; фа2
dw 677-16 ; фа2#
dw 638-16 ; соль2
dw 602-16 ; соль2#
Exit_: ; Выход из процедуры
end
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
movc a,@a+pc
работает относительно текущего счетчика на момент самой команды
ххххх nop
yyyyy movc a,@a+pc
yyyyy+1 эта точка будет при а=0
.........
yyyyy+256 это при а=255 (0хff)
однако... акумулятор-то загружен, но выполняется дальше чей-то несообразное...
обычно при подобной ситуации применяется "сцепка" загрузки и последующего обхода области таблицы:
movc a,@a+pc
ajmp over_tbl
table:
db ...............
over_tbl:
НО...
поскольку между movc a,@a+pc и началом (объектом для а=0) table стоит какая-то дополнительная последовательность то требуется ее скомпенсировать...
либо предварительно добавить к значению в а количество байт дополнительной последовательности, либо дать эту задачу на откуп препроцессору компилятора, как сделано в тексте.
Однако с поправкой на размещение таблицы и естественно при соответствующем уменьшении диапазона значений в аккумуляторе.
Вот тута и попандос...
0х100 add A,#(Tab-$+2+1)
0x102 movc A,@A+PC
????
кусок текста
Tab
0x110 db 0
0x111 db 1
0x112 db 2
0x113 db 3
примерно a=a+(0x110-0x100+0х2+0х1)=a+0х13 при а=0 имеем 0х13 (ибо в данном случае $=0x100)
а далее 0x103+0х13=0х116 вместо ожидаемого 0x110
как уже не раз говорилось - пользуйтесь метками, а не текущим счетчиком!
иже:
0х100 add A,#(Tab-point)
0x102 movc A,@A+PC
point:
0x103 nop ; к примеру - вообще любая следующая команда
????
кусок текста
Tab
0x110 db 0
0x111 db 1
0x112 db 2
0x113 db 3
даст верный результат а=а+0x110-0x103=а+0xd
при
a=1
после movc A,@A+PC будем иметь в а содержимое ячейки
0x103+0xd+1=0x111
иже 1

работает относительно текущего счетчика на момент самой команды
ххххх nop
yyyyy movc a,@a+pc
yyyyy+1 эта точка будет при а=0
.........
yyyyy+256 это при а=255 (0хff)
однако... акумулятор-то загружен, но выполняется дальше чей-то несообразное...
обычно при подобной ситуации применяется "сцепка" загрузки и последующего обхода области таблицы:
movc a,@a+pc
ajmp over_tbl
table:
db ...............
over_tbl:
НО...
поскольку между movc a,@a+pc и началом (объектом для а=0) table стоит какая-то дополнительная последовательность то требуется ее скомпенсировать...
либо предварительно добавить к значению в а количество байт дополнительной последовательности, либо дать эту задачу на откуп препроцессору компилятора, как сделано в тексте.
Однако с поправкой на размещение таблицы и естественно при соответствующем уменьшении диапазона значений в аккумуляторе.
Вот тута и попандос...
0х100 add A,#(Tab-$+2+1)
0x102 movc A,@A+PC
????
кусок текста
Tab
0x110 db 0
0x111 db 1
0x112 db 2
0x113 db 3
примерно a=a+(0x110-0x100+0х2+0х1)=a+0х13 при а=0 имеем 0х13 (ибо в данном случае $=0x100)
а далее 0x103+0х13=0х116 вместо ожидаемого 0x110
как уже не раз говорилось - пользуйтесь метками, а не текущим счетчиком!
иже:
0х100 add A,#(Tab-point)
0x102 movc A,@A+PC
point:
0x103 nop ; к примеру - вообще любая следующая команда
????
кусок текста
Tab
0x110 db 0
0x111 db 1
0x112 db 2
0x113 db 3
даст верный результат а=а+0x110-0x103=а+0xd
при
a=1
после movc A,@A+PC будем иметь в а содержимое ячейки
0x103+0xd+1=0x111
иже 1
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
[quote="Пока_без_кота"]наверное я что-то не так написал[code]
Если это вся программа, то по подаче питания на МК в PC загружается 0 и программа начинает выполнение с адреса 0. А у Вас там данные! Поставьте перед Song хотя-бы "ljmp Music" или переместите весь массив Song в конец программы. Ещё подумайте куда производится выход из программы.
Если это вся программа, то по подаче питания на МК в PC загружается 0 и программа начинает выполнение с адреса 0. А у Вас там данные! Поставьте перед Song хотя-бы "ljmp Music" или переместите весь массив Song в конец программы. Ещё подумайте куда производится выход из программы.
-
Rtmip
- Держит паяльник хвостом
- Сообщения: 963
- Зарегистрирован: Чт апр 03, 2014 23:16:55
- Откуда: Россия
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Ваши подозрения оправданы!Пока_без_кота писал(а):Так что наверное я что-то не так написал, когда разместил ее во внутренней памяти программ.
Сделайте так:
Код: Выделить всё
Main:
Вместо:
movx A,@DPTR ; Загрузка кода ноты
Напишите:
mov A, #0h
movc A,@A+DPTR ; Загрузка кода ноты
Вместо:
movx A,DPTR ; Повторная загрузка кода ноты
Напишите:
mov A, #0h
movc A,@A+DPTR ; Повторная загрузка кода ноты
А вместо:
anl A,0Fh ; Выделение тетрады из байта
Напишите:
anl A,#0Fh ; Выделение тетрады из байта
Но мне кажется, что это еще не все, что-то еще неверно переписано...
Если последуете совету Ser60, то можно и нужно ее зациклить, а стартовать с метки "Music".
И не забывайте, что на выходе прямоугольные импульсы, значит нужен фильтр перед усилителем.
Интересно на какую частоту кварца эта программа расчитана?
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Ser60
у Пока_без_кота вредная привычка - выкладывать только "выдранный" из общего исходника фрагмент.
Надеюсь, что и обход таблицы векторов и размещение таблиц данных им были все же учтены верно.

у Пока_без_кота вредная привычка - выкладывать только "выдранный" из общего исходника фрагмент.
Надеюсь, что и обход таблицы векторов и размещение таблиц данных им были все же учтены верно.
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Книжка: Сташин В.В. Урусов А.В. Мологонцева О.Ф. Проектирование цифровых устройств на однокристальных МК
https://yadi.sk/d/_SmpTfQDREotr
Описане конструкции со страницы 173. Про кварц и фильтр ни слова. В качестве звуковоспроизводителя использую комповый бузер с п-н-п транзистором КТ361, включенным по схеме с общим эмитером.
https://yadi.sk/d/_SmpTfQDREotr
Описане конструкции со страницы 173. Про кварц и фильтр ни слова. В качестве звуковоспроизводителя использую комповый бузер с п-н-п транзистором КТ361, включенным по схеме с общим эмитером.
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Ну от "очепяток" для "иностранных шпиенов" книжки времен СССР не гарантированы - читать с карандашиком ( и с вниманием ) требуется.
Кстати... подобными "нюёнсами" и современные производители "балуются" - к примеру Atmel и STMicroelectronics и мноого кого еще (см. обнаруженное в errata sheets).

Кстати... подобными "нюёнсами" и современные производители "балуются" - к примеру Atmel и STMicroelectronics и мноого кого еще (см. обнаруженное в errata sheets).
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Rtmip писал(а):...
Сделайте так:
...
Спасибо, поправил. Даже стыдно стало, что не заметил, что использую команду movx. А так гордо заявил, что "переписал под использование ВПП"
Но действительно, что-то еще не так, хотя все зациклил.
Спойлер
Код: Выделить всё
Buzzer equ P3.5
cseg
org 0
jmp Music
Song:
db 27h,27h,47h,27h,27h,47h,27h,27h
db 23h,25h,87h,28h,28h,28h,28h,28h
db 27h,27h,27h,27h,25h,25h,27h
db 45h,4Ah
db 27h,27h,47h,27h,27h,47h,27h,2Ah
db 23h,25h,87h,28h,28h,28h,28h,28h
db 27h,27h,27h
db 2Ah,28h,27h,27h,83h
db 00h ; Знак-терминатор "Конец текста"
Music:
mov DPTR,#Song ; Загрузка начального адреса Song
mov TMOD,#11h ; Инициализация T/C0 и T/C1
Main:
mov A,#0h ; Загрузка кода ноты
movc A,@A+DPTR
jz Exit_ ; Выход, если код равен 0
; Вычисление значений D и N
anl A,#0Fh ; Выделение тетрады из байта
rl A ; Удвоение кода N
mov r6,A
mov A,#0h ; Повторная загрузка кода ноты
movc A,@A+DPTR
anl A,#0F0h ; Выделение тетрады D из байта
swap A
rl A ; Удвоение кода D
mov r7,A
Sound: ; Процедура генерации одной ноты
clr TCON.4 ; Остановим Timer0, инициализация
mov TL0,#low(not(62500)+1)
mov TH0,#high(not(62500)+1)
setb TCON.4 ; Запустим Timer0
S1:
cpl Buzzer ; Инвертируем звуковой выход
jbc TCON.5,S2 ; Проверка флага переполнения T/C0
; Задержка на 1/2 периода
clr TCON.6 ; Остановим Timer1
mov A,r6 ; Формируем в аккумуляторе разность адресов старшего байта полупериода ноты и команды обращения к таблице Tab
add A,#(Tab-$+2)
movc A,@A+PC ; Обращение к таблице Tab за старшим байтом поолупериода ноты
mov TH1,A ; Загрузка старшего байта в T/C1
mov A,r6
add A,#(Tab-$+2+1)
movc A,@A+PC ; Обращение к таблице Tab за младшим байтом поолупериода ноты
mov TL1,A ; Загрузка младшего байта в T/C1
setb TCON.6 ; Запустим Timer1
S0:
jbc TCON.7,S1 ; Проверка флага переполнения T/C1
jmp S0
S2: ; Декремент счетчика длительности звука
djnz r7,Sound ; Повторение D, пока не равно 0
inc DPTR ; Инкремент указателя кодов
jmp Main ; Переход к началу процедуры
Tab:
dw 1136-16 ; ля1
dw 1073-16 ; ля1#
dw 1012-16 ; си1
dw 956-16 ; до2
dw 902-16 ; до2#
dw 850-16 ; ре2
dw 804-16 ; ре2#
dw 758-16 ; ми2
dw 716-16 ; фа2
dw 677-16 ; фа2#
dw 638-16 ; соль2
dw 602-16 ; соль2#
Exit_: ; Выход из процедуры
jmp Main
end
И какого плана нужен фильтр, просто RC-цепочка ?
Бузер тихонько тикает, вроде какую-то мелодию, секунд 30, и потом замолкает. Кварц пробовал на 12 Мгц, и на 6 Мгц, примерно одинаково
-
Rtmip
- Держит паяльник хвостом
- Сообщения: 963
- Зарегистрирован: Чт апр 03, 2014 23:16:55
- Откуда: Россия
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Да, можно обычную RC цепочку. Но и так будет работать.
Разобрался я с этой музыкальной программой
Послушал эту песенку в протеусе, можно и без RC, все одно, но ничего так, АОНы сразу вспомнил
Вообщем смотрите, что надо изменить, чтобы все пело и плясало:
Чтобы легче разобраться, строки, которые изменены или добавлены, по-сравнению с книгой "Сташин Урусов и соавторы",
отмечены знаками "!!!!!!!". Кварц на 12 МГц.
Кстати, прав наш BOB51 по поводу опечаток.
Вообще, главная проблема была в том, что в оригинале длительность полупериода ноты заносили в таймер напрямую
и он считал очень долго. А надо 65535 минус длительность полупериода ноты в мкс. Остальные проблемы это опечатки.
Разобрался я с этой музыкальной программой
Послушал эту песенку в протеусе, можно и без RC, все одно, но ничего так, АОНы сразу вспомнил
Вообщем смотрите, что надо изменить, чтобы все пело и плясало:
Спойлер
Код: Выделить всё
Buzzer equ P3.5
jmp Music ; !!!!!!!!!!
org 30h ; !!!!!!!!!!
Song:
db 27h,27h,47h,27h,27h,47h,27h,2Ah ; !!!!!!!!!!!!!!
db 23h,25h,87h,28h,28h,28h,28h,28h
db 27h,27h,27h,27h,25h,25h,27h
db 45h,4Ah
db 27h,27h,47h,27h,27h,47h,27h,2Ah
db 23h,25h,87h,28h,28h,28h,28h,28h
db 27h,27h,27h
db 2Ah,28h,27h,25h,0B3h ; !!!!!!!!!!!!!!!
db 00h ; Знак-терминатор "Конец текста"
org 100h ; !!!!!!!!!!!!!!!!!!!!!!!!!
Music:
mov DPTR, #Song ; Загрузка начального адреса Song
mov TMOD, #11h ; Инициализация T/C0 и T/C1
Main:
clr A ; !!!!!!!!!!!!!!!!!!!!!
movc A, @A+DPTR ; Загрузка кода ноты !!!!!!!!!!!!!!
jz Exit_ ; Выход, если код равен 0
; Вычисление значений D и N
anl A, #0Fh ; Выделение тетрады из байта
rl A ; Удвоение кода N
mov r6, A
clr A ; !!!!!!!!!!!!!!!!!!!!
movc A, @A+DPTR ; Повторная загрузка кода ноты !!!!!!!!!!
anl A, #0F0h ; Выделение тетрады D из байта !!!!!!!!!!
swap A
rl A ; Удвоение кода D
mov r7, A
Sound: ; Процедура генерации одной ноты
clr TCON.4 ; Остановим Timer0, инициализация
mov TL0, #low(not(62500)+1)
mov TH0, #high(not(62500)+1)
setb TCON.4 ; Запустим Timer0
S1:
cpl Buzzer ; Инвертируем звуковой выход
jbc TCON.5,S2 ; Проверка флага переполнения T/C0
; Задержка на 1/2 периода
clr TCON.6 ; Остановим Timer1
mov A, r6 ; Формируем в аккумуляторе разность адресов старшего байта полупериода ноты и команды обращения к таблице Tab
add A, #(Tab-($+1)) ; !!!!!!!!!!!!!!!!!!!
movc A, @A+PC ; Обращение к таблице Tab за старшим байтом поолупериода ноты
mov TH1, A ; Загрузка старшего байта в T/C1
mov A, r6
add A, #(Tab-($+2)) ; !!!!!!!!!!!!!!!!!!!!!
movc A, @A+PC ; Обращение к таблице Tab за младшим байтом поолупериода ноты
mov TL1, A ; Загрузка младшего байта в T/C1
setb TCON.6 ; Запустим Timer1
S0:
jbc TCON.7,S1 ; Проверка флага переполнения T/C1
sjmp S0
S2:
; Декремент счетчика длительности звука
djnz r7, Sound ; Повторение D, пока не равно 0
inc DPTR ; Инкремент указателя кодов
sjmp Main ; Переход к началу процедуры
Tab: ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
dw not(1136-16) ; ля1
dw not(1073-16) ; ля1#
dw not(1012-16) ; си1
dw not(956-16) ; до2
dw not(902-16) ; до2#
dw not(850-16) ; ре2
dw not(804-16) ; ре2#
dw not(758-16) ; ми2
dw not(716-16) ; фа2
dw not(677-16) ; фа2#
dw not(638-16) ; соль2
dw not(602-16) ; соль2#
Exit_: ; Выход из процедуры
jmp Music ; !!!!!!!!!!!!!!!!!!!!!!
end
Чтобы легче разобраться, строки, которые изменены или добавлены, по-сравнению с книгой "Сташин Урусов и соавторы",
отмечены знаками "!!!!!!!". Кварц на 12 МГц.
Кстати, прав наш BOB51 по поводу опечаток.
Вообще, главная проблема была в том, что в оригинале длительность полупериода ноты заносили в таймер напрямую
и он считал очень долго. А надо 65535 минус длительность полупериода ноты в мкс. Остальные проблемы это опечатки.
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Спасибо уважаемый. Разжевали, и в рот положили 
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Доброго времени суток. Прошу подкинуть пример декодера ИК протокола NEC на ассемблере MCS-51. Нашел отличную библиотеку от Леонида Ридико, но она только под RC-5, а у меня из всей кучи пультов в доме только 1 под этот протокол, и тот убитый в хлам, половина кнопок не работает уже. Желательно с хоть какии-то коментариями, мне разобратся интересно.
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Вроде как написал сам, только оно не фурычит. Просьба подсказать, что не так.
Делал по алгоритму
, руководствуясь вот этим
, только пару моментов упростил.
Под спойлером подпрограмма обработки посылки протокола NEC по прерыванию на ножке Р3.2
В файле с основным циклом настройка периферии и вывод байта команды в порт на светодиоды. Они все время горят, при нажитии на кнопки ничего не меняется.
Делал по алгоритму
Под спойлером подпрограмма обработки посылки протокола NEC по прерыванию на ножке Р3.2
Спойлер
Код: Выделить всё
IR equ P3.2 ; Выбираем INTO (INT1) ножку для подключения выхода TSOP
Frequency equ 12000 ; Тактовая частота микроконтроллера в кГц, ввести нужное значение и скомпилировать, остальные значение расчитываются автоматически
StartBitLow equ (Frequency/12000)*50 ; 50 - старший байт таймера (в десятичной системе) для фиксации нижней границы старт бита (13 мс)
StartBitHigh equ (Frequency/12000)*54 ; 54 - старший байт таймера (в десятичной системе) для фиксации верхней границы старт бита (14 мс)
TimeBit equ (Frequency/12000)*6 ; 6 - старший байт таймера (в десятичной системе) для порогового значения бита данных (примерно 1600 мкс, все что меньше - 0, все что больше - 1)
dseg at 7h
ShiftCounter: ; Счетчик 8 бит (1 байта)
ds 1
Symbol: ; Здесь появляется байт посылки после каждого вызова попдрограммы Receive
ds 1
ByteClass: ; Байт класса устройства
ds 1
InvByteClass: ; Инвертированнный байт класса устройства
ds 1
ByteCommand: ; Байт принятой команды
ds 1
InvByteCommand: ; Инвертированнный байт принятой команды
ds 1
Stack: ; А дальше пойдет стек
cseg
mov ShiftCounter,#8 ; Занесем значение в счетчик сдвига
NEC: ; Процедура обработки входящего сигнала, запускается по переходу уровня из 1 в 0 на ножке внешнего прерывания
setb TR0 ; Запустим Timer0
Overflow_1:
jb TF0,Error ; При переполнении таймера выходим из цикла
jnb IR,Overflow_1 ; Ждем конца низкого уровня старт-бита
Overflow_2:
jb TF0,Error ; При переполнении таймера выходим из цикла
jb IR,Overflow_2 ; Ждем конца высокого уровня старт-бита
clr TR0 ; Остановим Timer0
mov A,TH0 ; Загрузим старший байт счетного регистра Timer0
cjne A,StartBitlow,Compare_1 ; Проверим
jmp Error ; Равно, значит неправильный старт-бит, значит это не посылка
Compare_1:
jc Error ; Меньше минимальной длинны, значит неправильный старт-бит, значит это не посылка
cjne A,StartBitHigh,Compare_2 ; Опять проверим
jmp Error ; Равно, значит неправильный старт-бит, значит это не посылка
Compare_2:
jnc Error ; Больше максимальной длинны, значит неправильный старт-бит, значит это не посылка ;
; Старт-бит правильный, начинаем прием посылки
call Receive
mov ByteClass,Symbol ; Первый байт - класс устройства
call Receive
mov InvByteClass,Symbol ; Второй байт - инверсный байт класса устройства
call Receive
mov ByteCommand,Symbol ; Третий байт - байт команды
call Receive
mov InvByteCommand,Symbol ; Четвертый байт - инверсный байт команды
Error:
mov TH0,#0 ; Обнулим таймер, нам заново считать длинну байтов
mov TL0,#0
clr TF0 ; Очистим флаг переполнения таймера, на всякий случай, может мы сюда из-за этого и попали
reti
Receive: ; Подпрограмма приема посылки (1 байта, 8 бит)
mov TH0,#0 ; Обнулим таймер, нам заново считать длинну байтов
mov TL0,#0
setb TR0 ; Запустим Timer0
Overflow_3:
jb TF0,Error ; При переполнении таймера выходим из цикла
jnb IR,Overflow_3 ; Пока низкий уровень - ждем
Overflow_4:
jb TF0,Error ; При переполнении таймера выходим из цикл
jb IR,Overflow_4 ; Ждем конца высокого уровня бита данных
clr TR0 ; Остановим Timer0
mov A,TH0 ; Загрузим старший байт счетного регистра Timer0
cjne A,TimeBit,Compare_3 ; Проверим
jmp Error ; Пороговое значение, скорее всего ошибка, валим из прерывания
Compare_3:
jc Log_0 ; Если был установлен флаг С, значит A меньше, чем TimeBit
log_1:
setb C ; Это лог. 1
jmp Sdvig ; Идем сдвигать
Log_0:
clr C ; Это лог. 0
Sdvig:
clr A
mov A,Symbol ; Закинем значение в А
rrc A ; Сдвинем вправо, потому что команды передаются младшим битом вперед
mov Symbol,A ; И закинем назад
djnz ShiftCounter,Receive ; И валим принимать опять, пока не примем 8 бит
mov ShiftCounter,#8 ; Заново занесем значение в счетчик сдвига
ret
end
В файле с основным циклом настройка периферии и вывод байта команды в порт на светодиоды. Они все время горят, при нажитии на кнопки ничего не меняется.
Спойлер
Код: Выделить всё
Out_Port equ P0
cseg
org 00h ; Reset heandler
jmp Ini
org 03h ; INT0 heandler
jmp NEC
org 30h
include 'NEC.asm'
Ini:
mov SP,#Stack
mov TMOD, #00010001b ; Режим работы таймеров Т0 и Т1
; ||||||||
; ||||||++-------Режим работы Т0 (01 - 16-бит, 10 - 8-бит с автоперезагрузкой, 11 - 2 независимых 8-бит)
; |||||+---------С/Т0: 0-таймер, 1-счетчик
; ||||+----------: 0-управление по TR0, 1-Управление по TR0 и INT0
; ||++---------- работы Т1 (01 - 16-бит, 10 - 8-бит с автоперезагрузкой, 11 - невозможно)
; |+----------/Т1: 0-таймер, 1-счетчик
; +----------: 0-управление по TR1, 1-управление по TR1 и INT1
mov TCON, #00000001b ; Управление таймерами Т0 и Т1 и режимом работы внешних прерываний
; ||||||||
; |||||||+-------IT0 - Тип INT0: 0-срабатывание по низкому уровню, 1-динамический по спаду (переходу из 1 в 0)
; ||||||+--------IE0 - Запрос прерывания INT0 (при IT0=1 автоматически сбрасывается в обработчике)
; |||||+---------IT1 - Тип INT1: 0-срабатывание по низкому уровню, 1-динамический по спаду (переходу из 1 в 0)
; ||||+---------- - Запрос прерывания INT1 (при IT1=1 автоматически сбрасывается в обработчике)
; |||+---------- - Запуск Т0
; ||+---------- - Флаг переполнения Timer0
; |+---------- - Запуск Т1
; +---------- - Флаг переполнения Timer1
mov IE, #10000001b ; Прерывания
; ||||||||
; |||||||+-------EX0 - разрешение обработки прерываний от внешнего входа INT0
; ||||||+--------ЕТ0 - разрешение обработки прерываний от Timer0
; |||||+---------EX1 - разрешение обработки прерываний от внешнего входа INT1
; ||||+---------- - разрешение обработки прерываний от Timer1
; |||+---------- - разрешение обработки прерываний от посл.порта
; ||+---------- - разрешение обработки прерываний от Timer2
; |+----------, не используеться
; +---------- - разрешение обработки всех прерываний
mov Out_Port,#0
mov TH0,#0 ; Обнулим таймер, нам считать длинну байтов
mov TL0,#0
Main:
mov Out_Port,ByteCommand
jmp Main
end
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
При подключении дисплея HD44780 к MCS-51 в режиме работы с внешней памятью куда нужно подключать выводы RS и R/W ?
http://www.gaw.ru/html.cgi/txt/app/lcd/51to_lcd.htm
http://www.gaw.ru/html.cgi/txt/app/lcd/51to_lcd.htm
-
Rtmip
- Держит паяльник хвостом
- Сообщения: 963
- Зарегистрирован: Чт апр 03, 2014 23:16:55
- Откуда: Россия
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Через регистр-защелку, как внешнюю память к Р0.0 и Р0.1.
По поводу вашей программы ИК-приемника, вы в "кейле" пишете?
Зачем на два файла разделили? Помощь еще нужна или разобрались?
По поводу вашей программы ИК-приемника, вы в "кейле" пишете?
Зачем на два файла разделили? Помощь еще нужна или разобрались?
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Пока_без_кота писал(а):При подключении дисплея HD44780 к MCS-51 в режиме работы с внешней памятью куда нужно подключать выводы RS и R/W ?
Любая свободная линия порта Р1 или Р2 при использовании команд обмена диапазона адресного пространства 0-255 (movx a,@ri / movx @ri,a) с предварительно программно выставленным значением на управляющих линиях.
Либо фиксированные адресные поля с а8-а16 соответствующими требуемой комбинации сигналов (Р2.8 - Р2.0) при использовании команд группы "полноадресного" обмена movx a,@dptr / movx@dptr,a.
-
Rtmip
- Держит паяльник хвостом
- Сообщения: 963
- Зарегистрирован: Чт апр 03, 2014 23:16:55
- Откуда: Россия
Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..
Судя по листингу программы из ссылки, порты Р1 и Р2 не подходят или я не понимаю, как это будет работать? 
Конечно, если немного изменить программу, то можно упростить подключение.

Спойлер
Пересылка байта осуществляется по командам:
MOVX A,@DPTR или MOVX A,@DPTR.
В этом случае в DPTR следует загружать адрес с учётом того, что младший бит А0 будет обозначать направление передачи (запись/чтение), а бит А1 тип передаваемой информации (команда/данные).
Ниже приведены исходные тексты подпрограммы на языке ассемблера ASM51, позволяющие записывать данные, инструкции в контроллер, считывать данные. Приведен так же примерный текст подпрограммы инициализации контроллера в режим восьми битного интерфейса, при работе с двумя строками. Отображение курсора и мигание отключено. Курсор установлен в начало первой (верхней) строки.
Код: Выделить всё
WRC_LC EQU ХХХ0H
RDC_LC EQU ХХХ1H
WRD_LC EQU ХХХ2H
RDD_LC EQU ХХХ3H
;ИНИЦИАЛИЗАЦИЯ HD44780
LCDINIT: MOV A,#38H ; 8-BIT 2-LINES
ACALL WRC
MOV A,#0CH ; DISP-ON, CUR-OFF, FLASH-OFF
ACALL WRC
MOV A,#06H ; MOVE CURSOR RIGHT
ACALL WRC
CLS: MOV A,#01H ; CLEAR SCREEN
ACALL WRC
RET
;ЧТЕНИЕ ДАННЫХ ИЗ HD44780 В ACC
RDD_LCD: MOV DPTR,#(RDC_LC)
WAITDD: MOVX A,@DPTR
JB ACC.7,WAITDD
MOV DPTR,#(RDD_LC)
MOVX A,@DPTR
RET
;ЗАПИСЬ ДАННЫХ В HD44780 ИЗ АСС
WRD: PUSH ACC
MOV DPTR,#(RDC_LC)
WAITRD: MOVX A,@DPTR ;ОЖИДАНИЕ
JB ACC.7,WAITRD ;ГОТОВНОСТИ
MOV DPTR,#(WRD_LC)
POP ACC
MOVX @DPTR,A
RET
;ЗАПИСЬ КОМАНДЫ В HD44780 ИЗ АСС
WRC: PUSH ACC
MOV DPTR,#(RDC_LC)
WAITRC: MOVX A,@DPTR ;ОЖИДАНИЕ
JB ACC.7,WAITRC ;ГОТОВНОСТИ
POP ACC
MOV DPTR,#(WRC_LC)
MOVX @DPTR,A
RET