Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Описание алгоритма обработчиков прерыванийСтр 1 из 2Следующая ⇒
Введение Использование микроЭВМ существенно повышает уровень автоматизации процессов управления. МП позволяют значительно уменьшить габаритные размеры устройств, при этом сложность решения задачи программирование может оказаться значительно меньшей чем при реализации такого же устройства на дискретных элементах. Данный аспект значительно расширяет область применения МП-систем, в системах управления. Поэтому современный специалист в области промышленной электроники должен обладать некоторыми определенными навыками и знаниями, позволяющими ему успешно использовать и внедрять микропроцессорную технику в промышленное производство. В данной работе решается определенная задача с использованием однокристальной ЭВМ МК51, получившей широкое распространение. Это 8-ми битное устройство, содержащее 4 программируемых порта ввода-вывода, 2 таймера/счетчика, поддерживающее обмен по последовательному каналу (RS232), с возможностью подключения внешней памяти программ и данных. В данной курсовой работе была реализована микропроцессорная система замера и индикации температуры на индикаторе. Для получения данных о температуре был использован датчик с ШИМ - сигналом на выходе. Данные с этого датчика обрабатываются программой микроконтроллера, преобразуются в необходимый формат и выводятся на индикацию. Одновременно идет проверка на вхождение текущей температуры в предложенный задании диапазон. В случае выхода температуры за его пределы начинается генерация звукового сигнала определенной частоты. Также проверяется факт прихода данных с датчика. Для этого измеряется промежуток времени с момента последнего поступления данных и если он превышает определенное значение, то контроллер решает, что датчик вышел из строя и также делает предупреждение об этом. Описание программы В данной курсовой работе необходимо обеспечить вывод текущего значения температуры на индикацию. Для реализации этого задания, необходимо иметь устройство, сообщающее о текущей температуре в том или ином месте. В качестве такого устройства выбран датчик температуры TMP03, который выдает ШИМ сигнал, временные параметры которого позволяют судить о температуре. И по соотношению T1 и T2, определяют значение измеряемой температуры. В документации по данному датчику для выполнения последнего действия предлагается следующая формула:
Для использования этого выражения необходимо иметь величины T1 и T2, т.е. контроллер, на который поступает сигнал датчика должен решать проблему определения его временных параметров. В данном случае для реализации этой задачи применен следующий метод: Выход датчика соединен к контактами внешних прерываний процессора, но к одному их них он подключен через инвертор. Это говорит о том, что при приходе импульса будет вызываться одно прерывание, а по приходу паузы - другое прерывание, а программа должна решить вопрос замера интервала времени между двумя соседними вызовами. В данном случае необходимо установить вид прерывания по фронту, и по приходу прерывания запустить таймер, после окончания импульса или паузы вызывается другое прерывание и данные из таймера считываются и счет продолжается до прихода нового прерывания. По окончании тракта счет останавливается и в таймере будет суммарное время процесса (импульс + пауза). Такой принцип и реализован в данной работе. Ниже приведены блок-схемы алгоритмов работы обработчиков прерываний INT1 и INT0 (рис. 1).
Описание основной программы
Основная программа (рис. 2) начинается со стандартных процедур инициализации флагов, используемых в программе (fready, begread, errtemp). Также настраиваются прерывания. Внешние прерывания устанавливаются по фронту и получают наивысший приоритет для повышения точности измерения температуры. Далее программа входит в цикл ожидания и ожидает флаг готовности данных, который, как ранее было сказано, устанавливается в конце каждого измерения. После установления этого флага начинается обработка пришедших данных, но сначала он сбрасывается для организации следующего цикла ожидания. Далее вызывается процедура вычисления температуры по выше приведенной формуле (она (процедура) будет рассмотрена несколько ниже). Абсолютное значение температуры, вычисленное данной процедурой возвращается в аккумуляторе, а знак температуры можно узнать анализируя специализированный флаг знака pos, который устанавливается если знак температуры положительный. На следующем этапе проверяется вхождение текущей температуры в предложенный в задании промежуток. Для этого вызывается специализированная процедура testlimit, которая осуществляет данную операцию. Внутри этой процедуры может сбросится или установится флаг errtemp, который и предупреждает о выходе температуры за заданные пределы. Последствия этого события будут выяснены позже Далее абсолютное значение температуры, записанное в аккумуляторе необходимо перевести в BCD-код. Для реализации этой операции воспользуемся командой деления с остатком и разделим acc на 10. В результате в аккумуляторе окажется число десятков, а остаток будет представлять собой число единиц делимого (в данном случае подразумевается, что число двухзначное). Далее: · меняются тетрады в acc и в старшей тетраде оказываются десятки производится операция “ИЛИ” аккумулятора с остатком и в результате в acc оказывается абсолютное значение температуры в BCD-коде. Этот BCD-код на следующем этапе преобразуется в код семисегментного индикатора. Этот процесс производится по специальной таблице кодов, записанной в ПЗУ. В данном случае это инверсные коды, поскольку светодиоды индикатора будут управляться нулем. Выводимое число для каждого разряда заносятся в специальную область памяти, где каждому разряду отводится 1байт. В самый старший разряд выводится знак температуры, если таковой присутствует. Также поверяется на равенство 0 старший разряд числа и если это равенство выполняется производится гашение второго разряда индикатора, а в случае если температура отрицательна в него выводится знак “минус”, а гашению подвергается третий разряд Далее программа переходит в цикл ожидания новых данных.
Динамическая индикация
В данной работе индикация является динамической и осуществляется по прерыванию от таймера, переполнение которого наступает с определенной частотой. В данном случае используется таймер T1. Блок-схема обработчика этого прерывания представлена на рис. 3. В него входит участок, непосредственно динамической индикации, а также участок генерации звуковых сигналов в критических ситуациях; под последними понимается авария датчика или выход температуры за заданные пределы. В самом начале обработчика происходит проверка исправности датчика. Для этого используется ранее упоминаемая переменная control. Она содержит количество интервалов по 10ms (период возникновения переполнения таймера) прошедших с момента последнего прихода данных. Если содержимое этой переменной достигает 50, то возникает подозрение, что с датчиком случилось несчастье и выставляется флаг аварии датчика, в данном случае это пользовательский флаг 0V и в специальную область памяти для индикации загружаются коды слова “ERR”, которое с этого момента и выводится на индикатор свидетельствуя об аварии. В случае, если данные приходят нормально производится вывод численного значения температуры. За один раз выводится один разряд. Предварительно проверяется флаг разрешения индикации и в случае если она запрещена данный участок программы игнорируется и происходит переход на участок генерации звука. Необходимость запрещения индикации возникает в процессе модификации специальной области памяти. В этот момент основная программа выставляет флаг запрета и сама же его потом сбрасывает. Индикация начинается с процесса записи управляющего слова в P1(напр. 11011111). Разрешение работы индикатора производится нулем. В приведенном выше примере выбран самый младший индикатор. Далее в порт P0 выводится содержимое соответствующего разряд, которое берется по адресу, записанному в специальной переменной rcount. Далее этот адрес модифицируется, а управляющее слово сдвигается на бит влево, т.е. в следующий раз будет выводится другой разряд. Этот процесс повторяется до тех пор пока 0 в управляющем слове не попадет в флаг переноса. В этом случае управляющее слово настраивается снова на самый младший разряд индикатора, а в rcount заносится адрес на байт данных младшего индикатора. На следующем шаге программа переходит в блок генерации звуковых сигналов. В начале проверяется наличие флага аварии датчика и если он есть производится переход на генерацию меандра 1000Гц. В случае если аварии не произошло проверяется флаг выхода температуры за пределы Errtemp, который ранее упоминался и если он установлен производится переход, на генерацию меандра 500Гц, т.е. инверсия бита в порту производится через раз, для этого используется специальный флаг delaybit, который инвертируется при каждом возникновении прерывания, а инверсия бита в порту производится только в случае его единичного значения. Далее в конце проверяется промежуток времени который прошел с момента начала генерации (переменная soundgen), если это время равно 5 с., то происходит запрещение генерации на 5 мин., которые тоже контролируются с помощью этой переменной. Листинг программы May 8 2012 11: 24 Page 1 2500 A.D. 8051 Macro Assembler - Version 4.02a Input Filename: E: \ASM51\KURS\KURS.ASM Output Filename: KURS.obj 1 0077 notsound: equ 119; флаг перерыва 5 мин. в генерации звука 2 0078 fready: equ 120; флаг готовности результата 3 0079 begread: equ 121; флаг начала чтения данных с датчика 4 007A pos: equ 122; знак температуры 5 007B inden: equ 123; разрешение динамической индикации 6 007C errtemp: equ 124; разрешение генерации звука при выходе температуры за 7 ; заданные границы 8 9 F830 indfreq: equ -2000; частота индикации (1 маш. цикл 0.5uS) 10 0000 11 0040 ph: equ 40h 12 0041 pl: equ 41h 13 0000 14 0042 ih: equ 42h 15 0043 il: equ 43h 16 0000 17 0044 indicat: equ 44h; информация, выводимая на индикацию (3 байта) 18 0047 rcount: equ 47h; указатель активного разряда при индикации 19 0048 soundgenl: equ 48h; переменная для хранения промежутка времени 20 0049 soundgenh: equ 49h; в течение которого генерируется звук 21 0000 22 0050 Temper: equ 50h; текущее значение температуры 23 0000 24 0052 pulse: equ 52h; длина импульса (3 байта) 25 0055 pause: equ 55h; длина паузы (3 байта) 26 0058 mem: equ 58h 27 0061 control: equ 61h; контрольное время в интервалах по 10mS, 28 ; которое прошло с момента последнего прихода данных с датчика. 29 ; Если данное число превышает 250 (250mS), то это говорит о том, 30 ; что с датчиком произошло несчастье (напр. нарушение соединения 31 ; с контроллером или выход из строя самого датчика) 32 0000 33 0062 minutes: equ 62h; счетчик минут в перерыве генерации звука 34 0032 tempmax: equ 50; максимальное положительное значение температуры 35 0028 tempmin: equ 40; минимальное отрицательное значение температуры 36 0000 37 0000 80 2E sjmp start 38 0002 39 ; Обработчик INT0 (импульс) 40 0003 org 0003h 41 0003 02 00 C9 jmp int_0 42 0006 43 ; Обработчик INT1 (пауза) 44 0013 org 0013h 45 0013 02 00 EE jmp int_1 46 0016 47 001B org 001bh 48 001B 02 00 FF jmp dynind; динамическая индикация 49 001E 50 0030 org 30h 51 0030 52 ; Основная программа 53 0030 start: 54 ; Настройка таймера 55 0030 75 89 11 mov tmod, #00010001b; T0-режим 01 T1-режим 01 56 0033 57 ; Загрузка таймера динамической индикации 58 0033 75 8D F8 mov th1, #> indfreq 59 0036 75 8B 30 mov tl1, #< indfreq 60 0039 61 ; Разрешение прерываний 62 0039 75 A8 8D mov ie, #10001101b; разрешить int0, int1 и T1 63 003C 43 88 05 orl tcon, #00000101b; внешние прерывания по фронту 64 003F 65 ; Расстановка приоритетов 66 003F 75 B8 05 mov ip, #00000101b; INT1 и INT2-наивысшие приоритеты 67 0042 68 ; Инициализация флагов и переменных 69 0042 C2 78 clr fready; инициализация флага готовности 70 0044 C2 79 clr begread; инициализация флага начала чтения 71 0046 C2 7C clr errtemp; генерация сигнала запрещена 72 0048 C2 77 clr notsound 73 004A 74 004A 75 61 00 mov control, #0 75 004D 75 47 44 mov rcount, #indicat; указатель на данные для индикации 76 0050 90 03 4E mov dptr, #seg7ind; адрес массива кодов индикатора 77 0053 78 ; Обнуление временных счетчиков 79 0053 75 48 00 mov soundgenl, #0 80 0056 75 49 00 mov soundgenh, #0 81 0059 75 62 00 mov minutes, #0 82 005C 83 005C 75 90 EF mov p1, #11101111b; инициализация порта, управляющего включением 84 ; определенных разрядов индикатора 85 005F 86 ; Запуск таймера динамической индикации 87 005F D2 8E setb tr1 88 0061 89 0061 waitnew: 90 0061 D2 7B setb inden; динамическая индикация разрешена 91 92 0063 30 78 FD jnb fready, $; ожидание новых данных с датчика 93 0066 C2 78 clr fready; сброс флага готовности до следующего раза 94 0068 95 ; Определение длины паузы 96 ; ih, il-длина импульса 97 ; ph, pl-длина импульса+длина паузы 98 0068 99 ; Перепишем в первую очередь данные из спец ячеек в регистры, чтобы не 100 ; потерять их (данные) 101 0068 AC 42 mov r4, ih 102 006A AD 43 mov r5, il 103 006C AE 40 mov r6, ph 104 006E AF 41 mov r7, pl 105 0070 106 ; Найдем длину паузы 107 0070 C3 clr c 108 0071 109 0071 ED mov a, r5 110 0072 9F subb a, r7 111 0073 FF mov r7, a 112 0074 113 0074 EE mov a, r6 114 0075 9C subb a, r4 115 0076 FE mov r6, a; r6, r7-длина паузы 116 117 ; Пересылка длины импульса и паузы в специальные трехбайтные переменные 118 0077 78 52 mov r0, #pulse 119 0079 ED mov a, r5 120 007A F6 mov @r0, a 121 007B 08 inc r0 122 007C EC mov a, r4 123 007D F6 mov @r0, a 124 007E 08 inc r0 125 007F 76 00 mov @r0, #0 126 0081 127 0081 78 55 mov r0, #pause 128 0083 EF mov a, r7 129 0084 F6 mov @r0, a 130 0085 08 inc r0 131 0086 EE mov a, r6 132 0087 F6 mov @r0, a 133 0088 08 inc r0 134 0089 76 00 mov @r0, #0 135 136 ; Подсчитаем численное значение температуры 137 008B 12 01 AD call Calc_Temp 138 008E F5 50 mov Temper, a 139 0090 140 0090 12 02 27 call testlimit; проверить вхождение текущего значения температуры 141 ; в заданные пределы 142 0093 143 ; Перевод десятичного числа в BCD-код 144 0093 75 F0 0A mov b, #10 145 0096 84 div ab 146 0097 C4 swap a 147 0098 45 F0 orl a, b 148 009A 149 ; Переведем BCD-число в код семисегментного индикатора 150 009A seg7code: 151 009A 78 44 mov r0, #indicat; адрес переменной для динамической индикации 152 009C 153 ; Для дальнейшего использования сохраним в стеке температуру в BCD-коде 154 009C C0 E0 push acc 155 156 009E 54 0F anl a, #00001111b 157 00A0 158 ; Приостановим динамическую индикацию 159 00A0 C2 7B clr inden 160 00A2 161 ; Выборка из массива кода, по смещению соотв. кодируемому числу 162 00A2 93 movc a, @a+dptr 163 00A3 F6 mov @r0, a 164 00A4 08 inc r0; младший разряд 165 00A5 166 ; Кодируем таким же образом старший разряд 167 00A5 D0 E0 pop acc 168 00A7 54 F0 anl a, #11110000b 169 00A9 C4 swap a 170 00AA 171 ; Поскольку это старший разряд числа, то имеет смысл гашение нуля 172 00AA B4 00 04 cjne a, #0, notguish 173 00AD 74 FF mov a, #ffh; гашение разряда 174 00AF 80 01 sjmp outind 175 00B1 176 ; Разряд не нулевой - гашение не нужно 177 00B1 notguish: 178 00B1 93 movc a, @a+dptr 179 00B2 180 00B2 outind: 181 00B2 F6 mov @r0, a 182 183 ; Выведем знак числа 184 00B3 185 ; Подготовим байт для знакового разряда 186 00B3 A2 7A mov c, pos 187 00B5 75 F0 FF mov b, #ffh 188 00B8 92 F6 mov b.6, c; (диод G) 189 00BA 190 ; Имеется трехразрядный индикатор(общий анод, активный-0) 191 00BA 192 ; Если старший разряд числа погашен, то знак выводится в него, иначе... 193 00BA B4 FF 07 cjne a, #ffh, notnull 194 00BD 195 00BD A6 F0 mov @r0, b; вывод знака в старший разряд (2-й слева) 196 00BF 197 ; Погасим самый старший разряд 198 00BF 08 inc r0 199 00C0 76 FF mov @r0, #ffh 200 00C2 01 61 jmp waitnew 201 00C4 202 ; Разряд не нулевой 203 00C4 notnull: 204 00C4 08 inc r0 205 00C5 A6 F0 mov @r0, b; (диод G) 206 00C7 01 61 jmp waitnew 207 00C9 208 00C9 209 ; 210 ; INT0-вызывается по приходу импульса 211 00C9 int_0: 212 00C9 20 79 0A jb begread, rpause 213 00CC 214 00CC 75 61 00 mov control, #0 215 00CF D2 8C setb tr0; запуск таймера 216 00D1 D2 79 setb begread; установка флага начала нового процесса тения 217 00D3 C2 78 clr fready; данные не готовы 218 00D5 32 reti 219 00D6 220 ; Чтение данных о общей длине (импульс+пауза) 221 00D6 rpause: 222 00D6 C2 8C clr tr0; останов таймера 223 00D8 85 8C 40 mov ph, th0 224 00DB 85 8A 41 mov pl, tl0 225 00DE 226 ; Обнуление таймера 227 00DE 75 8C 00 mov th0, #0 228 00E1 75 8A 00 mov tl0, #0 229 00E4 230 00E4 C2 79 clr begread; ожидание нового импульса для начала измерения 231 00E6 D2 78 setb fready; данные прочитаны 232 00E8 75 61 00 mov control, #0; обнулен контрольный счетчик времени задержки прихода 233 ; данных 234 00EB C2 D2 clr f0; данные пришли-следовательно датчик исправен 235 00ED 32 reti 236 ; 237 00EE 238 239 ; 240 ; INT1-вызывается при наступлении паузы 241 00EE int_1: 242 00EE 30 79 0D jnb begread, end_I1 243 00F1 244 ; Сохранение данных о длине импульса 245 00F1 C2 8C clr tr0 246 00F3 85 8C 42 mov ih, th0 247 00F6 85 8A 43 mov il, tl0 248 00F9 D2 8C setb tr0; дальнейший подсчет 249 00FB 75 61 00 mov control, #0 250 00FE 251 00FE end_I1: 252 00FE 32 reti 253 ; 254 00FF 255 256 ; 257 ; DYNIND-прерывание от T1 для динамической индикации и выдачи сигналов 258 00FF dynind: 259 00FF C0 E0 push acc 260 ; Сохранение флага переноса 261 0101 65 E0 xrl a, a 262 0103 13 rrc a 263 0104 C0 E0 push acc 264 0106 C0 01 push 1 265 266 0108 05 61 inc control; прошел еще один интервал 10mS с момента последнего 267 ; прихода данных с датчика 268 010A E5 61 mov a, control 269 010C 270 ; Проверка исправности датчика 271 ; Датчик считается неисправным, если данные с него не поступают 500mS 272 273 ; Если флаг уже установлен, то дальнейший контроль является бесмысленным 274 010C 20 D2 19 jb f0, display 275 010F B4 FA 16 cjne a, #250, display 276 ; Авария датчика (данные подозрительно долго не приходят) 277 0112 D2 D2 setb f0; установка флага неисправности датчика 278 0114 279 ; Загрузка слова ERR в переменную динамической индикации 280 0114 79 44 mov r1, #indicat; адрес переменной 281 0116 77 08 mov @r1, #08h; R 282 0118 09 inc r1 283 0119 77 08 mov @r1, #08h; R 284 011B 09 inc r1 285 011C 77 46 mov @r1, #46h; E 286 ; С этого момента индикатор будет отображать слово ERR, говорящее об 287 ; аварии датчика 288 011E 289 ; Досрочный звуковой сигнал в любом случае 290 011E 75 48 00 mov soundgenl, #0 291 0121 75 49 00 mov soundgenh, #0 292 0124 C2 77 clr notsound 293 0126 80 08 sjmp newind 294 0128 295 ; Данные приходят нормально 296 0128 display: 297 0128 30 7B 21 jnb inden, bell; проверка наличия разрешающего флага индикации 298 012B 299 ; Флаг установлен 300 012B E5 90 mov a, p1 301 012D 33 rlc a 302 012E 40 05 jc indicts 303 304 0130 newind: 305 ; Подготовка для повторной индикации 306 0130 75 47 44 mov rcount, #indicat 307 0133 74 DF mov a, #11011111b; инициализация порта, управляющего включением 308 ; индикаторов 309 0135 indicts: 310 ; Данные выведены не полностью 311 ; Открыть соответствующий разряд 312 0135 F5 90 mov p1, a 313 0137 A9 47 mov r1, rcount; адрес информации для текущего активного разряда 314 315 ; Вывести очередной разряд в порт 316 0139 E7 mov a, @r1 317 013A F5 80 mov p0, a 318 013C 05 47 inc rcount 319 013E 320 ; Выход из прерывания динамической индикации 321 013E exit_ind: 322 013E 323 ; Перезагрузить таймер 324 013E 75 8D F8 mov th1, #> indfreq 325 0141 75 8B 30 mov tl1, #< indfreq 326 0144 327 ; Если не установлен ни один и флагов ошибок то переход на генерацию не 328 ; происходит 329 0144 20 D2 05 jb f0, bell 330 0147 20 7C 02 jb errtemp, bell 331 014A 80 59 sjmp exitin 332 014C 333 ; Генерация звуковых сигналов в критических ситуациях 334 014C bell: 335 014C 20 77 11 jb notsound, endbell; идет пауза в 5 мин или нет 336 014F 337 ; Проверка флага аварии датчика 338 014F 30 D2 04 jnb f0, LimitErr 339 0152 340 ; Предупреждающий сигнал об ошибке датчика 341 0152 SensorErr: 342 ; Генерация меандра (1000Гц), в случае если данные долго не приходят данные 343 0152 B2 A0 cpl p2.0 344 0154 80 0A sjmp endbell; генерация меандра в случае аварии имеет высший приоритет 345 0156 346 ; Сигнал выхода температуры за заданные пределы 347 007D delaybit: equ 125; вспомогательный бит 348 0156 349 0156 LimitErr: 350 0156 30 7C 4C jnb errtemp, exitin 351 ; Генерация меандра 500Гц. Инверсия бита в порту производится через раз 352 0159 B2 7D cpl delaybit 353 015B 30 7D 47 jnb delaybit, exitin 354 015E B2 A0 cpl p2.0 355 0160 356 0160 357 0160 endbell: 358 0160 C3 clr c 359 0161 05 48 inc soundgenl 360 0163 361 0163 E5 49 mov a, soundgenh 362 0165 34 00 addc a, #0 363 0167 F5 49 mov soundgenh, a 364 0169 365 0169 30 77 1E jnb notsound, p3_second 366 016C 367 ; Проверка на истечение 5 минут 368 016C p5_minutes: 369 016C C3 clr c 370 016D E5 48 mov a, soundgenl 371 016F 94 70 subb a, #< 6000 372 0171 70 32 jnz exitin 373 0173 374 0173 E5 49 mov a, soundgenh 375 0175 94 17 subb a, #> 6000 376 0177 70 2C jnz exitin 377 0179 378 ; Обнулить счетчик миллисекунд 379 0179 75 48 00 mov soundgenl, #0 380 017C 75 49 00 mov soundgenh, #0 381 017F 382 ; Добавить к счетчику минут 1 383 017F 05 62 inc minutes 384 0181 E5 62 mov a, minutes 385 0183 B4 05 1F cjne a, #5, exitin 386 0186 387 ; Прошло 5 минут нужно повторить предупреждающий сигнал 388 0186 C2 77 clr notsound 389 0188 80 1B sjmp exitin 390 018A 391 ; Проверка кончился ли промежуток генерации звука 3 c. 392 018A p3_second: 393 018A C3 clr c 394 018B E5 48 mov a, soundgenl 395 018D 94 2C subb a, #< 300 396 018F 70 14 jnz exitin 397 0191 398 0191 C3 clr c 399 0192 E5 49 mov a, soundgenh 400 0194 94 01 subb a, #> 300 401 0196 70 0D jnz exitin 402 0198 403 ; Остановить генерацию 404 0198 C2 A0 clr p2.0 405 019A 406 ; Обнуление переменных-счетчиков миллисекунд 407 019A 75 48 00 mov soundgenl, #0 408 019D 75 49 00 mov soundgenh, #0 409 01A0 75 62 00 mov minutes, #0 410 01A3 D2 77 setb notsound; начать отсчитывание промежутка в 5 мин. 411 01A5 412 01A5 exitin: 413 ; Восстановление данных из стека перед выходом 414 01A5 D0 01 pop 1 415 01A7 416 ; Восстановление флага переноса 417 01A7 D0 E0 pop acc 418 01A9 33 rlc a 419 01AA 420 01AA D0 E0 pop acc 421 01AC 32 reti 422 ; 423 424 ; Процедура подсчета значения температуры425 ; Выход: a-численное значение температуры (модуль) 426 ; 427 01AD Calc_Temp: 428 01AD C0 00 push 0 429 01AF C0 01 push 1 430 01B1 C0 07 push 7 431 01B3 432 ; 400*T1 433 01B3 434 01B3 78 58 mov r0, #mem; mem=400 435 01B5 76 90 mov @r0, #90h 436 01B7 08 inc r0 437 01B8 76 01 mov @r0, #1h 438 01BA 08 inc r0 439 01BB 76 00 mov @r0, #0h 440 01BD 441 01BD 78 58 mov r0, #mem 442 01BF 79 52 mov r1, #pulse 443 01C1 444 01C1 12 03 08 call MUL_3B; mem=400*T1 445 446 01C4 78 52 mov r0, #pulse 447 01C6 79 55 mov r1, #pause 448 01C8 449 ; Сохраним значение длины паузы в переменной pulse 450 ; для дальнейшего процесса округления 451 01C8 7F 03 mov r7, #3 452 01CA moveb: 453 01CA E7 mov a, @r1 454 01CB F6 mov @r0, a 455 01CC 09 inc r1 456 01CD 08 inc r0 457 01CE DF FA djnz r7, moveb 458 01D0 459 ; Восстановим адреса в регистрах 460 01D0 78 58 mov r0, #mem 461 01D2 79 55 mov r1, #pause 462 01D4 12 02 A8 call DIV_3B; mem=(400*T1)/T2 463 01D7 464 ; После выполнения деления в pause содержится остаток 465 01D7 466 ; Из переменной mem можно взять только младшие два байта 467 01D7 C3 clr c 468 01D8 74 EB mov a, #235 469 01DA 96 subb a, @r0 470 01DB F6 mov @r0, a 471 01DC 08 inc r0 472 01DD 74 00 mov a, #0 473 01DF 96 subb a, @r0 474 01E0 F6 mov @r0, a 475 01E1 476 ; Запись знака числа 477 01E1 92 7A mov pos, c 478 01E3 B2 7A cpl pos 479 01E5 E5 58 mov a, mem 480 01E7 481 ; Округление модуля температуры 482 01E7 trunc: 483 ; Проверим остаток после операции деления и округлим модуль температуры 484 ; в ту или иную сторону 485 01E7 486 ; pause-остаток 487 ; pulse-делитель 488 ; Для примерного округления разделим делитель на 2 и сравним с остатком 489 ; если последний больше, то модуль температуры -1 490 ; В случае когда они равны условимся округлять в большую сторону 491 01E7 492 01E7 C0 E0 push acc 493 ; Проверим не равняется ли остаток 0 494 01E9 78 55 mov r0, #pause 495 ; Тестирование младшей части остатка 496 01EB E6 mov a, @r0 497 01EC B4 00 07 cjne a, #0, testost 498 ; Тестирование старшей части остатка 499 01EF 08 inc r0 500 01F0 E6 mov a, @r0 501 01F1 B4 00 02 cjne a, #0, testost 502 ; Остаток при делении равен 0 503 01F4 80 23 sjmp exitcalk 504 01F6 505 ; Протестируем величину погрешности 506 01F6 testost: 507 ; Разделим делитель на 2 508 01F6 78 52 mov r0, #pulse 509 01F8 79 55 mov r1, #pause 510 01FA 12 02 59 call RRC_3B 511 01FD 512 ; Сравним остаток с полученным результатом (сравниваем младшие 2 байта) 513 01FD 514 ; Для начала сравним старшие байты, если они отличаютя то дальнейшее 515 ; сравнение излишне 516 01FD 08 inc r0 517 01FE 09 inc r1 518 01FF 519 01FF 7F 02 mov r7, #2; счетчик итераций цикла сравнения 520 0201 521 0201 test: 522 0201 C3 clr c 523 0202 E6 mov a, @r0; байт поделенного делителя 524 0203 97 subb a, @r1 525 0204 50 07 jnc testequ 526 ; Делитель меньше-от температуры нужно отнять 1 527 0206 D0 E0 pop acc 528 0208 14 dec a 529 0209 C0 E0 push acc 530 020B 80 0C sjmp exitcalk 531 020D 532 ; Проверка на равенство байты 533 020D testequ: 534 020D E6 mov a, @r0 535 020E 87 F0 mov b, @r1 536 0210 B5 F0 06 cjne a, b, exitcalk 537 ; Проверим, какие байты тестируются (старшие или младшие) 538 0213 DF 04 djnz r7, exitcalk 539 0215 540 ; Тестировались старшие байты 541 ; Старшие части равны, следовательно нужно проверять младшие 542 ; Настройка указателей на младшие части 543 0215 19 dec r1 544 0216 18 dec r0 545 0217 80 E8 sjmp test 546 0219 547 0219 548 0219 exitcalk: 549 0219 D0 E0 pop acc 550 ; Если температура отрицательна переведем число и дополнительного кода 551 ; в пряиой 552 021B 20 7A 02 jb pos, ex 553 021E 14 dec a 554 021F F4 cpl a 555 556 0220 ex: 557 0220 D0 07 pop 7 558 0222 D0 01 pop 1 559 0224 D0 00 pop 0 560 0226 561 ; a-модуль температуры 562 0226 22 ret 563 ; 564 0227 565 0227 566 ; Проверка допустимости данной температуры 567 ; Вход: a-численное значение температуры 568 ; 569 0227 testlimit: 570 0227 C0 E0 push acc 571 0229 C0 F0 push b 572 022B C3 clr c 573 022C 574 022C C2 7C clr errtemp; предварительный сброс флага ошибки 575 022E 576 022E 20 7A 05 jb pos, positivs 577 ; Отрицательная температура 578 0231 75 F0 28 mov b, #tempmin 579 0234 80 03 sjmp limittest 580 0236 581 ; Положительная температура 582 0236 positivs: 583 0236 75 F0 32 mov b, #tempmax 584 0239 585 ; Проверка вхождния в заданные пределы 586 0239 limittest: 587 0239 95 F0 subb a, b 588 023B 40 02 jc exitlim 589 023D D2 7C setb errtemp 590 023F 591 023F exitlim: 592 023F D0 F0 pop b 593 0241 D0 E0 pop acc 594 0243 22 ret 595 ; 596 597 598 0244 .include math.asm 599 ; Файл math.asm процедуры выпонения арифметических операций с трехбайтными 600 ; числами 601 602 ; Процедура сдвига влево через флаг переноса 603 ; Вход: R0-указатель на трехбайтное число 604 ; Выход: R0-указатель на результат 605 ; 606 0244 607 0244 RLC_3B: 608 0244 C0 00 push 0 609 0246 C0 07 push 7 610 0248 C0 E0 push acc 611 024A 612 ; Сдвиг числа побайтно от младшего к старшему 613 024A 7F 03 mov r7, #3 614 024C RL: 615 024C E6 mov a, @r0 616 024D 33 rlc a 617 024E F6 mov @r0, a 618 024F 08 inc r0 619 0250 DF FA djnz r7, RL 620 0252 621 0252 D0 E0 pop acc 622 0254 D0 07 pop 7 623 0256 D0 00 pop 0 624 0258 22 ret 625 ; 626 0259 627 0259 628 629 ; Процедура сдвига вправо через флаг переноса630 ; Вход: R0-указатель на трехбайтное число 631 ; Выход: R0-указатель на результат 632 ; 633 0259 634 0259 RRC_3B: 635 0259 C0 00 push 0 636 025B C0 07 push 7 637 025D C0 E0 push acc 638 025F 639 025F 640 ; Настройка на старший байт 641 025F E8 mov a, r0 642 0260 24 02 add a, #2 643 0262 F8 mov r0, a 644 645 ; Сдвиг числа побайтно от старшего к младшему 646 0263 7F 03 mov r7, #3 647 0265 RR: 648 0265 E6 mov a, @r0 649 0266 13 rrc a 650 0267 F6 mov @r0, a 651 0268 18 dec r0 652 0269 DF FA djnz r7, RR 653 026B 654 026B D0 E0 pop acc 655 026D D0 07 pop 7 656 026F D0 00 pop 0 657 0271 22 ret 658 ; 659 0272 660 661 0272 662 ; Процедура сложения трехбайтных чисел663 ; Вход: 664 ; R0-указатель на первое слагаемое 665 ; R1-указатель на второе слагаемое 666 ; Выход: 667 ; R0-указатель на сумму 668 ; C-перенос 669 ; 670 0272 671 0272 ADD_3B: 672 0272 C0 00 push 0 673 0274 C0 01 push 1 674 0276 C0 07 push 7 675 0278 C0 E0 push acc 676 027A 677 ; Предварительная очистка флага C 678 027A C3 clr c 679 027B 7F 03 mov R7, #3; число байт в числе 680 027D 681 ; Сложение числа побайтно с использованием флага переноса 682 027D ADD: 683 027D E6 mov a, @R0 684 027E 37 addc a, @R1 685 027F F6 mov @R0, a 686 0280 687 0280 08 inc R0 688 0281 09 inc R1 689 0282 DF F9 djnz r7, ADD 690 0284 691 0284 D0 E0 pop acc 692 0286 D0 07 pop 7 693 0288 D0 01 pop 1 694 028A D0 00 pop 0 695 028C 22 ret 696 ; 697 028D 698 699 ; Процедура вычитания трехбайтных чисел700 ; Вход: 701 ; R0-указатель на уменьшаемое 702 ; R1-указатель на вычитаемое 703 ; Выход: 704 ; R0-указатель на разность 705 ; C-заем 706 ; 707 028D 708 028D SUB_3B: 709 028D C0 00 push 0 710 028F C0 01 push 1 711 0291 C0 07 push 7 712 0293 C0 E0 push acc 713 0295 714 ; Предварительное обнуление флага переноса 715 0295 C3 clr c 716 0296 717 0296 7F 03 mov r7, #3 718 0298 719 ; Реализация вычитания 720 0298 SUB: 721 0298 E6 mov a, @R0 722 0299 97 subb a, @R1 723 029A F6 mov @R0, a 724 029B 725 029B 08 inc r0 726 029C 09 inc r1 727 029D DF F9 djnz r7, SUB 728 029F 729 029F D0 E0 pop acc 730 02A1 D0 07 pop 7 731 02A3 D0 01 pop 1 732 02A5 D0 00 pop 0 733 02A7 22 ret 734 ; 735 02A8 736 737 ; Процедура деления трехбайтных чисел 738 ; Вход: 739 ; R0-указатель на делимое 740 ; R1-указатель на делитель 741 ; Выход: 742 ; R0-указатель на частное 743 ; R1-указатель на остаток 744 ; 745 02A8 746 02A8 DIV_3B: 747 0070 Remain: equ 70h; промежуточный остаток 748 0073 REZ: equ 73h; ячейка для временного хранения результата 749 02A8 C0 E0 push acc 750 02AA C0 07 push 7 751 02AC 752 02AC C0 00 push 0 753 02AE C0 01 push 1 754 02B0 755 ; Начальная инициализация промежуточного остатка 756 02B0 78 70 mov R0, #Remain 757 02B2 79 73 mov r1, #REZ 758 02B4 759 02B4 7F 03 mov r7, #3 760 02B6 init: 761 02B6 76 00 mov @R0, #0 762 02B8 77 00 mov @R1, #0 763 02BA 08 inc R0 764 02BB 09 inc r1 765 02BC DF F8 djnz r7, init 766 02BE 767 02BE D0 01 pop 1 768 02C0 D0 00 pop 0 769 02C2 770 ; Реализация операции деления 771 02C2 7F 18 mov r7, #24; число битов в операндах 772 02C4 DIVIDE: 773 ; Сдвинем делимое влево через флаг переноса 774 02C4 51 44 call RLC_3B; R0-указатель на результат (тот же, что и входной) 775 02C6 776 02C6 C0 00 push 0 777 02C8 78 70 mov r0, #Remain; адрес промежуточного остатка 778 02CA 51 44 call RLC_3B; сдвиг остатка влево с переносом 779 02CC 780 ; Вычтем из остатка делитель 781 02CC 51 8D call SUB_3B 782 02CE 50 0A jnc NOADD 783 784 ; Сохраним флаг переноса в стеке 785 02D0 65 E0 xrl a, a 786 02D2 33 rlc a 787 02D3 C0 E0 push acc 788 02D5 789 ; Остаток отрицательный, необходимо его восстановление 790 02D5 51 72 call ADD_3B 791 02D7 792 ; Восстановление флага переноса 793 02D7 D0 E0 pop acc 794 02D9 13 rrc a 795 02DA 796 02DA NOADD: 797 ; Сформируем бит частного 798 02DA B3 cpl c; инверсия флага переноса 799 02DB 78 73 mov R0, #REZ; загрузка адреса ячейки результата 800 02DD 51 44 call RLC_3B; перенос флага C в ячейку результата 801 02DF D0 00 pop 0; восстановление в R0 адреса делимого 802 02E1 803 02E1 DF E1 djnz r7, DIVIDE 804 02E3 805 806 ; Копируем результаты по входным адресам 807 02E3 C0 00 push 0 808 02E5 C0 01 push 1 809 02E7 79 73 mov R1, #REZ 810 02E9 811 02E9 7F 03 mov R7, #3h 812 02EB 813 ; Копирование частного 814 02EB copy1: 815 02EB E7 mov a, @R1 816 02EC F6 mov @r0, a 817 02ED 09 inc r1 818 02EE 08 inc r0 819 02EF DF FA djnz R7, copy1 820 821 02F1 D0 01 pop 1 822 02F3 823 ; Копирование остатка 824 02F3 C0 01 push 1 825 02F5 78 70 mov R0, #Remain 826 02F7 827 02F7 7F 03 mov r7, #3 828 02F9 copy2: 829 02F9 E6 mov a, @r0 830 02FA F7 mov @r1, a 831 02FB 09 inc r1 832 02FC 08 inc r0 833 02FD DF FA djnz R7, copy2 834 02FF D0 01 pop 1 835 0301 836 0301 D0 00 pop 0 837 0303 838 0303 D0 07 pop 7 839 0305 D0 E0 pop acc 840 0307 22 ret 841 ; 842 843 0308 844 ; Процедура умножения трехбайтных чисел 845 ; Вход: 846 ; R0-указатель на первый множитель 847 ; R1-указатель на второй множитель 848 ; Выход: 849 ; R0-указатель на произведение (трехбайтное!!! ) 850 ; 851 0308 MUL_3B: 852 0070 Rezm: equ 70h; ячейка для результата 853 0308 C0 E0 push acc 854 030A C0 07 push 7 855 856 ; Предварительный сброс бита переноса 857 030C C3 clr c 858 030D 859 ; Очиска ячейки результатов 860 030D C0 00 push 0 861 030F 78 70 mov r0, #Rezm 862 0311 863 0311 7F 03 mov r7, #3 864 0313 865 ; Очистка ячейки временного хранения результатов 866 0313 clear: 867 0313 76 00 mov @r0, #0 868 0315 08 inc r0 869 0316 DF FB djnz r7, clear 870 0318 D0 00 pop 0 871 031A 872 031A 7F 18 mov r7, #24; 24 бита в трехбайтном числе 873 031C 874 031C MULT: 875 ; Отправление младшего бита в битовый аккумулятор 876 031C C0 00 push 0 877 031E E9 mov a, r1 878 031F F8 mov r0, a 879 0320 51 59 call RRC_3B 880 0322 D0 00 pop 0 881 0324 882 0324 50 10 jnc noadds 883 0326 C0 00 push 0 884 0328 C0 01 push 1 885 032A 886 032A C0 00 push 0 887 032C D0 01 pop 1 888 032E 78 70 mov r0, #Rezm 889 0330 51 72 call ADD_3B; результат помещается по адресу Rezm 890 0332 891 0332 D0 01 pop 1 892 0334 D0 00 pop 0 893 0336 894 0336 noadds: 895 0336 C3 clr c; сброс флага 896 0337 51 44 call RLC_3B; сдвиг первого множителя 897 0339 898 0339 newiter: 899 0339 DF E1 djnz r7, MULT 900 033B 901 ; Копирование результата в ячейки по входному адресу 902 033B 79 70 mov r1, #Rezm 903 033D 904 033D C0 00 push 0 905 033F 7F 03 mov r7, #3 906 0341 907 0341 copym: 908 0341 E7 mov a, @r1 909 0342 F6 mov @r0, a 910 0343 08 inc r0 911 0344 09 inc r1 912 0345 DF FA djnz r7, copym 913 0347 D0 00 pop 0 914 0349 915 0349 D0 07 pop 7 916 034B D0 E0 pop acc 917 034D 22 ret 918 ; 919 920 921 ; Коды семисегментного индикатора 922 034E seg7ind: 923 034E C0 db C0h; 3fh; 0 924 034F F9 db F9h; 06h; 1 925 0350 A4 db A4h; 5bh; 2 926 0351 B0 db B0h; 4fh; 3 927 0352 99 db 99h; 66h; 4 928 0353 92 db 92h; 6dh; 5 929 0354 82 db 82h; 7dh; 6 930 0355 F8 db F8h; 07h; 7 931 0356 80 db 80h; 7fh; 8 932 0357 90 db 90h; 6fh; 9 933 934 0358 FUCK: Lines Assembled: 934 Assembly Errors: 0 Введение Использование микроЭВМ существенно повышает уровень автоматизации процессов управления. МП позволяют значительно уменьшить габаритные размеры устройств, при этом сложность решения задачи программирование может оказаться значительно меньшей чем при реализации такого же устройства на дискретных элементах. Данный аспект значительно расширяет область применения МП-систем, в системах управления. Поэтому современный специалист в области промышленной электроники должен обладать некоторыми определенными навыками и знаниями, позволяющими ему успешно использовать и внедрять микропроцессорную технику в промышленное производство. В данной работе решается определенная задача с использованием однокристальной ЭВМ МК51, получившей широкое распространение. Это 8-ми битное устройство, содержащее 4 программируемых порта ввода-вывода, 2 таймера/счетчика, поддерживающее обмен по последовательному каналу (RS232), с возможностью подключения внешней памяти программ и данных. В данной курсовой работе была реализована микропроцессорная система замера и индикации температуры на индикаторе. Для получения данных о температуре был использован датчик с ШИМ - сигналом на выходе. Данные с этого датчика обрабатываются программой микроконтроллера, преобразуются в необходимый формат и выводятся на индикацию. Одновременно идет проверка на вхождение текущей температуры в предложенный задании диапазон. В случае выхода температуры за его пределы начинается генерация звукового сигнала определенной частоты. Также проверяется факт прихода данных с датчика. Для этого измеряется промежуток времени с момента последнего поступления данных и если он превышает определенное значение, то контроллер решает, что датчик вышел из строя и также делает предупреждение об этом. Описание программы В данной курсовой работе необходимо обеспечить вывод текущего значения температуры на индикацию. Для реализации этого задания, необходимо иметь устройство, сообщающее о текущей температуре в том или ином месте. В качестве такого устройства выбран датчик температуры TMP03, который выдает ШИМ сигнал, временные параметры которого позволяют судить о температуре. И по соотношению T1 и T2, определяют значение измеряемой температуры. В документации по данному датчику для выполнения последнего действия предлагается следующая формула:
Для использования этого выражения необходимо иметь величины T1 и T2, т.е. контроллер, на который поступает сигнал датчика должен решать проблему определения его временных параметров. В данном случае для реализации этой задачи применен следующий метод: Выход датчика соединен к контактами внешних прерываний процессора, но к одному их них он подключен через инвертор. Это говорит о том, что при приходе импульса будет вызываться одно прерывание, а по приходу паузы - другое прерывание, а программа должна решить вопрос замера интервала времени между двумя соседними вызовами. В данном случае необходимо установить вид прерывания по фронту, и по приходу прерывания запустить таймер, после окончания импульса или паузы вызывается другое прерывание и данные из таймера считываются и счет продолжается до прихода нового прерывания. По окончании тракта счет останавливается и в таймере будет суммарное время процесса (импульс + пауза). Такой принцип и реализован в данной работе. Ниже приведены блок-схемы алгоритмов работы обработчиков прерываний INT1 и INT0 (рис. 1).
Описание алгоритма обработчиков прерываний
|
Последнее изменение этой страницы: 2020-02-17; Просмотров: 51; Нарушение авторского права страницы