PC端编制控制程序_seabird_新浪博客

下面的文章详细的说明了如何在PC端编制控制程序,并且通过串口输出数据来控制单片机硬件,单片机外围连接了若干继电器,达到控制继电器开关的作用。
要说的是,有很多的方法可以实现上述的功能,下面的方法只是其中的一种,并且出于便于大家学习阅读的目的,很多代码并没有进行优化,而是将其展开编写,在你理解后,你xx可以在此基础上修改、优化代码,使之更优化和精简,并符合你的其他要求。
如果你读完这篇文章,觉得给你带来了帮助,我非常高兴。如果你无法理解,你应该再看一下其他更基础的书籍、文章。

我想应该分成二个部分来讲(单片机部分、PC程序部分),并且希望能写得较为详细,把基础的讲述清楚。
1、单片机部分
电路图:

PC端编制控制程序此主题相关图片如下:


单片机源代码(asm格式):
;--------------------------------------------------
;--------------------------------------------------

;设置串行口 波特率9600
;串行口设置MODE1,SM1=0,REN=1,SMOD=1
;晶振11.0592,定时设置为0FDH
;常用端口设置参数
;FD 9600
;FA 4800
;F4 2400
;E8 1200
;--------------------------------------------------
;***********************************************************
ORG 00H
JMP START

ORG 23H
JMP UART

ORG 30H
START: MOV SP,#70H

MOV SCON,#50H
MOV TMOD,#00100001B ;TIM1在模式2 TIM0在模式1
MOV TH1,#0F4H ;设置定时时间

SETB TR1 ;启动定时器1
SETB ES ;允许串口中断
SETB EA ;允许总中断

MOV P0,#0 ;P0、P2输出低电平
MOV P2,#0

JMP $ ;等待状态
;*****************************************
;串行口中断
;*****************************************
UART: PUSH ACC
PUSH PSW
CLR ES ;关闭串行口中断

MOV TH0,#HIGH(65536-65536)
MOV TL0,#LOW(65536-65536)
SETB TR0 ;开定时器0

MOV 30H,#00 ;同步位
MOV 31H,#00 ;数据1
MOV 32H,#00 ;数据2
MOV 33H,#00 ;结束位

MOV R0,#30H
REC:
jbc tf0,FS ;接收时间是否超时?是则执行FS

JNB RI,REC ;接收数据
CLR RI

MOV A,SBUF
MOV @R0,A
INC R0
JMP REC
FS: CLR TR0 ;关定时器0
;********************************
CALL FUN ;解码并控制继电器
SETB ES ;开串行口中断
POP PSW
POP ACC
RETI ;中断子程序返回

;****************************************
;解码并控制继电器
;下面的程序可以更简洁,但为了方便,展开来编制
;****************************************
FUN: MOV A,#0AH ;判断第1字节即同步位
CJNE A,30H,ERR
MOV A,#0DH ;判断第4字节即结束位
CJNE A,33H,ERR
;****************************************
;第2字节即数据位1,代表继电器J1-8
;第3字节即数据位2,代表继电器J9-16
;****************************************
MOV A,31H
MOV P0,A

MOV A,32H
MOV P2,A

RET
;**************************************
; 数据错误处理
;**************************************
ERR:
MOV 30H,#00 ;同步位
MOV 31H,#00 ;数据1
MOV 32H,#00 ;数据2
MOV 33H,#00 ;结束位

RET

END ;程序结束
;--------------------------------------------------
;--------------------------------------------------

单片机源代码(asm格式)+电路图下载:





电路图说明:
  这个电路非常典型,串行口(也称RS232)接口集成电路MAX232与单片机AT89S51引脚P3.0(RXD)\P3.1(TXD)连接,构成与主机的通讯接口电路。AT89S51引脚P0、P2口连接达林顿管阵列驱动IC uln2803,通过它控制继电器动作。
