Разработка подпрограммы индикации 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Разработка подпрограммы индикации



Теперь можно заняться следующим блоком часов – блоком индикации. При разработке часов мы получили устройство, в разных частях которого действуют различные частоты. Поэтому первоначально необходимо определить частоту, с которой необходимо производить обновление информации на светодиодных индикаторах.

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

Индикацию внутреннего состояния часов легче всего произвести в составе отдельной подпрограммы. Это, как уже говорилось ранее, позволит разделить задачи и решать их независимо. На данный момент уже реализованы часы. Блок индикации может непосредственно обращаться к переменным часов для считывания хранящейся в них информации. Исходный текст основной программы с циклом, в котором производится вызов подпрограммы индикации, приведен в листинге 25.9.

 

Листинг 25.9. Исходный текст основной программы.

 

#include<reg51.h>

#include "clock.h"

#include "Indic.h"

 

...

 

/********************************************************************

ВЫПОЛНЕНИЕ ПРОГРАММЫ НАЧИНАЕТСЯ ОТСЮДА

********************************************************************/

char Delit=20; //8-ми разрядная ячейка памяти для делителя частоты (1с)

void main(void)

{//-------------ИНИЦИАЛИЗАЦИЯ МИКРОКОНТРОЛЛЕРА-------------------------

Timer0_Init(); //Настроить таймер T0 на прерывания с периодом 50мс

//-------------ОСНОВНАЯ ПРОГРАММА МИКРОКОНТРОЛЛЕРА--------------------

while(1) //Бесконечный цикл

{

Indic(); //Произвести индикацию состояния часов на светодиодных

//индикаторах

 

if(--Delit==0) //Если прошла одна секунда, то

{Delit=20; //настроить делитель на коэффициент деления 20

Clock(); //и вызвать подпрограмму счётчика секунд.

}

PCON=1; //Перевести микроконтроллер в пониженный режим

} //потребления тока и подождать переполнения таймера

}

 

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

Теперь можно заняться подпрограммой блока индикации. На принципиальной схеме часов не указано, что и на каком индикаторе должно отображаться. Зададимся, что на индикаторе, подключенном к порту P0, будут отображаться единицы минут. На индикаторе, подключенном к порту P1, будут отображаться десятки минут. На индикаторе, подключенном к порту P2, будут отображаться десятки минут. На индикаторе, подключенном к порту P3, будут отображаться десятки минут.

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

Для декодирования двоично-десятичного кода предусмотрим подпрограмму-функцию decod. При этом декодируемое двоично-десятичное число будет передаваться в подпрограмму через ее параметр. Полученный в результате работы подпрограммы семисегментный код будет возвращаться самой функцией.

Точно так же как и в случае с часами для индикации создадим отдельный файл (модуль). Исходный текст модуля индикации приведен в листинге 25.10.

 

Листинг 25.10. Исходный текст модуля индикации.

 

#include<reg51.h>

#include "clock.h"

 

/*****************************************************************************

Подпрограмма семисегментного дешифратора

*****************************************************************************/

char Decod(char inp)

{

}

 

/*****************************************************************************

Подпрограмма блока индикации

*****************************************************************************/

void Indic(void)

{char tmp;

tmp=MIN%10; //Считать содержимое счётчика минут и выделить младшую тетраду

P1=Decod(tmp); //Преобразовать её в семисегментный код и передать через

//порт P1 на индикатор

 

tmp=MIN/10; //Считать содержимое счётчика минут и выделить старшую тетраду

P2=Decod(tmp); //Преобразовать её в семисегментный код и передать через

//порт P2 на индикатор

 

tmp=Chas%10; //Считать содержимое счётчика часов и выделить младшую тетраду

P0=Decod(tmp); //Преобразовать её в семисегментный код и передать через

//порт P0 на индикатор

 

tmp=Chas/10; //Считать содержимое счётчика минут и выделить старшую тетраду

P3=Decod(tmp); //Преобразовать её в семисегментный код и передать через

//порт P3 на индикатор

}

 

Выделение единиц минут осуществляется при помощи операции взятия остатка от деления на константу 10. Эта операция выполняется при использовании символа ‘%’. При этом осуществляется целочисленное беззнаковое деление содержимого счетчика минут на число 10. В результате в остатке мы получим единицы минут. Это число не будет превышать числа 10, а значит для его представления достаточно четырех бит (тетрады).

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

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

 

