Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Упражнения. Пример 1.Используя встроенный в среду Borland® Delphi ассемблер, разработать две подпрограммы для определения текущего состояния счетчика и его значения




Пример 1. Используя встроенный в среду Borland® Delphi ассемблер, разработать две подпрограммы для определения текущего состояния счетчика и его значения. Обе подпрограммы должны быть функциями. Первая подпрограмма должна использовать регистр задвижки и возвращать текущее значение счетчика. Вторая подпрограмма должна использовать режим «Read back command» и в зависимости от переданного параметра возвращать режим работы счетчика либо его текущее значение.

 

Решение. Функция LatchCNT() возвращает текущее значение счетчика с помощью задвижки и поэтому может работать с обеими микросхемами таймера 8253(4). Единственным параметром функции является порядковый номер канала CNT, который может принимать значения [0,1,2]. Формат управляющего регистра показан в табл. 88, а алгоритм работы функции – на рис. 38.

 

 

Табл. 88. Формат управляющего регистра.

Биты                
Значение SC1 SC0     x x x x

 

 

Исходный текст функции приведен ниже.

 

function LatchCNT(CNT: Byte): Word;

begin

asm

{ Сохранение в стеке используемых регистров }

PUSH AX

PUSH DX

{ Фиксировать текущее значение счетчика }

MOV AL, CNT

SHL AL, 6

MOV DX, 43h

OUT DX, AL

{ Код выбора сначала LSB, а затем MSB }

OR AL, 00110000b

MOV DX, 43h

OUT DX, AL

{ Адрес регистра счетчика }

MOV DX, 40h

ADD DL, CNT

{ Получение младшего байта регистра счетчика }

IN AL, DX

{ Сохранение младшего байта в AH }

MOV AH, AL

{ Получение старшего байта регистра счетчика }

IN AL, DX

{ Обмен младшего и старшего байтов аккумулятора }

XCHG AL, AH

{ Функция возвращает результат }

MOV @Result, AX

{ Восстановление из стека содержимого регистров }

POP DX

POP AX

end

end;

 
 

 

 


Рис. 38. Алгоритм работы функции LatchCNT().

 

Функция GetCNT() предназначена для работы только с микросхемой 8254, т.к. использует режим «Read back command». Первый параметр CNT по-прежнему задает номер канала, а параметр Mode – запрашиваемое действие. При Mode = 0 функция возвращает текущее значение, при Mode = 1 – режим работы указанного канала (табл. 89).

 

 

Табл. 89. Формат управляющего регистра.

Значение счетчика
Биты                
Значение         C2 C1 C0 X
Статус канала
Биты                
Значение         C2 C1 C0 X

 

 

Коды выбора счетчика перечислены в табл. 90. Для упрощения не используется комбинация (C2=1, C1=1, C0=1).

 

Табл. 90. Коды выбора счетчика.

Счетчик C2 C1 C0
       
       
       

 

 

Алгоритм работы функции GetCNT() может быть следующим (рис. 39). Вначале код канала CNT сдвигается влево на CNT+1 разрядов. Затем код необходимо сложить по маске 0E0h (получить статус канала) или по маске 0D0h (получить значение счетчика). Полученный управляющий код должен быть выведен в порт 43h. После этого может быть прочитано содержимое регистра счетчика, вначале младший значимый байт, а затем старший.

Исходный текст функции приведен ниже.

 

function GetCNT(CNT,Mode: Byte): Word;

begin

asm

{ Сохранение в стеке используемых регистров }

PUSH AX

PUSH BX

PUSH DX

{ Сохранение номера счетчика в AL }

MOV AL,CNT

{ Сдвиг на CNT+1 влево содержимого AL для размещения

номера канала в разрядах D3D2D1 управляющего кода }

MOV CL, CNT

INC CL

SHL AL,CL

{ Определение запрашиваемого действия }

CMP Mode, 0

JNE @@1

{ Сложение по маске $0E0 }

OR AL, 0E0h

JMP @@2

{ Сложение по маске $0D0 }

@@1: OR AL, 0D0h

@@2: MOV DX, 43h

{ Передача кода в управляющий регистр }

OUT DX, AL

{ Получить адрес счетчика }

MOV DH, 0

MOV DL, 40h

ADD DL, CNT

{ Получение младшего байта регистра счетчика }

IN AL, DX

MOV AH, 0

{ Вновь определение запрашиваемого действия }

CMP Mode, 0

JNE @@3

{ Сохранение младшего байта в AH }

MOV AH, AL

{ Получение старшего байта регистра счетчика }

IN AL, DX

{ Обмен младшего и старшего байтов аккумулятора }

XCHG AL, AH

{ Функция возвращает результат }

@@3: MOV @Result, AX

{ Восстановление из стека содержимого регистров }

POP DX

POP BX

POP AX

end;

end;

 

 

 
 

 

 


Рис. 39. Алгоритм работы функции GetCNT().

 

Пример 2. Используя ассемблер TASM, разработать программу определения внутренней тактовой частоты микропроцессора в МГц. Использовать режим работы ассемблера IDEAL и упрощенные директивы сегментации. Для подсчета количества тактов процессора применить команду RDTSC (код операции 0F31h).

 

 

Решение. Команда RDTSC предназначена для загрузки в регистровую пару EDX:EAX содержимого 64-разрядного регистра MSR (Model Specific Register). Он используется для хранения значения счетчика тактовых импульсов TSC (Time Stamp Counter). Значение счетчика увеличивается на единицу с приходом очередного такта микропроцессора, а обнуление происходит при системном сбросе.Заметим, что команда RDTSC работает на микропроцессорах Intel Pentium и выше.

Внутренняя тактовая частота микропроцессора может быть рассчитана исходя из количества тактов, прошедших за временной интервал, равный периоду следования импульсов. Число тактов определяется с помощью команды RDTSC по содержимому регистра MSR в моменты изменения значения таймера. Эти изменения можно отследить с помощью переменной BIOS, расположенной по адресу 0040:006Ch. На рис. 40 показан алгоритм вычисления тактовый частоты.

 

 
 

 

 


Рис. 40. Алгоритм расчета внутренней тактовой частоты процессора.

 

 

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

 

 

или

 

 

Количество замеров для вычисления среднего значения длительности интервалов может быть произвольным, исходя из принципа «чем больше, тем лучше». Однако в случае реализации на ассемблере оптимальным является выбор значения, на единицу большего числа, кратного степени 2. Связано это с тем, что операция деления на 2n в двоичной арифметике реализуется простым сдвигом на n разрядов вправо. Число итераций равно 33, а количество интервалов 32.

Возможный вариант программы, реализующей алгоритм вычислений, представлен ниже.

 

IDEAL

.386

 

MODEL MEDIUM

 

STACK 100h

 

DATASEG

; Массив для хранения значений отсчетов счетчика

; тактов в моменты срабатывания системного таймера

TimeCounter DD 33 DUP(?)

; Разность между соседними замерами

DeltaT DD 32 DUP(?)

; Среднее значение длительности интервала

AverageTime DD?

; Предыдущее значение системного таймера

Time DD?

; Результат вычислений

FreqResult DD?

ENDS

 

CODESEG

PROC ProcFrequency

; Настроить регистр DS на глобальный сегмент данных

MOV AX, DGROUP

MOV DS, AX

; Настроить сегментный регистр ES на область данных BIOS

MOV AX, 0

MOV ES, AX

; Инициализация начальных параметров

MOV BX, 33

MOV DI, OFFSET TimeCounter

; Текущее время, выраженное в 1/18.2 долях секунды

MOV EAX, [ES:046Ch]

MOV [Time], EAX

; Сохранение значений счетчика TSC каждые 1/18.2 сек

@@t0:CALL WaitTimerStateChange

; Выполнить команду RDTSC

DB 0Fh, 31h

; Сохранить значение в массиве

MOV [DI], EAX

; Переход к следующему элементу массива

ADD DI, 4

DEC BX

; Число замеров равно 33

JNZ @@t0

; Вычислить длительность каждого интервала в тактах

MOV BX, 32

MOV DI, OFFSET TimeCounter

MOV SI, OFFSET DeltaT

MOV EDX, 0

; Из значения счетчика в момент t+1 вычесть значение в момент t

@@t1:MOV EAX, [DI+4]

SUB EAX, [DI]

MOV [SI], EAX

; Накопление суммы значений

ADD EDX, EAX

; Индексирование массивов

ADD DI, 4

ADD SI, 4

DEC BX

JNZ @@t1

; Вычислить среднюю длительность интервала в тактах

SHR EDX, 5

MOV [AverageTime], EDX

; Умножить среднее значение на частоту генератора

MOV EAX, [AverageTime]

MOV EDX, 1193180

MUL EDX

; Разделить результат на делитель таймера (65536)

SHRD EAX, EDX, 16

; Вычислить частоту микропроцессора в МГц

XOR EDX, EDX

; Разделить результат на 106

MOV EBX, 1000000

DIV EBX

; Сохранить результат вычислений

MOV [FreqResult],EAX

; Выход в MS DOS

MOV AX, 4C00h

INT 21h

ENDP ProcFrequency

 

; Процедура ожидания очередного изменения значения таймера

PROC WaitTimerStateChange NEAR

MOV EAX, [Time]

; Цикл до тех пор, пока текущее значение времени

; не будет отличаться от ранее сохраненного значения

@@T: CMP EAX, [ES:046Ch]

JE @@T

; Сохранить новое значение времени

MOV EAX,[ES:046Ch]

MOV [Time], EAX

RET

ENDP WaitTimerStateChange

 

ENDS

 

END

 

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

 

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

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

Даже цикл на языке ассемблера может приводить к различным време­нам задержки. Поэтому разумно определять время программной задержки непосредственно по часам. Частота отсчета в 18.2 Гц, используемая в модификации счетчика времени суток, должна вполне удовлетворять большинство потребностей.

Чтобы обеспечить задержку заданной продолжительности, программа должна подсчитать требуемое число импульсов счетчика времени суток. Значение добавляется к считанному текущему значению счетчика. Затем программа постоянно считывает текущее значение счетчика и сравнивает его с запомненным значением. Когда достигается равенство, то считается, что требуемая задержка прошла. Значение счетчика времени суток хранится по адресу 0040:006Ch.

Более высокую дискретность отсчетов, требуемую по условиям задачи, можно достичь, воспользовавшись счетчиком тактовых импульсов TSC. Однако в этом случае требуется предварительная калибровка таймера. Первым шагом алгоритма будет вычисление среднего числа тактов за период системного таймера и расчет продолжительности одного такта (см. задачу 2).

Дело в том, что использование паспортных данных процессора приведет к неточности, т.к. всегда имеется некоторый технологический разброс значений параметра. Лучший выход в данной ситуации – определение значения экспериментальным путем. Далее применим адаптированный для счетчика TSC приведенный выше алгоритм. Описанные алгоритмы организации временных задержек реализуйте самостоятельно на языке ассемблера, используя TASM.

Контрольные вопросы

1. Приведите общую структуру таймера-счетчика и его назначение.

2. Перечислите режимы работы таймера-счетчика.

3. Опишите структуру регистров таймера-счетчика.




Поделиться с друзьями:


Дата добавления: 2014-11-16; Просмотров: 698; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.14 сек.