相关基础知识简要说明:
1、串行口(也称RS232接口)是用途最广的一种通讯接口,一般电脑主机上都有这个接口,缺点是传输距离短,市场上也有很多USB-RS232 转换接口卖。
**常用的通讯接口还有RS485、RS422、LPT打印接口、CAN总线接口、网卡接口等等,与RS232比较接近的通讯接口是RS485,它的通讯距离较远,广泛用于工业控制。
2、串行口(也称RS232)接口集成电路MAX232,接口芯片种类繁多,MAX232只是其中的一种,可以说是串行接口集成电路的代表型号,图纸上一般都标MAX232,但实际使用时,可以选用更多兼容的芯片,其中一个理由,兼容芯片更便宜。
3、达林顿管阵列驱动IC uln2803,TTL输入(0-5v),可以同时驱动8个继电器,内部不仅封装了达林顿管阵列,并且含有钳位二极管,连接继电器时,不需要再连接保护二极管,使用非常方便,因而用途广泛。相同功能的芯片有ULN2003,只是它只有7个输出口。
内部电路如图所示:

PC端编制控制程序此主题相关图片如下:

接口IC ULN2083内部有反相缓冲器(参见技术手册),简单来说,输入高电平,输出为低电平;输入低电平,则输出高电平。如图所示:

PC端编制控制程序此主题相关图片如下:

ULN2803数据手册下载:

注:一般单片机输入、输出电流有限,无法驱动继电器等大电流外围部件,因此需要有驱动电路,常用的是三极管驱动(如2SD8050)和IC 驱动(如ULN2803)。
上拉电阻的问题:
1、51单片机的P0口内部没有上拉电阻,其他P1、P2、P3口内部也只是弱上拉,为了在高电平输出时得到较高的输出电流,提高驱动能力,有必要在P0口与+5v间连接上拉电阻(通常取值在1k-4.7k左右)。见AT89C51数据手册第4页。

PC端编制控制程序此主题相关图片如下:

AT89C51数据手册下载:


51源程序详解:
  
源程序主要分三个部分:初始化程序、串口中断程序、协议解析或叫解码程序。

 

初始化程序:
  初始化是单片机通电后首先执行的一部分程序,主要是对单片机中的寄存器做一些必要的设置(即写入值):
  1、设置串口 波特率为9600 串行口设置MODE1,SM1=0,REN=1,SMOD=1
  2、由于电路上晶振采用11.0592M(最常用),定时器1设置初值为0FDH
;常用串口波特率对应初值(11.0592M晶振)
;FD 9600
;FA 4800
;F4 2400
;E8 1200
3、启动定时器1、允许串口中断、允许总中断

相关代码:

MOV SCON,#50H
MOV TMOD,#00100001B ;TIM1在模式2 TIM0在模式1
MOV TH1,#0F4H ;设置定时时间

SETB TR1 ;启动定时器1
SETB ES ;允许串口中断
SETB EA ;允许总中断

 


需要注意:
1、波特率越高,通讯速度越快,但也更容易出错,一般来说,通讯距离短时,可以用较高的波特率,通讯距离长时,选用较低的波特率可使通讯更为可靠。
2、硬件电路采用不同的晶振,波特率设置时初值是不同的,初值可由公式()取得,通过计算你会发现有些晶振(如10M、12M)计算结果有余数,实质上就是波特率有误差,最终结果就是用了这个晶振的电路,在通讯时会出现无法通讯、数据错乱、时好时坏、误动作等等情况。
很多朋友都是这个问题)。
我不多写了,这里相关参考: 出自:明皓

因此,一般我们在用到串口的单片机电路中,如无特殊需要,一般晶振选用11.0592M、22.1184等。而在没有用到串口的电路中,一般晶振选用6M、12M、24M等,因为计算定时更简单,如6M时钟,周期=2us ;12M时钟,周期=1us ;24M时钟,周期=0.5us。
3、提高波特率的方法有二种:将SM1设为1;或是换一个频率更高的晶振。

由于接口IC ULN2083输入输出的反相特性,即输入为高电平,输出为低电平;输入为低电平,则输出为高电平。同时51单片机上电复位后,其引脚为高电平,这样会引起连接在P0、P2口的继电器全部得电吸合的情况,应此,初始化程序中应对端口作如下设置:
相关代码:
MOV P0,#0 ;P0、P2输出低电平
MOV P2,#0


