当前位置:文档之家› 在Delphi 2007 中用Indy10开发Socket应用程序

在Delphi 2007 中用Indy10开发Socket应用程序

在Delphi 2007 中用Indy10开发Socket应用程序
在Delphi 2007 中用Indy10开发Socket应用程序

笔者在前一段的工作中,需要开发一套简单的网络数据传输程序。由于平时常用Delphi做点开发,故此次也不例外。Delphi 7中带有两套TCP Socket组件:Indy Socket组件(IdTC PClient和IdTCPServer)和Delphi原生的TCP Socket组件(ClientSocket和ServerSocket)。但是,Borland已宣称ClientSocket和ServerSocket组件即将被废弃,建议用相应的Indy组件来代替。因此,笔者使用了Indy。本文在对Indy进行简要介绍的基础上,创建了一组简单的TCP Socket数据传输应用来演示了Indy的使用方法。

开放源代码的Internet组件集——Internet Direct(Indy)

Internet Direct(Indy)是一组开放源代码的Internet组件,涵盖了几乎所有流行的Internet协议。Indy用Delphi编写,被包含在Delphi 6,Kylix 1和C++ Builder 6及以上各个版本的Borland开发环境中。Indy曾经叫做WinShoes(双关于WinSock——Windows 的Socket库),是由Chad Z. Hower领导的一群开发者构建的,可以从Indy的站点https://www.doczj.com/doc/3717341484.html,/indy上找到更多的信息并下载其新版本。到笔者撰写本文时为止,Indy 的最新稳定版是9.0.14,Indy 10也进入了Beta测试阶段。

Delphi 7中所带的是Indy 9。在其的组件面板上,一共安装有100多个Indy组件。使用这些组件你可以开发基于各种协议的TCP客户和服务器应用程序,并处理相关的编码和安全问题。你可以通过前缀Id来识别Indy组件。

Indy是阻塞式(Blocking)的

当你使用Winsock开发网络应用程序时,从Socket中读取数据或者向Socket写入数据都是异步发生的,这样就不会阻断程序中其它代码的执行。在收到数据时,Winsock会向应用程序发送相应的消息。这种访问方式被称作非阻塞式连接,它要求你对事件作出响应,设置状态机,并通常还需要一个等待循环。

与通常的Winsock编程方法不同的是,Indy使用了阻塞式Socket调用方式。阻塞式访问更像是文件存取。当你读取数据,或是写入数据时,读取和写入函数将一直等到相应的操作完成后才返回。比如说,发起网络连接只需调用Connect方法并等待它返回,如果该方法执行成功,在结束时就直接返回,如果未能成功执行,则会抛出相应的异常。同文件访问不同的是,Socket调用可能会需要更长的时间,因为要读写的数据可能不会立即就能准备好(在很大程度上依赖于网络带宽)。

阻塞式Socket并非恶魔(Evil)

长期以来,阻塞式Socket都遭到了毫无理由的攻击。其实阻塞式Socket并非如通常所说的那样可怕。这还要从Winsock的发展说起。

当Socket被从Unix移植到Windows时,一个严重的问题立即就出现了。Unix支持fork,客户程序和服务器都能够fork新的进程,并启动这些进程,从而能够很方便地使用阻塞式Socket。而Windows 3.x既不支持fork也不支持多线程,当使用阻塞式Socket时,用户界面就会被“锁住”而无法响应用户输入。

为克服Windows 3.x的这一缺陷,微软在Winsock中加入了异步扩展,以使Winsock 不会“锁住”应用程序的主线程(也是唯一的线程)。然而,这需要了一种完全不同的编程方式。于是有些人为了掩饰这一弱点,就开始强烈地诽谤阻塞式Socket。

当Win32出现的时候,它能够很好地支持线程。但是既成的观念已经很难更改,并且说出去的话也无法收回,因此对阻塞式Socket的诽谤继续存在着。

事实上,阻塞式Socket仍然是Unix实现Socket的唯一方式,并且它工作得很好。

阻塞式Socket的优点

归结起来,在Windows上使用阻塞式Socket开发应用程序具有如下优点:

○ 编程简单——阻塞式Socket应用程序很容易编写。所有的用户代码都写在同一个地方,并且顺序执行。

○ 容易向Unix移植——由于Unix也使用阻塞式Socket,编写可移植的代码就变得比较容易。Indy就是利用这一点来实现其多平台支持而又单一源代码的设计。

○ 很好地利用了线程技术——阻塞式Socket是顺序执行的,其固有的封装特性使得它能够很容易地使用到线程中。

阻塞式Socket的弱点

事物都具有两面性,阻塞式Socket也不例外。它的一个主要的缺点就是使客户程序的用户界面“冻结”。当在程序的主线程中进行阻塞式Socket调用时,由于要等待Socket调用完成并返回,这段时间就不能处理用户界面消息,使得Update、Repaint以及其它消息得不到及时响应,从而导致用户界面被“冻结”。

使用TIdAntiFreeze对抗“冻结”

Indy使用一个特殊的组件TIdAntiFreeze来透明地解决客户程序用户界面“冻结”的问题。TIdAntiFreeze在Indy内部定时中断对栈的调用,并在中断期间调用Application.ProcessMessages方法处理消息,而外部的Indy调用继续保存阻塞状态,就好像TIdAntiFreeze对象不存在一样。你只要在程序中的任意地方添加一个TIdAntiFreeze对象,就能在客户程序中利用到阻塞式Socket的所有优点而避开它的一些显著缺点。

Indy使用了线程技术

阻塞式Socekt通常都采用线程技术,Indy也是如此。从最底层开始,Indy的设计都是线程化的。因此用Indy创建服务器和客户程序跟在Unix下十分相似,并且Delphi的快速开发环境和Indy对WinSock的良好封装使得应用程序创建更加容易。

Indy服务器模型

一个典型的Unix服务器有一个或多个监听进程,它们不停地监听进入的客户连接请求。对于每一个需要服务的客户,都fork一个新进程来处理该客户的所有事务。这样一个进程只处理一个客户连接,编程就变得十分容易。

Indy服务器工作原理同Unix服务器十分类似,只是Windows不像Unix那样支持fork,而是支持线程,因此Indy服务器为每一个客户连接分配一个线程。

图1显示了Indy服务器的工作原理。Indy服务器组件创建一个同应用程序主线程分离的监听线程来监听客户连接请求,对于接受的每一个客户,都创建一个新的线程来为该客户提供服务,所有与这一客户相关的事务都由该线程来处理。

使用组件TIdThreadMgrPool,Indy还支持线程池。

图1 Indy服务器工作原理

线程与Indy客户程序

Indy客户端组件并未使用线程。但是在一些高级的客户程序中,程序员可以在自定义的线程中使用Indy客户端组件,以使用户界面更加友好。

简单的Indy应用示例

下面将创建一个简单的TCP客户程序和一个简单的TCP服务器来演示Indy的基本使用方法。客户程序使用TCP协议同服务器连接,并向服务器发送用户所输入数据。服务器支持两条命令:DATA和QUIT。在DATA命令后跟随要发送的数据,并用空格将命令字DATA和数据分隔开。

表单布局

建立一个项目组,添加一个客户程序项目和一个服务器项目。客户程序和服务器程序的表单布局如同2和图3所示。客户程序表单上放置了TIdTCPClient组件,服务器程序表单上放置了TIdTCPServer组件。为防止客户程序“冻结”,还在其表单上放置TIdAntiFreeze 组件。

客户程序和服务器程序的表单上都放置有TListBox组件,用来显示通信记录。

图2 简单的TCP客户程序表单

图 3 简单的TCP服务器程序表单

客户程序代码

客户程序片断如代码列表1所示。

代码列表1

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, StdCtrls;

type

TForm1 = class(TForm)

IdTCPClient: TIdTCPClient;

IdAntiFreeze1: TIdAntiFreeze;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

EdtPort: TEdit;

EdtHost: TEdit;

EdtData: TEdit;

BtnConnect: TButton;

BtnSend: TButton;

BtnDisconnect: TButton;

Button4: TButton;

LbLog: TListBox;

procedure BtnConnectClick(Sender: TObject);

procedure BtnSendClick(Sender: TObject);

procedure BtnDisconnectClick(Sender: TObject); private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BtnConnectClick(Sender: TObject); begin

IdTCPClient.Host := EdtHost.Text;

IdTCPClient.Port := StrToInt(EdtPort.Text);

LbLog.Items.Add('正在连接' + EdtHost.Text + '...');

with IdTCPClient do

begin

try

Connect;

try

LbLog.Items.Add(IOHandler.ReadLn);

BtnConnect.Enabled := False;

BtnSend.Enabled := True;

BtnDisconnect.Enabled := True;

except

LbLog.Items.Add('远程主机无响应!');

IdTCPClient.Disconnect();

end;//end try

except

LbLog.Items.Add('无法建立到' + EdtHost.Text + '的连接!'); end;//end try

end;//end with

end;

procedure TForm1.BtnDisconnectClick(Sender: TObject);

//var

// Received: string;

begin

LbLog.Items.Add('QUIT');

try

IdTCPClient.IOHandler.WriteLn('QUIT');

finally

IdTCPClient.Disconnect();

LbLog.Items.Add('同主机' + EdtHost.Text + ' 的连接已断开!');

BtnConnect.Enabled := True;

BtnSend.Enabled := False;

BtnDisconnect.Enabled := False;

end;//end try

end;

procedure TForm1.BtnSendClick(Sender: TObject);

begin

LbLog.Items.Add('DATA ' + EdtData.Text);

with IdTCPClient do

begin

try

IOHandler.WriteLn('DATA ' + EdtData.Text);

LbLog.Items.Add(IOHandler.ReadLn)

except

LbLog.Items.Add('发送数据失败!');

IdTCPClient.Disconnect();

LbLog.Items.Add('同主机' + EdtHost.Text + ' 的连接已断开!');

BtnConnect.Enabled := True;

BtnSend.Enabled := False;

BtnDisconnect.Enabled := False;

end;//end try

end;//end with

end;

end.

在“连接”按钮事件响应过程中,首先根据用户输入设置IdTCPClient的主机和端口,并调用IdTCPClient的Connect方法向服务器发出连接请求。然后调用ReadLn方法读取服务器应答数据。

在“发送”按钮事件响应过程中,调用WriteLn方法写DATA命令,向服务器发送数据。

在“断开”按钮事件响应过程中,向服务器发送QUIT命令,并调用Disconnect方法断开连接。

程序中还包含有通信信息记录和异常处理的代码。

服务器程序代码

服务器程序片断如代码列表2所示。

代码列表2

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, StdCtrls, IdCmdTCPServer, IdTCPConnection, IdTCPClient, IdCmdTCPClient,IdContext,idsync,StrUtils;

type

TForm1 = class(TForm)

Button1: TButton;

BtnStop: TButton;

BtnStart: TButton;

EdtData: TEdit;

EdtPort: TEdit;

Label1: TLabel;

Label2: TLabel;

IdTCPServer: TIdTCPServer;

Label3: TLabel;

LbLog: TListBox;

procedure BtnStartClick(Sender: TObject);

procedure BtnStopClick(Sender: TObject);

procedure IdTCPServerConnect(AContext: TIdContext);

procedure IdTCPServerExecute(AContext: TIdContext); private

{ Private declarations }

FLogEntry, FReceived : String;

public

{ Public declarations }

procedure DisplayData();

procedure AddLogEntry();

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DisplayData();

begin

EdtData.Text := FReceived;

end;

procedure TForm1.AddLogEntry();

begin

LbLog.Items.Add(FLogEntry);

end;

procedure TForm1.BtnStartClick(Sender: TObject);

begin

IdTCPServer.DefaultPort := StrToInt(EdtPort.Text); IdTCPServer.Active := True;

BtnStart.Enabled := False;

BtnStop.Enabled := True;

LbLog.Items.Add('服务器已成功启动!');

end;

procedure TForm1.BtnStopClick(Sender: TObject);

begin

IdTCPServer.Active := False;

BtnStart.Enabled := True;

BtnStop.Enabled := False;

LbLog.Items.Add('服务器已成功停止!');

end;

procedure TForm1.IdTCPServerConnect(AContext: TIdContext); //uses IdContext begin

//对端IP

//AContext.Connection.Socket.Binding.PeerIP

//对端端口

//AContext.Connection.Socket.Binding.PeERPort

LbLog.Items.Add('来自主机'+AContext.Connection.Socket.Binding.PeerIP+' 的连接请求已被接纳!');

AContext.Connection.IOHandler.WriteLn('100: 欢迎连接到简单TCP服务器!');

//AContext.Connection.IOHandler.ReadLn

//AContext.Connection.WriteLn('100: 欢迎连接到简单TCP服务器!');

end;

{

首部function AnsiStartsText(const ASubText, AText: string): Boolean; $[StrUtils.pas 功能返回字符串AText是否以子串ASubText开头

说明不区分大小写

参考function https://www.doczj.com/doc/3717341484.html,pareString

例子CheckBox1.Checked := AnsiStartsText(Edit1.Text, Edit2.Text);

RightStr是Delphi的自有函数,作用是取出字符串最右边的字符。

如:RightStr('jiang_011', 3) 返回的是'011'。

还有很多相关函数如LeftStr等,都包含在StrUtils 单元中。

你可以包含StrUtils 单元来直接使用这些函数。

}

procedure TForm1.IdTCPServerExecute(AContext: TIdContext);

var

sCommand: string;

begin

with AContext.Connection do

begin

sCommand := IOHandler.ReadLn();

FLogEntry := sCommand + ' 来自于主机'+ AContext.Connection.Socket.Binding.PeerIP;

TIdSync.SynchronizeMethod(AddLogEntry);

if AnsiStartsText('DATA ', sCommand) then

begin

FReceived := RightStr(sCommand, Length(sCommand)-5);

Socket.WriteLn('200: 数据接收成功!');

TIdSync.SynchronizeMethod(DisplayData);

end

else if SameText(sCommand, 'QUIT') then begin

FLogEntry := '断开同主机'

+ AContext.Connection.Socket.Binding.PeerIP

+ ' 的连接!';

TIdSync.SynchronizeMethod(AddLogEntry);

Disconnect;

end

else begin

WriteLn('500: 无法识别的命令!');

FLogEntry := '无法识别命令:' + sCommand;

TIdSync.SynchronizeMethod(AddLogEntry);

end;//endif

end;

end;

end.

“启动”按钮设置IdTCPServer 的Active属性为True来启动服务器,“停止”按钮设置Active属性为False来关闭服务器。

IdTCPServerConnect方法作为IdTCPServer 的OnCorrect事件响应过程,向客户端发送欢迎信息。OnCorrect事件在一个客户连接请求被接受时发生,为该连接创建的线程AThread被作为参数传递给IdTCPServerConnect方法。

IdTCPServerExecute方法是IdTCPServer 的OnExecute事件响应过程。OnExecute 事件在TIdPeerThread对象试图执行其Run方法时发生。OnExecute事件与通常的事件有所不同,其响应过程是在某个线程上下文中执行的,参数AThread就是调用它的线程。这一点很重要,它意味着可能有多个OnExecute事件响应过程被同时执行。在连接被断开或中断前,OnExecute事件响应过程会被反复执行。

在IdTCPServerExecute方法中,首先读入一条指令,然后对指令进行判别。如果是DATA指令,就解出数据并显示它。如果收到的是QUIT指令,则断开连接。需要特别指出的是,由于IdTCPServerExecute方法在某一线程上下文中执行,因此显示数据和添加事件记录都是将相应的方法传递给Synchronize调用来完成的。

运行程序

运行客户端和服务器程序,按如下流程进行操作:

1.按服务器程序的“启动”按钮启动服务器;

2.按客户程序的“连接”按钮,建立同服务器的连接;

3.在客户程序的待发送数据编辑框中输入“Hello, Indy!”,并按“发送”按钮发送数据;

4.按客户程序的“断开”按钮,断开同服务器的连接;

5.按服务器程序的“停止”按钮停止服务器。

程序运行的结果如图4和图5所示。

更多信息

要了解更多的关于Indy的信息,可以参阅:

[1] Indy主页https://www.doczj.com/doc/3717341484.html,/indy;

[2] Indy的帮助文件;

[3] https://www.doczj.com/doc/3717341484.html,/en/indyarticles.php上有关Indy的文章;

[4] Chad Z. Hower(Indy的原始作者)和Hadi Hariri合著的“Indy In Depth”,可以从https://www.doczj.com/doc/3717341484.html,/找到;

[5] Marco Cantu著,Sybex出版“Mastering Delphi 7”中相关的章节。

51单片机集成开发系统MedWin

51单片机集成开发系统MedWin 一、安装Medwin 直接从万利公司网站上下载的MedWin不含汇编/编译/连接器,也不包含c51的函数和连结库。为此,我站将medwin 和其必须的附件一同打包,重新生成解压式安装文件MedWinSetup.exe。该文件在配套光盘中。 点击MedWinSetup.exe,即弹出安装对话框,请不要改变安装路径!点击“安装”程序会自动完成全部安装。 安装完后,桌面上会生成一个图标。点击该图标就开始启动Medwin开发系统,启动后在第一个弹出的对话框中选择“模拟仿真”: 接下来的设置仅在第一次启动时所必要的设置:

在“工作向导”对话框中选择“新建或打开一个文件”。 在打开文件对话框中可根据你的情况处理;若打开现有文件,就直接点击现有文件后再点击“打开”按钮;若你新建一个文件,请在“文件名(N):”框中键入你新文件的名字再点击“打开”按钮。需注意的是,新建的汇编程序其扩展名必须是ASM,c51程序扩展名必须是C。下面是已打开的MedWin环境快照。 在有些时候,可能会出现环境参数设置,请依下面方法设置。

工作目录我们设到C:\C51\Mypro下。 “编译/汇编/连接配置”应与下面设置一致。 二、MedWin的简单使用:

启动medwin,新建一个文件后就出现编辑窗,我们在就可以在这个窗中编写汇编或c原程序。 当编写完成后,应先保存。再按下图步骤产生烧写单片机用的hex文件。

先在工具栏中按“”按钮,主窗体下面会出现汇编或编译过程提示,若错误=0,就编译或汇编成功;若有错误,请以依提示逐个排除错误后再按“”按钮汇编或编译,直至错误=0,编译或汇编成功。 最后从菜单中点击“项目管理”下的“输出 Intel HEX 文件 (H)...”,在c:\c51\Mypro下就生成与原程序同名的hex文件。 下面我们用流水灯程序直接做一遍 将光盘中McuCai\liushun\的liu1.asm复制到c:\c51\Mypro目录中,取掉其只读属性。启动Medwin,打开 c:\c51\Mypro\liu1.asm 。 编辑窗中就是用汇编语言编写的流水灯程序。现在我们不要管他是什么意思,按下面步骤将这些汇编“符号”生成单片机需要的代码就行啦。 第一步,点击工具按钮“”生成Medwin调试代码;第二步,从菜单中点击“项目管理”下的“输出 Intel Hex 文件 (H)...”,

单片机开发与仿真软件keilc51的使用

单片机开发与仿真软件Keil C51的使用 一、Keil C51 操作入门 Keil C51 简介 Keil C51 是德国知名软件公司Keil(现已并入ARM 公司)开发的基于8051 内核的微控制器软件开发平台,是目前开发8051 内核单片机的主流工具。Keil 51支持汇编语言、C语言等各种开发语言。其中,uVision2集成开发环境包含项目管理、源代码编辑和强大的程序调试环境。uVision2调试器是一个强大的全特性调试器,允许用户在PC机上完全模拟目标程序、指令集和片内外围功能。 实验所用的是Keil C51 评估版。 Keil C51 的启动 双击桌面上的“Keil uVision2”图标,启动Keil C51程序,启动界面如图1所示。 图1 Keil C51的启动界面 建立第1 个Keil C51 程序 Keil C51 是一个功能很强大的软件,但是使用起来并不复杂。现在就通过建立一个简单的LED(发光二极管)闪烁发光的实例来初步掌握Keil C51的基本用法。硬件电路参见图2,单片机I/O 输出低电平可点亮LED。 图2 LED 闪烁发光电路 ●新建工程。执行Keil C51 软件的菜单“Project | N ew Project…”,弹出一个名 为“Create New Project”的对话框。先选择一个合适的文件夹准备来存放工程文件,比如“E:\Project\LedFlash”,其中“LedFlash”是新建的文件夹。建议:今后每新建一个工程都要在适当的磁盘位置新建一个文件夹用来保存工程文件,以方便管理,并养成良好的习惯。最后,为工程取名为“LedFlash”,并保存。参见图3。 图3 新建Keil C51 工程 ●选择CPU。紧接着,Keil C51 提示选择CPU 器件。8051 内核单片机最早是由鼎鼎 大名的Intel 公司发明的,后来其他厂商如Philips 、Atmel 、Winbond 等先后推出其兼容产品,并在8051 的基础上扩展了许多增强功能。在这里可以选择Philips 的第1 个器件“80/87C51”,该器件与Intel 的8051 完全兼容。参见图 4 。

STC单片机开发系统的建立及使用

实验一:STC单片机开发系统的建立及使用 ——Keil μVision、Proteus软件的使用 ——单片机最小硬件系统搭建【实验目的】: (1)、学习、掌握和使用8051单片机开发软件KeilμVision的使用,在该开发平台的支持下,完成汇编语言程序的编写、调试等开发的过程。 (2)、掌握STC单片机最小硬件系统的原理,并使用面包板搭建STC单片机最小硬件系统;了解LY-51S单片机开发板的功能和使用方法;掌握STC单片机下载软件的使用方法。 (3)、学习、掌握Proteus仿真软件的使用方法,使用该软件搭建8051单片机电路,配合KeilμVision软件生成的代码,学习、调试单片机的硬件系统。 【实验仪器及材料】 PC计算机1台、直流稳压电源1台、LY-51S单片机开发板1块(含STC89C52RC 单片机)、30pF瓷片电容2只、10uF电解电容1只、10K电阻1只、330Ω电阻1只、LED发光二极管1只、12MHz石英晶振1只、面包板1块(含连线若干) 【实验原理/实验基础知识】 单片机最小硬件系统由时钟电路、复位电路、电源电路及单片机构成,任何单片机应用系统均是在最小系统的基础之上扩展而来。 STC单片机属于可以ISP编程的单片机,其ISP功能由单片机机的UART (Universal Asynchronous Receiver Transmitter通用异步收发器)实现,使用PC机的串行通信接口来下载程序。PC机的串行通信接口为RS-232逻辑电平,需要通过一个RS-232到TTL电平的转换芯片才能与单片机连接,也可以通过USB转串行接口芯片来连接单片机。 LY-51S单片机开发板为功能模块独立设计的开发板,板上带有RS232转TTL 电平芯片MAX232、USB转串口芯片PL2303,可以直接连接PC机RS232串口或PC机USB 接口。根据实验需求使用杜邦线连接开发板各功能模块。 【实验内容及步骤】: 1、认识LY-51S单片机开发板各功能部件

单片机编程软件的基本使用

硬件实验报告 学生:张小强 学号:1252100210 指导老师:莫荣

实验一:单片机开发系统应用初步 ——基本I/O口赋值 1. 内容提要: 1)KEIL C软件对程序进行编译调试及烧录软件的使用方法。 2)单片机基本I/O口的驱动方式、特点等。 3)汇编语句的基本用法;对基本I/O口的赋值方法;程序的具体流程等。 2.实验目的及要求: 1) 课前预习好编程的基本知识。程序的基本概念、*.asm、*.c、*.hex、*.uv2 所表示的文件类型等。 2) 熟练掌握不同数据类型之间的相互转换,不同类型的数据在程序中的表示方 法等。 3)课前弄清楚单片机I/O口的基本驱动方式,理解何谓上拉及下拉方式,单片机驱动电流、灌入电流等概念。 4)复习数码管的相关知识,弄清数码管需显示某个字符应如何对其进行控制等。 ORG 0000H AJMP MAIN MAIN: MOV P0,#0FH JMP MAIN END 4.实验的实施: 1)实验前准备:基础知识的统计学习 A.程序:完成某种任务的计算机代码。 B.文件类型: *.asm:汇编语言编写的程序文件。 *.c: c语言编写的程序文件。 *.hex:机器语言文件,指通过*.asm、*.c等程序编译成功后转换而得到的hex文件。 *.uv2:表示keil c软件的工程文件。 C.对源程序的相关阐释:

ORG 0000H 定义程序起始地址 AJMP MAIN 直接跳到main(主程序) MAIN: MOV P0,#0FH 对p0口赋初值 JMP MAIN 跳转到main END 程序结束 2)通过keil c进行程序编译,生成正确的*.hex机器语言文件: A.打开keil c,建立工程文件: a.在主菜单下右键点击选中project 再点击New Project新建工程文件,弹出下面对话框: b选择保存位置,定义文件名,点击保存,弹出下面对话框

单片机c语言开发sbit使用方法

单片机C语音开发sbit使用方法·· 1.bit和sbit都是C51扩展的变量类型。 bit和int char之类的差不多,只不过char=8位, bit=1位而已。都是变量,编译器在编译过程中分配地址。除非你指定,否则这个地址是随机的。这个地址是整个可寻址空间,RAM+FLASH+扩展空间。bit只有0和1两种值,意义有点像Windows下VC中的BOOL。 sbit是对应可位寻址空间的一个位,可位寻址区:20H~2FH。一旦用了sbi xxx = REGE^6这样的定义,这个sbit量就确定地址了。sbit大部分是用在寄存器中的,方便对寄存器的某位进行操作的。 2.bit位标量 bit位标量是C51编译器的一种扩充数据类型,利用它可定义一个位标量,但不能定义位指针,也不能定义位数组。它的值是一个二进制位,不是0就是1,类似一些高级语言中的Boolean类型中的True和False。 3.sfr特殊功能寄存器 sfr也是一种扩充数据类型,点用一个内存单元,值域为0~255。利用它可以访问51单片机内部的所有特殊功能寄存器。如用sfr P1 = 0x90这一句定P1为P1端口在片内的寄存器,在后面的语句中我们用以用P1 = 255(对P1端口的所有引脚置高电平)之类的语句来操作特殊功能寄存器。 sfr P1 = 0x90; //定义P1 I/O 口,其地址90H sfr 关键定后面是一个要定义的名字,可任意选取,但要符合标识符的命名规则,名字最好有一定的含义如P1 口可以用P1 为名,这样程序会变的好读好多.等号后面必须是常数,不允许有带运算符的表达式,而且该常数必须在特殊功能寄存器的地址范围之内(80H-FFH),具体可查看附录中的相关表. sfr 是定义8 位的特殊功能寄存器而sfr16 则是用来定义16 位特殊功能寄存器, 如8052 的T2 定时器,可以定义为: sfr16 T2 = 0xCC; //这里定义8052 定时器2,地址为T2L=CCH,T2H=CDH

开发51单片机操作系统时应注意哪些问题

开发51单片机操作系统时应注意哪些问题 51系列单片机是美国Intel公司在1980年推出的高性能8位单片机,在我国的应用非常广泛。目前,在软件设计中需要软件工程师从底层做起,在系统软件设计方面需要做大量的重复性劳动。如果开发一套基于51系列单片机的操作系统,那么用户只需要编写各个任务的程序,不必同时将所有任务运行的各种情况记在心中,不但大大减少了程序编写的工作量,而且减少了出错的可能性。 1 开发平台的选择和论证 开发平台的选择至关重要,因为有时它不光影响进度、产品质量、可维护性等一般问题,还涉及到方案的可实现性。 在本系统中,选择51系列单片机作为操作系统的运行平台有以下原因。 首先,51系列单片机应用非常广泛,一大批性能优越的51兼容单片机相继推出。这里包括:低功耗、高速度和增强型的Philips公司的系列产品;完美地将Flash(非易失闪存技术)EEPROM与80C51内核结合起来的Atmel公司的系列产品;在抗干扰性能,电磁兼容和通信控制总线功能上独树一帜,其产品常用于工作环境恶劣场合的Siemens公司的系列产品以及一些其它公司的产品。既然产品如此丰富,性能如此优越,那么在处理多任务并且对实时性要求严格的系统设计中,为了充分挖掘单片机的潜能(尤其是在实时性方面),也是为了简化开发的过程,基于51系列单片机的实时操作系统的需求就十分强烈了。Keil公司的RTX51 Full就是一个基于51系列单片机的有实用价值的实时操作系统,但该操作系统是一个源码不公开的收费软件。 其次,借助于Keil C51的集成开发环境,完全可以开发出适用于51系列单片机的操作系统代码。 Keil C51软件提供丰富的库函数和功能强大的Windows界面集成开发调试工具。 另外重要的一点,Keil C51生成的目标代码效率非常高,多数语句生成的汇编代码很紧凑,容易理解。在开发大型软件时,更能体现高级语言的优势。C编译器能产生可重入代码,而且用C语言可以打开和关闭中断。

