Бегущая строка на Intel 8051: How-To. Часть 2

Написал Vanger, в Статьи » Прочее.
Вторая часть статьи Бегущая строка на Intel 8051: How-To. В статье рассказывается, как спроектировать и написать на ассемблере программу бегущей строки для системы на Intel 8051. В этой части будет рассмотрена архитектура программы и собственно сам код. Для всех дZенствующих асм-программеров и сочувствующих им =].

ВЫБОР АРХИТЕКТУРЫ ПРОГРАММЫ

Нормальная программа, естесственно, имеет какую-то структуру. Разобъем для начала всю программу на части, а потом объединим все в одно целое. Благодаря тому, что в ассемблере Intel 8051 есть возможность использовать метки перехода, программу можно разбить на более-менее независимые части, а связь между ними сделать за счет меток. Заметим, что переход на обработчики прерываний также выполняется с помощью меток.

Для того, чтобы все рассчитанные нами алгоритмы работали, нужно задать режим работы микроконтроллера, настроить все порты, etc.

;______________МОДУЛЬ 1. Основной модуль программы________________
Для начала описываем адресов расположения модулей программы в памяти, хранящей код: основного модуля (в наших программах начинается с метки START) и обработчков прерываний.
Задаем начальные значения переменных, портов, режим работы таймеров.

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

;______________МОДУЛЬ 2. Цикл ожидания прерываний от таймеров_______
Просто бесконечный цикл.

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

;______________МОДУЛЬ 3. Обработка прерываний_________________
Обработчики прерываний от таймеров. Тут именно 2 обработчика и метки, ведущие к этим обработчикам.

Далее можно разместить массив символов для передачи на индикаторы. Вообще, не важно, где размещать его, лишь бы все символы шли подряд.
Слово "STROKA" - это тоже всего лишь метка.

;______________МОДУЛЬ 4. Вывод строки на индикаторы___________
Строка для вывода на индикаторы

Смотрим общую структуру кода программы:

;______________МОДУЛЬ 1. Основной модуль программы____________
Для начала описываем адресов расположения модулей программы в памяти, хранящей код: основного модуля (в наших программах начинается с метки START) и обработчков прерываний.
Задаем начальные значения переменных, портов, режим работы таймеров.

;___________________МОДУЛЬ 2. Цикл ожидания прерывания от таймеров___
Просто бесконечный цикл.

;___________________МОДУЛЬ 3. Обработка прерываний__________________
Обработчики прерываний от таймеров. Тут именно 2 обработчика и метки, ведущие к этим обработчикам.

;___________________МОДУЛЬ 4. Вывод строки на индикаторы______________
Строка для вывода на индикаторы.

Теперь словесные алгоритмы преобразуем в ассемблерные.
Модуль 1. Основной модуль программы

;-------Описание адресов расположения модулей программы
            ORG    00h
            JMP    START;переход на инициализацию
            ORG    0Bh
            JMP    TC_0;переход по прерыванию на обработчик таймера T/C 0
            ORG    1Bh            
            JMP    TC_1;переход по прерыванию на обработчик таймера T/C 1
            ORG    30h
;-------Описание адресов расположения модулей программы

Почему мы выбрали именно эти адреса? Потому что прерываниям TC_0 и TC_1 как раз соответствуют адреса 0Bh и 1Bh (см. документацию по микроконтроллеру; каждому из возможных прерываний микроконтроллера назначен определенный адрес), а адреса 00h и 30h должны ограничивать блок описания разделов программы. Идем далее.
Задаем начальные значения переменных и портов:

START:; Инициализация программы
;-------Начальные описания
            CLR    P3.2; Выбор 1-го индикатора
            CLR    P3.3; Обнуление строба записи в регистре
            CLR    P3.4; Сброс разрешения переключения дешифратора
            CLR    P3.5            
            SETB    P3.4; Разрешаем работу дешифратора
            MOV    R0,#0h; Инициализация итерационной переменной R0
                ; 7 прерываний = 0,5с.
            MOV    R1,#0h; Инициализация итерационной переменной R1,
                ; где R1=0..3 - так осуществляется выбор индикатора
            MOV    R2,#0h; Инициализация итерационной переменной R2
                ; (отсчитывает цикл смещения в строке STROKA)
;-------Начальные описания

Итак, регистр R0 будет считать 7 прерываний таймера TC_0, чтобы получилось 77мс*7=500мс. Регистр R1 считает от 0 до 3, это 4 LED индикатора, данные по очереди посылаются на каждый из них. R2 считает номер символов, которые передаются на индикаторы.
Задаем режимы работы таймеров, их начальные значения:

;-------Описание работы таймеров
            MOV    TH0,#0h; Установка времени срабатывания таймера 0 на
            MOV    TL0,#0h; максимально возможное значение (71 мс)
            MOV    TH1,#0F6h; Установка времени срабатывания
            MOV    TL1,#0FFh; таймера 1 на 2,5 мс (400 Гц)
            MOV    TMOD,#00010001b; Определяем таймеры/счетчики в качестве таймеров
            MOV    IP,#00000010b; Устанавливаем приоритет TC_0=1, TC_1 = 0
            MOV    IE,#10001010b; Разрешаем прерывания
            MOV    TCON,#01010000b; Включение таймеров
;-------Описание работы таймеров

Если что-то здесь непонятно - смотрите в документацию. Все сделано по мануалу от дяди Интела (смайл). Read the fu... the manual, наконец.

Модуль 2. Цикл ожидания прерывания от таймеров
С начальными описаниями разобрались. Далее идет бесконечный цикл. Ну, тут разбирать нечего :).

    TSIKL:;-------Цикл без операторов, в нем происходит ожидание прерывания от таймеров
            NOP; Если бы тут были какие-то операторы, то выполнялись бы именно они
    JMP TSIKL

Модуль 3. Обработка прерываний
Далее в нашей программе обработчики прерываний от таймеров.
Прерывание от таймера ТС_0
TC_0:;-------Подпрограмма обработки прерывания таймера 0
; Таймер 0 выполняет задержку на 0.5 с
            INC    R0    ; Увеличение на 1 итерационной переменной R0
            CJNE    R0,#7h,TC_0_END; Если R0==7, то R0 сбрасываем
            MOV    R0,#0h; если нет, то выходим из прерывания        
            INC    R2    ; Увеличение на 1 итерационной переменной R2
            CJNE    R2,#0Ch,TC_0_END; Если R2==11, то
            MOV    R2,#0h; R2 сбрасываем, если нет, то выходим из прерывания
    TC_0_END:    RETI    ; Выход из прерывания
;--------Конец подпрограммы обработки прерывания таймера 0

Алгоритм работы этого прерывания простой и понятный: таймер 7 раз считает по 77 секунд, потом делает сдвиг бегущей строки. Также следим за состоянием регистра R2. Он считает от 0 до 12 (0Ch в шестнадцатеричном представлении), это 11 символов бегущей строки, которые также хранятся в памяти программ. Как номер символа преобразуется в конкретный символ - описано в обработчике TC_1.
Прерывание от таймера ТС_1
TC_1:;--------Подпрограмма обработки прерывания таймера 1
; Таймер 1 выполняет "мигание" индикаторов с частотой 400 Гц

            MOV  TCON,#00010000b; Останавливаем таймер 1 на время установки
                        ; времени срабатывания
            MOV    TH1,#0F6h    ; Установка времени срабатывания
            MOV    TL1,#0FFh    ; таймера 1 на 2.5 мс (400 Гц)
            MOV    TCON,#01010000b; Включение таймера 1
            CJNE    R1,#4h, METKA1; Если R1==4, то R1 сбрасываем,
            MOV    R1,#0h    ; если нет, то переходим на метку TSIKL

Как только наступило прерывание - остановили таймер, заново установили его на 2.5 мс, снова включили. Если R1 не равно 4, переходим по метке METKA1 в процедуру передачи текущего символа на текущий индикатор. Напомню, R1 отвечает за выбор индикатора, на который в данный момент отправляется символ для отображения. Если R1 равно 4, сбрасываем его в 0 и переходим в бесконечный цикл.

Как происходит выбор текущего символа бегущей строки? Мы не можем работать с массивами, когда процессор сам выделяет переменным адреса и память. Поэтому нам нужно брать символы напрямую из памяти ))). Метка STROKA указывает на адрес первого из символов бегущей строки. Текущий символ вычисляется как сумма номера текущего индикатора и регистра R2, который считает смещение символов. Эта сумма записывается в аккумулятор A, прибавляется к адресу первого символа (на который указывает метка STROKA), и получаем адрес нужного символа. Это происходит в процедуре передачи символа на индикатор:

    METKA1:
            MOV    A,R1        ; A=R1
            ADD    A,R2        ; A=R1+R2 (вычисляем смещение в строке, как сумму номера
                        ; индикатора и циклического смещения R2)
            MOV    DPTR,#STROKA; Заносим в DPTR адрес начала строки STROKA
            MOVC    A,@A+DPTR; байт из строки
            MOV    P1,A        ; Вывод этого байта в порт для индикации
            SETB    P3.3        ; Устанавливаем бит 3 порта P3 (вывод строба записи в регистр)
            MOV    B,R1
            MOV    C,B.0
            MOV    P3.2,C    ; Подаем на вход дешифратора через P3.2 и P3.5      
            MOV    C,B.1    ; номер индикатора
            MOV    P3.5,C    ; записанный в R1
            INC    R1        ; Переключаемся на следующий индикатор
            CLR    P3.3        ; Конец строба записи в регистр
    TC_1_END:     RETI        ; Выход из прерывания
;--------Конец подпрограммы обработки прерывания таймера 1

Кроме передачи нужного символа в порт P1 (MOV P1,A), здесь описан процесс управления дешифратором (он управляется через порт P3; процесс описан в разделе «Алгоритм динамической индикации»).

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

; Здесь описывается, как данные передаются на индикаторы.
    STROKA:; Строка для вывода на индикаторы
            db    11111111b; <пробел>
            db    11111111b; <пробел>
            db    11111111b; <пробел>
            db     11001000b; П
            db     11000110b; С
            db     10111111b; -
            db     10011001b; 4
            db     11111000b; 7
            db     10000010b; 6
            db     10111111b; -
            db     11000000b; 0
            db     10010010b; 8
            db     11111111b; <пробел>
            db     11111111b; <пробел>
            db     11111111b; <пробел>
    FINAL:
END.; Конец кода программы

Готово. Можно объединить все модули в программу.

КОД ПРОГРАММЫ

;_______________МОДУЛЬ 1. Основной модуль программы__________________________________

;-------Описание адресов расположения модулей программы

            ORG    00h
             JMP    START; переход на инициализацию
            ORG    0Bh
            JMP    TC_0    ; переход по прерыванию на обработчик таймера T/C 0
            ORG    1Bh            
            JMP    TC_1    ; переход по прерыванию на обработчик таймера T/C 1
            ORG    30h

;-------Описание адресов расположения модулей программы


START:
;-------Начальные описания

            CLR    P3.2    ; Выбор 1-го индикатора
            CLR    P3.3    ; Обнуление строба записи в регистре
            CLR    P3.4    ; Сброс разрешения переключения дешифратора
            CLR    P3.5            
            SETB    P3.4    ; Разрешаем работу дешифратора

            MOV    R0,#0h; Инициализация итерационной переменной R0
                    ; 7 прерываний = 0,5с.
            MOV    R1,#0h; Инициализация итерационной переменной R1,
                    ; где R1=0..3 - так осуществляется выбор индикатора
            MOV    R2,#0h; Инициализация итерационной переменной R2
                    ; (отсчитывает цикл смещения в строке STROKA)
                    ; 7 прерываний = 0,5с.
;-------Начальные описания

;-------Описание работы таймеров

            MOV    TH0,#0h; Установка времени срабатывания таймера 0 на
            MOV    TL0,#0h; максимально возможное значение (71 мс)

            MOV    TH1,#0F6h; Установка времени срабатывания
            MOV    TL1,#0FFh; таймера 1 на 2,5 мс (400 Гц)

            MOV    TMOD,#00010001b; Определяем таймеры/счетчики в качестве таймеров
            MOV    IP,#00000010b; Устанавливаем приоритет T/C_0=1, T/C_1 = 0
            MOV    IE,#10001010b; Разрешаем прерывания
            MOV    TCON,#01010000b; Включение таймеров

;-------Описание работы таймеров

;________________МОДУЛЬ 2. Цикл ожидания прерывания от таймеров_______________________

    TSIKL:;-------Цикл без операторов, в нем происходит ожидание прерывания от таймеров
            NOP; Если бы тут были какие-то операторы, то выполнялись бы именно они
    JMP TSIKL




;________________МОДУЛЬ 3. Обработка прерываний_______________________________________


TC_0:;-------Подпрограмма обработки прерывания таймера 0
; Таймер 0 выполняет задержку на 0.5 с

            INC    R0    ; Увеличение на 1 итерационной переменной R0
            CJNE    R0,#7h,TC_0_END; Если R0==7, то R0 сбрасываем
            MOV    R0,#0h; если нет, то выходим из прерывания
            INC    R2    ; Увеличение на 1 итерационной переменной R2
            CJNE    R2,#0Ch,TC_0_END; Если R2==11, то
            MOV    R2,#0h; R2 сбрасываем, если нет, то выходим из прерывания

    TC_0_END:    RETI;; Выход из прерывания

;--------Конец подпрограммы обработки прерывания таймера 0


TC_1:;--------Подпрограмма обработки прерывания таймера 1
; Таймер 1 выполняет "мигание" индикаторов с частотой 400 Гц

            MOV  TCON,#00010000b; Останавливаем таймер 1 на время установки времени срабатывания
            MOV    TH1,#0F6h; Установка времени срабатывания
            MOV    TL1,#0FFh; таймера 1 на 2.5 мс (400 Гц)
            MOV    TCON,#01010000b; Включение таймера 1
            CJNE    R1,#4h, METKA1; Если R1==4, то R1 сбрасываем,
            MOV    R1,#0h; если нет, то переходим на метку TSIKL

    METKA1:
            MOV    A,R1    ; A=R1
            ADD    A,R2    ; A=R1+R2 (вычисляем смещение в строке, как сумму номера индикатора
                    ; и циклического смещения R2)
            MOV    DPTR,#STROKA; Заносим в DPTR адрес начала строки STROKA
            MOVC    A,@A+DPTR; байт из строки
            MOV    P1,A    ; Вывод этого байта в порт для индикации

            SETB    P3.3    ; Устанавливаем бит 3 порта P3 (вывод строба записи в регистр)
    
            MOV    B,R1
            MOV    C,B.0
            MOV    P3.2,C; Подаем на вход дешифратора через P3.2 и P3.5      
            MOV    C,B.1; номер индикатора
            MOV    P3.5,C; записанный в R1
            INC    R1    ; Переключаемся на следующий индикатор
            CLR    P3.3    ; Конец строба записи в регистр

    TC_1_END:     RETI    ; Выход из прерывания
        
;--------Конец подпрограммы обработки прерывания таймера 1



;________________МОДУЛЬ 4. Вывод строки на индикаторы_________________________________

; Здесь описывается, как данные передаются на индикаторы.


    STROKA:; Строка для вывода на индикаторы

            db    11111111b; <пробел>
            db    11111111b; <пробел>
            db    11111111b; <пробел>
            db     11001000b; П
            db     11000110b; С
            db     10111111b; -
            db     10011001b; 4
            db     11111000b; 7
            db     10000010b; 6
            db     10111111b; -
            db     11000000b; 0
            db     10010010b; 8
            db     11111111b; <пробел>
            db     11111111b; <пробел>
            db     11111111b; <пробел>

    FINAL:
END.; Конец кода программы

Написали. Теперь остается прогнать все это во Franklin'е. Если компилятор ошибок не выдает - значит синтаксических ошибок мы не сделали (большой радостный все ломающий смайл). Чтобы полностью проверить, правильно ли работает программа, нужно само устройство, распаянное на текстолитовой (или не текстолитовой) плате.. Паяйте :). Но вообще прога уже проверена в боевых условиях. Можно сильно не бояться (смайл).
#1 Vanger |  

ассемблер реально мозг ест
как было в статье на wasm.ru, чтобы хорошо писать на асме - нужно иметь особый склад ума
голова уже болит от вникания во все эти регистры-адресацию-чеготамеще. дофига всего приходится в голове держать. а программа то в сотню строк))
Дата публикации: 10 апреля 2009 01:08 | ICQ: --
цитировать
#2 djnz |  

огромное спасибо! )статья очень помогла)
вот только на индикаторе скорее всего будет выводиться ПС-476-05
Дата публикации: 6 ноября 2009 21:54 | ICQ: --
цитировать
#3 Oxide |  

Большое спасибо! Очень помогла ваша статья!

Кстати, в комментариях небольшая помарочка laughing :


CJNE R1,#4h, METKA1; Если R1==4, то R1 сбрасываем,
MOV R1,#0h; если нет, то переходим на метку TSIKL METKA1
Дата публикации: 19 мая 2011 19:34 | ICQ: --
цитировать
#4 zasadaxxx |  

В [url=http://4.ru]2010[/url] году Вернер Херцог снял о [url=http://3.ru]загадках[/url] пещеры и её окрестностей документальный фильм «Пещера забытых снов» Пещера Шове находится вблизи небольшого города Вальон-Пон-д’Арк в долине реки Ардеш на юге Франции
Дата публикации: 7 августа 2011 12:19 | ICQ: --
цитировать
#5 rISKaAS |  

[url=http://8.ru]ru/new/sozdanie-semantisego-yadra/]семантич
еское[/url] [url=http://7.ru]ядро[/url][/url] сео [url=http://riskaaaa [url=http://5.ru]ru/new/sozdanie-semantisego-yadra/]семантич
еское[/url] [url=http://6.ru]ядро[/url][/url] seo
Дата публикации: 10 августа 2011 16:25 | ICQ: --
цитировать
#6 checkertrast |  

В пещере обнаружено свыше 300 рисунков с изображениями животных [url=http://8.ru]Методом[/url] радиоуглеродной датировки [url=http://5.ru]возраст[/url] рисунков [url=http://6.ru]установлен[/url] [url=http://7.ru]между[/url] 33

at [url=http://6.ru]ua/[/url] [url=http://5.ru]детское[/url] [url=http://8.ru]питание,[/url] [url=http://7.ru]малютка[/url]

at [url=http://5.ru]ua/[/urlДетское[/url] [url=http://6.ru]питание][url=]http://detskoe-pitanie[/url]
Дата публикации: 29 августа 2011 12:18 | ICQ: --
цитировать

Добавить комментарий


Включите эту картинку для отображения кода безопасности
обновить код



 

Лучшие новости

Наш опрос

Мы в интернете


Профиль

Добро пожаловать, гость. Войдите, или зарегистрируйтесь.
Логин:

Пароль:

Забыли пароль?

Друзья


хомяк Немиро Алексея


Музыка микросхем
Хак-академия

Интересные ссылки


Продажа оборудования для салонов - виброплатформы. Виброплатформы PowerPlate.