由于本例中单片机在初始化后没有其它事情做,我们就让它没事歇着。
相关代码:
JMP $ ;自循环(等待状态)


串口中断程序:
串口接收数据流程图

PC端编制控制程序此主题相关图片如下:


串口接收定长或不定长数据的原理:
(很多朋友没理解的)

接收定长或不定长数据关键是要知道数据什么时候发送完毕。
我们知道串口中传送数据是以位(BIT)来传送,通常串口设置为MODE1状态,MODE1状态收发数据是10个位,一个起始位,8个数据位(我们要传送的一个字节数据),1个停止位。如果波特率9600,请注意单位是BIT/S,也就是速度1秒钟9600位,换算一下,发送或接收10位需要1MS毫秒多一点。
那么OK,对于不定长度数据,我们在每接收完1个字节数据后,开始设定时值如2 MS,并开启定时器,如果后面还有数据 ,则重新设定时值如2 MS,并开启定时器;如果后面没有数据了,超过2MS,即表示数据接收完毕了,下面可以对收到的数据处理了。
对于指定长度的数据,我们可以设定全部数据接收完需要多长时间,在引起串口中断后(即准备接收第1个字节),开始设定时值如2 MS,并开启定时器,循环接收字节数据,如果超时,即表示数据接收完毕了,下面可以对收到的数据处理了。
在本例中我们接收的是4个字节的定长数据,相关代码如下:
MOV TH0,#HIGH(65536-65536)
MOV TL0,#LOW(65536-65536)
SETB TR0 ;开定时器0

MOV 30H,#00 ;同步字节
MOV 31H,#00 ;数据1
MOV 32H,#00 ;数据2
MOV 33H,#00 ;结束字节

MOV R0,#30H
REC:
jbc tf0,FS ;接收时间是否超时?是则执行FS

JNB RI,REC ;接收数据
CLR RI

MOV A,SBUF
MOV @R0,A
INC R0
JMP REC
FS: CLR TR0 ;关定时器0
;********************************
CALL FUN ;解码并控制继电器

如何定义通讯协议:

通讯协议就是通讯各方的约定,没有固定的格式方法,由开发商自行定义。我们来看一个最简单的通讯协议:
接收字节数据 功能
00 继电器1开
01 继电器1关
02 继电器2开
03 继电器2关
。。。 。。。
这个协议说明,单片机接收到1个数据如果是00H,则继电器1打开,依次类推。
在实际使用时,由于各种干扰因素,往往会发生误动作的情况,因此通讯协议必须能抵挡各种干扰因素。为了得到可靠的通讯协议,我们常常在要发送的数据前加同步位,发送的数据后加结束位,以及加入校验字节等等方法。
本例中我们确定如下的通讯协议:
1、数据为4个字节,第1字节表示同步位,第2字节表示数据1,第3字节表示数据2,第4字节表示结束位。
2、第1字节表示同步位,固定为0AH;第4字节表示结束位,固定为0DH。
3、第2字节即数据1,8个位依次代表继电器1-8,位=1则继电器开,位=0则继电器关。
4、第3字节即数据2,8个位依次代表继电器9-16,位=1则继电器开,位=0则继电器关。
因此如果接收到数据0A01020D,首先判断第1字节是否=0AH,再判断第4字节是否=0DH,如果不同,则发生了错误,反之正确。
第2字节=01H,表示继电器器1开,继电器2-8关;第3字节=02H,表示继电器10开,继电器9、11-16关。
协议解析(解码)程序
FUN: MOV A,#0AH ;判断第1字节即同步位
CJNE A,30H,ERR
MOV A,#0DH ;判断第4字节即结束位
CJNE A,33H,ERR
;****************************************
;第2字节即数据位1,代表继电器J1-8
;第3字节即数据位2,代表继电器J9-16
;****************************************
MOV A,31H
MOV P0,A

MOV A,32H
MOV P2,A

RET

已投稿到:
郑重声明:资讯 【PC端编制控制程序_seabird_新浪博客】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——