最新单片机应用系统设计开发主要步骤资料

单片机应用系统设计开发主要步骤 单片机应用系统的研究开发步骤,大致分为几个部分: 1.策划阶段: 策划阶段决定研发方向,是整个研发流程中的重中之重,所谓“失之毫厘谬以千里”。因此必须“运筹帷幄,谋定而动”。策划有两大内涵:做什么?怎么做? 1)项目需求分析。解决“做什么?”“做到什么程度?”问题。 对项目进行功能描述,要能够满足用户使用要求。对项目设定性能指标,要能够满足可测性要求。所有的需求分析结果应该落实到文字记录上。 2)总体设计,又叫概要设计、模块设计、层次设计,都是一个意思。解决“怎么做?”“如何克服关键难题?”问题。 以对项目需求分析为依据,提出解决方案的设想,摸清关键技术及其难度, 明确技术主攻问题。 针对主攻问题开展调研工作, 查找中外有关资料, 确定初步方案,包括模块功能、信息流向、输入输出的描述说明。在这一步,仿真是进行方案选择时有力的决策支持工具。 3)在总体设计中还要划分硬件和软件的设计内容。单片机应用开发技术是软硬件结合的技术, 方案设计要权衡任务的软硬件分工。硬件设计会影响到软件程序结构。如果系统中增加某个硬件接口芯片, 而给系统程序的模块化带来了可能和方便, 那么这个硬件开销 是值得的。在无碍大局的情况下, 以软件代替硬件正是计算机技术的长处。 4)进行总体设计时要注意,尽量采纳可借鉴的成熟技术, 减少重复性劳动,同时还能增加可靠性,对设计进度也更具可预测性。 2. 实施阶段之硬件设计 策划好了之后就该落实阶段,有硬件也有软件。随着单片机嵌入式系统设计技术的飞速发展,元器件集成功能越来越强大,设计工作重心也越来越向软件设计方面转移。硬件设计的特点是设计任务前重后轻。 单片机应用系统的设计可划分为两部分: 一部分是与单片机直接接口的电路芯片相关数字电路的设计,如存储器和并行接口的扩展, 定时系统、中断系统扩展, 一般的外部设备的接口, 甚至于A/D、 D/A芯片的接口。另一部分是与模拟电路相关的电路设计, 包括信号整形、变换、隔离和选用传感器,输出通道中的隔离和驱动以及执行元件的选用。 工作内容: 1)模块分解。策划阶段给出的方案只是个概念方案,在这一步要把它转化为电子产品设计的概念描述的模块,并且要一层层分解下去,直到熟悉的典型电路。尽可能选用符合单片机用法的典型电路。当系统扩展的各类接口芯片较多时, 要充分考虑到总线驱动能力。当 负载超过允许范围时, 为了保证系统可靠工作, 必须加总线驱动器。 2)选择元器件。尽可能采用新技术, 选用新的元件及芯片。 3)设计电原理图及说明。 4)设计PCB及说明。 5)设计分级调试、测试方法。 设计中要注意: 1)抗干扰设计是硬件设计的重要内容, 如看门狗电路、去耦滤波、通道隔离、合理的印制板布线等。

相关主题
文本预览
相关文档 最新文档