📄 pic16c74_485.asm
字号:
;******************************************************************************
; *
; 文件名称:RS485通讯,PORTD输出.asm *
; 日期:2004-10-31 12:10 *
; 文件版本:V3.0 *
;;******************************************************************************
; 注意: 如果你要更改,请先保存本文件,然后新建立一个文件!!!!
; 说明: *
; 端口设置: *
; MAX485 通讯 *
; RC0-->/RE-->DE *
; RC6-->TXD-->DI ( MAX485: 1-RO 2-/RE 3-DE 4-DI 5-GND 6-A 7-B 8-VCC *
; RC7-->RXD-->RO *
;-----------------------------------------------------------------------------*
;
; D口为继电器输出口 *
; 输出高电位为打开,外面接光耦隔离继电器输出,继电器为直流24V供电. *
;
; 指令格式为:#AA(DATA)CR *
; 前导字符:# ,地址:AA,命令数据ATA,结束符:回车(ODH)-->CR,共6个字符 *
; (DATA)-- 00-FF *
; 00-FF 表示从D口输出的数据 *
; 要D口输出数据时返回输出的格式为:>AACR
; ****标准的ADAM4050、4060指令格式,共4个字符 *
;
;!!!!!!!! 必须注意在启动发送时,要给他延迟时间
;
; 本机地址为"01" *
; 60-65H-->接收存储区 *
; 66H开始为发送数据的存储区
; 使用了接收中断,使用发送中断 *
; 用TMR1做为接收时间限制, *
; 如果在固定时间(2ms)内没有接收到下一个字符,则接收计数器清0 *
; *
;******************************************************************************
LIST P=16C74,R=HEX
INCLUDE "P16C74.INC"
;------------------定义变量寄存器----------------------------------------------
W_TEMP EQU 0x020
S_TEMP EQU 0x021
MYSTATUS EQU 0x022 ;0--接收完毕;1-D口输出数据允许;
RC_CP EQU 0x023 ;接收数据个数的寄存器
RC_FSR EQU 0x024 ;接收到的数据存储的地址指针寄存器
TX_CP EQU 0x025 ;发送个数计数器
TX_FSR EQU 0x026 ;发送缓冲区的地址指针
COMMAND_BUF EQU 0x027 ;接收到的指令缓存寄存器
COMMAND EQU 0x028 ;命令寄存器
COMMAND_ASCII_L EQU 0x029 ;命令低4位的ASCII码
COMMAND_ASCII_H EQU 0x02A ;命令高4位的ASCII码
Delay256us_Reg EQU 0x02E ;定时器寄存器
Delay1ms_Reg EQU 0x02F ;定时器寄存器
;------------------定义字符常量------------------------------------------
RC_FSR_S EQU 0x060 ;接收存储区首地址
RC_CNT EQU 0x006 ;接收字符的个数
TX_FSR_S EQU 0x066 ;发送区首地址
START_RC EQU '#' ;0x23接收的前导字符
START_TX EQU '>' ;0x3E发送的前导字符
END_ASCII EQU 0x0D ;回车 发送的结束字符
ADDRESSH EQU '0' ;0x30 本机地址高字节
ADDRESSL EQU '1' ;0x31 本机地址底字节
;--------------------程序开始--------------------------------------------
ORG 0x0000
GOTO MAINLINE
ORG 0x0004
GOTO IntService
;----------------------------------------------------------------
;----------------------------------------------------------------
MAINLINE
CALL MAIN_INIT
MAINLOOP
CLRWDT
BCF STATUS,RP0
BTFSC MYSTATUS,0
CALL TEST_RCFIFO ;是,执行测试接收到的字符是否为本机命令,执行输出程序,和发送配制
BTFSC MYSTATUS,1 ;是否允许更新D口数据
CALL PORTD_OUT ;YES 将指令从D口输出
GOTO MAINLOOP
;----------------------------------------------------------------
;------------------查表程序---------------------
;----------------------------------------------------------------
ATH_TABEL
ADDWF PCL,F ;ASCII CHR
RETLW 0x000 ;0X30 ;0
RETLW 0x001 ;0x31 ;1
RETLW 0x002 ;0x32 ;2
RETLW 0x003 ;0x33 ;3
RETLW 0x004 ;0x34 ;4
RETLW 0x005 ;0x35 ;5
RETLW 0x006 ;0x36 ;6
RETLW 0x007 ;0x37 ;7
RETLW 0x008 ;0x38 ;8
RETLW 0x009 ;0x39 ;9
RETLW 0 ;0x3A ;:
RETLW 0 ;0x3B ;;
RETLW 0 ;0x3C ;<
RETLW 0 ;0x3D ;=
RETLW 0 ;0x3E ;>
RETLW 0 ;0x3F ;?
RETLW 0 ;0x40 ;@
RETLW 0x00A ;0x41 ;A
RETLW 0x00B ;0x42 ;B
RETLW 0x00C ;0x43 ;C
RETLW 0x00D ;0x44 ;D
RETLW 0x00E ;0x45 ;E
RETLW 0x00F ;0x46 ;F
;*******************************;程序初始化************************************
MAIN_INIT
;^^^^^^^^^^^^^^^^^^^^^^^^^^^各个功能寄存器设置^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
BANKSEL OPTION_REG ;BANK1
MOVLW B'00001111' ;下降沿触发,1:128用于WDT
MOVWF OPTION_REG ;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
BANKSEL TRISB ;
MOVLW B'11111111' ;
MOVWF TRISB ;PORTB IS INPUT
BCF TRISC,0 ;PORTC0 IS OUTPUT ,MAX485-->/RE-->DE
CLRF TRISD ;PORTD IS OUTPUT
BSF PIE1,RCIE ;允许接收中断
BANKSEL INTCON ;BANK 0
MOVLW B'11010000' ;
MOVWF INTCON ;开总中断,允许外围中断,INT中断
;^^^^^^^^^^^^^^^^^^^^^^^^^^^串口通讯设定^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UART_INIT
BANKSEL SPBRG ;BANK 1
MOVLW 0x019 ;4MHz
MOVWF SPBRG ;9600dps
BSF TXSTA,BRGH ;高速模式
BSF TXSTA,TXEN ;启动UART的传送功能,
BCF TRISC,6 ;TX,数据输出功能引脚
BSF TRISC,7 ;RX,数据接收功能引脚
BANKSEL RCSTA ;BANK 0
BSF RCSTA,CREN ;启动UART的接收功能,
BSF RCSTA,SPEN ;激活UART的全部功能,
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^其他寄存器设置^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
BCF PORTC,0 ;SET MAX485 IS 接收状态 ( PC.0=0 )
CLRF PORTD ;
MOVLW RC_FSR_S ;
MOVWF RC_FSR ;确定接收存储的首地址
CLRF RC_CP ;复位接收计数器
MOVLW TX_FSR_S ;
MOVWF TX_FSR ;确定发送存储的首地址
CLRF TX_CP ;复位发送计数器
CLRF COMMAND
RETURN
;====================中断服务程序=================================================
IntService:
MOVWF W_TEMP ;||||||||||
SWAPF STATUS,W ;||||||||||
MOVWF S_TEMP ;||||||||||保存现场
BANKSEL INTCON ;BANK 0
COLSEInt:
BCF INTCON,GIE
BTFSC INTCON,GIE
GOTO COLSEInt ;确认关闭了总中断则向下执行,否则继续关闭总中断.
BTFSC PIR1,RCIF ;判断是否为接收中断?是则执行<接收服务>程序.否则向下执行
CALL RC_Service
BANKSEL PIE1
BTFSS PIE1,TXIE
GOTO $+4
BANKSEL PIR1
BTFSC PIR1,TXIF ;判断是否为发送中断,是,执行TX中断服务
CALL TX_Service
BANKSEL PIR1
BTFSC PIR1,TMR1IF ;判断是否为定时器中断,是,执行定时器中断服务
CALL TMR1_Service
POP_S
BANKSEL S_TEMP
SWAPF S_TEMP,W ;|||||||||
MOVWF STATUS ;|||||||||
SWAPF W_TEMP,F ;|||||||||
SWAPF W_TEMP,W ;|||||||||恢复现场
RETFIE
;*********************************接收服务****************************
RC_Service
;PUT_RCFIFO ;接收队列,将接收到的数据保存起来,用来判断是不是发到本机的数据
BANKSEL RC_CP ;BANK 0
MOVF RC_CP,W
SUBLW RC_CNT
BTFSC STATUS,Z ;判断接收队列是否已经满了,
RETURN ;如果满了就退出本服务,否则向下执行
INCF RC_CP,F ;RC_CP+1 接收计数器+1
MOVF RC_FSR,W ;存储地址
MOVWF FSR ;设定间接寻址的目标寄存器为RC_FSR
MOVF RCREG,W ;RCDATA
MOVWF INDF ;SAVE DATA
INCF RC_FSR,F ;将地址指针加1
;****必须这么做的原因是:不这么做的时候,存储区的地址超出了他的范围,
;进入了后面的存储区域,造成程序错误.!!!!!!!!
;这样可以使存储区进行循环不会超出范围
MOVLW RC_CNT
ADDLW RC_FSR_S ;个数+首地址=结束地址+1.
SUBWF RC_FSR,W ;
BTFSS STATUS,Z ;判断是否存储区满?
GOTO SET_TMR1 ;否:执行接收超时设置
MOVLW RC_FSR_S ;是: 初始化接收存储器地址指针
MOVWF RC_FSR
BSF MYSTATUS,0 ;接收完成,放置自己的标志位
RETURN
SET_TMR1
BANKSEL TMR1L ;复位定时器,为定时器设置初值
MOVLW 0x00 ;定时为1ms,所以开始初值为"FC17" 大约为FC00
MOVWF TMR1L ;晶体震荡为4MHZ,每条指令为1us.
MOVLW 0xFC
MOVWF TMR1H
MOVLW B'00010001' ;打开TMR1定时器,1:2,为进行2ms延时
MOVWF T1CON ;工作在定时器方式
BANKSEL PIE1
BSF PIE1,TMR1IE ;启动接收计时器中断
BCF STATUS,RP0
RETURN
;********************************接收《判断服务》*********************************
TEST_RCFIFO
BANKSEL MYSTATUS
BCF MYSTATUS,0 ;清除标志位,防止重复调用
CLRF RC_CP ;CLEAR RC_CP 复位接收计数器,允许下次接收
BANKSEL PIE1
BCF PIE1,RCIE ;禁止接收中断
BCF PIE1,TMR1IE ;禁止接收定时器中断,
BCF STATUS,RP0
CLRF T1CON ;清除定时器内的数据,复位定时器
;~~~~~~~~~~~~ TEST START ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOVLW RC_FSR_S
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -