Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Ser60 »

Понял лучше про логику работы лестницы. Если регистрировать только момент входа человека на лестницу и организации подсветки в направлении последнего входа, в случае с одной лестницей (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 придется помещать ЦПУ в режим неглубокого сна с работающим тактовым генератором. Вы писали, что токопотребление Вам неважно, но меня сильно нервирует если МК зря пожирает миллиамперы. В случае "нормального" МК все устройство контроля вообще можно от батареек запитать, которых хватит на несколько лет. Или от изредка подзаряжаемого аккума. Тогда можно будет подумать о коммутировании БП устройства, если он все-таки нужен для управления лампами, в моменты простоя (основное состояние). А то сетевой адаптер то там, то сям, еще один здесь - так и набегает.
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Спасибо за столь развернутую консультацию.
Аватара пользователя
FireProoF
Мучитель микросхем
Сообщения: 424
Зарегистрирован: Чт май 14, 2015 15:11:39
Откуда: Саратов

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение FireProoF »

Кто может расшифровать строку из Кеил о размере программы?
Program Size: data=63.3 xdata=0 code=2271
Желательно рассказать что где лежит) :))
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15553
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение BOB51 »

Читать хелп по компилятору для кейла надоть. 8)
А у атмелевского табличка несколько другая, но смысл одинаков:
Снимок_2015_09_21_12_00_36_468.GIF
(9.73 КБ) 438 скачиваний

вот только не пойму откуда дробное число в Вашем блоке data...
с51asm по описанию дает аналогию с кейлом - так битовая секция вроде отдельно печатается...
:roll:
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 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
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15553
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение BOB51 »

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
как уже не раз говорилось - пользуйтесь метками, а не текущим счетчиком!
8)
иже:
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
:wink:
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Ser60 »

[quote="Пока_без_кота"]наверное я что-то не так написал[code]
Если это вся программа, то по подаче питания на МК в PC загружается 0 и программа начинает выполнение с адреса 0. А у Вас там данные! Поставьте перед Song хотя-бы "ljmp Music" или переместите весь массив Song в конец программы. Ещё подумайте куда производится выход из программы.
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Rtmip »

Пока_без_кота писал(а):Так что наверное я что-то не так написал, когда разместил ее во внутренней памяти программ.
Ваши подозрения оправданы! :idea:
Сделайте так:

Код: Выделить всё

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".
И не забывайте, что на выходе прямоугольные импульсы, значит нужен фильтр перед усилителем.
Интересно на какую частоту кварца эта программа расчитана?
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15553
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение BOB51 »

Ser60
у Пока_без_кота вредная привычка - выкладывать только "выдранный" из общего исходника фрагмент. :evil:
Надеюсь, что и обход таблицы векторов и размещение таблиц данных им были все же учтены верно.
8)
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Книжка: Сташин В.В. Урусов А.В. Мологонцева О.Ф. Проектирование цифровых устройств на однокристальных МК
https://yadi.sk/d/_SmpTfQDREotr
Описане конструкции со страницы 173. Про кварц и фильтр ни слова. В качестве звуковоспроизводителя использую комповый бузер с п-н-п транзистором КТ361, включенным по схеме с общим эмитером.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15553
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение BOB51 »

Ну от "очепяток" для "иностранных шпиенов" книжки времен СССР не гарантированы - читать с карандашиком ( и с вниманием ) требуется.
:wink:
Кстати... подобными "нюёнсами" и современные производители "балуются" - к примеру Atmel и STMicroelectronics и мноого кого еще (см. обнаруженное в errata sheets).
:(
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Пока_без_кота »

Rtmip писал(а):...
Сделайте так:
...

Спасибо, поправил. Даже стыдно стало, что не заметил, что использую команду movx. А так гордо заявил, что "переписал под использование ВПП" :roll:
Но действительно, что-то еще не так, хотя все зациклил.
Спойлер

Код: Выделить всё

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 и не только..

Сообщение Rtmip »

Да, можно обычную RC цепочку. Но и так будет работать.
Разобрался я с этой музыкальной программой :idea:
Послушал эту песенку в протеусе, можно и без RC, все одно, но ничего так, АОНы сразу вспомнил :music:
Вообщем смотрите, что надо изменить, чтобы все пело и плясало:
Спойлер

Код: Выделить всё

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 и не только..

Сообщение Пока_без_кота »

Спасибо уважаемый. Разжевали, и в рот положили :oops:
Пока_без_кота
Потрогал лапой паяльник
Сообщения: 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
Спойлер

Код: Выделить всё

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
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Rtmip »

Через регистр-защелку, как внешнюю память к Р0.0 и Р0.1.
По поводу вашей программы ИК-приемника, вы в "кейле" пишете?
Зачем на два файла разделили? Помощь еще нужна или разобрались?
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15553
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение BOB51 »

Пока_без_кота писал(а):При подключении дисплея 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.
8)
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: Мелкие вопросы по МК-51 а-ка MCS-51, ASM и не только..

Сообщение Rtmip »

Судя по листингу программы из ссылки, порты Р1 и Р2 не подходят или я не понимаю, как это будет работать? :dont_know:
Спойлер
Пересылка байта осуществляется по командам:
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
Конечно, если немного изменить программу, то можно упростить подключение.
Ответить

Вернуться в «Разные вопросы по МК»