当前位置:首页 > 单片机 > 单片机
[导读] ;*******************************************************************************;*;*子程序名:USART_AINT.asm;*程序名称:通用同步和异步串行接收器和转发器(USART);*异步中断接收和发送通信程序;*

;*******************************************************************************
;*
;*子程序名:USART_AINT.asm
;*程序名称:通用同步和异步串行接收器和转发器(USART)

;*异步中断接收和发送通信程序
;*版本:1.0
;*适用MCU型号:AVR所有型号
;*使用资源:r5,r6,r16,r17,r18,r19,r20,r28,r29,r30,r31
;*定时器/计数器0(溢出中断)
;*
;*程序功能:
;*  本程序是通用同步和异步串行接收器和转发器(USART)在异步状态下使用中断
;*方式进行全双工接收和发送数据的通信程序。共包括下面列表中这四个子程序。这
;*四个子程序的具体使用方法请参考各自的说明。
;*┏───────────┳───────────────────────┓
;*┃子程序名称┃子程序功能描述┃
;*┣───────────╋───────────────────────┫
;*┃USART_AINT_INI┃USART异步通信中断接收和发送初始化┃
;*┣───────────╋───────────────────────┫
;*┃USART_INT_ACOM┃USART异步通信中断接收与发送协议命令和数据处理┃
;*┣───────────╋───────────────────────┫
;*┃USART_RXCINT┃USART异步通信接收结束中断处理┃
;*┣───────────╋───────────────────────┫
;*┃USART_TXDREINT┃USART异步通信数据寄存器空中断发送处理┃
;*┗───────────┻───────────────────────┛
;*
;*注意:
;*  ①.r5(USARTAI_RXNum)《接收作业次数寄存器》和r6(USARTAI_TXNum)
;*《发送作业次数寄存器》为全局寄存器变量,不得被其他程序使用,否则将导致接收
;*和发送的数据错误。
;*  ②.本程序共使用了3个中断向量,需在主程序中设置其中断向量转移地址,分
;*别为如下具体设置:
;*┏─────────────┳───────┳─────────────┓
;*┃中断名称┃中断向量地址┃中断处理程序┃
;*┣─────────────╋───────╋─────────────┫
;*┃USART接收结束中断┃URXCaddr┃USART_RXCINT┃
;*┣─────────────╋───────╋─────────────┫
;*┃USART数据寄存器空中断┃UDREaddr┃USART_TXDREINT┃
;*┣─────────────╋───────╋─────────────┫
;*┃T/C0溢出中断┃OVF0addr┃TC0_Timer_OVFINT┃
;*┗─────────────┻───────┻─────────────┛
;*
;*通信协议:
;*  ①.每次进行接收和发送的作业时均以协议命令来决定下一步操作方式,关于通信
;*协议命令的约定方法请见下述详细说明和命令字符串的具体定义。接收和发送的命令
;*的数据字节长度固定为10个字节,其格式定义如下:COM(命令起始标识字符串)+
;*设备编号(4个字节)+命令字(3个字节)。
;*  ②.接收或发送的数据帧格式:“8个数据位,1个停止位,使用奇校验”。注:如
;*需更改本程序的数据帧格式可在“USART_AINT_INI”子程序中进行修改。
;*  ③.本程序约定双方通信的波特率为“115.2Kbps”。注:如需更改本程序的通
;*信波特率可在“波特率(bps)常数定义”中进行设置,但双方通信的波特率受定时器/
;*计数器0定时时间的约束,如果要修改最小双方通信波特率,则需修改定时器/计数器
;*0的定时时间(减小最小波特率需延长定时时间,增大则缩短定时时间)。定时器/计
;*数器0的定时时间应略大于在约定双方通信的波特率下接收完255个字节所用的时间
;*总和,也不宜取得过大,过大则影响双方通信的速度。
;*  ④.接收和发送的数据时均以[命令>数据,命令>数据……]形式为作业方式进行
;*通信,但接收和发送的命令时可以任意形式进行通信。对于接收和发送的数据的校验方
;*法采用循环冗余检测(CRC)校验法,接收和发送的双方必须采用相同的校验算法,具
;*体的检测校验算法请参考子程序“Data_CRC_2Byte”中的具体说明。
;*  ⑤.每次接收和发送的数据总长度均不超过255个字节。而且每次接收或发送数据
;*的第一个字节为本次接收或发送的数据长度字符,最后两个字节为循环冗余检测校验字
;*节,因此每次接收和发送的有效数据长度均不得超过252个字节。,其计算公式如下:
;*数据长度数值=有效数据字节长度+3(1个长度字符本身+2个校验字节)
;*  ⑥.在发送数据前要向对方先发送一请求发送数据命令字符串“COMXXXXATX”,等待
;*对方回应一允许发送命令字符串“COMXXXXYET”的握手信号后,方可接着进行发送数据。
;*  ⑦.当接收到的数据或命令有错误时,可向对方发送要求重新发送命令字符串“CO
;*MXXXXRPT”,要求对方重新发送。对方在接收到此命令字符串后,依据上次发送的作业
;*类型来重新发送数据或命令。对于接收到的数据经循环冗余检测校验错误后,也可使用
;*重新发送一次允许发送命令字符串“COMXXXXYET”来要求对方重新发送数据。
;*  ⑧.当接收到的数据(不包括命令)经循环冗余检测校验正确后,必须向对方发送
;*一接收数据正确命令字符串“COMXXXXOKD”,来结束本次接收数据操作。如果对方不发
;*送收到此命令字符串“COMXXXXOKD”错误的信息(即发回“COMXXXXRPT”),不允许多
;*次发送此命令字符串,否则将导致接收数据错误。
;*  ⑨.本程序通信协议命令还包括了下面三个协议命令字符串,具体用法如下述:
;*“COMXXXXSTD”[要求对方发送指定数据],此命令用于启动双方对指定数据的收发
;*操作。
;*“COMXXXXRII”[要求对方重新初始化USART端口状态],此命令用于当通信协议命令
;*混乱,致使收发作业操作无法正常运行时,向对方发出从头再重新开始收发作业请求。
;*此命令也可用于双方开始通信前向对方发送开始通信命令使用,使双方的USART端口
;*均处于起始状态。
;*“COMXXXXYRI”[重新初始化USART端口状态完成],此命令用于通知对方,我方己可
;*以从头再重新开始收发作业。
;*  ⑩.“COMXXXXCIT”[从USART端口传送控制操作指令],此命令用于通知对方下
;*面接着发送的数据为控制操作指令字符串,其字符串的第一个字节也为数据长度字符,
;*但字符串的数值有无CRC校验码都可以,有CRC校验码时长度值相应也加2个。发送
;*和回应控制操作指令字符串的通信协议遵循发送数据方式。接收方在收到控制操作指令
;*字符串后,可能会发回三种回应协议命令:
;*⑴.无法正确识别控制操作指令字符串的内容,表示接收到的指令错误或受到干扰,将
;*发回要求对方重新发送命令字符串“COMXXXXRPT”。
;*⑵.己经完成了控制操作指令字符串的内容指定的操作程序,将发回接收数据正确命令
;*字符串“COMXXXXOKD”。
;*⑶.控制操作指令字符串的内容为要求向其发送指定的数据,将发回请求发送数据命令
;*字符串“COMXXXXATX”。
;*
;*注释: 
;*  ①.定时器/计数器0用于约束接收作业全部完成(指从接收第一个数据到最后一
;*个数据之间)的时间范围,如果在规定的时间内没有接收作业全部完成,则强制结束
;*此次接收作业,以便下次接收作业正确操作。其定时时间应略大于在约定双方通信的
;*波特率下接收完256个字节所用的时间总和。
;*  ②.当收发命令字符串“COMXXXXRPT”超过16次时,即双方接收和发送无论是数
;*据还是协议命令只要其错误总次数超过16次,那么就认为双方通信处于不同步状态,
;*或通信协议命令混乱。系统将会首先重新初始化本身的USART端口状态和数据处理状
;*态,然后向对方发送要求对方重新初始化USART端口状态命令字符串“COMXXXXRII”,
;*以使双方通信重新处于同步状态。
;*
;*******************************************************************************
;*
;*指令条数:1398+return
;*指令执行周期:0+return
;*低位寄存器使用:2(r5,r6)(注:此两个为全局寄存器变量,不得被其他程序使用)
;*高位寄存器使用:5(r16,r17,r18,r19,r20)
;*指针寄存器使用:Y,Z
;*
;*******************************************************************************

;********本程序需调用的子程序定义:

.include"DataCheck_CRC2B.asm";包括2字节数据循环冗余检测校验子程序


;********依据硬件设置需修改的SRAM存储地址定义:

.equUSARTAI_TXCOM=$0070;发送命令作业标志
.equDataUPD_TXALW=$0071;允许更新发送数据标志
.equUSARTAI_TXEnd=$0072;发送作业全部结束标志
.equUSARTAI_TXAPL=$0074;发送地址指针低字节
.equUSARTAI_TXAPH=$0075;发送地址指针高字节
.equUSARTAI_TXCOA=$0076;首个发送命令字符地址
;要再占用往下的10个字节位置
.equUSARTAI_TXDAA=$0080;首个发送数据地址
;要再占用往下的255个字节位置

.equUSARTAI_RXCOM=$0182;接收命令作业标志
.equDataUPD_RXALW=$0183;允许处理接收数据标志
.equUSARTAI_RXUPD=$0184;接收作业己更新标志
.equUSARTAI_RXEnd=$0185;接收作业全部结束标志
.equUSARTAI_RXAPL=$0186;接收作业地址指针低字节
.equUSARTAI_RXAPH=$0187;接收作业地址指针高字节
.equUSARTAI_RXCOA=$0188;首个接收命令字符地址
;要再占用往下的10个字节位置
.equUSARTAI_RXDAA=$0192;首个接收数据地址
;要再占用往下的255个字节位置

.equUSARTAI_ERRNum=$0293;USART发生收发错误次数计数器
.equUSARTAI_T0VNum=$0294;定时器/计数器0溢出次数计数器


;***波特率(bps)常数定义:
;下面波特率设置以单片机的时钟=11.0592MHz,且不打开倍速的条件下进行定义。
;波特率(bps)=115.2Kbps,误差=0.0%
.equUSARTAI_UBRRL=$05
.equUSARTAI_UBRRH=0

;***定时器/计数器0定时2秒常数定义:
;下面定时器/计数器0定时参数设置以 单片机 的时钟=11.0592MHz,且定时器/计数
;器0的预分频因子=1024进行的条件下定义。其计算公式如下:
;定时时间=1÷ 单片机 的时钟频率×1024×USARTAI_T0CNT×USARTAI_T0Num
.equUSARTAI_T0CNTI=$80;定时器/计数器0计数预定比例值
.equUSARTAI_T0NumI=$03;定时器/计数器0溢出次数值


;*******************************************************************************
;*
;*通用同步和异步串行接收器和转发器(USART)异步中断接收和发送通信程序:
;*
;*“USART_AINT_INI”---USART异步通信中断接收和发送初始化子程序
;*
;*“USART_RXCINT”------USART异步通信接收结束中断处理子程序。
;*
;*“USART_TXDREINT”----USART异步通信数据寄存器空中断发送处理子程序。
;*
;*“USART_INT_ACOM”----USART异步通信中断接收与发送协议命令和数据处理子程序
;*
;*******************************************************************************


;********全局程序寄存器变量定义(不得被其他程序使用):
.defUSARTAI_RXNum=r5;接收作业次数寄存器
.defUSARTAI_TXNum=r6;发送作业次数寄存器


;********本程序寄存器变量定义:

.defUSARTAI_TEMP=r16;暂存寄存器
.defUSARTAI_TEMP2=r17;暂存寄存器2
.defUSARTAI_TEMP3=r18;暂存寄存器3


;********本程序常数定义:

.equUSARTAI_TCOMI=$e0;发送命令作业标志值(11100000)
.equDataUPD_TALWI=$c0;允许更新发送数据标志值(11000000)
.equUSARTAI_TEndI=$f0;全部数据发送结束标志值(11110000)
.equUSARTAI_RCOMI=$07;接收命令作业标志值(00000111)
.equDataUPD_RALWI=$03;允许处理接收数据标志值(00000011)
.equUSARTAI_RUPDI=$0a;接收作业己更新标志值(00001010)
.equUSARTAI_REndI=$0f;全部数据接收结束标志值(00001111)
.equUSARTAI_ENALWI=$10;允许USART发生收发错误次数值(16次)
.equUSARTAI_CMATNI=$0a;收发命令的字符串总长度数值(10个)
.equUSARTAI_CMANI=$03;收发命令的有效字符串长度数值(3个)


;********程序指令代码清单:

;*******************************************************************************
;*
;*USART异步通信中断接收和发送初始化子程序 - “USART_AINT_INI”
;*
;*说明:
;*  本子程序用于初始化USART异步中断接收和发送通信。本初始化子程序只打开了
;*USART的中断接收功能,没有打开中断发送功能。
;*  本子程序只需在主程序中运行一次即可。除非释放RXD与TXD引脚功能作为其
;*他用途,如要再使用USART通信则需在主程序中再运行一次本子程序。
;*
;*******************************************************************************

