中央民族大学 03电子班 杨忠学
l 实验目的:进一步熟悉TPC_H实验系统是使用,学习运用地址译码技术和基本接口电路,掌握8253的基本工作原理和编程方法。
l 实验要求:
1. 在TPC_H实验系统环境下,设计实现对可编程定时/计时器8253的确定译码,即接到8253CS端的信号是唯一有效的,只能支持四个端口地址。
2. 通过相应的电路连接及初始化编程,验证8253的六种工作方式,观察其输出现象。(8253的地址线、数据线和控制线已与系统连接好,连接电路时,只需考虑CS、CLK、GATE、OUT信号的连接。)
l 实验内容:
1. 硬件电路方案
硬件电路说明:用定时/计时器1做分频器(工作方式2,3都可以)。对于方式1,4,其GATE信号是脉冲信号,其他方式的GATE信号是高电平,因此定时/计时器0,通过开关选择不同的GATE信号。OUT信号:用示波器观测方式2,3的输出波形,用查询方式查询其他方式的输出跳变。
1. 软件流程以及相关程序
在软件的设计过程中,考虑软件运行程序后,能自主选择当前工作的记时器,又能修改记时器的计数值和工作模式。
我设计了一种在文本模式下定时控制系统:通过控制上下方向键设置工作模式,按回车键确认;数字键0、1、2(其它数字键无效)设置当前的计时器;按ESC键可以退出程序;F1键查看程序的帮助文件,其他键开始设置频率,Enter键确认输入。该系统的默认定时器为T0,工作方式Mode=0,频率Frq=1000,T0的初值通过value=119800/Frq算得。
程序运行后的界面如下:
选择0,1,4,5工作方式,在计数值为0,输出发生跳变后,程序会给予相应的提示(或是重装计数初值(0,5)或是给予GATE触发信号(1,4))。
程序的流程:
1. Initial system;
2. Get 8253 IO port;
3. Print Menu;
4. Get key;
5. Switch(key) {
Case Esc: Exit system; break;
Case F1: Print help; break;
Case Enter: Start Timer; break;
Case UP/Down: modifier mode; break;
Case 0, 1, 2: Modifier current timer; break;
Default: modifier current frequency;}
6. Goto 3
l 实验结果:
程序经过多次修改调试之后,运行良好,实验现象比较明显。
其中,方式2和方式3最容易,只需要选择好工作方式,输出波形都很稳定。CLK时钟信号和输出的OUT信号正确显示。
方式0和方式1时,可以看到OUT输出的是一个稳定的方波,每一个上升沿说明计数器工作结束一次。方波的占空比很大,输入的计数值变高,占空比就降低,方式1时变化比较明显。方式0不需要触发信号,GATE输入信号可以暂停计数。而方式1必须由GATE输入信号触发才能开始计数,计数中有GATE输入信号则重新计数而不是暂停计数。
方式4和方式5时,得到的波形是连续的负脉冲。两种方式都是只计数一次就停,且计数过程重新给计数值不影响当前计数,计数时GATE上升沿到来则计数器重新装入计数值,重新计数。计数结束后,方式4要重新给计数值才能再次计数,而方式5只要GATE又给触发信号就能再次工作。
l 实验小结:
在电路的设计中,因为实验箱上提供的脉冲频率太高,不利于观察定时器的输出波形,因此选用8253的定时器1作为分频器,其输出作为脉冲时钟供定时器0选用。
这一次实验感觉比前两次要好做,首先是电路的连接比较简单,不像前两次那样要接好多的线。考虑到8253有3个计数器,当其中一个不能用时,可以用另一个代替,程序设计中允许选择计数器,所以在电路的连接上,可以用的两个计数器都连接好了。除了方式2和方式3外都用了查询方式。因此用上了74LS244。
计数器的6种工作方式验证都做完了,从中更深刻地认识8253定时计数器的结构和计数原理。对于这6种不同的工作方式,可以满足各种软件和硬件定时计数的要求。
附录:定时控制系统源代码:
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <bios.h>
#include <conio.h>
unsigned char curr_timer=0; /*Current working timer*/
unsigned int curr_frq=100;
unsigned int io_address=0x280;
#define CONTROLWD(i) (curr_timer<<6)|0x30|(i<<1) /*cal the control word*/
union{ unsigned int b;
unsigned char d[2];
}count;
void inittimer(int i){
outportb(io_address|0x03,CONTROLWD(i));
outportb(io_address|curr_timer,count.d[0]);
outportb(io_address|curr_timer,count.d[1]);
}
unsigned char selecmenu(void);
/*the function is the special working mode*/
void spec_mode(int i) {
unsigned char portst;
inittimer(i);
switch(i)
{ case 0: ;
case 1: portst=0x01;break;
case 4: ;
case 5: portst=0x00;break;
}
/* D0 is connect with out of timerX */
while(!kbhit()) {
while(inportb(io_address|curr_timer)&0x01!=portst) ;
gotoxy(1,15);
cprintf("Init timer or Give the Gate signal");
gotoxy(50,20);
return ;
}
}
void main(){
unsigned char mode;
clrscr();
printf("input IO ADDRESS\n");
scanf("%x%*c",io_address);
while(1) {
clrscr();
mode=selecmenu();
/*Exit the system*/
if(mode>=6){
clrscr();
printf("Press any key to continue ...");
getch();
exit(1);}
count.b=119318.0/curr_frq; /*cal the initvalue*/
switch(mode)
{case 0:spec_mode(0);break;
case 1:spec_mode(1);break;
case 2:inittimer(2);break;
case 3:inittimer(3);break;
case 4:spec_mode(4);break;
case 5:spec_mode(5);break;
} /*end switch*/
} /*if the expection is false,the quit the while*/
}
void getfrq() /*modifier frequency*/
{
char ch=0;
unsigned frq=0;
gotoxy(60,16);
cprintf(" Hz");
gotoxy(60,16);
while(ch!=13)
{
ch=getch();
if(ch-48>=0&&ch-48<=9)
{frq=10*frq+ch-48;
printf("%d",ch-48);
}
if(frq>6553)
break;
}
curr_frq=(frq>0)?frq%65536:curr_frq;
gotoxy(60,16);
cprintf("%uHz",curr_frq);
}
void help()
{
clrscr();
printf(" \n\nThank you for using TPH_100 timer control system\n");
printf(" Press Enter to start timerX with mode Y int fre Z\n");
printf(" Init timer is timer 0 and Mode is mode 0 and frq=100Hz\n\n");
printf(" OPERATOR AS:\n");
printf(" Press direct key to select the mode\n");
printf(" Press Digtal key 0,1,2 to set current timer\n");
printf(" Press ESC key to quit system\n");
printf(" Press any other key to input new frequency and press Enter to end\n");
printf(" Press F1 to get help\n");
printf("\n\nPress any key to continue.");
getch();
}
unsigned char selecmenu(){
int i;
int key;
static unsigned char index=0;
unsigned char curr_index; /*record curent index*/
unsigned int flag=1;
static char *menu[]={ "-----Timer system Version 1.0-----",
" 0---End AND Interrupt",
" 1---Progarmmed Pluse",
" 2---Frequency Function",
" 3---Wave Fuction",
" 4---Control with Software",
" 5---Control with Hardware",
" 6---Quit system"};
clrscr();
for(i=0;i<8;i++){
gotoxy(25,4+i);
cprintf("%s",menu[i]);}
gotoxy(1,21);
printf("Press F1 get help\n");
printf("Thank you for using Timer system\n");
printf("Programme desigend:Y.Z.X\n");
printf("2006.5\n");
gotoxy(24,14);
cprintf("The current timer is timer%d !",curr_timer); /*40*/
while(flag){
curr_index=index;
gotoxy(20,5+curr_index);
cprintf("---->");
gotoxy(20,16);
cprintf("Input the Initial Fre (DEC) like 0234 : %u Hz ",curr_frq);
gotoxy(60,16);
key=bioskey(0);
key=key&0xff?key&0xff:key>>8;
switch(key) {
case 72: index=(curr_index==0?index=6:curr_index-1);break;
case 80: index=(curr_index==6?index=0:curr_index+1);break;
case 13: flag=0; break;
case 48: ;
case 49: ;
case 50: {gotoxy(50,14);
curr_timer=key-48;
printf("%d",curr_timer);
gotoxy(50,20); break; }
case 27: exit(1);
case 59: help();flag=0;break;
default: getfrq();break;
}
gotoxy(20,5+curr_index);
cprintf(" ");
gotoxy(20,5+index);
cprintf("---->");
gotoxy(60,16);
}
return index;
}