接口机编程
‘壹’ 求教一道微机原理的接口编程题!!谢谢!!
(方波半上周期计数溢出,OUT0电平置反,进入下半周期)
4Hz的方波的半周期=(1/4Hz)/2 =0.125s =125ms
10KHz脉冲周期=(1/10kHz) =0.1ms
计数初装值 =125ms/0.1ms =1250
控制字 =00110110b,通道0,方式3,二进制初值先低字节后高字节装入
.
初始化程序如下:
MOV AL,00110110b ;控制字送入AL
OUT 283h, AL ;控制字送8253控制口
MOV AX, 1250 ;计数初装值
OUT 280h, AL ;装入计数初值低字节
MOV AL, AH
OUT 280h, AL ;装入计数初值高字节
‘贰’ 急求关于C# 的USB接口编程
C#操作USB口需要看是什么硬件。
一些硬件虽然使用USB接口和PC通讯,但是它的驱动程序将它模拟成一个COM口、网口或者大容量存储设备。
那么C#完全可以按照COM通讯、网络通讯和文件读写的方法操作这些设备。
关键看你的USB设备的驱动程序。
‘叁’ 微机接口编程采用的是什么语言
c语言。汇编语言移植性差。
‘肆’ 什么叫作编程接口
简单的说,编程就是为了借助于计算机来达到某一目的或解决某个问题,而使用某种程序设计语言编写程序代码,并最终得到结果的过程。
计算机虽然功能十分强大。可以供你上网、打游戏、管理公司人事关系等等,但是没有程序,它就等于是一堆废铁,不会理会我们对它下达的“命令”。于是,我们要驯服它,只有通过一种方式——程序,这也是我们和计算机沟通的唯一方式。
程序也就是指令的集合,它告诉计算机如何执行特殊的任务。
写出程序后,再由特殊的软件将你的程序解释或翻译成计算机能够识别的“计算机语言”,然后计算机就可以“听得懂”你的话了,并会按照你的吩咐去做事了。因此,编程实际上也就是“人给计算机出规则”这么一个过程。
随计算机语言的种类非常的多,总的来说可以分成机器语言,汇编语言,高级语言三大类。
电脑每做的一次动作,一个步骤,都是按照已经用计算机语言编好的程序来执行,程序是计算机要执行的指令的集合,而程序全部都是用我们所掌握的语言来编写的。所以人们要控制计算机一定要通过计算机语言向计算机发出命令。
计算机所能识别的语言只有机器语言,即由构成的代码。但通常人们编程时,不采用机器语言,因为它非常难于记忆和识别。
汇编语言的实质和机器语言是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,更容易识别和记忆。它同样需要编程者将每一步具体的操作用命令的形式写出来。
汇编程序的每一句指令只能对应实际操作过程中的一个很细微的动作,例如移动、自增,因此汇编源程序一般比较冗长、复杂、容易出错,而且使用汇编语言编程需要有更多的计算机专业知识,但汇编语言的优点也是显而易见的,用汇编语言所能完成的操作不是一般高级语言所能实现的,而且源程序经汇编生成的可执行文件不仅比较小,而且执行速度很快。
高级语言是目前绝大多数编程者的选择。和汇编语言相比,它不但将许多相关的机器指令合成为单条指令并且去掉了与具体操作有关但与完成工作无关的细节,例如使用堆栈、寄存器等,这样就大大简化了程序中的指令。由于省略了很多细节,所以编程者也不需要具备太多的专业知识。
高级语言主要是相对于汇编语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,如目前流行的VB、VC、FoxPro、Delphi等,这些语言的语法、命令格式都各不相同。
从二十世纪60年代以后,计算机得到了突飞猛进的发展。似乎历史上没有任何一门科学的发展速度超过了计算机的发展,无论硬件、软件、还是网络都以惊人的速度向前发展。软件的发展速度和硬件一样,二十世纪九十年代中国的软件业还不是很成熟,而现在大大小小 的软件企业四处耸立,共享软件网上随处可见。不断发展的技术需要不断变化的程序员,例如,如今Visual Basic可以快速构建Windows下的应用程序,程序设计方面的技术不断发展着,不断引进新的概念、新的方法,如从结构化的C开始,当面向对象的思想被提出后,出现了C++,微软在C++的基础上为使用户构建win32应用程序更加方便,推出了Visual C++。这也就需要程序员也要不断的更新自己的技术。
目前常用的基本程序语言的种类比较繁多,比较简单的有:Pascal、c语言、qBasic、 Fortran、Visual Basic等等。但前几种都是在DOS下进行编程的工具,Visual Basic是在 Windows下进行应用程序设计的编程工具,现在一般的计算机用户几乎都不再使用DOS了,因此我们通常会选择Visual Basic作为初学者的编程工具。Visual Basic是Windows应用程序设计中最容易上手的编程工具,学习步骤也比较容易被初学者接受。对于刚开始学习编程的初学者来说,还是选择Visual Basic,学习编程语言不能想象着一步登天,一步一个脚印的学习才是最佳方法。
‘伍’ 【高分】微机接口编程,两个cup通过8251A向对方发送100个字符
(1)收发联络信号DTR、DSR、RTS、CTS
注意,RS-232-C标准的对应信号是:DTR、DSR、RTS、CTS。
(1)/DTR——数据终端准备好信号/DTR是由8251A送往外设的,CPU通过命令可以使/DTR变为低电平即有效低电平,从而通知外部设备,CPU当前已经准备就绪。
(2)/DSR——数据设备准备好信号/DSR是由外设送往8251A的,低电平时有效,它用来表示当前外设已经准备好。当/DSR端出现低电平时,会在8251A的状态寄存器第7位上反映出来,所以,CPU通过对状态寄存器的读取操作,便可以实现对/DSR信号的检测。例如,数据通信设备(Modem)准备好,该信号是外部设备(数据通信设备Modem)送给8251的。8251收到该信号后,使状态寄存器的DSR位置1。CPU可以查询状态寄存器的DSR位,以了解外部设备的状态。
(3)/RTS——请求发送信号/RTS是8251A送往外设,低电平时有效,CPU可以通过编程命令使/RTS变为有效电平,以表示CPU已经准备好发送。
(4)/CTS——清除请求发送信号/CTS是对/RTS的响应信号,它是由外设送往8251A的,当/CTS为低电平时,8251A才能执行发送操作。
‘陆’ java编写一个有关接口的程序
给你的也不是什么系统之类的.
也就是一个思想而已,想了一下用<设计模式之Factory>来回答你的问题.
///////////////////////////////////////////////////////////////
工厂模式定义:提供创建对象的接口.
为何使用?
工厂模式是我们最常用的模式了,着名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。
为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
我们以类Sample为例, 如果我们要创建Sample的实例对象:
Sample sample=new Sample();
可是,实际情况是,通常我们都要在创建sample实例时做点初始化的工作,比如赋值 查询数据库等。
首先,我们想到的是,可以使用Sample的构造函数,这样生成实例就写成:
Sample sample=new Sample(参数);
但是,如果创建sample实例时所做的初始化工作不是象赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,那你的代码很难看了(就需要Refactor重整)。
为什么说代码很难看,初学者可能没有这种感觉,我们分析如下,初始化工作如果是很长一段代码,说明要做的工作很多,将很多工作装入一个方法中,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有背于Java面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间偶合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。
在本例中,首先,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。
这时我们就需要Factory工厂模式来生成对象了,不能再用上面简单new Sample(参数)。还有,如果Sample有个继承如MySample, 按照面向接口编程,我们需要将Sample抽象成一个接口.现在Sample是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:
Sample mysample=new MySample();
Sample hissample=new HisSample();
随着项目的深入,Sample可能还会\"生出很多儿子出来\", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的.
但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了.
工厂方法
你会建立一个专门生产Sample实例的工厂:
public class Factory{
public static Sample creator(int which){
//getClass 产生Sample 一般可使用动态类装载装入类。
if (which==1)
return new SampleA();
else if (which==2)
return new SampleB();
}
}
那么在你的程序中,如果要实例化Sample时.就使用
Sample sampleA=Factory.creator(1);
这样,在整个就不涉及到Sample的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻:就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,范错误可能性就越少.好象我们从编程序中也能悟出人生道理?呵呵.
使用工厂方法 要注意几个角色,首先你要定义产品接口,如上面的Sample,产品接口下有Sample接口的实现类,如SampleA,其次要有一个factory类,用来生成产品Sample,如下图,最右边是生产的对象Sample:
进一步稍微复杂一点,就是在工厂类上进行拓展,工厂类也有继承它的实现类concreteFactory了。
抽象工厂
工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory).
这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法中是创建一个对象Sample,如果我们还有新的产品接口Sample2.
这里假设:Sample有两个concrete类SampleA和SamleB,而Sample2也有两个concrete类Sample2A和SampleB2
那么,我们就将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现,下面就是将上例中的Factory拓展成抽象工厂:
public abstract class Factory{
public abstract Sample creator();
public abstract Sample2 creator(String name);
}
public class SimpleFactory extends Factory{
public Sample creator(){
.........
return new SampleA
}
public Sample2 creator(String name){
.........
return new Sample2A
}
}
public class BombFactory extends Factory{
public Sample creator(){
......
return new SampleB
}
public Sample2 creator(String name){
......
return new Sample2B
}
}
从上面看到两个工厂各自生产出一套Sample和Sample2,也许你会疑问,为什么我不可以使用两个工厂方法来分别生产Sample和Sample2?
抽象工厂还有另外一个关键要点,是因为 SimpleFactory内,生产Sample和生产Sample2的方法之间有一定联系,所以才要将这两个方法捆绑在一个类中,这个工厂类有其本身特征,也许制造过程是统一的,比如:制造工艺比较简单,所以名称叫SimpleFactory。
在实际应用中,工厂方法用得比较多一些,而且是和动态类装入器组合在一起应用.
....后面还有一些,但是我想这些应该可以解决你想知道的了.
‘柒’ 禹鼎遥控器和接收机编程接口怎么定义的
禹鼎行车遥控器配对需要完成两个步骤:
第一需要将内部的晶振换成成对的 比如接收机装R068发射器上装T068
第二步将识别码(SN号)弄成相同的 这个有两个方法弄都能完成
1.用拷贝机直接拷贝 2.你用电脑软件用数据编程线连接发射器或者接收机直接修改或者复制这个识别码输入进去就可以 完成上面步骤就可以了 。
‘捌’ 在VC++如何对微机的接口进行编程
对于串口的使用,可以使用winapi,这里使用串口就像文件的读写,在开始打开串口,然后读写数据,结束后关闭串口.
在VC++中,串口和磁盘文件可以统一的方式来简单读写。这两者几乎没有什么不同,只是在WINDOWS 9X下磁盘文件只能做同步访问,而串口只能做异步访问。
CreateFile:用指定的方式打开指定的串口。通常的方式为
m_hCom = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
m_hCom为文件句柄。GENERIC_READ | GENERIC_WRITE指定可以对串口进行读写操作。第三个参数0表示串口为独占打开。OPEN_EXISTING表示当指定串口不存在时,程序将返回失败。 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED则表示文件属性。当打开串口时,必须指定 FILE_FLAG_OVERLAPPED,它表示文件或设备不会维护访问指针,则在读写时,必须使用OVERLAPPED 结构指定访问的文件偏移量。
ReadFile:读取串口数据。
WriteFile:向串口写数据。
CloseHandle:关闭串口。
COMMTIMEOUTS:COMMTIMEOUTS主要用于串口超时参数设置。COMMTIMEOUTS结构如下:
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
ReadIntervalTimeout:两字符之间最大的延时,当读取串口数据时,一旦两个字符传输的时间差超过该时间,读取函数将返回现有的数据。设置为0表示该参数不起作用。
ReadTotalTimeoutMultiplier:读取每字符间的超时。
ReadTotalTimeoutConstant:一次读取串口数据的固定超时。所以在一次读取串口的操作中,其超时为ReadTotalTimeoutMultiplier乘以读取的字节数再加上 ReadTotalTimeoutConstant。将ReadIntervalTimeout设置为MAXDWORD,并将ReadTotalTimeoutMultiplier 和ReadTotalTimeoutConstant设置为0,表示读取操作将立即返回存放在输入缓冲区的字符。
WriteTotalTimeoutMultiplier:写入每字符间的超时。
WriteTotalTimeoutConstant:一次写入串口数据的固定超时。所以在一次写入串口的操作中,其超时为WriteTotalTimeoutMultiplier乘以写入的字节数再加上 WriteTotalTimeoutConstant。
SetCommTimeouts函数可以设置某设备句柄的超时参数,要得到某设备句柄的超时参数可以用GetCommTimeouts函数。
DCB:DCB结构主要用于串口参数设置。该结构太庞大,这里就不一一讲述了,有兴趣者可查看MSDN关于DCB的描述。其中下面两个是比较重要的属性。
BaudRate:串口的通讯速度。一般设置为9600。
ByteSize:字节位数。一般设置为8。
DCB结构可以用SetCommState函数来设置,并可以用GetCommState来得到现有串口的属性。
SetupComm:设置串口输入、输出缓冲区。
OVERLAPPED:保存串口异步通讯的信息。具体结构如下:
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED;
Internal,InternalHigh是保留给系统使用的,用户不需要设置。
Offset,OffsetHigh是读写串口的偏移量,一般设置OffsetHigh为NULL,可以支持2GB数据。
hEvent读写事件,因为串口是异步通讯,操作可能被其他进程堵塞,程序可以通过检查该时间来得知是否读写完毕。事件将在读写完成后,自动设置为有效。
通过以上这些函数和结构,我们就可以通过串口进行通讯了,现在我们具体看下面的实例:
BOOL CSerial::Open( int nPort, int nBaud )
{
if( m_bOpened ) return( TRUE );
char szPort[15];
DCB dcb;
wsprintf( szPort, "COM%d", nPort );
m_hComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hComDev == NULL ) return( FALSE );
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hComDev, &CommTimeOuts );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = 8;
if( !SetCommState( m_hComDev, &dcb ) ||
!SetupComm( m_hComDev, 10000, 10000 ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL ){
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hComDev );
return FALSE;
}
m_bOpened = TRUE;
return m_bOpened;
}
int CSerial::InBufferCount( void )
{
if( !m_bOpened || m_hComDev == NULL ) return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
return (int)ComStat.cbInQue;
}
DWORD CSerial::ReadData( void *buffer, DWORD dwBytesRead)
{
if( !m_bOpened || m_hComDev == NULL ) return 0;
BOOL bReadStatus;
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return 0;
dwBytesRead = min(dwBytesRead,(DWORD) ComStat.cbInQue);
bReadStatus = ReadFile( m_hComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return dwBytesRead;
}
return 0;
}
return dwBytesRead;
}
DWORD CSerial::SendData( const char *buffer, DWORD dwBytesWritten)
{
if( !m_bOpened || m_hComDev == NULL ) return( 0 );
BOOL bWriteStat;
bWriteStat = WriteFile( m_hComDev, buffer, dwBytesWritten, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat){
if ( GetLastError() == ERROR_IO_PENDING ) {
WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 );
return dwBytesWritten;
}
return 0;
}
return dwBytesWritten;
}
‘玖’ 1.编程接口是什么我应该如何理解
“接口”是个抽象的概念!
编程接口,就是所谓的API(Application Programming Interface),是软件系统不同组成部分衔接的约定。
在软件里面,接口开放给程序员,让他们可以通过简单的接口来调用已有程序所具有的功能,而无需关心这个程序的细节。通过接口把多个程序组合到一起,就成了一个“系统”了。
举个例子,就好比说你看电视,遥控器就是电视机的接口,你通过控制遥控器从而打开电视(调用了电视机的打开功能),而无需关心电视机到底是怎么工作的。
再举个例子,水龙头就是自来水公司的接口,你打开水龙头(调用了水公司的服务),但是你无需关心这水来自哪家水厂。
‘拾’ 微型计算机原理与接口技术的编程题都有哪些
一、8253
.MODEL TINY
PCIBAR3 EQU 1CH ;8位I/O空间基地址(它就是实验仪的基地址,也为DMA & 32 BIT RAM板卡上的8237提供基地址)
Vendor_ID EQU 10EBH ;厂商ID号
Device_ID EQU 8376 ;设备ID号
.STACK 100
.DATA
COM_ADDR DW 00B3H
T0_ADDR DW 00B0H
T1_ADDR DW 00B1H
IO_Bit8_BaseAddress DW
msg0 DB 'BIOS不支持访问PCI
msg1 DB '找不到Star PCI9052板卡
msg2 DB '读8位I/O空间基地址时出错
.CODE
START: MOV AX,@DATA
MOV DS,AX
NOP
CALL InitPCI
CALL ModifyAddress ;根据PCI提供的基地址,将偏移地址转化为实地址
mov dx,COM_ADD
mov al,35h;?
out dx,al ;计数器T0设置在模式2状态,BCD码计数
mov dx,T0_ADDR
mov al,00h
out dx,al
mov al,10h
out dx,al ;CLK0/1000
mov dx,COM_ADDR
mov al,77h
out dx,al ;计数器T1为模式3状态,输出方波,BCD码计数
mov dx,T1_ADDR
mov al,00h
out dx,al
mov al,10h
out dx,al ;CLK1/1000
START1: CALL IfExit ;OUT1输出频率为1S的方波
JZ START1
JMP Exit
IfExit PROC NEAR
PUSH AX
PUSH DX
MOV AH,06H
MOV DL,0FFH
INT 21H
POP DX
POP AX
RET
IfExit ENDP
InitPCI PROC NEAR
MOV AH,00H
MOV AL,03H
INT 10H ;清屏
MOV AH,0B1H
MOV AL,01H
INT 1AH
CMP AH,0
JZ InitPCI2
LEA DX,msg0
InitPCI1: MOV AH,09H
INT 21H
JMP Exit
InitPCI2: MOV AH,0B1H
MOV AL,02H
MOV CX,Device_ID
MOV DX,Vendor_ID
MOV SI,0
INT 1AH
JNC InitPCI3 ;是否存在Star PCI9052板卡
LEA DX,msg1
JMP InitPCI1
InitPCI3: MOV DI,PCIBAR3
MOV AH,0B1H
MOV AL,09H
INT 1AH ;读取该卡PCI9052基地址
JNC InitPCI4
LEA DX,msg2
JMP InitPCI1
InitPCI4: AND CX,0FFFCH
MOV IO_Bit8_BaseAddress,CX
RET
InitPCI ENDP
ModifyAddress PROC NEAR
ADD COM_ADDR,CX
ADD T0_ADDR,CX
ADD T1_ADDR,CX
RET
ModifyAddress ENDP
Exit: MOV AH,4CH
INT 21H
END START
二、8259
.MODEL TINY
PCIBAR1 EQU 14H ;PCI9052 I/O基地址(用于访问局部配置寄存器)
PCIBAR3 EQU 1CH ;8位I/O空间基地址(它就是实验仪的基地址,也为DMA & 32 BIT RAM板卡上的8237提供基地址)
PCIIPR EQU 3CH ;IRQ号
INTCSR EQU 4CH ;PCI9052 INTCSR地址
mask_int_9052 EQU 24H
Vendor_ID EQU 10EBH ;厂商ID号
Device_ID EQU 8376 ;设备ID号
.STACK 100
.DATA
IO8259_0 DW 00F0H
IO8259_1 DW 00F1H
RD_IO8259 DW 0000H
IO_Bit8_BaseAddress DW ?
PCI_IO_BaseAddress0 DW ?
PCI_IRQ_NUMBER DB ?
INT_MASK DB ?
INT_Vector DB ?
INT_CS DW ? ;保护原中断入口地址
INT_IP DW ?
msg0 DB 'BIOS不支持访问PCI
msg1 DB '找不到Star PCI9052板卡
msg2 DB '读PCI9052 I/O基地址时出错$'
msg3 DB '读8位I/O空间基地址时出错$'
msg4 DB '读IRQ号出错$'
msg5 DB '8259中断 00H 次$'
BUFFER DB
Counter DB ?
ReDisplayFlag DB 0
.CODE
START: MOV AX,@DATA
MOV DS,AX
MOV ES,AX
NOP
CALL InitPCI
CALL ModifyAddress ;根据PCI提供的基地址,将偏移地址转化为实地址
CALL ModifyVector ;修改中断向量、允许中断
MOV AH,00H
MOV AL,03H
INT 10H ;清屏
MOV AH,09H
LEA DX,msg5
INT 21H
CALL Init8259
MOV Counter,0 ;中断次数
MOV ReDisplayFlag,1 ;需要显示
STI ;开中断
START1: CALL IfExit
CMP ReDisplayFlag,0
JZ START1
CALL LedDisplay
MOV ReDisplayFlag,0
JMP START1
Init8259 PROC NEAR
MOV DX,IO8259_0
mov al,13H
out dx,al
MOV DX,IO8259_1
mov al,08H
out dx,al
MOV AL,09H
OUT DX,AL
mov al,0feH ;屏蔽寄存器
OUT DX,AL
RET
Init8259 ENDP
ToChar PROC NEAR ;转化为可显示的16进制数
ADD AL,'0'
CMP AL,'9'
JBE ToChar1
ADD AL,07H
ToChar1: RET
ToChar ENDP
LedDisplay PROC NEAR
MOV AL,Counter
MOV AH,AL
AND AL,0FH
CALL ToChar
MOV Buffer + 1,AL
AND AH,0F0H
ROR AH,4
MOV AL,AH
CALL ToChar
MOV Buffer,AL
MOV AH,02H
MOV DL,10
MOV DH,0
INT 10H ;定位光标
MOV AH,09H
LEA DX,Buffer
INT 21H
RET
LedDisplay ENDP
INT_0: PUSH DX
PUSH AX
CALL ClearInt
JC INT_0_0
MOV DX,RD_IO8259
IN AL,DX
IN AL,DX ;判断由哪个中断源引起的中断
MOV AL,Counter
ADD AL,1
DAA
MOV Counter,AL
MOV ReDisplayFlag,1
INT_0_0: MOV DX,IO8259_0
MOV AL,20H
OUT DX,AL
POP AX
POP DX
IRET
IfExit PROC NEAR
PUSH AX
PUSH DX
MOV AH,06H
MOV DL,0FFH
INT 21H
POP DX
POP AX
JZ IfExit1
JMP Exit
IfExit1: RET
IfExit ENDP
InitPCI PROC NEAR
MOV AH,00H
MOV AL,03H
INT 10H ;清屏
MOV AH,0B1H
MOV AL,01H
INT 1AH
CMP AH,0
JZ InitPCI2
LEA DX,msg0
InitPCI1: MOV AH,09H
INT 21H
JMP Exit
InitPCI2: MOV AH,0B1H
MOV AL,02H
MOV CX,Device_ID
MOV DX,Vendor_ID
MOV SI,0
INT 1AH
JNC InitPCI3 ;是否存在Star PCI9052板卡
LEA DX,msg1
JMP InitPCI1
InitPCI3: MOV DI,PCIBAR1
MOV AH,0B1H
MOV AL,09H
INT 1AH ;读取该卡PCI9052基地址
JNC InitPCI4
LEA DX,msg2
JMP InitPCI1
InitPCI4: AND CX,0FFFCH
MOV PCI_IO_BaseAddress0,CX
MOV DI,PCIBAR3
MOV AH,0B1H
MOV AL,09H
INT 1AH ;读取该卡扩展的8位IO基地址
JNC InitPCI5
LEA DX,msg3
JMP InitPCI1
InitPCI5: AND CX,0FFFCH
MOV IO_Bit8_BaseAddress,CX
MOV DI,PCIIPR
MOV AH,0B1H
MOV AL,09H
INT 1AH ;读取IRQ号
JNC InitPCI6
LEA DX,msg4
JMP InitPCI1
InitPCI6: MOV PCI_IRQ_NUMBER,CL
RET
InitPCI ENDP
ModifyAddress PROC NEAR
MOV AX,IO_Bit8_BaseAddress
ADD IO8259_0,AX
ADD IO8259_1,AX
ADD RD_IO8259,AX
RET
ModifyAddress ENDP
ModifyVector PROC NEAR
PUSH ES
MOV AL,PCI_IRQ_NUMBER
CMP AL,08H
JAE ModifyVector1
ADD AL,08H ;IRQ0..7 -> 中断向量8..F
JMP ModifyVector2
ModifyVector1: ADD AL,70H-08H ;IRQ8..F -> 中断向量70H..77H
ModifyVector2: MOV INT_Vector,AL
MOV AH,35H
INT 21H
MOV INT_IP,BX ;保护原中断处理例程地址
MOV AX,ES
MOV INT_CS,AX
MOV AL,INT_Vector
LEA DX,INT_0
PUSH DS
PUSH CS
POP DS
MOV AH,25H
INT 21H ;设置新中断向量
POP DS
MOV BL,PCI_IRQ_NUMBER
MOV DX,21H
CMP AL,08H
JB ModifyVector3
MOV DX,0A1H
ModifyVector3: IN AL,DX
MOV INT_MASK,AL
AND BL,07H
MOV CL,BL
MOV BL,1
SHL BL,CL
NOT BL
AND AL,BL
OUT DX,AL ;允许中断
POP ES
STI
RET
ModifyVector ENDP
ClearInt PROC NEAR ;清楚PCI9052、系统中断控制器的中断标志
MOV DX,PCI_IO_BaseAddress0
ADD DX,INTCSR
; IN AL,DX
; AND AL,mask_int_9052
; JZ ClearInt3 ;不是8259引取的中断
INC DX
IN AL,DX
OR AL,0CH
OUT DX,AL ;清除PCI9052的中断标志位
MOV AL,PCI_IRQ_NUMBER
CMP AL,08H
JAE ClearInt1
AND AL,7
OR AL,60H
MOV DX,20H
OUT DX,AL
JMP ClearInt2
ClearInt1: AND AL,7
OR AL,60H
MOV DX,0A0H
OUT DX,AL
MOV DX,20H
MOV AL,62H
OUT DX,AL
ClearInt2: CLC
RET
;ClearInt3: STC
; RET
ClearInt ENDP
Exit: CLI
MOV BL,PCI_IRQ_NUMBER
MOV DX,21H
CMP AL,08H
JB Exit1
MOV DX,0A1H
Exit1: MOV AL,INT_MASK
OUT DX,AL ;屏蔽中断
PUSH DS
MOV AL,INT_Vector
MOV DX,INT_IP ;保护原中断处理例程地址
MOV AX,INT_CS
MOV AH,25H
INT 21H ;设置新中断向量
POP DS
STI
MOV AH,4CH
INT 21H
END START
三、8251
.MODEL TINY
;使用8253的计数器0,外接2Mhz,经26分频后,送给8251,产生4800bps
PCIBAR3 EQU 1CH ;8位I/O空间基地址(它就是实验仪的基地址,也为DMA & 32 BIT RAM板卡上的8237提供基地址)
Vendor_ID EQU 10EBH ;厂商ID号
Device_ID EQU 8376 ;设备ID号
.STACK 100
.DATA
CTL_ADDR DW 00F1H ;控制字或状态字
DATA_ADDR DW 00F0H ;读写数据
W_8253_T0 DW 00B0H ;计数器0地址
W_8253_C DW 00B3H ;控制字
IO_Bit8_BaseAddress DW
msg0 DB 'BIOS不支持访问PCI
msg1 DB '找不到Star PCI9052板卡
msg2 DB '读8位I/O空间基地址时出错$'
Receive_Buffer DB 10 DUP(0) ;接受缓冲器
Send_Buffer EQU Receive_Buffer ;发送缓冲器
.CODE
START: MOV AX,@DATA
MOV DS,AX
MOV ES,AX
NOP
CALL InitPCI
CALL ModifyAddress ;根据PCI提供的基地址,将偏移地址转化为实地址
CALL INIT_8253
CALL INIT_8251
START1: MOV CX,10
CALL Receive_Group
MOV CX,10
CALL Send_Group
CALL IfExit ;OUT1输出频率为1S的方波
JZ START1
JMP Exit
; JMP START1
INIT_8253 PROC NEAR
MOV DX,W_8253_C
MOV AL,37H ;定时器0,方式3
OUT DX,AL
MOV DX,W_8253_T0
MOV AL,26H ;BCD码26(2000000/26)=16*4800
OUT DX,AL
MOV AL,0
OUT DX,AL
RET
INIT_8253 ENDP
INIT_8251 PROC NEAR
CALL RESET_8251
mov dx,CTL_ADDR
mov al,7eh ;波特率系数为16,8个数据位
out dxx,al ;一个停止位,偶校验
CALL DLTIME ;延时
mov al,15h ;允许接收和发送发送数据,清错误标志
out dx,al
CALL DLTIME
RET
INIT_8251 ENDP
Reset_8251 PROC NEAR
MOV DX,CTL_ADDR
MOV AL,0
OUT DX,AL ;向控制口写入"0"
CALL DLTIME ;延时,等待写操作完成
OUT DX,AL ;向控制口写入"0"
CALL DLTIME ;延时
OUT DX,AL ;向控制口写入"0"
CALL DLTIME ;延时
MOV AL,40H ;向控制口写入复位字40H
OUT DX,AL
CALL DLTIME
RET
Reset_8251 ENDP
;接受一组数据,CX--接受数目
Receive_Group PROC NEAR
LEA DI,Receive_Buffer
Receive_Group1: CALL Receive_Byte
STOSB
LOOP Receive_Group1
RET
Receive_Group ENDP
;接受一个字节
Receive_Byte PROC NEAR
MOV DX,CTL_ADDR
Receive_Byte1: in al,dx ;读入状态
test al,2
jz Receive_Byte1 ;
mov dx, DATA_ADDR ;有
in al,dx
RET
Receive_Byte ENDP
;发送一组数据,CX--发送数目
Send_Group PROC NEAR
LEA SI,Send_Buffer
Send_Group1: lodsb
call Sendbyte
loop Send_Group1
RET
Send_Group ENDP
;发送一个字节
Sendbyte PROC NEAR
PUSH AX
MOV DX,CTL_ADDR ;读入状态
Sendbyte1: in al,dx
test al,1
jz Sendbyte1 ;允许数据发送吗?
pop ax ;发送
mov dx,DATA_
MOV CX,Device_ID
MOV DX,Vendor_ID
MOV SI,0
INT 1AH
JNC InitPCI3 ;是否存在Star PCI9052板卡
LEA DX,msg1
JMP InitPCI1
InitPCI3: MOV DI,PCIBAR3
MOV AH,0B1H
MOV AL,09H
INT 1AH ;读取该卡PCI9052基地址
JNC InitPCI4
LEA DX,msg2
JMP InitPCI1
InitPCI4: AND CX,0FFFCH
MOV IO_Bit8_BaseAddress,CX
RET
InitPCI ENDP
ModifyAddress PROC NEAR
ADD COM_ADD,CX
ADD PA_ADD,CX
ADD PB_ADD,CX
ADD PC_ADD,CX
RET
ModifyAddress ENDP
Exit: MOV AH,4CH
INT 21H
END START