⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbus.asm

📁 c51 单片机平台写的MODBUS通讯协议(汇编)
💻 ASM
字号:
;***********************************************************************************
;D331点胶机程序号选择及与运动控制卡通讯控件.
                              ;编制: 洪天长    公司:特盈自动化    日期:06.01.12
                              ;修改:彭铿      公司:特盈自动化    日期:07.07.19
;晶振选择11.0592M,采用波特率为19200,误差为0.00%. 
;系统采用RS232通讯,MODBUS通讯协议,并进行CRC_16校验,字节不进行奇偶校验(但有校验位).
;主程序进行键盘扫描并通过查询方式与运动控制卡通讯.
;定时器T0中断程序进行LED数码显示器的查表扫描显示及状态指示灯的扫描显示.
;***********************************************************************************
   ORG	0000H	              ;
   AJMP	START                 ;跳转到主程序.  
   ORG 	30H	              ; 
START:NOP          
;系统初始化程序.
INITIALIZE1:MOV	TMOD,#20H     ;定时器T1工作于方式2,可自动重载8位串口用.
   MOV 	TH1,#0FDH             ;---------------串口波特率设定为19200-----------------
   MOV   TL1,#0FDH            ;
   MOV 	PCON,#80H   	      ;波特率翻倍.
   MOV 	SCON,#0DCH	      ;串行口工作于方式3,SM0=1,SM1=1,SM2=0.
	                      ;并允许接收REN=1,TB8=1,RB8=1,TI=0,RI=0.
   SETB  EA	              ;开总中断.
   SETB  EX0                  ;允许中断0中断.
   SETB  PX0                  ;外部中断设定为高优先级.
   CLR   IT0                  ;外部中断0为电平触发. 
   SETB  ET0                  ;允许定时器T0中断.
   CLR	ET1	              ;禁止定时器T1中断.
   CLR   ES                   ;禁止串行中断.
   CLR   TI                   ;清发送中断标志.
   CLR   RI                   ;清接收中断标志.

;以下为写8255控制字程序,
;其中PA口地址:7FFCH,PB口地址:7FFDH,PC口地址:7FFEH,控制口地址:7FFFH
PRINT: MOV DPTR,#7FFFH  ;控制口地址
       MOV A,#8BH  	;控制字
       MOVX @DPTR,A     ;写入控制字
;以下为单片机从主机读取数据的程序段
;以下为发送数据的程序段.
READ_P:MOV   51H,#01H         ;读单片机的地址
   MOV   52H,#03H             ;功能代码
   MOV   53H,#00H             ;
   MOV   54H,#0BH             ;选择十进制12号寄存器。
   MOV   55H,#00H             ;
   MOV   56H,#01H             ;需读的寄存器个数
   MOV   50H,#06              ;写需要发送的数据个数(不包括CRC_16校验码).
   LCALL SEND                 ;调用发送子程序.
;以下为接收数据的程序段.
   MOV   50H,#08              ;需接收的数据位数赋值.
   LCALL RECE                 ;调用接收子程序.
   MOV   A,42H                ;
   CJNE  A,#100,READ_WRO      ;通讯不成功则跳转.
   AJMP  READ_P_OK            ;
READ_WRO:AJMP READ_WRONG
   mov A,51H
   CJNE  A,#1,READ_P           ;比较地址,若不是本单片机地址则重发
;以下为接收成功后的数据处理程序.接收的数据送PA口输出
READ_P_OK: 
   MOV 48H,55H               ;保存读回低字节数值
   MOV DPTR,#7FFCH           ;PA口地址
   MOV A,48H                 ;
   MOVX @DPTR,A               ;低字节数值由PA口输出


;以下为单片机发送数据到主机程序段
WRITE_STATE:MOV   51H,#01H    ;写主机的就绪状态.
   MOV   52H,#06H             ;写单个寄存器.
   MOV   53H,#00H             ;写需要写的寄存器地址#25(十进制).
   MOV   54H,#19H             ;
   MOV   DPTR,#7FFEH          ;C口地址→DPTR
   MOVX  A,@DPTR              ;从C口读数据
   MOV   55H,A                ;写需要写入的数据PC读入的值. 
   MOV   DPTR,#7FFDH          ;B口地址→DPTR
   MOVX  A,@DPTR              ;从B口读数据
   MOV   56H,A                ;写需要写入的数据PB读入的值.   
   MOV   50H,#06              ;写需要发送的数据个数(不包括CRC_16校验码).
   LCALL SEND                 ;调用发送子程序.
;以下为接收数据的程序段.
   MOV   50H,#08              ;需接收的数据位数赋值.
   LCALL RECE                 ;调用接收子程序.
   MOV   A,42H                ;
   CJNE  A,#100,WRITE_WRONG   ;通讯不成功则跳转.


WRITE_WRONG:AJMP  READ_WRONG  ;写失败的程序与读失败的处理程序相同.
;以下为读参数失败后的处理程序段.
READ_WRONG:	SETB P2.0      ;显示功能码A.
   AJMP READ_P                ;
;主程序结束.




;以下为单片机向主机发送数据的子程序,需要输入待发送的数据(51H地址为起始地址),
                              ;以及需要发送的数据个数(存在50H,不包括CRC_16校验码).
			      ;调用该子程序时会自动计算CRC_16结果并添加到数据块最后
			      ;并发送;40H为已经发送的数据个数计算存储器.
SEND:LCALL  CRC_16            ;根据待发送的内容及许发送的数据个数计算CRC_16.
   MOV    A,50H               ;取出需发送的数据个数.
   ADD    A,#51H              ;写入CRC_16结果的低字节.
   MOV    R1,A                ;
   MOV    @R1,4DH             ;
   INC    R1                  ;写入CRC_16结果的高字节.
   MOV    @R1,4EH             ;
   INC    50H                 ;需要发送的数据个数加2.
   INC    50H                 ;
   MOV    40H,#00H            ;已发送的数据清零. 
SEND_LOOP:	MOV    A,40H      ;计算待发送的数据地址.
   ADD    A,#51H              ;
   MOV    R1,A                ;
   MOV    A,@R1               ;
   MOV    SBUF,A              ;发送数据.
SEND_WAIT:JNB TI,SEND_WAIT    ;等待发送完毕.
   CLR    TI                  ;
   INC    40H                 ;
   MOV    A,40H               ;
   CJNE   A,50H,SEND_LOOP     ;
   RET                        ;
;发送子程序结束.
;以下为接收子程序.需要输入需接收的数据个数(存在50H中,不包含CRC_16的校验码),
                              ;当接收到指定个数时(接收过程有超时控制),该子程序会自动
     			      ;计算其CRC_16是否为0(正确),并返回接收成功或失败标志
			      ;(42H=100表示成功);41H用作已接收的数据个数计算.
RECE:MOV    42H,#100          ;置通讯成功标志.
   MOV    41H,#00H            ;已经接收的数据个数清零.
RECE_WAIT:MOV R7,#02          ;2006-09-19 21:00更改通讯超时为100ms,
RECE_L0:  MOV   R6,#200       ;
RECE_L1:  MOV   R5,#250       ;
RECE_L2:  JB    RI,RECE_NEXT  ;
   DJNZ   R5,RECE_L2          ;	
   DJNZ   R6,RECE_L1          ;
   DJNZ   R7,RECE_L0          ;
   MOV    42H,#00             ;置超时通讯失败标志.
RECE_NEXT:CLR   RI            ;清接收中断标志.
   MOV    A,41H               ;计算待接收的数据存放地址.
   ADD    A,#51H              ;
   MOV    R1,A                ;地址存放在R1中.
   MOV    A,SBUF              ;读取接收到的数据.
   MOV    @R1,A               ;
   INC    41H                 ;已接收的数据个数加1.
   MOV    A,41H               ;
   CJNE   A,50H,RECE_WAIT     ;
   LCALL  CRC_16              ;
   MOV    A,4EH               ;判断CRC_16结果中高字节是否位0.
   CJNE   A,#00H,RECE_WRONG   ;
   MOV    A,4DH               ;判断CRC_16结果中低字节是否位0.
   CJNE   A,#00H,RECE_WRONG   ;
   AJMP   RECE_OUT            ;
RECE_WRONG:MOV  42H,#00H      ;置通讯失败标志.
RECE_OUT:RET                  ;子程序结束.
;接收子程序结束.
;以下为进行CRC-16校验的子程序.
;CRC_16校验模块使用的存储器如下:
;51H,52H,53H,......:为要进行CRC_16校验的数据块,并且进行校验程序时总是将51H的内容
                              ;当第一字节,52H内容为第二字节,......
;50H:要进行CRC_16校验的数据块长度设定存储器.
;4FH:进行CRC_16校验时对已处理字节进行计数用存储器.
;4EH:CRC_16校验结果存储器的高字节.
;4DH:CRC_16校验结果存储器的低字节.
;4CH:进行CRC_16校验时对当前字节已移位次数进行记录的存储器.
CRC_16:MOV  4EH,#0FFH         ;CRC_16检验结果存储器的高位字节置全1.
   MOV   4DH,#0FFH            ;CRC_16检验结果存储器的低位字节置全1.
   MOV   4FH,#51H             ;已进行CRC_16处理的数据地址初始化.
;以下为对逐个数据进行CRC_16检验.
CRC_LOOP1:MOV 4CH,#00H        ;已对单字节进行移位的次数清零.
   MOV   R0,4FH               ;将要处理的数据地址赋值给R0.
   MOV   A,@R0                ;以R0中的内容为地址,取出该地址中的数据到A.
   XRL   4DH,A                ;单字节数据与CRC_16检验结果存储器中的低位进行异或,
	                      ;结果存入CRC_16存储器的低字节.
CRC_LOOP2:CLR   C             ;进位标志清零. 
   MOV   A,4EH                ;取出CRC_16检验结果存储器中的高字节.
   RRC   A                    ;带进位标志右移一位.
   MOV   4EH,A                ;将移位后的数据回传给CRC_16检验结果存储器中的高位.
   MOV   A,4DH                ;取出CRC_16检验结果存储器中的低字节.
   RRC   A                    ;带进位标志右移一位.
   MOV   4DH,A                ;将移位后的数据回传给CRC_16检验结果存储器中的低位.
   INC   4CH                  ;移位次数存储器加1.
   JC    CRC_CAL              ;如果移出的数为1则跳转到CRC_CAL.
   AJMP  CRC_NEXT             ;跳转到移位次数判断.
CRC_CAL:XRL 4EH,#10100000B    ;CRC_16存储器中高字节与多项式的高字节进行异或,
                              ;结果存入CRC_16存储器的高字节.
   XRL   4DH,#00000001B       ;CRC_16存储器中低字节与多项式的低字节进行异或,
                              ;结果存入CRC_16存储器的低字节.
CRC_NEXT:MOV A,4CH            ;移位次数判断.
   CJNE  A,#08,CRC_LOOP2      ;移位次数不到8则转移.
   INC   4FH                  ;已处理的数据地址加1.
   MOV   A,4FH                ;取出已处理的数据地址.
   SUBB  A,#51H               ;通过减法求实际已处理的数据个数. 
   CJNE  A,50H,CRC_LOOP1      ;数据处理个数不到预定值则转移继续处理.
   RET                        ;子程序返回.
;CRC_16子程序结束.
;以下为字型表:
;          0   1   2   3   4   5   6   7   8   9   P   A
TABLE:DB  192,249,164,176,153,146,130,248,128,144,140,136
    	END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -