用单片机实现温度远程显示

摘  要:文章介绍了用AT89S8252单片机的串行接口与智能温度巡回检测仪(XJ-08S)通过RS—485总线相互通讯实现热水温度远程显示的一种低成本解决方案,内容涉及RS—485总线通讯、单片机驱动数码管显示、数据转换以及键盘处理软硬件设计等内容。

关键词:单片机  RS—485总线  数码管显示  数据转换  键盘处理

一、前  言

目前检测温度一般采用热电偶或热敏电阻作为传感器,这种传感器至仪表之间一般都要用专用的温度补偿导线,而温度补偿导线价格很贵,并且线路太长也会影响测量精度。在实际应用中往往需要对较远处(1KM左右)的温度信号进行监视。现有的解决方案有很多,例如:

  1. 在现场用智能仪表对温度信号进行测量,用计算机作上位机与智能仪表进行通讯来实现远程温度监测(采用这种方案要增加计算机设备及相关计算机软件)。
  2. NCU+DDC实现远程温度监测。用两个DDC,一个安装在现场测量温度,另一个安装在监视地,两个DDC通过NCU进行通讯从而实现远程温度监测。

但以上方案都存在成本高的问题,有没有低成本的解决方案呢?其实,在单片机应用日益广泛的今天,完全可以用单片机以极低的成本来实现远程温度监测。

二、问题的提出

我单位管理的锅炉房同时给两栋建筑物内的两家酒店供应蒸汽,由安装在两栋建筑物地下室的热交换器进行热交换后产生热水送给客房。从锅炉房至两个热交换站的距离分别约600米,值班人员要不停地奔波于两个热交换站与锅炉房之间进行设备巡视,检查热水温度是否控制在规定的范围,这样不仅增加了值班人员的劳动强度,同时也使锅炉房经常无人(因每班1人值班)。如果能在锅炉房显示两个热交换站内各热交换器的热水温度,则值班人员仅在热水温度异常时才需到各热交换站检查设备,这样便可解决上述问题。我公司曾就此问题找专业公司作过方案,其报价在人民币10万元左右,后因种种原因该项目未实施。经过分析,本人发现可以用单片机+智能仪表以低成本实现温度远程显示,并且经过实验取得了成功,现将设计方案简述如下:

三、控制要求及解决方案选择 

1、 两个热交换站分高低区共安装有8个热交换器,正常水温在45oC至65oC之间;两个热交换站与锅炉房的距离分别为500米和600米左右。

  1. 要求在锅炉房能以巡回及定点两种方式显示8个热交换器的热水温度,巡回方式以3秒为周期轮流更新及显示各热交换器热水温度。定点方式时每按上键或下键一次则显示上或下一个热交换器热水温度,每3秒自动更新数据一次。
  2. 根据控制要求选择单片机+智能仪表的解决方案:用带通讯接口的智能仪表安装在现场测量温度,设计制作一个单片机装置完成与智能仪表的通讯及数据显示。

四、通讯协议、智能仪表选择及其参数介绍

因热水温度信号变化较慢,因而对通信的速度要求不高,对于这种低速率远距离的通讯选用RS-485总线适宜。RS-485是EIA(美国电子工业联合会)在1983年公布的新的平衡传输标准,是工业界使用最为广泛的双向、平衡传输线标准接口,它以半双工方式通信,支持多点连接,传统驱动器允许创建多达32个节点的网络,且其具有传输距离远(最大传输距离为1200M),传输速度快(1200M时为100KBPS)等优点。其连接方法如下图所示。

为了满足现场温度检测及与单片机装置通讯的要求,必须选择至少有5个温度检测点及具有RS—485通讯端口的智能仪表。经过对市场上常用的温度检测仪进行分析,选择由重庆川仪十八厂生产的XJ-08S型巡回检测仪作现场测量仪表。

(一)该仪表主要特点如下:

  1. 多量程方式,热电偶、热电阻,1-5V标准信号混合输入,可通过键盘进行设置;
  2. 最多8个测量通道(能测量8个温度信号);
  3. 采用RS-485通讯标准,可将各通道最新数据向上位机传送。


重要的是,该仪表的说明书详细介绍了与该仪表进行数据交换的命令及格式,其通讯协议也相对较简单,这给我们用单片机实现温度远程显示降减低了难度(虽然有RS-485端口的仪表很多,但大多没有通讯命令的详细说明,给我们用单片机编程增加了难度)。

(二)XJ-08S巡回检测仪通讯协议

1、通讯口设置

  1. 通讯方式:RS-485标准电平
  2. 同步方式:起停同步方式
  3. 波特率:9600BPS
  4. 通讯距离:不大于1200M
  5. 通讯线:二线
  6. 数据代码:ASCII码
  7. 数据格式:每字符10位,1个起始位,8个数据位,1个停止位
  1. 数据传输格式
    1. 地址:2字节(高字节在前,低字节在后);
    2. 数据:按地址顺序,仪表数据传输格式为十六进制2字节定点数;

2字节定点数=低字节高4位(ASCII码)+低字节低4位(ASCII码)

高字节高4位(ASCII码)+高字节低4位(ASCII码)

若数据为负数,则采用补码方式传输;

  1. 在传输实时测量值时,传输完2字节定点数后,紧接着又传输2字节定点数,其中高字节低4位为小数点位数。

例 :(50.0)10 表示为 46  34  30  31  30  30  30  31

        低字节  高字节  小数位数

  1. 仪表通讯格式:

@ DE 帧类型 帧数据 CRC CR

    1. @ :通讯起始符
    2. DE :仪表设备号(地址)
    3. 帧类型 :操作命令
    4. 帧数据 :各种操作命令所对应的命令及数据
    5. CRC :校验字节(@外CRC之前的其他几个字节的异或值
    6. CR :结束符(回车符)

4、应用中用到的命令及数据格式:

  1. 读仪表全部动态数据命令帧 @ DE RD CRC CR
  2. 命令回送帧 正确 @DE RD 帧数据  CRC CR

错误 @DE * * CRC CR

例:读28号仪表的全部动态数据

命令:’@1CRD64’,0D(ASCII码40 31 43 52 44 36 34 0d)

错误返回码 ‘@1C**72’,0D(ASCII码40 31 43 2A 2A 37 32 0D)

正确返回数据’@ 1C RD XXXX  XXXX  XXXX  XXXX  XXXX  XXXX

第0通道     第1通道 第2通道

XXXX  XXXX  XXXX  XXXX  XXXX  XXXX  XXXX  XXXX

第3通道 第4通道 第5通道 第6通道

XXXX  XXXX  XX’,0D

第7通道 校验

五、单片机选择及硬件电路设计

  1. 选用ATMEL公司生产的AT89S8252-24PC单片机,其主要参数及特点如下:
  1. 与MCS-51产品兼容(其引脚图见原理图)
  2. 具有8K字节可擦写的FLASH内部程序存储器,可擦写1000次;2K字节EEPROM,可擦写100,000次,SPI口(用PC机的并口连接5条线即可通过SPI口下载程序,下载软件可从网上下载,这样可节省购买编程器的费用;)。

注:笔者现已制作成了ISP2000三合一烧写器,详情见http://www.mcudiy.com

  1. 256字节RAM,32根可编程I/O线,可编程串行口,内置看门狗。

与看门狗有关的特殊功能寄存器WMCON 地址= 96H,与看门狗有关的控制位为96h第0、1、5、6、7位,第5、6、7位用于设置看门狗定时时间(具体见第5页表格),本应用中第5、6、7位均置1,设置看门狗溢出时间为2048ms,第0位为看门狗使能控制位,该位置1将使能看门狗,其第1位为复用位,向第1位写1将复位看门狗定时器,具体操作如下:

a,使能看门狗,并将其溢出时间设定为2048ms:ORL  96H, #0E1H;

b,看门狗定时器清0:ORL  96H, #2

2、按键设计:

为方便使用,设计了三个按键,分别为巡回/定点切换键、键、键。切换键用于巡检与定点模式的切换,上键向上切换通道,下键向下切换通道;其中巡检/定点切换键通过外部中断1以中断方式工作,中断程序将巡回/定点标志取反后直接跳到主程序中巡回/定点标志判断程序前运行,由判断程序完成巡回/定点的切换。按键信号由单片机P3.3,P3.4,P3.5引脚输入。

3、显示电路设计

为方便观察,选用三个二位共阳级8段数码显示管(TOD5201AE)动态显示,一位显示仪表地址(从A至F),一位显示通道号(从0至7通道),其余四位用来显示实时温度值;用单片机P1口驱动一片74HC244以吸收电流的方式控制段码,用单片机P0.0至P0.5引脚驱动六个PNP三极管(9012)控制位选。

4、电源选用5V/1A市售成品开关电源。

5、 根据智能仪表通讯协议的要求,串行口定义为方式1工作,一帧10位:1个起始位、8个数据位、一个停止位;用一片75176完成数据的发送与接收,由于RS-485为半双工,故用单片机P3.2引脚控制发送与接收的切换;两个智能仪表处于RS-485总线的两个端点,为提高可靠性,在RS-485总线的两个端点上分别并联一个120Ω、1/4W终端电阻。

    1. 系统方框图如右示:
    2. 单片机装置电原理图见下页:

六、单片机软件设计说明及程序流程图

为方便调试,采用模块化编程,共分1个主模块及5个子模块,各模块功能说明及流程图如下(源程序见附录):

  1. 主模块(rand_main.a51)

上电后程序显示初始化标志并等待3秒,然后进入巡回模式,自动检测地址为A(10)至F(15)的智能仪表,对在线的仪表及已使用通道以3秒为周期自动巡回读取实时温度并送数码管显示,仪表未在线或未用通道则自动跳过;定点模式时根据上、下按键情况自动向前或向后移动一个通道后等待下一次按键(向上至最高通道号时跳到上一个仪表的最低在用通道,向下至最低通道号时跳到下一个仪表的最高在用通道);等待期间以3秒为周期读取当前仪表当前通道实时温度并送数码管显示,另外,为了区分巡回、定点工作模式,定点工作模式时最低位数码管以约0.5Hz的频率闪烁显示。当检测到巡回/定点切换键按下时自动在巡回及定点模式间转换,当检测到温度值低于-199.9度时显示-199.9度。

主模块流程图见下页:


2、数据转换子模块(rand_data.a51)

功能: 本模块先将ASCII码转换成BIN码,然后将BIN码转换成BCD码并将数据转换成可直接显示的格式

入口: a=通道号

出口: r1=个位,r2=十位,r3=百位,r4=千位(显示数据)

a=非0表示该通道未用

注:本子模块中直接将小数点信息加到相应位数据上,如需在某位显示小数点,则将该位数据加10H,显示子模块根据此信息显示小数点

各子程序功能介绍:

  1. bcd2_bcd1:将r3,r4中的4位bcd码由低至高分别存入r1,r2,r3,r4中;
  2. ascii4_bcd3:将(r0)为首地址的4字节ascii码转换成bcd码并将bcd码由低至高依次存放在r3,r4,r5中,r3,r4中各存放2位bcd码,r5中存放一位bcd码;
  3. bin_bcd:将r1,r2中的bin码转换成bcd码并将bcd码由低至高依次存放在r3,r4,r5中,r3,r4中各存放2位bcd码,r5中存放一位bcd码;
  4. ascii4_bin2:将(r0)为首地址的4字节ascii码转换成2位bin码存放在r1(低字节),r2(高字节)中;

注:[(r0)指r0中内容]

  1. ascii_bin:将(r0)为地址的一位ascii码转换成bin码存A中。

(高级子程序调用低级子程序以实现更强的功能,源程序中对各子程序有较详细的注释,故此处仅画出主流程图)

3、显示、软件看门狗、20ms定时器子程序(rand_disp.a51)

功能: 通过定时器0以1MS为周期动态显示缓冲区中的内容;同时完成20ms定时器及软件看门狗计数;当软件看门狗定时器溢出时自动复位。

入口: 以disp_buf为首地址依次存放从个位至十万位待显示数据,以disp_wc为首地址(位地址)依次存放个位至千位闪烁控制位信息,为'0'常亮,为'1'闪烁.

出口: wdt中存放软件看门狗计数值,time_20ms中存放20ms的计数值。Wdt溢出时跳至程序存储器0000H单元

  1. 将定时器0设定为模式1定时工作,每ms产生一次中断,即显示一位,每10ms 6位数据轮流显示1ms;为进一步提高可靠性,在该模块中设计了软件看门狗,实现方法见源程序。

模块流程图如本页所示:

4、命令发送及接收控制子模块(rand_send.a51)

功能: 发送命令缓冲区中命令并等待接收完毕,然后检查接收到的数据,接收错误则重发命令,达到设定的次数仍错则存入错误码后退出.

入口: A=仪表地址

出口: A=0 表示接收正确  1 表示校验错 '*'表示命令错 'N'表示无回应

模块流程图如下:

5、串行接收子模块(rand_rec.a51)

功能: 串行接收模块通过中断自动执行,程序检测到@时置ri_f标志并开始接收,检测到回车符时清ri_f后退出,接收到的数据存放在以rec_buf为首地址的缓冲区中。

串行中断(rand_rec.a51)流程图 巡回/定点键中断(rand_key.a51)流程图

6、巡回/定点转换检测模块(rand_key.a51)

功能: 模块通过外部中断1自动执行,检测到巡回/定点按键后先延时去抖动,并等待按键释放后将巡回/定点标志位取反,然后自动跳至主模块中start处,并不返回原中断点。

模块流程图如见本页:

七、调测及运行情况介绍

  1. 调试步骤:
    1. 硬件连接:将各芯片插在面包板上并用导线按原理图连接
    2. 软件开发环境:Keil uVision2 for Windows ,该软件的模拟调试器支持C语言及汇编语言源代码调试,其汇编程序支持宏汇编及模块化编程,使用方便。
    3. 首先在模拟调试器中调试各子模块,各子模块调试正常后再将各子模块及主模块全部汇编连接成目标文件,最后将目标代码下载到单片机中并连接智能仪表进行统调。
  2. 该系统软件部分除报警子模块外已全部开发完成并实际测试通过,测试时用一对长度约1100M的0.5mm2 普通电话线作为单片机装置与两个智能仪表的通讯线,经过一个多星期的连续运行观察,运行可靠稳定,完全满足使用要求。

[注:报警子模块的开发及硬件制版工作正在进行中。]

八、结束语

用单片机+智能仪表构成的温度远程显示系统总造价约人民币7000元(两块智能仪表+温度传感器约3500元,通讯电缆约2000元,单片机装置及施工费用约1500元),与采用其它方案的系统比较造价较低,其硬件及软件的设计、制作都较简单,有一定的电子及单片机知识便可完成。同时对该装置软件稍加修改即可与其他带有RS-485通讯端口的仪器仪表通讯(如变频器、电路传感器等),实现远程测量、监视及控制。

与发达国家相比,我国单片机应用的普及程度较低。通过该实例说明,我们完全可以把我们学到的单片机知识应用到实际工作中,直接创造经济效益。

九、参考资料

<<单片机高级语言C51Windows环境编程与应用>> 电子工业出版社

徐爱钧 彭秀华 编著

<<ATMEL89系列Flash单片机原理与应用>> 电子工业出版社

余永权 主编

<<标准集成电路数据手册高速CMOS电路>> 电子工业出版社

<<ATMEL  AT89S8252数据手册>> ATMEL公司

<<XJ-08H(S)巡回检测仪使用说明书>> 重庆川仪十八厂

<<工业控制计算机组成原理>> 清华大学出版社

孙廷才 王杰 孙中健 编著

<<电子技术>>2001年11期

十、附录(源程序)

1、主模块(rand_main.a51

;------------1--------rand_main.a51----------------

name rand_main

EXTRN CODE(I_T0,send_order,rec_si,ascii_bcd,key)

extrn data (DISP_buf,disp_wc,time_20ms,wdt)

extrn idata (rec_buf)

public TH0_H,TL0_L,START,ri_f,wdt_time,key_work,key_f

prog SEGMENT CODE ;定义代码段

byte_buff segment data ;定义字节数据段1

byte_buffI segment idata ;定义字节数据段2

bit_buff segment data bitaddressable ;定义位数据段

bit_flag segment bit

stack segment idata ;定义堆栈数据段

   rseg stack ;为堆栈保留20个字节

ds 20

   CSEG AT 00H ;定义绝对代码段

USING 0 ;选择工作寄存器组第0组

lJMP rand ;复位时程序执行执行点

CSEG AT 03H ;外部中断0

RETI

CSEG AT 0BH ;定时器0中断

lJMP I_T0

CSEG AT 13H ;外部中断1

ljmp key

RETI

CSEG AT 1BH ;定时器1中断

RETI

CSEG AT 23H ;串行中断

ljmp rec_si

RSEG BYTE_BUFF

td_temp: ds 1

TD_n: DS 1 ;通道号

YD_n100: ds 1 ;仪表地址

;----------------------------------

rseg bit_flag

key_work:dbit 1

ri_f: dbit 1 ;串行口正在接收标志

;----主程序

RSEG prog

;------------------------------符号定义

key_f equ p3.3

key_up equ p3.4

key_down equ p3.5

wdt_time equ 100 ;软件看门狗定时器计数值

scon_c equ 01010000b ;串行口设置为10位UART,允许接收

th1_h equ 0fdh ;晶振为11.0592M,波特率为9600时初值

tmod_n equ 21h ;设置定时器(T1作为波特率发生器工作在模式2,T0为模式1)

ie_n equ 82h ;设置串行,定时器0中断

ip_n equ 12h ;设置串行,定时器0中断为高级中断

TH0_H EQU 0FCH

TL0_L EQU 06BH ;设定定时器0为1MS中断初值

;------------------初始化代码

clear_wdt macro ;清硬看门狗宏定义

orl 96h,#2

ENDM

rand: ORL 96H,#0E1H ;启动硬件看门狗

mov p0,#0ffh

mov r0,#20h

mov a,#0

start_300:mov @r0,a

inc r0

cjne r0,#128,start_300

setb key_work ;置巡回/定点标志

mov p3,#0ffh

mov p2,#0ffh

mov disp_wc,#0 ;初始化闪烁控制位

mov ip,#ip_n ;设置串行,定时器0中断为高级中断

mov scon,#scon_c

MOV TMOD,#tmod_n

MOV TH0,#TH0_H ;设定定时器初值

MOV TL0,#TL0_L

mov th1,#th1_h

mov tl1,#th1_h

mov ie,#ie_n

mov pcon,#0

SETB tr1

SETB TR0

;-------显示初始化提示

acall chuhao

CLEAR_WDT

start: clr ea

mov sp,#stack-1

setb ea

clr ri_f ;清接收中标志

clr p3.2 ;置75176为接收状态

jnb key_work,db_work

;-----------------------------------

setb ex1

mov yd_n100,#0ah

mov td_n,#0

s_0: anl disp_wc,#0f0h

mov wdt,#0 ;清看门狗定时器

clear_wdt

mov a,yd_n100

lcall send_order

JNZ s_1

mov disp_buf+5,yd_n100

mov a,td_n

lcall ascii_bcd

jnz s_2

mov disp_buf+4,td_n

acall mov_to_disp

mov wdt,#0

clear_wdt

mov a,#75

add a,time_20ms

cjne a,time_20ms,$

mov wdt,#0

clear_wdt

mov a,#75

add a,time_20ms

cjne a,time_20ms,$

s_2: inc td_n

mov a,td_n

cjne a,#8,s_0

mov td_n,#0

s_1: inc yd_n100

MOV A,YD_N100

cjne a,#10h,s_0

mov yd_n100,#0ah

ajmp s_0

;-----------------------------

db_work:setb ex1

orl disp_wc,#01h

d_3: mov wdt,#0 ;清看门狗定时器

clear_wdt

jb key_up,d_4

mov a,#2

add a,time_20ms

cjne a,time_20ms,$

jb key_up,d_4

d_5: mov wdt,#0

clear_wdt

jnb key_up,d_5 ;等待向上键松开

;------------------------------------------------

d_53: mov a,td_n

cjne a,#7,d_50

mov td_n,#0

d_52: inc yd_n100

mov a,yd_n100

cjne a,#10h,d_51

mov yd_n100,#0ah

ajmp d_51

d_50: inc td_n

d_51: mov a,yd_n100

lcall send_order

JNZ d_52

mov disp_buf+5,yd_n100

mov a,td_n

lcall ascii_bcd

jnz d_53

mov disp_buf+4,td_n

acall mov_to_disp

mov a,#100 ;2秒钟定时设定

add a,time_20ms

ajmp d_3

;------------------------------------------------

d_4: jb key_down,d_10

mov a,#2

add a,time_20ms

cjne a,time_20ms,$

jb key_down,d_3

d_6: mov wdt,#0

clear_wdt

jnb key_down,d_6 ;等待向下键松开

;-----------------------------------------------

d_43: mov a,td_n

cjne a,#0,d_40

mov td_n,#7

d_42: dec yd_n100

mov a,yd_n100

cjne a,#9h,d_41

mov yd_n100,#0fh

ajmp d_41

d_40: dec td_n

d_41: mov a,yd_n100

lcall send_order

JNZ d_42

mov disp_buf+5,yd_n100

mov a,td_n

lcall ascii_bcd

jnz d_43

mov disp_buf+4,td_n

acall mov_to_disp

mov a,#100 ;2秒钟定时设定

add a,time_20ms

ajmp d_3

;----------------------------------

d_10: cjne a,time_20ms,d_30

mov a,yd_n100

lcall send_order

jnz d_30

mov a,td_n

lcall ascii_bcd

jnz d_30

acall mov_to_disp

mov a,#100

add a,time_20ms

d_30:ajmp d_3

;----------------------------------

mov_to_disp:mov disp_buf,r1

mov disp_buf+1,r2

mov disp_buf+2,r3

mov disp_buf+3,r4

ret

chuhao: mov r1,#1eh ;初始化等待提示

mov r2,#22h

mov r3,#21h

mov r4,#1fh

mov disp_buf+4,#21h

mov disp_buf+5,#20h

acall mov_to_disp

mov a,#75

add a,time_20ms

cjne a,time_20ms,$

mov wdt,#0

clear_wdt

mov a,#75

add a,time_20ms

cjne a,time_20ms,$

ret

end

2、数据转换子模块(rand_data.a51)

;-----------2-------rand_data.a51----------------

name  rand_data

extrn idata (rec_buf)

public ascii_bcd

prog SEGMENT CODE ;定义代码段

byte_buff segment data ;定义字节数据段1

byte_buffI segment idata ;定义字节数据段2

bit_buff segment data bitaddressable ;定义位寻址区字节数据段

rseg prog

using 0

;-------------------------------------

ASCII_BCD:mov b,#8 ;计算该通道数据偏移首地址

mul ab

add a,#5

mov r0,#rec_buf

add a,r0

mov b,a

mov r0,a

acall ascii4_bcd3

mov a,b ;还原小数位数

add a,#7

mov r0,a

acall ascii_bin

mov r6,a ;小数位数暂存在R6中

mov a,r5

jz asc_oK

mov a,dpl

cpl a

clr c

inc a

mov dpl,a

mov a,dph

cpl a

addc a,#0

mov dph,a

jnz asc_b

asc_0: mov a,dpl

dec a

jnz asc_b

mov r1,#0fh

mov r2,#0fh

mov r3,#0fh

mov r4,#0fh

mov a,#0fh

ajmp asc_out

asc_b: mov r1,dpl ;为负数处理

mov r2,dph

acall bin_bcd

mov a,b ;还原小数位数

add a,#7

mov r0,a

acall ascii_bin

mov r6,a ;小数位数暂存r6

acall bcd2_bcd1

mov a,r4

dec a

jnz asc_100 ;数据小于-199.9时显示-199.9

mov r4,#23h

ajmp asc_sw

asc_100:mov r4,#23h

mov r3,#9

mov r2,#19h

mov r1,#9

ajmp asc_sw_1

asc_ok: acall bcd2_bcd1 ;正常数据处理程序

asc_sw: mov a,r4 ;清除有效位前面的0

jnz asc_sw_1

mov r4,#1ch

mov a,r3

jnz asc_sw_1

mov r3,#1ch

asc_sw_1:clr a

asc_out:ret

;------------每字节两位BCD码转换为每字节一位BCD码子程序

;入口:r3=个位及十位BCD码,r4=百位及千位BCD码,r6=小数位数

;出口:r1=个位BCD码,r2=十位BCD码,r3=百位BCD码,r4=千位BCD码

bcd2_bcd1:mov a,r3 ;个位及十位BCD数处理

anl a,#0fh

mov r1,a

mov a,r3

anl a,#0f0h

swap a

mov r2,a

mov a,r4  ;百位及千位BCD数处理

anl a,#0fh

mov r3,a

mov a,r4

anl a,#0f0h

swap a

mov r4,a

mov a,r6 ;加入小数点信息

jz bcd2_out

add a,#ar1

mov r0,a

mov a,@r0

add a,#10h

mov @r0,a

bcd2_out:ret

;---------------ASCii4_BCD3转换子程序

;入口:r0=四字节ASCII码首地址

;出口:r5,r4,r3从高至低依次存放BCD码(r3,r4各存2位,r5存1位)

ascii4_bcd3:acall ascii4_bin2

mov dpl,r1

mov dph,r2

acall bin_bcd

ret

;---------------BIN_BCD转换子程序

;入口:r1=BIN低字节,r2=BIN高字节 共2字节

;出口:r3=低2位BCD码,r4=高2位BCD码,r5=可能的最高位BCD码

bin_bcd:PUSH ACC

PUSH PSW

mov r3,#0 ;BCD单元清0

mov r4,#0

mov r5,#0

mov r6,#16 ;设置二进制数位数

clr c

bin_0: mov a,r1

rlc a

mov r1,a

mov a,r2

rlc a

mov r2,a

mov r0,#ar3

mov r7,#3 ;设置BCD字节数

bin_1: mov a,@r0

addc a,@r0

da a

mov @r0,a

inc r0

djnz r7,bin_1

djnz r6,bin_0

POP PSW

POP ACC

ret

;---------------ASCII4_BIN2转换子程序

;入口:R0=ASCII码首地址(共四字节ASCII码)

;出口:r1=BIN码低字节,R2=BIN码高字节

ascii4_bin2:PUSH ACC

acall ascii_bin

anl a,#0fh

swap a

mov r1,a

inc r0

acall ascii_bin

anl a,#0fh

orl ar1,a

inc r0

acall ascii_bin

anl a,#0fh

swap a

mov r2,a

inc r0

acall ascii_bin

anl a,#0fh

orl ar2,a

POP ACC

ret

;---------------ASCII_BIN转换子程序

;入口:R0=ASCII地址

;出口:A=BIN码

ascii_bin:mov a,@r0

clr c

subb a,#3ah

jnc ascii_0

add a,#7

ascii_0:add a,#3

ret

end

3、显示、软件看门狗及20ms定时器子模块(rand_disp.a51

;--------3--------rand_disp.a51-------------------------

name  rand_disp

extrn number(TH0_H,TL0_L,wdt_time)

PUBLIC I_T0,disp_buf,disp_wc,time_20ms,wdt

  prog SEGMENT CODE ;定义代码段

  BYTE_BUFF segment data ;定义字节数据段1

  byte_buffI segment idata ;定义字节数据段2

  bit_buff segment data bitaddressable ;定义位数据段

 RSEG BYTE_BUFF

wdt: ds 1

time_s_c: ds 1

time_20ms: ds 1

DISP_C: ds 11 ;显示位

   disp_buf data disp_c+1 ;个位缓冲区,此个位并非真正的个位,指最右一位,以下类推

  disp_2 data disp_c+2 ;十个位缓冲区

disp_3 data disp_c+3   ;百位缓冲区

disp_4 data disp_c+4    ;千位缓冲区

disp_5 data disp_c+5 ;通道位缓冲区

disp_6 data disp_c+6 ;地址位缓冲区

disp_7 data disp_c+7 ;无

disp_8 data disp_c+8 ;无

disp_s data disp_c+9 ;闪烁计数器

rseg bit_buff

disp_wc: ds 1

disp_c_1 bit disp_wc.0 ;个位闪烁标志位 1-闪烁

disp_c_2 bit disp_wc.1 ;十位闪烁标志位

disp_c_3 bit disp_wc.2 ;百位闪烁标志位

disp_c_4 bit disp_wc.3 ;千位闪烁标志位

disp_s_c bit disp_wc.4 ;闪烁控制位 1-闪烁

RSEG PROG

using 0

dsb equ p3.4

cr_not equ p3.5

cp equ p3.6

I_T0: push acc

push ar0

push dph

push dpl

push psw

mov th0,#th0_h

mov tl0,#tl0_l

mov dptr,#tab

;---------------------------------------------

djnz disp_s,d_20

cpl disp_s_c

;---------------------------------------------

d_20: INC DISP_C

MOV R0,DISP_C

CJNE R0,#1,DISP2 ;r0=1显示个位

mov c,disp_c_1

mov A,disp_buf

mov p1,#0FFH

mov p0,#0feh

ajmp d_10

DISP2: CJNE R0,#2,DISP3 ;显示十位

setb p0.0

mov c,disp_c_2

mov A,disp_2

mov p1,#0FFH

mov p0,#0fdh

ajmp d_10

DISP3: CJNE R0,#3,DISP4 ;显示百位

mov c,disp_c_3

mov A,disp_3

mov p1,#0FFH

mov p0,#0fbh

ajmp d_10

DISP4: CJNE R0,#4,DISP5 ;显示千位

mov c,disp_c_4

mov A,disp_4

mov p1,#0FFH

mov p0,#0f7h

ajmp d_10

DISP5: CJNE R0,#5,DISP6 ;显示通道号

mov A,disp_5

mov p1,#0FFH

mov p0,#0efh

ajmp d_10

DISP6:  CJNE R0,#6,DISP7 ;显示仪表地址

mov A,disp_6

mov p1,#0FFH

mov p0,#0dfh

ajmp d_10

DISP7: CJNE R0,#7,DISP8 ;无

mov A,disp_7

mov p1,#0FFH

mov p0,#0bfh

ajmp d_10

DISP8: CJNE R0,#8,d_10 ;无

mov A,disp_8

mov p1,#0FFH

mov p0,#7fh

d_10: acall disp_w

mov r0,disp_c

cjne r0,#10,d_12 ;若disp_c=10则清disp_c

mov disp_c,#0

inc time_s_c ;MS,S计数处理程序

mov a,time_s_c

cjne a,#2,d_12

mov time_s_c,#0

inc time_20ms

inc wdt ;软看门狗处理程序

mov a,wdt

cjne a,#wdt_time,d_12

mov wdt,#0

mov a,#0

push acc

push acc

reti

;-----------------------

d_12: pop psw

pop dpl

pop dph

pop ar0

pop acc

RETI

disp_w: jnc d_0

jnb disp_s_c,d_0

mov p1,#0FFH

ajmp d_1

d_0: movc a,@a+dptr

cpl a

mov p1,a

D_1: ret

;---------------------------------------------------------

TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH

    ;  0   1    2   3   4   5   6   7   8   9

db 77H,7CH,39H,5EH,79H,71H

;   A   B   C   D   E   F

DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH

;   0.   1.  2.   3.   4.   5.   6.   7.   8.  9.

db 40H,80H,00H,37h,5ch,1ch,58h,74h,0dch,46h

;   -   .   空   n   o u   c    h   a   -1

;   1a  1b  1c 1d  1e 1f  20  21  22 23

END

4、命令发送及接收控制子模块(rand_send.a51

;----------4--------rand_send.a51----------------

name send_order

extrn idata (rec_buf) ;rec_buff 接收缓冲区

extrn data (time_20ms)

extrn bit (ri_f) ;ri_f 正在接收标志

PUBLIC send_order

prog SEGMENT CODE ;定义代码段

byte_buff segment data ;定义字节数据段1

byte_buffI segment idata ;定义字节数据段2

bit_buff segment data bitaddressable ;定义位数据段

rseg byte_buff

send_n:ds 1

order_buf:ds 10

rseg prog

dd_c equ 4 ;等待回应20m数

cw_n equ 7 ;设置允许错误次数

using 0

;---------------------清命令缓冲区

send_order:

mov dpl,#8

mov r0,#order_buf

send_0: mov @r0,#0

inc r0

djnz dpl,send_0

MOV DPL,#72 ;清接收缓冲区

MOV R0,#REC_BUF

SEND_A: MOV @R0,#0

INC R0

DJNZ DPL,SEND_A

;----------------------发送命令控制程序

mov send_n,#cw_n ;设置允许错误次数

mov b,#10

clr c

subb a,b

mov b,#8

mul ab

mov dptr,#a_order

mov r0,#order_buf-1

mov r1,#10

start_mov:inc r0

push acc

movc a,@a+dptr

mov @r0,a

inc dptr

pop acc

cjne @r0,#0dh,start_mov

;----------------------发送命令子程序

send_start:setb p3.2 ;切换75176至发送状态

mov r0,#order_buf-1

send_10:inc r0

mov sbuf,@r0

jnb ti,$ ;等待一帧数据发完

CLR TI

        cjne @r0,#0dh,send_10 ;检测到结束标志退出

;------------------------检测接收标志

mov r0,#30 ;延时60uS等待停止位发送完毕

djnz r0,$

setb es

clr p3.2 ;切换75176至接收状态

mov a,#dd_c ;延时检测仪表有无回应

add a,time_20ms

send_21:jb ri_f,send_20

cjne a,time_20ms,send_21

mov a,#'N'

ajmp send_23

;-------------------------检测接收是否正确

send_20:mov a,#10 ;延时200MS等待接收结束

add a,time_20ms

send_28:jnb ri_f,send_29

cjne a,time_20ms,send_28

clr ri_f ;200MS仍未结束清接收中标志

send_29:mov r0,#rec_buf+4

cjne @r0,#'*',send_22

mov a,#'*'

send_23:djnz send_n,send_start ;达到允许错误次数退出

ajmp send_out

send_22:mov r0,#rec_buf+71

cjne @r0,#0dh,send_23 ;接收缓冲区第72字节不为回车符转出错处理

;------------------------------还原校验码

mov r0,#rec_buf+70

mov a,@r0

clr c

subb a,#3ah

jnc SEND_25

add a,#7

send_25:add a,#3

mov @r0,a

dec r0

mov a,@r0

clr c

subb a,#3ah

jnc SEND_26

add a,#7

send_26:ADD A,#3

swap a

inc r0

xchd a,@r0

dec r0

xch a,@r0

inc r0

mov @r0,#0dh ;检验码后加回车符

;------------------------------检验接收缓冲区数据

mov r0,#rec_buf+1

mov a,@r0

inc r0

send_24:xrl a,@r0

inc r0

cjne @r0,#0dh,send_24

cjne a,#0,send_200 ;接收校验未通过转出错处理

send_out:clr es

ret

send_200:mov a,#1

ajmp send_23

;----------------------------------------------------

a_order: db '@0ARD67',0DH ;读A表全部动态数据命令

b_order: db '@0BRD64',0DH ;读B表全部动态数据命令

c_order: db '@0CRD65',0DH ;读c表全部动态数据命令

d_order: db '@0DRD62',0DH ;读d表全部动态数据命令

e_order: db '@0ERD63',0DH ;读e表全部动态数据命令

f_order: db '@0FRD60',0DH ;读f表全部动态数据命令

END

5、串行接收子模块(rand_rec.a51

;-------5----------rand_rec.a51

name rec_si

extrn bit (ri_f)

public rec_si,rec_buf

prog SEGMENT CODE ;定义代码段

byte_buff segment data ;定义字节数据段1

byte_buffI segment idata ;定义字节数据段2

bit_buff segment data bitaddressable ;定义位数据段

rseg byte_buff

rec_buf_z: ds 1 ;接收区指针

rec_err: ds 1 ;接收缓冲区溢出计数器

rseg byte_buffi

rec_buf: ds 75

rseg prog

using 0

rec_si: PUSH PSW

push ar0

push acc

JNB RI,REC_OUT ;为发送中断跳出

clr ri

jb ri_f,rec_0

mov a,sbuf

cjne a,#'@',rec_out ;无效命令过滤处理

setb ri_f ;置接收中标志

mov rec_buf_z,#rec_buf ;接收缓冲区首地址给接收指针

mov rec_err,#73 ;设置最大接收字节数

ajmp rec_1

rec_0: mov a,sbuf

cjne a,#0dh,rec_1

clr ri_f

rec_1: mov r0,rec_buf_z

mov @r0,a

inc rec_buf_z

djnz rec_err,rec_out ;接收溢出清接收标志

clr ri_f

rec_out:pop acc

pop ar0

POP PSW

reti

end

6、巡回/定点转换检测子模块(rand_key.a51

;-----------6----rand_key.a51

name key

EXTRN CODE(START)

extrn bit(key_work,key_f)

EXTRN DATA(DISP_buf,disp_wc,time_20ms,wdt)

PUBLIC KEY

prog SEGMENT CODE ;定义代码段

RSEG PROG

;-------------------------------------

KEY: mov a,#2

add a,time_20ms

cjne a,time_20ms,$

key_1: mov wdt,#0

orl 96h,#0e1h

jnb key_f,key_1

mov a,#2

add a,time_20ms

cjne a,time_20ms,$

jnb key_f,key_1

clr ea

clr ex1

cpl key_work

;--------------------------------------

key_out:mov dptr,#start

push dpl

push dph

reti

end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等天晴i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值