Листинг 25.11. Дизассемблированный текст подпрограммы индикации.

 

14: void Indic(void)

15: {char tmp;

16: tmp=MIN%10; //Считать содержимое счётчика минут и выделить младшую тетраду

C:0x0099 E50A MOV A,MIN(0x0A)

C:0x009B 75F00A MOV B(0xF0),#MIN(0x0A)

C:0x009E 84 DIV AB

C:0x009F AFF0 MOV R7,B(0xF0)

17: P1=Decod(tmp); //Преобразовать её в семисегментный код и передать через

18: //порт P1 на индикатор

19:

C:0x00A1 110A ACALL Decod(C:000A)

C:0x00A3 8F90 MOV P1(0x90),R7

20: tmp=MIN/10; //Считать содержимое счётчика минут и выделить старшую тетраду

C:0x00A5 E50A MOV A,MIN(0x0A)

C:0x00A7 75F00A MOV B(0xF0),#MIN(0x0A)

C:0x00AA 84 DIV AB

C:0x00AB FF MOV R7,A

21: P2=Decod(tmp); //Преобразовать её в семисегментный код и передать через

22: //порт P2 на индикатор

23:

C:0x00AC 110A ACALL Decod(C:000A)

C:0x00AE F5A0 MOV P2(0xA0),A

 

Как видно из этого листинга, деление осуществляется встроенной командой целочисленного деления DIV AB. В качестве примера неправильного использования данных операций воспользуемся листингом 25.12, где переменная MIN объявлена не как unsigned char, а как просто char.

 

Листинг 25.12. Дизассемблированный текст подпрограммы индикации с переменной MIN char типа.

 

14: void Indic(void)

15: {char tmp;

16: tmp=MIN%10; //Считать содержимое счётчика минут и выделить младшую тетраду

C:0x0099 E50A MOV A,MIN(0x0A)

C:0x009B 75F00A MOV B(0xF0),#MIN(0x0A)

C:0x009E 11CA ACALL C?SCDIV(C:00CA)

C:0x00A0 AFF0 MOV R7,B(0xF0)

17: P1=Decod(tmp); //Преобразовать её в семисегментный код и передать через

18: //порт P1 на индикатор

19:

C:0x00A2 110A ACALL Decod(C:000A)

C:0x00A4 8F90 MOV P1(0x90),R7

20: tmp=MIN/10; //Считать содержимое счётчика минут и выделить старшую тетраду

C:0x00A6 E50A MOV A,MIN(0x0A)

C:0x00A8 75F00A MOV B(0xF0),#MIN(0x0A)

C:0x00AB 11CA ACALL C?SCDIV(C:00CA)

C:0x00AD FF MOV R7,A

21: P2=Decod(tmp); //Преобразовать её в семисегментный код и передать через

22: //порт P2 на индикатор

23:

C:0x00AE 110A ACALL Decod(C:000A)

C:0x00B0 F5A0 MOV P2(0xA0),A

 

Как видно из приведенного листинга, в этой программе вместо машинной команды DIV AB используется подпрограмма знакового деления C?SCDIV, что вовсе не входило в наши планы, так как вряд ли эта подпрограмма состоит из одной машинной команды. Этот пример показывает насколько важен выбор типа переменной для каждого конкретного случая.

Теперь вспомним, а где же индикация, ведь именно для этого мы и начали писать подпрограмму. Собственно говоря, индикация осуществляется при копировании полученного из подпрограммы декодирования семисегментного кода в параллельный порт. В рассмотренном листинге подпрограммы индикации мы осуществили индикацию всех четырех цифр времени: десятков часов, часов, десятков минут и минут.

У нас осталась неразработанной подпрограмма семисегментного дешифратора, которая преобразует двоично-десятичное значение, содержащееся в локальной переменной tmp, в семисегментный код, пригодный для отображения на светодиодном индикаторе. Приступим к разработке этой подпрограммы.



Поделиться:


Последнее изменение этой страницы: 2017-02-07; просмотров: 181; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.142.35.75 (0.017 с.)