?? 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 ;清接收中斷標志.
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 + -