Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные работы СПО-new.docx
Скачиваний:
7
Добавлен:
14.11.2019
Размер:
239.58 Кб
Скачать

Методические указания к выполнению работы

К п. 1. См методические указания к п.1 лабораторной работы №1.

К п.2. Работой клавиатуры в IBM PC управляет специализированный микропроцессор - контроллер клавиатуры, который воспринимает каждое нажатие и отжатие клавиш и выдает скан-код клавиши в порт контроллера клавиатуры с адресом 60Н.

рисунок

Скан-код клавиши это однобайтное число, младшие 7 бит которого являются идентификационным номером, присвоенным каждой клавише (табл. 9). Старший бит (бит 7) является признаком нажатия (бит равен 0) или освобождения (бит равен 1) клавиши. Таким образом, каждая клавиша генерирует два типа скан-кодов: “код нажатия” и “код освобождения”, когда клавиша отпускается. Код освобождения на 128 больше кода нажатия клавиши.

После поступления скан-кода в порт 60Н формируется сигнал запроса прерывания процессору для обработки нажатия клавиши. Процессор прерывает на время свою работу и переходит на п/пр обслуживания прерывания от клавиатуры (09Н), которая выполняет следующие функции:

  • считывает скан-код клавиши из порта 60Н;

  • анализирует состояние слова статуса клавиатуры (при нажатии клавиш статуса изменяет это слово) и осуществляет трансляцию скан-кода нажатой клавиши в коды ASCII, формируя 2-х байтовый код;

  • записывает полученный 2-х байтовый код в буфер клавиатуры.

табл. 9

Скан-код

Клавиша

Скан-код

Клавиша

Скан-код

Клавиша

Скан-код

Клавиша

1

Esc

28

Enter

54

RightShift

70

ScrollLock

2-11

1’‘9’,’0

29

Ctrl

55

PrtScr

7173

7’’9’

12

‘–‘

3040

A’’’’

56

Alt

74

‘–‘

13

=

41

`’

57

‘ ‘

7577

4’’6’

14

Backspace

42

LeftShift

58

CapsLock

78

+’

15

Tab

43

\’

5968

F1F10

7982

1’’3’,’0’

1627

‘Q’‘]’

4453

Z’’/’

69

NumLock

83

.’

Поскольку скан-коды клавиш считываются из порта 60Н п/пр обслуживания прерываний от клавиатуры, то для выполнения задания к лабораторной работе можно рекомендовать следующую последовательность действий:

  • запретить прерывания от клавиатуры;

  • считать содержимое порта 60H после нажатия клавиши;

  • считать содержимое порта 60H после отпускания клавиши;

  • разрешить прерывания от клавиатуры;

  • вывести полученные скан-коды на экран.

В языке Pascal для прямого обращения к содержимому портов ввода/вывода предварительно объявлены массивы Port и PortW. Элементами массива Port являются значения типа Byte, а массива PotrW – типа Word. Индексами этих массивов должны быть выражения типа Byte, которые указывают абсолютный адрес порта, например:

State := Port [$80]; { считать из порта 80Н в переменную State}

Port [$90] := State+1; { записать в порт 90Н новое значение }

Фрагмент программы чтения скан-кодов клавиш:

Uses crt, dos;

Var ScanCodeDown, ScanCodeUp,Scan :byte;

Begin

……..

Delay(1000); { задержка времени для отработки отжатия клавиши }

{ при выборе пункта меню }

Port [$21]:=2; { запретить ПКП прерывания от клавиатуры }

Scan:=Port [$60]; { считать текущее содержимого порта клавиатуры }

Writeln(‘Нажмите заданную клавишу’);

Repeat

ScanCodeDown:=Port [$60]; { считать содержимое клавиатуры }

Until ScanCodeDown <> Scan; { ждать нажатия клавиши }

Scan:=ScanCodeDown; { сохранить скан-код нажатия }

Repeat

ScanCodeUp:=Port [$60]; { считать содержимое клавиатуры }

Until ScanCodeUp <> Scan; { ждать отжатия клавиши }

Port [$21]:=0; { разрешить ПКП прерывания от клавиатуры }

Writeln (‘Скан-код нажатия клавиши’, ScanCodeDown);

Writeln (‘Скан-код отжатия клавиши’, ScanCodeUp);

Writeln (‘Нажмите любую клавишу’);

Readkey;

………

End.

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

Сам буфер занимает 32 байта с адреса 0040Н:001EH по 0040Н:003СН. Указатели на начало и конец буфера расположены по адресам 0040Н:001AH и 0040Н:001CH соответственно. Значения указателей меняются от 1EH до 3CH, что соответствует области данных BIOS.

Новое нажатие на клавишу сохраняется в позициях следующих за хвостом буфера, т.е. в более старших адресах памяти и поэтому при вводе данных используются значения только хвоста очереди. Буфер может накапливать до 15 нажатий на клавишу. Для разрешения ввода 15 символов требуется 16 позиция, которая располагается перед головой буфера, и в этой позиции записывается значение кода возврата каретки (ASCII13) и скан-код клавиши ‘Enter’. Когда буфер заполнен, новые вводимые символы игнорируются, и выдается сигнал на динамик.

Рисунок

Как отмечалось выше, после трансляции скан-кодов клавиш в коды ASCII в буфере отводится по два байта для каждого нажатия на клавишу. Для трансляции скан-кодов в коды ASCII используются 3 таблицы:

  • скан-кодов клавиш (табл. 9);

  • кодов символов ASCII (табл. 11);

  • расширенных кодов ASCII (табл. 12).

Символам ASCII соответствуют клавиши, которые отображаются на экране – символы алфавита, цифры и т.д. Скан-код таких клавиш преобразуется в 2-х байтовый код, младший байт которого содержит код ASCII, а старший – скан-код клавиши.

Расширенные коды присвоены клавишам или комбинациям клавиш, которые не отображаются на экране – функциональные клавиши F1-F10, Home, PageUp и т.д, комбинации ‘Alt-A’, ‘Ctrl-B’ и т.д. Скан-код таких клавиш преобразуется в 2-х байтовый код, младший байт которого равен 0, а старший содержит номер расширенного кода, который обычно совпадает со скан-кодом клавиши, но не всегда, поскольку некоторые клавиши можно комбинировать с клавишами сдвига для генерации различных кодов.

В прикладных программах ввод данных осуществляется из буфера клавиатуры. При этом прикладная программа должна решить две задачи:

  • определить наличие символа в буфере клавиатуры;

  • выполнить ввод символа и очистить позицию буфера , соответствующую введенному символу.

Для решения первой задачи достаточно проверить значения указателей головы и хвоста буфера клавиатуры: если они равны - буфер пуст; в противном случае – в буфере находится новый символ. В Turbo Pascal наличие символа в буфере проверяется с помощью функции Keypressed.

При вводе данных в прикладную программу код символа читается из буфера клавиатуры, после чего значения указателя головы буфера увеличивается на единицу или приравнивается значению хвоста (буфер пуст). В Turbo Pascal ввод символа из буфера выполняется с помощью функции Readkey, которая вместе с тем ожидает и ввод символа, т.е. определяет наличие символа в буфере.

Фрагмент программы ввода данных в прикладных программах:

Begin

………

{ вывод содержимого указателей на экран}

writeln(‘Начало буфера до нажатия: ’,MemW[$0040:$001A);

writeln(‘Конец буфера до нажатия: ’,MemW[$0040:$001C);

repeat until keypressed; { ждать нажатия клавиши }

{ вывод содержимого указателей на экран}

writeln(‘Начало буфера после нажатия: ’,MemW[$0040:$001A);

writeln(‘Конец буфера после нажатия: ’,MemW[$0040:$001C);

ch:=readkey; { считать символ из буфера клавиатуры }

writeln('Символ: ',ch);

writeln (‘ASCII код символа: ’,ord(ch));

{ вывод содержимого указателей на экран}

writeln(‘Начало буфера после чтения из буфера: ’,MemW[$0040:$001A);

writeln(‘Конец буфера после чтения из буфера: ’,MemW[$0040:$001C);

Writeln (‘Нажмите любую клавишу’);

Readkey;

………

End.

К п. 4. Хотя скан-код и указывает однозначно на нажатую клавишу, по нему нельзя судить, включен ли на клавиатуре верхний или нижний регистр или пользователь вводит латинские или русские буквы. Кроме того, на клавиатуре компьютера клавиши статуса ‘Alt’, ‘Ctrl’, ‘Shift’,’CapsLock’ и др. Таким образом, прерывание от клавиатуры должно анализировать не только скан-коды, но и факты нажатия перечисленных клавиш. Информация о текущем состоянии клавиш статуса клавиатуры хранится в двух ячейках памяти с адресами 0040Н:0017Н и 0040Н:0018Н и называется словом состояния клавиатуры (табл. 10).

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

табл. 10

Адрес ячейки

Номер бита

Клавиша

Значение, когда бит установлен

0040Н:0017Н

7

6

5

4

3

2

1

0

Insert

Caps Lock

Num Lock

Scroll Lock

Alt

Ctrl

Левый Shift

Правый Shift

режим вставки включен

режим Caps Lock включен

режим Num Lock включен

режим Scroll Lock включен

клавиша нажата

клавиша нажата

клавиша нажата

клавиша нажата

0040Н:0018Н

7

6

5

4

3

2 - 0

Insert

Caps Lock

Num Lock

Scroll Lock

Ctrl – Num Lock

не используются

клавиша нажата

клавиша нажата

клавиша нажата

клавиша нажата

режим Ctrl – Num Lock включен

Для проверки состояния битов статуса клавиш необходимо обратиться к соответствующему элементу массива Mem, а затем сравнить его содержимое с словом-маской соответствующего бита. Например:

Status17:= Mem [$0040:$0017]; { считываем слово статуса }

If Status17 and 4 <> 0 { 4H = 00000100B }

then ….... { клавиша Ctrl нажата }

else …… { клавиша Ctrl отжата }

  • К п.5. Для модификации существующего прерывания BIOS 09Н необходимо выполнить следующую последовательность действий:

  • создать новую процедуру, вызывающую какое-либо неиспользуемое прерывание (табл. 3).

  • перенести вектор прерывания для 09Н в С8Н.

  • изменить вектор 09Н, чтобы он указывал на новую процедуру;

  • при завершении программы восстановить исходные значения векторов.

Модуль KeyBoard предоставляет возможность наглядного отображения на экране текущего значения слова состояния и буфера клавиатуры при нажатии на клавиши. Для пользователя доступны следующие переменные и процедуры модуля:

  • процедура ClearBuf – заполняет содержимое буфера нулями;

  • переменная count_press – подсчитывает количество нажатий на клавиши клавиатуры в текущем сеансе работы. Вы можете использовать значение этой переменной в основной программе для ограничения числа нажатий на клавиши, например:

…………..

ClearBuf; { заполнить буфер нулями }

Count_press := 0; { очистить счетчик нажатий клавиш }

repeat

until count_press = 7; { ждать пока будут нажаты 7 клавиш }

…….

  • процедура Status_Print – выводит на экран в наглядной форме значение слова состояния клавиатуры (только ячейки 0417Н);

  • процедура Status_Print – выводит на экран в наглядной форме значение слова состояния клавиатуры (только ячейки 0417Н);

  • процедура Buffer_Print – выводит на экран в наглядной форме значения указателей буфера клавиатуры (ячейки 041АН-041DН и содержимое самого буфера (ячейки 041ЕН-043СН).

К п.6. При анализе содержимого буфера вы можете воспользоваться следующими таблицами: скан-кодов клавиш (табл. 9), ASCII кодов символов (табл. 11.), или расширенных кодов (табл. 12.).

табл. 11

Код

Символ

Код

Символ

Код

Символ

Код

Символ

Код

Символ

Код

Символ

Код

Символ

Код

Символ

1

33

!

65

97

a

128

А

160

а

192

224

р

2

34

66

B

98

b

129

Б

161

б

193

225

с

3

35

#

67

C

99

c

130

В

162

в

194

226

т

4

36

$

68

D

100

d

131

Г

163

г

195

227

у

5

37

%

69

E

101

e

132

Д

164

д

196

228

ф

6

38

&

70

F

102

f

133

Е

165

е

197

229

х

7

BEL

39

71

G

103

g

134

Ж

166

ж

198

230

ц

8

BK

40

(

72

H

104

h

135

З

167

з

199

231

ч

9

Tab

41

)

73

I

105

i

136

И

168

и

200

232

ш

10

LF

42

*

74

J

106

j

137

Й

169

й

201

233

щ

11

43

+

75

K

107

k

138

К

170

к

202

234

ъ

12

44

76

L

108

i

139

Л

171

л

203

235

ы

13

CR

45

-

77

M

109

m

140

М

172

м

204

236

ь

14

46

.

78

N

110

n

141

Н

173

н

205

237

э

15

47

/

79

O

111

o

142

О

174

о

206

238

ю

16

48

0

80

P

112

p

143

П

175

п

207

239

я

17

49

1

81

Q

113

q

144

Р

176

208

240

Е

18

50

2

82

R

114

r

145

С

177

209

241

е

19

51

3

83

S

115

s

146

Т

178

210

242

20

52

4

84

T

116

t

147

У

179

211

243

21

53

5

85

U

117

u

148

Ф

180

212

244

22

54

6

86

V

118

v

149

Х

181

213

245

23

55

7

87

W

119

w

150

Ц

182

214

246

÷

24

56

8

88

X

120

x

151

Ч

183

215

247

25

57

9

89

Y

121

y

152

Ш

184

216

248

26

58

:

90

Z

122

z

153

Щ

185

217

249

.

27

59

;

91

123

{

154

Ъ

186

218

250

.

28

60

<

92

\

124

|

155

Ы

187

219

251

29

61

=

93

125

}

156

Ь

188

220

252

30

62

>

94

^

126

~

157

Э

189

221

253

z

31

63

95

_

127

Del

158

Ю

190

222

254

32

64

@

96

159

Я

191

223

255

табл. 12

Значение 2-го байта

Соответствующие клавиши

15

16-25

30-38

44-50

59-68

71

72

73

75

77

79

80

81

82

83

84-93

94-103

104-113

114

115

116

117

118

119

120-131

132

Shift + Tab (‘back-tab”)

Alt+Q –Alt+P (верхний ряд букв)

Alt+A – Alt+L (средний ряд букв)

Alt+Z – Alt+M (нижний ряд букв)

Функциональные клавиши F1-F10

Home

Cursor-up (стрелка вверх)

PgUp

Cursor-left (стрелка влево)

Cursor-right (стрелка вправо)

End

Cursor-down (стрелка вниз)

PgDn

Ins

Del

F1-F10 +Shift

F1-F10 +Ctrl

F1-F10 +Alt

Ctrl + PrtSc

Ctrl + Cursor-left

Ctrl + Cursor- right

Ctrl + End

Ctrl + PgDn

Ctrl + Home

Alt+l – Alt+= (верхний ряд)

Ctrl + PgUp