USART_AINT_INI:
pushZL;压入寄存器中的数值到堆栈
pushZH
inZL,SREG;压状态寄存器中的标志值到堆栈
pushZL
ldiZL,USARTAI_TEndI;置发送作业全部结束标志值
stsUSARTAI_TXEnd,ZL
ldiZL,USARTAI_TCOMI;置发送命令作业标志值,首次发送一定为
stsUSARTAI_TXCOM,ZL;请求向对方发送或允许对方发送命令
clrZL;清除允许更新发送数据标志
stsDataUPD_TXALW,ZL
ldiZL,USARTAI_REndI;置接收作业全部结束标志值
stsUSARTAI_RXEnd,ZL
ldiZL,USARTAI_RCOMI;置接收命令作业标志值,首次接收一定为
stsUSARTAI_RXCOM,ZL;对方请求发送或对方允许发送命令
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
clrZL;清除允许处理接收数据标志
stsDataUPD_RXALW,ZL
clrZL;清除USART发生收发错误次数计数器值
stsUSARTAI_ERRNum,ZL
clrZL;清除定时器/计数器0溢出次数计数器值
stsUSARTAI_T0VNum,ZL
cli;禁止全局中断
ldiZL,USARTAI_UBRRL;设置通信波特率
outUBRRL,ZL
ldiZL,USARTAI_UBRRH
outUBRRH,ZL
ldiZL,(1<;设置帧格式:8个数据位,1个停止位,
;并使能奇校验。USART异步模式
;ldiZL,(1<;设置帧格式:8个数据位,2个停止位,
;并使能奇校验。USART异步模式
outUCSRC,ZL
ldiZL,(1<outUCSRB,ZL;接收器与发送器使能和接收结束中断使能
sei;打开全局中断
popZL
outSREG,ZL;弹出堆栈中的标志值到状态寄存器
popZH;弹出堆栈中的数值到寄存器
popZL
ret;子程序返回


;*******************************************************************************
;*
;*USART异步通信接收结束中断处理子程序 - “USART_RXCINT”
;*
;*说明:
;*  本子程序用于USART异步通信接收结束中断处理。
;*
;*SRAM中标志字节用法:
;*  入口标志:本子程序将检查这些标志,依据这些标志置值来控制不同接收作业。
;*接收作业全部结束(USARTAI_RXEnd)=$07(USARTAI_REndI)
;*≠$07(USARTAI_REndI)
;*r5---接收作业次数(USARTAI_RXNum)
;*  出口标志:①.接收作业全部正确接收完成后,将对下面这两个标志置值。
;*接收作业全部结束(USARTAI_RXEnd)=$0f(USARTAI_REndI)
;*接收作业己更新(USARTAI_RXUPD)=$0a(USARTAI_RUPDI)
;*r5---接收作业次数(USARTAI_RXNum)=$00
;*  ②.接收作业开始后(正在进行中),将对下面这两个标志置值。
;*接收作业全部结束(USARTAI_RXEnd)=$00
;*接收作业己更新(USARTAI_RXUPD)=$00
;*  ③.接收作业发生错误时,将对下面这两个标志置值。
;*接收作业全部结束(USARTAI_RXEnd)=$00
;*接收作业己更新(USARTAI_RXUPD)=$0a(USARTAI_RUPDI)
;*
;*******************************************************************************

USART_RXCINT:
pushUSARTAI_TEMP;压入寄存器中的数值到堆栈
pushZL
pushZH
inUSARTAI_TEMP,SREG;压状态寄存器中的标志值到堆栈
pushUSARTAI_TEMP
ldsUSARTAI_TEMP,USARTAI_RXEnd;检查接收作业是否己全部结束?
cpiUSARTAI_TEMP,USARTAI_REndI;否,则继续
breqUSART_RXCINT_First;是,就转至接收第一个字节处理
ldiZH,(1<inUSARTAI_TEMP,UCSRA;数据溢出(DOR)及奇偶校验错误(UPE)
andUSARTAI_TEMP,ZH;否,则继续
brneUSART_RXCINT_Error;是,就转至接收错误处理
ldsZL,USARTAI_RXAPL;置接收作业地址指针
ldsZH,USARTAI_RXAPH
inUSARTAI_TEMP,UDR;从USART数据寄存器取出接收数据
stZ,USARTAI_TEMP;存储进SRAM中
adiwZL,$01;接收作业地址指针+1
stsUSARTAI_RXAPL,ZL;存储回SRAM中
stsUSARTAI_RXAPH,ZH
decUSARTAI_RXNum;全部接收作业完毕否?
breqUSART_RXCINT_End;是,就转至结束处理
rjmpUSART_RXCINT_RET;否,转到中断返回
USART_RXCINT_End:
ldiZL,USARTAI_REndI;置接收作业全部结束标志值
stsUSARTAI_RXEnd,ZL
ldiZL,USARTAI_RUPDI;置接收作业己更新标志值
stsUSARTAI_RXUPD,ZL
ldiZH,(1<comZH;注:仅只改变T/C中断屏蔽寄存
inZL,TIMSK;器中的此项设置,对于其他T/C
andZL,ZH;中断状态保留原来设置
outTIMSK,ZL
rjmpUSART_RXCINT_RET;转到中断返回
USART_RXCINT_Error:
ldiZH,(1<comZH;注:仅只改变T/C中断屏蔽寄存
inZL,TIMSK;器中的此项设置,对于其他T/C
andZL,ZH;中断状态保留原来设置
outTIMSK,ZL
inUSARTAI_TEMP,UDR;读USART数据寄存器使RXC标志清除,
;以结束本次USART接收结束中断处理
ldiZL,USARTAI_RUPDI;置接收作业己更新标志值
stsUSARTAI_RXUPD,ZL
rjmpUSART_RXCINT_RET;转到中断返回
USART_RXCINT_First:
clrZL;清除接收作业全部结束标志
stsUSARTAI_RXEnd,ZL
stsUSARTAI_T0VNum,ZL;定时器/计数器0溢出次数清0
inZL,TIFR;清除T/C0计数溢出标志
oriZL,(1<outTIFR,ZL;器中的此项标志,对于其他T/C
;中断标志保留原来状态
ldiZL,USARTAI_T0CNTI;置T/C0定时参数的预定计数比例值
outTCNT0,ZL
inZL,TIMSK;使能T/C0计数溢出中断
oriZL,(1<outTIMSK,ZL;器中的此项设置,对于其他T/C
;中断状态保留原来设置
ldiZL,(1<outTCCR0,ZL;按CK÷1024预分频因子启动T/C0
ldsZL,USARTAI_RXCOM;接收作业是否为接收命令
cpiZL,USARTAI_RCOMI;否,则为接收数据
breqUSART_RXCINT_FCOMM;是,就转至接收命令处理
USART_RXCINT_FData:
ldiZL,Low(USARTAI_RXDAA);置接收作业地址指针为
ldiZH,High(USARTAI_RXDAA);首个接收数据地址指针
inUSARTAI_TEMP,UDR;从USART数据寄存器取出接收数据
stZ,USARTAI_TEMP;存储进SRAM中
adiwZL,$01;接收作业地址指针+1
stsUSARTAI_RXAPL,ZL;存储回SRAM中
stsUSARTAI_RXAPH,ZH
MOV USARTAI_RXNum,USARTAI_TEMP;置接收作业次数计数器初值
decUSARTAI_RXNum;接收作业次数-1
rjmpUSART_RXCINT_RET;转到中断返回
USART_RXCINT_FCOMM:
ldiZL,Low(USARTAI_RXCOA);置接收作业地址指针为
ldiZH,High(USARTAI_RXCOA);首个接收命令地址指针
inUSARTAI_TEMP,UDR;从USART数据寄存器取出接收数据
stZ,USARTAI_TEMP;存储进SRAM中
adiwZL,$01;接收作业地址指针+1
stsUSARTAI_RXAPL,ZL;存储回SRAM中
stsUSARTAI_RXAPH,ZH
ldiUSARTAI_TEMP,(USARTAI_CMATNI-1)
;置接收作业次数计数器初值,
MOV USARTAI_RXNum,USARTAI_TEMP;第一个命令的字符串己接收
USART_RXCINT_RET:
popUSARTAI_TEMP;弹出堆栈中的标志值到状态寄存器
outSREG,USARTAI_TEMP
popZH;弹出堆栈中的数值到寄存器
popZL
popUSARTAI_TEMP
reti;中断返回


;*******************************************************************************
;*
;*USART异步通信数据寄存器空中断发送处理子程序 - “USART_TXDREINT”
;*
;*说明:
;*  本子程序用于USART异步通信数据寄存器空中断发送处理。
;*
;*注意:
;*  发送作业全部结束后,将禁止USART数据寄存器空中断操作。
;*
;*SRAM中标志字节用法:
;*  入口标志:本子程序将检查这些标志,依据这些标志置值来控制不同发送作业。
;*r6---发送作业次数(USARTAI_TXNum)
;*  出口标志:发送作业全部正确发送完成后,将对下面这两个标志置值。
;*发送作业全部结束(USARTAI_TXEnd)=$f0(USARTAI_TEndI)
;*r6---发送作业次数(USARTAI_TXNum)=$00
;*
;*******************************************************************************

USART_TXDREINT:
pushUSARTAI_TEMP;压入寄存器中的数值到堆栈
pushZL
pushZH
inUSARTAI_TEMP,SREG;压状态寄存器中的标志值到堆栈
pushUSARTAI_TEMP
ldsZL,USARTAI_TXAPL;置发送作业地址指针
ldsZH,USARTAI_TXAPH
ldUSARTAI_TEMP,Z;从SRAM中取出发送字节,
outUDR,USARTAI_TEMP;送入USART数据寄存器
adiwZL,$01;发送作业地址指针+1
stsUSARTAI_TXAPL,ZL;存储回SRAM中
stsUSARTAI_TXAPH,ZH
decUSARTAI_TXNum;发送作业全部完毕否?
brneUSART_TXDREINT1;否,转到中断返回
ldiUSARTAI_TEMP,USARTAI_TEndI;置发送作业全部结束标志值
stsUSARTAI_TXEnd,USARTAI_TEMP
cbiUCSRB,UDRIE;禁止USART数据寄存器空中断
USART_TXDREINT1:
popUSARTAI_TEMP;弹出堆栈中的标志值到状态寄存器
outSREG,USARTAI_TEMP
popZH;弹出堆栈中的数值到寄存器
popZL
popUSARTAI_TEMP
reti;中断返回


;*******************************************************************************
;*
;*USART异步通信数据寄存器空中断发送处理初始化子程序 - “USART_AINT_TXINI”
;*
;*说明:
;*  本子程序用于初始化USART异步通信数据寄存器空中断发送处理。
;*
;*注意:
;*  1.在运行本程序前必须先运行“USART_AINT_INI”子程序。
;*  2.在运行本程序前必须先将要发送的数据块复制到SRAM相应的存储区中。
;*  3.本子程序运行后,将立即启动数据寄存器空中断,进行发送作业。
;*
;*SRAM中标志字节用法:
;*  入口标志:本子程序将检查这些标志,依据这些标志置值来控制不同发送作业。
;*发送命令作业(USARTAI_TXCOM)=$e0(USARTAI_TCOMI)
;*  出口标志:本子程序运行后,将对下面这两个标志置值。
;*发送作业全部结束(USARTAI_TXEnd)=$00
;*r6---发送作业次数(USARTAI_TXNum)=发送的首个字节
;*
;*******************************************************************************

USART_AINT_TXINI:
clrZL;清除全部数据发送结束标志
stsUSARTAI_TXEnd,ZL
ldsZL,USARTAI_TXCOM;发送任务是否为发送命令
cpiZL,USARTAI_TCOMI;否,则为发送数据
breqUSART_AINT_TXINI1;是,就转至发送命令处理
ldiZL,Low(USARTAI_TXDAA);置首个发送地址指针为发送数据初值
ldiZH,High(USARTAI_TXDAA);发送的首个数据为本次发送作业次数
stsUSARTAI_TXAPL,ZL
stsUSARTAI_TXAPH,ZH
ldUSARTAI_TXNum,Z;置发送作业次数计数器初值
rjmpUSART_AINT_TXINI2
USART_AINT_TXINI1:
ldiZL,Low(USARTAI_TXCOA);置首个发送地址指针为发送命令初值
ldiZH,High(USARTAI_TXCOA);发送的首个命令为本次发送作业次数
stsUSARTAI_TXAPL,ZL
stsUSARTAI_TXAPH,ZH
ldiUSARTAI_TEMP,USARTAI_CMATNI;置发送作业次数计数器初值
MOV USARTAI_TXNum,USARTAI_TEMP;注:发送命令作业为固定次数
USART_AINT_TXINI2:
ldiZL,(1<outUCSRB,ZL;接收器与发送器使能和接收结束中断、
;与USART数据寄存器空中断使能
ret;子程序返回


;*******************************************************************************
;*
;*向USART端口发送通信协议命令子程序清单
;*
;*说明:
;*  本子程序用于向USART端口发送通信协议命令。调用这些子程序后,将立即
;*启动该命令的发送作业。共包括下列这些独立的子程序。
;*
;*  向端口发送[向对方请求发送]命令---------“USART_TX_COMM_AskTX”
;*  向端口发送[允许对方发送]命令-----------“USART_TX_COMM_OKRX”
;*  向端口发送[要求对方重新发送]命令-------“USART_TX_COMM_REPTX”
;*  向端口发送[接收数据正确]命令-----------“USART_TX_COMM_DataOK”
;*  向端口发送[要求对方发送指定数据]命令---“USART_TX_COMM_DCOMTX”
;*  向端口发送[要求对方重新初始化]命令-----“USART_TX_COMM_REPINI”
;*  向端口发送[重新初始化完成]命令---------“USART_TX_COMM_RINIOK”
;*
;*******************************************************************************


;***此段程序用于发送[重新初始化完成]命令 - “USART_TX_COMM_RINIOK”
USART_TX_COMM_RINIOK:
rcallUSART_TXD_COMM_Head;将开头字符串和端口编号复制到SRAM中
ldiZL,Low(USART_RINIOK*2);置Z指针为重新初始化完成命令字符串,
ldiZH,High(USART_RINIOK*2);在FLASH中的存储地址
rcallUSART_TXD_COMM_COM;将命令字符串复制到SRAM的发送地址中,
;并置发送命令作业标志值
rcallUSART_AINT_TXINI;发送本命令字符串
ret;子程序返回

;***此段程序用于发送[要求对方重新初始化]命令 - “USART_TX_COMM_REPINI”
USART_TX_COMM_REPINI:
rcallUSART_TXD_COMM_Head;将开头字符串和端口编号复制到SRAM中
ldiZL,Low(USART_REPINI*2);置Z指针为要求对方重新初始化命令字符串,
ldiZH,High(USART_REPINI*2);在FLASH中的存储地址
rcallUSART_TXD_COMM_COM;将命令字符串复制到SRAM的发送地址中,
;并置发送命令作业标志值
rcallUSART_AINT_TXINI;发送本命令字符串
ret;子程序返回

;***此段程序用于发送[向对方请求发送]命令 - “USART_TX_COMM_AskTX”
USART_TX_COMM_AskTX:
rcallUSART_TXD_COMM_Head;将开头字符串和端口编号复制到SRAM中
ldiZL,Low(USART_AskTX*2);置Z指针为向对方请求发送命令字符串,
ldiZH,High(USART_AskTX*2);在FLASH中的存储地址
rcallUSART_TXD_COMM_COM;将命令字符串复制到SRAM的发送地址中,
;并置发送命令作业标志值
rcallUSART_AINT_TXINI;发送本命令字符串
ret;子程序返回

;***此段程序用于发送[允许对方发送]命令 - “USART_TX_COMM_OKRX”
USART_TX_COMM_OKRX:
rcallUSART_TXD_COMM_Head;将开头字符串和端口编号复制到SRAM中
ldiZL,Low(USART_OKRX*2);置Z指针为向对方请求发送命令字符串,
ldiZH,High(USART_OKRX*2);在FLASH中的存储地址

rcallUSART_TXD_COMM_COM;将命令字符串复制到SRAM的发送地址中,
;并置发送命令作业标志值
rcallUSART_AINT_TXINI;发送本命令字符串
ret;子程序返回

;***此段程序用于发送[要求对方重新发送]命令 - “USART_TX_COMM_REPTX”
USART_TX_COMM_REPTX:
rcallUSART_TXD_COMM_Head;将开头字符串和端口编号复制到SRAM中
ldiZL,Low(USART_REPTX*2);置Z指针为向对方请求发送命令字符串,
ldiZH,High(USART_REPTX*2);在FLASH中的存储地址
rcallUSART_TXD_COMM_COM;将命令字符串复制到SRAM的发送地址中,
;并置发送命令作业标志值
rcallUSART_AINT_TXINI;发送本命令字符串
ret;子程序返回

;***此段程序用于发送[接收数据正确]命令 - “USART_TX_COMM_DataOK”
USART_TX_COMM_DataOK:
rcallUSART_TXD_COMM_Head;将开头字符串和端口编号复制到SRAM中
ldiZL,Low(USART_DataOK*2);置Z指针为向对方请求发送命令字符串,
ldiZH,High(USART_DataOK*2);在FLASH中的存储地址
rcallUSART_TXD_COMM_COM;将命令字符串复制到SRAM的发送地址中,
;并置发送命令作业标志值
rcallUSART_AINT_TXINI;发送本命令字符串
ret;子程序返回

;***此段程序用于发送[要求对方发送指定数据]命令 - “USART_TX_COMM_DCOMTX”
USART_TX_COMM_DCOMTX:
rcallUSART_TXD_COMM_Head;将开头字符串和端口编号复制到SRAM中
ldiZL,Low(USART_DCOMTX*2);置Z指针为向对方请求发送命令字符串,
ldiZH,High(USART_DCOMTX*2);在FLASH中的存储地址
rcallUSART_TXD_COMM_COM;将命令字符串复制到SRAM的发送地址中,
;并置发送命令作业标志值
rcallUSART_AINT_TXINI;发送本命令字符串
ret;子程序返回

;***此段程序用于发送命令开头字符串和端口编号 - “USART_TXD_COMM_Head”
USART_TXD_COMM_Head:
ldiYL,Low(USARTAI_TXCOA);置Y指针为发送命令SRAM中的地址
ldiYH,High(USARTAI_TXCOA)
ldiZL,Low(COMAgreement_Head*2);置Z指针为向发送命令开头字符串,
ldiZH,High(COMAgreement_Head*2);在FLASH中的存储地址
lpmUSARTAI_TEMP3,Z+;置循环计数器初值=开头命令字长度数值
USART_TXD_COMM_Head1:
lpmUSARTAI_TEMP,Z+;从FLASH中取出发送命令开头字符串
stY+,USARTAI_TEMP;装入SRAM的发送命令地址中
decUSARTAI_TEMP3;命令字长度数值—1
brneUSART_TXD_COMM_Head1;装入完成否?
USART_TXD_COMM_HeadDN:
ldiEEPROM_AddrL,Low(CC_EEPROM_DNAr)
ldiEEPROM_AddrH,High(CC_EEPROM_DNAr)
;置在EEPROM中的本端口编号地址指针
ldiUSARTAI_TEMP3,CTRLCDN_CharNI;置循环计数器初值=本端口编号长度数值
USART_TXD_COMM_HeadDN1:
callEEPROM_ReadSingle;读取EEPROM中的本USART端口编号
MOV USARTAI_TEMP2,EEPROM_Data
stY+,USARTAI_TEMP2;装入SRAM的发送命令地址中
adiwEEPROM_AddrL,$01;EEPROM中的端口编号地址指针+1
decUSARTAI_TEMP3;端口编号字符串长度数值长度数值—1
brneUSART_TXD_COMM_HeadDN1;端口编号装入完否?未完,则继续装入
ret;子程序返回

;***此段程序用于发送命令字符串公共子程序 - “USART_TXD_COMM_COM”
USART_TXD_COMM_COM:
lpmUSARTAI_TEMP,Z+;从FLASH中取出首个发送命令字符
stY+,USARTAI_TEMP;装入SRAM的发送命令地址中
lpmUSARTAI_TEMP,Z+;从FLASH中取出下一个发送命令字符
stY+,USARTAI_TEMP;装入SRAM的发送命令地址中
lpmUSARTAI_TEMP,Z+;从FLASH中取出下一个发送命令字符
stY+,USARTAI_TEMP;装入SRAM的发送命令地址中
ldiUSARTAI_TEMP,USARTAI_TCOMI;置发送命令作业标志值
stsUSARTAI_TXCOM,USARTAI_TEMP
ret;子程序返回


;*******************************************************************************
;*
;*从USART端口上接收到的通信协议命令处理子程序 - “USART_RXD_COMM”
;*
;*说明:
;*  本子程序用于从USART端口上接收到的通信协议命令处理。
;*  本子程序要在主程序中不间断循环查询运行。
;*
;*******************************************************************************

USART_RXD_COMM:
ldsZL,USARTAI_RXUPD;检查接收作业是否己更新?
cpiZL,USARTAI_RUPDI;否,直接返回
breqUSART_RXD_COMMTO1;是,则继续
rjmpUSART_RXD_COMM_RET
USART_RXD_COMMTO1:
ldsZL,USARTAI_RXCOM;检查接收作业是否为接收命令?
cpiZL,USARTAI_RCOMI;否,直接返回
breqUSART_RXD_COMMTO2;是,则继续
rjmpUSART_RXD_COMM_RET
USART_RXD_COMMTO2:
ldsZL,USARTAI_RXEnd;检查接收作业是否全部结束?
cpiZL,USARTAI_REndI;否,转至接收错误处理
breqUSART_RXD_COM_CAHead;是,则继续
rjmpUSART_RXD_COMM_Error
USART_RXD_COM_CAHead:
ldiYL,Low(USARTAI_RXCOA);置首个接收命令字符地址指针
ldiYH,High(USARTAI_RXCOA)
ldiZL,Low(COMAgreement_Head*2);置通信协议命令开头标识字符串地址指针
ldiZH,High(COMAgreement_Head*2)
lpmUSARTAI_TEMP,Z+;置循环计数器初值=开头命令字长度数值
MOV CTRLCOM_CNT,USARTAI_TEMP
rcallCTRLCOMM_IdentifyCOM;识别通信协议命令开头标识字符串
MOV USARTAI_TEMP,CCTSSDV_Right
cpiUSARTAI_TEMP,CCTSSDV_RightI;检查接收字节是否为命令开头标识字符?
breqUSART_RXD_COM_EAddr;是,则继续
rjmpUSART_RXD_COMM_Error;否,转至接收错误处理
USART_RXD_COM_EAddr:
ldiZL,Low(COMAgreement_Head*2);置通信协议命令开头标识字符串地址指针
ldiZH,High(COMAgreement_Head*2)
lpmUSARTAI_TEMP2,Z+;读取开头命令字长度数值
clrUSARTAI_TEMP
addYL,USARTAI_TEMP2;置Y指针为本端口编号字符串的地址指针
adcYH,USARTAI_TEMP
ldiUSARTAI_TEMP3,CTRLCDN_CharNI;置循环计数器初值=本端口编号长度数值
ldiEEPROM_AddrL,Low(CC_EEPROM_DNAr)
ldiEEPROM_AddrH,High(CC_EEPROM_DNAr)
;置在EEPROM中的本端口编号地址指针
USART_RXD_COM_EAddr1:
callEEPROM_ReadSingle;读取EEPROM中的本USART端口编号
MOV USARTAI_TEMP2,EEPROM_Data
ldUSARTAI_TEMP,Y+
cpUSARTAI_TEMP,USARTAI_TEMP2;检查是否为本USART端口编号?
brneUSART_RXD_COM_EAddr2;否,转至非本USART端口编号处理
adiwEEPROM_AddrL,$01;EEPROM中的端口编号地址指针+1
decUSARTAI_TEMP3;端口编号字符串长度数值长度数值—1
brneUSART_RXD_COM_EAddr1;端口编号识别完否?未完,则继续识别
rjmpUSART_RXD_COMM1
USART_RXD_COM_EAddr2:
rjmpUSART_RXD_COMM_NOADDR
USART_RXD_COMM1:
ldiZL,Low(USART_AskTX*2);置“向我方请求发送数据”命令地址指针
ldiZH,High(USART_AskTX*2)
ldiCTRLCOM_CNT,USARTAI_CMANI;置计数器初值=有效命令字长度数值
rcallCTRLCOMM_IdentifyCOM;对此条命令进行识别
cpiCCTSSDV_Right,CCTSSDV_RightI;命令是否为“向我方请求发送数据”?
brneUSART_RXD_COMM2;否,则继续
rcallUSART_RX_COMM_AskTX;是,调用处理此条命令处理程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM2:
ldiZL,Low(USART_DataOK*2);置“对方接收数据正确”命令地址指针
ldiZH,High(USART_DataOK*2)
ldiCTRLCOM_CNT,USARTAI_CMANI;置计数器初值=有效命令字长度数值
rcallCTRLCOMM_IdentifyCOM;对此条命令进行识别
cpiCCTSSDV_Right,CCTSSDV_RightI;命令是否为“对方接收数据正确”?
brneUSART_RXD_COMM3;否,则继续
rcallUSART_RX_COMM_DataOK;是,调用处理此条命令处理程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM3:
ldiZL,Low(USART_REPTX*2);置“要求我方重新发送”命令地址指针
ldiZH,High(USART_REPTX*2)
ldiCTRLCOM_CNT,USARTAI_CMANI;置计数器初值=有效命令字长度数值
rcallCTRLCOMM_IdentifyCOM;对此条命令进行识别
cpiCCTSSDV_Right,CCTSSDV_RightI;命令是否为“要求我方重新发送”?
brneUSART_RXD_COMM4;否,则继续
rcallUSART_RX_COMM_REPTX;是,调用处理此条命令处理程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM4:
ldiZL,Low(USART_DCOMTX*2);置“要求我方发送指定数据”命令地址指针
ldiZH,High(USART_DCOMTX*2)
ldiCTRLCOM_CNT,USARTAI_CMANI;置计数器初值=有效命令字长度数值
rcallCTRLCOMM_IdentifyCOM;对此条命令进行识别
cpiCCTSSDV_Right,CCTSSDV_RightI;命令是否为“要求我方发送指定数据”?
brneUSART_RXD_COMM5;否,则继续
rcallUSART_RX_COMM_DCOMTX;是,调用处理此条命令处理程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM5:
ldiZL,Low(USART_OKRX*2);置“允许我方发送数据”命令地址指针
ldiZH,High(USART_OKRX*2)
ldiCTRLCOM_CNT,USARTAI_CMANI;置计数器初值=有效命令字长度数值
rcallCTRLCOMM_IdentifyCOM;对此条命令进行识别
cpiCCTSSDV_Right,CCTSSDV_RightI;命令是否为“允许我方发送数据”?
brneUSART_RXD_COMM6;否,则继续
rcallUSART_RX_COMM_OKRX;是,调用处理此条命令处理程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM6:
ldiZL,Low(USART_REPINI*2);置“要求我方重新初始化”命令地址指针
ldiZH,High(USART_REPINI*2)
ldiCTRLCOM_CNT,USARTAI_CMANI;置计数器初值=有效命令字长度数值
rcallCTRLCOMM_IdentifyCOM;对此条命令进行识别
cpiCCTSSDV_Right,CCTSSDV_RightI;命令是否为“要求我方重新初始化”?
brneUSART_RXD_COMM7;否,则继续
rcallUSART_RX_COMM_REPINI;是,调用处理此条命令处理程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM7:
ldiZL,Low(USART_RINIOK*2);置“对方重新初始化完成”命令地址指针
ldiZH,High(USART_RINIOK*2)
ldiCTRLCOM_CNT,USARTAI_CMANI;置计数器初值=有效命令字长度数值
rcallCTRLCOMM_IdentifyCOM;对此条命令进行识别
cpiCCTSSDV_Right,CCTSSDV_RightI;命令是否为“对方重新初始化完成”?
brneUSART_RXD_COMM8;否,则继续
rcallUSART_RX_COMM_RINIOK;是,调用处理此条命令处理程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM8:
ldiZL,Low(USART_CTRLCOM*2);置“传送控制操作指令”命令地址指针
ldiZH,High(USART_CTRLCOM*2)
ldiCTRLCOM_CNT,USARTAI_CMANI;置计数器初值=有效命令字长度数值
rcallCTRLCOMM_IdentifyCOM;对此条命令进行识别
cpiCCTSSDV_Right,CCTSSDV_RightI;命令是否为“传送控制操作指令”?
brneUSART_RXD_COMM_Error;否,转至接收错误处理
rcallUSART_RX_COMM_CTRLCOM;是,调用处理此条命令处理程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM_Error:
rcallUSART_RXD_Error;调用接收错误处理子程序
rjmpUSART_RXD_COMM_RET
USART_RXD_COMM_NOADDR:
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
USART_RXD_COMM_RET:
ret;子程序返回


;***此段程序用于接收到[传送控制操作指令]命令处理
USART_RX_COMM_CTRLCOM:
ldsZL,DataUPD_RXALW;接收数据是否己处理?
cpiZL,DataUPD_RALWI;是,继续
breqUSART_RX_COMM_CTRLCOM_RET;否,返回,等待处理接收数据
ldsZL,USARTAI_TXEnd;发送作业是否全部结束?
cpiZL,USARTAI_TEndI;是,继续
brneUSART_RX_COMM_CTRLCOM_RET;否,返回,等待发送作业结束
ldsZL,CTRLCOM_MALWS;是否有正在处理控制操作指令?
cpiZL,CTRLCOM_MALWSI;否,继续
breqUSART_RX_COMM_CTRLCOM_RET;是,返回,等待处理控制操作指令结束
rcallUSART_TX_COMM_OKRX;向对方发送“允许对方发送”命令
clrZL;清除接收命令作业标志
stsUSARTAI_RXCOM,ZL
ldiZL,CTRLCOM_MALWSI;置允许处理控制操作指令标志值
stsCTRLCOM_MALWS,ZL
ldiZL,CCTSSDV_USARTI;置控制操作指令发送者标志值
stsCCOM_TSourceS,ZL;为USART端口送来控制操作指令
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
USART_RX_COMM_CTRLCOM_RET:
ret;子程序返回

;***此段程序用于接收到[重新初始化完成]命令处理
USART_RX_COMM_RINIOK:
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
ret;子程序返回

;***此段程序用于接收到[要求对方重新初始化]命令处理
USART_RX_COMM_REPINI:
ldiZH,(1<comZH;禁止接收器和发送器,禁止USART
inZL,UCSRB;接收结束中断和数据寄存器空中断
andZL,ZH
outUCSRB,ZL


;此处插入从头开始重新进行数据处理操作程序


ldiZH,(1<comZH;清除帧错误(FE)、数据溢出(DOR)
inZL,UCSRA;及奇偶校验错误(UPE)标志
andZL,ZH
outUCSRA,ZL
ldiZH,(1<inZL,UCSRA;置数据寄存器空(UDRE)标志
orZL,ZH
outUCSRA,ZL
rcallUSART_AINT_INI;重新初始化USART异步中断接收和发送
rcallUSART_TX_COMM_RINIOK;向对方发送“重新初始化完成”命令
ret;子程序返回

;***此段程序用于接收到[向对方请求发送]命令处理
USART_RX_COMM_AskTX:
ldsZL,DataUPD_RXALW;接收数据是否己处理?
cpiZL,DataUPD_RALWI;是,继续
breqUSART_RX_COMM_AskTX_RET;否,返回,等待处理接收数据
ldsZL,USARTAI_TXEnd;发送作业是否全部结束?
cpiZL,USARTAI_TEndI;是,继续
brneUSART_RX_COMM_AskTX_RET;否,返回,等待发送作业结束
rcallUSART_TX_COMM_OKRX;向对方发送“允许对方发送”命令
clrZL;清除接收命令作业标志
stsUSARTAI_RXCOM,ZL
ldiZL,DataUPD_RALWI;置允许处理接收数据标志值
stsDataUPD_RXALW,ZL
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
USART_RX_COMM_AskTX_RET:
ret;子程序返回

;***此段程序用于接收到[允许对方发送]命令处理
USART_RX_COMM_OKRX:
ldsZL,DataUPD_TXALW;发送数据是否己更新?
cpiZL,DataUPD_TALWI;是,继续
breqUSART_RX_COMM_OKRX_RET;否,返回,等待更新发送数据
ldsZL,USARTAI_TXEnd;发送作业是否全部结束?
cpiZL,USARTAI_TEndI;是,继续
brneUSART_RX_COMM_OKRX_RET;否,返回,等待发送作业结束
clrZL;清除发送命令作业标志
stsUSARTAI_TXCOM,ZL
rcallUSART_AINT_TXINI;启动发送数据
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
USART_RX_COMM_OKRX_RET:
ret;子程序返回

;***此段程序用于接收到[要求对方重新发送]命令处理
USART_RX_COMM_REPTX:
ldsZL,USARTAI_ERRNum;USART发生收发错误次数是否超过允许次数?
cpiZL,USARTAI_ENALWI;是,转至USART通信发生错误处理
brloUSART_RX_COMM_REPTX1;否,继续
rcallUSART_Error;调用USART通信发生错误处理程序
rjmpUSART_RX_COMM_REPTX_RET;返回
USART_RX_COMM_REPTX1:
ldsZL,USARTAI_TXEnd;发送作业是否全部结束?
cpiZL,USARTAI_TEndI;是,继续
brneUSART_RX_COMM_REPTX_RET;否,返回,等待发送作业结束
rcallUSART_AINT_TXINI;重新启动原发送作业
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
ldsZL,USARTAI_ERRNum;USART发生收发错误次数+1
incZL
stsUSARTAI_ERRNum,ZL
USART_RX_COMM_REPTX_RET:
ret;子程序返回

;***此段程序用于接收到[接收数据正确]命令处理
USART_RX_COMM_DataOK:
ldiZL,USARTAI_TCOMI;置发送命令作业标志值
stsUSARTAI_TXCOM,ZL
ldiZL,DataUPD_TALWI;置允许更新发送数据标志值
stsDataUPD_TXALW,ZL
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
ret;子程序返回

;***此段程序用于接收到[要求对方发送指定数据]命令处理
USART_RX_COMM_DCOMTX:
ldiZL,DataUPD_TALWI;置允许更新发送数据标志值
stsDataUPD_TXALW,ZL
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
USART_RX_COMM_DCOMTX_RET:
ret;子程序返回

;***此段程序用于“USART接收器错误”和“接收命令或数据错误”处理
USART_RXD_Error:
ldsZL,USARTAI_ERRNum;USART发生收发错误次数是否超过允许次数?
cpiZL,USARTAI_ENALWI;是,转至USART通信发生错误处理
brloUSART_RXD_Error1;否,继续
rcallUSART_Error;调用USART通信发生错误处理程序
rjmpUSART_RXD_Error_RET;返回
USART_RXD_Error1:
ldsZL,USARTAI_TXEnd;发送作业是否全部结束?
cpiZL,USARTAI_TEndI;是,继续
brneUSART_RXD_Error_RET;否,返回,等待发送作业结束
rcallUSART_TX_COMM_REPTX;向对方发送“要求重新发送”命令
ldiZH,(1<comZH;清除帧错误(FE)、数据溢出(DOR)
inZL,UCSRA;及奇偶校验错误(UPE)标志
andZL,ZH
outUCSRA,ZL
ldiZL,USARTAI_REndI;置接收作业全部结束标志值
stsUSARTAI_RXEnd,ZL
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
ldsZL,USARTAI_ERRNum;USART发生收发错误次数+1
incZL
stsUSARTAI_ERRNum,ZL
USART_RXD_Error_RET:
ret;子程序返回


;*******************************************************************************
;*
;*从USART端口上接收到的数据处理子程序 - “USART_RXD_Data”
;*
;*说明:
;*  本子程序用于处理从USART端口上接收到的数据,本子程序中包含有数据循环
;*冗余检测校验子程序。
;*  本子程序要在主程序中不间断循环查询运行。
;*
;*SRAM中标志字节用法:
;*  入口标志:本子程序将检查这三个标志,只有这三个标志置值后才允许处理数据。
;*允许处理接收数据(DataUPD_RXALW)=$03(DataUPD_RDALWI)
;*接收作业己更新(USARTAI_RXUPD)=$0a(USARTAI_RUPDI)
;*接收作业全部结束(USARTAI_RXEnd)=$0f(USARTAI_REndI)
;*  出口标志:接收数据处理操作得到执行后,将对下面这两个标志置值。
;*允许处理接收数据(DataUPD_RXALW)=$00
;*接收作业己更新(USARTAI_RXUPD)=$00
;*
;*******************************************************************************
USART_RXD_Data:
ldsZL,DataUPD_RXALW;检查是否允许处理接收数据?
cpiZL,DataUPD_RALWI;是,则继续
brneUSART_RXD_Data_RET;否,直接返回
ldsZL,USARTAI_RXUPD;检查接收作业是否己更新?
cpiZL,USARTAI_RUPDI;是,则继续
brneUSART_RXD_Data_RET;否,直接返回
ldsZL,USARTAI_TXEnd;发送作业是否全部结束?
cpiZL,USARTAI_TEndI;是,继续
brneUSART_RXD_Data_RET;否,返回,等待发送作业结束
ldsZL,USARTAI_RXEnd;检查接收作业是否全部结束?
cpiZL,USARTAI_REndI;是,则继续
brneUSART_RXD_Data_Error;否,转至接收错误处理
USART_RXD_Data_Check:
ldiZL,Low(USARTAI_RXDAA);Z指针指向接收数据的首字节
ldiZH,High(USARTAI_RXDAA)
ldsDCRC2B_DLength,USARTAI_RXDAA;置校验的数据长度初值
callDataCheck_CRC2B;校验接收的数据是否正确?
orYL,YH;是,继续
brneUSART_RXD_Data_Error;否,转至接收错误处理
rcallUSART_TX_COMM_DataOK;向对方发送“接收数据正确”命令
ldiZL,USARTAI_RCOMI;置接收命令作业标志值
stsUSARTAI_RXCOM,ZL
rcallUSART_RXData_Process;调用接收数据处理子程序
clrZL;清除接收作业己更新标志
stsUSARTAI_RXUPD,ZL
clrZL;清除允许处理接收数据标志
stsDataUPD_RXALW,ZL
rjmpUSART_RXD_Data_RET;返回
USART_RXD_Data_Error:
rcallUSART_RXD_Error;调用接收错误处理子程序
USART_RXD_Data_RET:
ret;子程序返回

;***此段程序用于对从USART端口上接收到的数据进行处理操作
USART_RXData_Process:


;此处插入接收数据处理程序


ret;子程序返回


;*******************************************************************************
;*
;*向USART端口上发送数据更新子程序 - “USART_TXD_Data”
;*
;*说明:
;*  本子程序用于更新向USART端口上上发送数据,本子程序中包含有数据循环
;*冗余检测校验子程序。
;*  本子程序要在主程序中不间断循环查询运行。
;*
;*SRAM中标志字节用法:
;*  入口标志:本子程序将检查这个标志,只有这个标志置值后才允许更新数据。
;*允许更新发送数据(DataUPD_TXALW)=$c0(DataUPD_TALWI)
;*  出口标志:更新发送数据操作得到执行后,将对下面这个标志置值。
;*允许更新发送数据(DataUPD_TXALW)=$00
;*
;*******************************************************************************
USART_TXD_Data:
ldsZL,DataUPD_TXALW;检查是否允许更新发送数据?
cpiZL,DataUPD_TALWI;是,则继续
brneUSART_TXD_Data_RET;否,直接返回
ldsZL,USARTAI_TXEnd;发送作业是否全部结束?
cpiZL,USARTAI_TEndI;是,继续
brneUSART_TXD_Data_RET;否,返回,等待发送作业结束
rcallUSART_TX_COMM_AskTX;发送“向对方请求发送”命令
rcallUSART_TXData_Process;调用更新发送数据子程序
USART_TXD_Data_Check:
ldsZL,USARTAI_TXDAA;取发送的数据长度值
adiwZL,$03;发送的总长度=发送的数据长度值+
stsUSARTAI_TXDAA,ZL;1个长度字符字节+2个校验字节
MOV USARTAI_TEMP2,ZL
ldiZL,Low(USARTAI_TXDAA-2);发送数据的校验字节在发送数据序列
ldiZH,High(USARTAI_TXDAA-2);尾部后两个字节
clrUSARTAI_TEMP
addZL,USARTAI_TEMP2;Z指针指向发送数据的校验字节
adcZH,USARTAI_TEMP
clrUSARTAI_TEMP
stZ+,USARTAI_TEMP;清除发送数据的尾部后两个字节
stZ+,USARTAI_TEMP;的校验字节值
ldiZL,Low(USARTAI_TXDAA);Z指针指向发送数据首个字节
ldiZH,High(USARTAI_TXDAA)
ldsDCRC2B_DLength,USARTAI_TXDAA;置校验的数据长度初值
callDataCheck_CRC2B;生成发送数据序列的CRC码
clrZL;清除允许更新发送数据标志
stsDataUPD_TXALW,ZL
USART_TXD_Data_RET:
ret;子程序返回

;***此段程序用于向USART端口上发送数据的更新操作
USART_TXData_Process:


;此处插入更新发送数据程序


;此段程序为示例数据的更新操作
MOV USARTAI_TEMP,r3
ldiUSARTAI_TEMP2,$fc
stsUSARTAI_TXDAA,USARTAI_TEMP2
ldiYL,Low(USARTAI_TXDAA+1);置接收作业地址指针为
ldiYH,High(USARTAI_TXDAA+1);首个接收数据地址指针
USART_TXData_Process1:
stY+,USARTAI_TEMP
incUSARTAI_TEMP
decUSARTAI_TEMP2
brneUSART_TXData_Process1
incr3
;示例程序结束

ret;子程序返回


;*******************************************************************************
;*
;*USART通信发生错误处理子程序 - “USART_Error”
;*
;*说明:
;*  本子程序用于当USART通信发生错误时的处理。
;*
;*******************************************************************************
USART_Error:
pushZL;压入寄存器中的数值到堆栈
pushZH
inZL,SREG;压状态寄存器中的标志值到堆栈
pushZL
ldiZH,(1<comZH;禁止接收器和发送器,禁止USART
inZL,UCSRB;接收结束中断和数据寄存器空中断
andZL,ZH
outUCSRB,ZL


;此处插入错误处理程序
;此处插入从头开始重新进行数据处理操作程序


ldiZH,(1<comZH;清除帧错误(FE)、数据溢出(DOR)
inZL,UCSRA;及奇偶校验错误(UPE)标志
andZL,ZH
outUCSRA,ZL
ldiZH,(1<inZL,UCSRA;置数据寄存器空(UDRE)标志
orZL,ZH
outUCSRA,ZL
callUSART_AINT_INI;重新初始化USART异步中断接收和发送
callUSART_TX_COMM_REPINI;向对方发送“要求其重新初始化”命令
USART_Error_RET:
popZL
outSREG,ZL;弹出堆栈中的标志值到状态寄存器
popZH;弹出堆栈中的数值到寄存器
popZL
ret;子程序返回


;*******************************************************************************
;*
;*所有通信协议命令开头标识字符串 - “COMAgreement_Head”
;*
;*******************************************************************************
COMAgreement_Head:
.DB$03,"COM";通信协议命令开头标识字符(COM)
;││
;│通信协议命令开头标识字符(COM)
;本指令字符串字符长度数值(不包括自已在内共3个字符)


;*******************************************************************************
;*
;*向对方请求发送命令字符串 - “USART_AskTX”
;*
;*******************************************************************************
USART_AskTX:
.DB"ATX";向对方请求发送命令字符串(ATX)

;*******************************************************************************
;*
;*允许对方发送命令字符串 - “USART_OKRX”
;*
;*******************************************************************************
USART_OKRX:
.DB"YET";允许对方发送命令字符串(YET)

;*******************************************************************************
;*
;*要求对方重新发送命令字符串 - “USART_REPTX”
;*
;*******************************************************************************
USART_REPTX:
.DB"RPT";要求对方重新发送命令字符串(RPT)

;*******************************************************************************
;*
;*接收数据正确命令字符串 - “USART_DataOK”
;*
;*******************************************************************************
USART_DataOK:
.DB"OKD";接收数据正确命令字符串(OKD)

;*******************************************************************************
;*
;*要求对方发送指定数据的命令字符串 - “USART_DCOMTX”
;*
;*******************************************************************************
USART_DCOMTX:
.DB"STD";要求对方发送指定数据的命令字符串(STD)

;*******************************************************************************
;*
;*要求对方重新初始化USART端口状态命令字符串 - “USART_REPINI”
;*
;*******************************************************************************
USART_REPINI:
.DB"RII";要求对方重新初始化状态命令字符串(RII)

;*******************************************************************************
;*
;*重新初始化USART端口状态完成命令字符串 - “USART_RINIOK”
;*
;*******************************************************************************
USART_RINIOK:
.DB"YRI";重新初始化状态完成命令字符串(YRI)

;*******************************************************************************
;*
;*从USART端口传送控制操作指令命令字符串 - “USART_CTRLCOM”
;*
;*******************************************************************************
USART_CTRLCOM:
.DB"CIT";从端口传送控制操作指令命令字符串(CIT)


;*******************************************************************************
;*
;*USART异步通信中断接收与发送协议命令和数据处理子程序 - “USART_INT_ACOM”
;*
;*说明:
;*  本子程序用于USART异步通信中断接收与发送协议命令和数据处理。
;*  本子程序要在主程序中不间断地循环运行。
;*
;*******************************************************************************
USART_INT_ACOM:
inZL,SREG;压状态寄存器中的标志值到堆栈
pushZL
callUSART_RXD_COMM;接收通信协议命令处理程序
callUSART_RXD_Data;调用接收数据处理程序
callUSART_TXD_Data;调用更新发送数据程序
popZL;弹出堆栈中的标志值到状态寄存器
outSREG,ZL
ret;子程序返回


;*******************************************************************************
;*
;*定时器/计数器0溢出中断处理子程序 - “TC0_Timer_OVFINT”
;*
;*说明:
;*  本子程序用于约束接收作业全部完成(指从接收第一个数据到最后一个数据之间)
;*的时间范围,如果在规定的时间内没有接收作业全部完成,则强制结束此次接收作业,
;*以便下次接收作业正确操作。此程序主要用于检查第一个的数据长度字节的数值与所接
;*收到的数据帧数是否匹配,避免由于不匹配而产生的错误死循环。也用于接收端受干扰
;*后能够及时恢复正确操作接收作业标志值。
;*
;*注意:
;*  本子程序在多次执行到T/C0计数溢出次数超出设置数值后,将禁止定时器/计
;*数器0溢出中断。
;*
;*SRAM中标志字节用法:
;*  出口标志:
;*  接收作业己更新(USARTAI_RXUPD)=$0a(USARTAI_RUPDI)
;*
;*******************************************************************************
TC0_Timer_OVFINT:
pushZL;压入寄存器中的数值到堆栈
pushZH
inZL,SREG;压状态寄存器中的标志值到堆栈
pushZL
ldiZL,USARTAI_T0CNTI;置T/C0定时参数的预定计数比例值
outTCNT0,ZL
ldsZL,USARTAI_T0VNum;检查T/C0计数溢出次数是否超出设置值?
cpiZL,USARTAI_T0NumI;是,执行超出次数处理操作
brloTC0_Timer_OVFINT1;否,转至继续
ldiZL,USARTAI_RUPDI;置接收作业己更新标志值
stsUSARTAI_RXUPD,ZL
ldiZH,(1<comZH;注:仅只改变T/C中断屏蔽寄存
inZL,TIMSK;器中的此项设置,对于其他T/C
andZL,ZH;中断状态保留原来设置
outTIMSK,ZL
rjmpTC0_Timer_OVFINT_RET;返回
TC0_Timer_OVFINT1:
incZL;T/C0计数溢出次数+1
stsUSARTAI_T0VNum,ZL
TC0_Timer_OVFINT_RET:
popZL
outSREG,ZL;弹出堆栈中的标志值到状态寄存器
popZH;弹出堆栈中的数值到寄存器
popZL
reti;中断返回

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

上个月,爱立信刚刚传出“对中国区业务进行战略调整,研发岗大面积裁员”的消息。这几天,就有员工确认,爱立信“核心网”成为了此次裁员的“重灾区”。

关键字: 爱立信 通信

设计工程师为了解决ISI问题,常常需要在链路损耗和均衡技术之间做出综合考虑。泰克的SDLA软件不仅可以模拟发送端的Tx EQ和接收端的Rx EQ,还能模拟传输链路的不同损耗。

关键字: 通信 示波器 测试测量

5G网络相较于4G网络,具有更高的数据传输速率,能够支持更高的峰值速率,理论上峰值传输速率可以达到10Gbit/s,这比4G网络快了大约10到100倍。

关键字: 5G 通信 4G网络

泰克实时示波器支持TekExpressLVDS自动测量软件,涵盖LVDS时钟和数据的30多个测量项目,一键完成一致性测量。

关键字: 通信 示波器 测试测量

2024年2月26日,国际通信行业盛会MWC 24于西班牙巴塞罗那召开,全球通信及其相关供应链的顶尖企业荟聚一堂,展示移动通信领域的前沿研究成果,与国际行业同仁展开深入技术交流。三安集成作为射频前端整合解决方案服务提供商...

关键字: 三安集成 射频 通信

在意大利媒体对沃达丰的并购交易提出多种猜测之后,该公司2月28日发布声明称,正在就将沃达丰意大利公司(Vodafone Italy)出售给瑞士电信进行独家谈判,但尚未达成有约束力的协议。

关键字: 沃达丰 瑞士电信 通信 宽带

即将于2024年6月竣工交付的华为上海研发基地(青浦),不仅是上海市重点工程,也是长三角一体化示范区西岑科创中心的亮点项目。

关键字: 华为 通信 芯片

全球4G和5G的部署速度比商业服务的推进速度更快,6G预计到2030年也会到来,电信运营商如何以正确姿势迎接未来?

关键字: AI 通信 5G 6G

近日,华为又新增了多条专利信息,其中一项关于人体通信的“黑科技”最引人注目。

关键字: 华为 通信

近日,华为接连曝出两大重磅消息:一个事关智能汽车,另一个事关卫星通信。

关键字: 华为 通信 汽车电子
关闭
关闭