📄 新建 文本文档.txt
字号:
rjmp Main
ProcPrepareOutContinuousBuffer:
rcall PrepareOutContinuousBuffer ;从缓冲区输出连续数据
ldi ActionFlag,DoReadySendAnswer ;工作标志
rjmp Main
ProcReceiveSetupData: ;接收到配置数据
ldi USBBufptrY,InputBufferBegin ;将输入缓冲区用作 USB 输入/输出缓冲区
mov ByteCount,InputBufferLength ;接收到的数据长度(设置状态的 DATA 包)
rcall DecodeNRZI ;将 NRZI 编码解释为二进制码
rcall MirrorInBufferBytes ;镜像输入缓冲区
rcall BitStuff ;去掉填充位
;rcall CheckCRCIn ;CRC 校验
rcall PrepareUSBOutAnswer ;根据配置数据进行进一步的处理
ldi ActionFlag,DoReadySendAnswer
rjmp Main
;********************************************************************
;* Main program END
;********************************************************************
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt0 interrupt handler
;********************************************************************
INT0Handler: ;prerusenie INT0
in backupSREG,SREG ;INT0 中断中的SREG备份
push temp0
push temp1
ldi temp0,3 ;pocitadlo trvania log0
ldi temp1,2 ;pocitadlo trvania log1
;测试信号沿,用来达到同步
CheckchangeMinus:
sbis inputport,DATAminus ;等待 D- 为 1
rjmp CheckchangeMinus
CheckchangePlus:
sbis inputport,DATAplus ;等待 D+ 为 1
rjmp CheckchangePlus
DetectSOPEnd: ;同步完成
sbis inputport,DATAplus ;检测数据为1还是为0
rjmp Increment0 ;D+ =0
Increment1:
ldi temp0,3 ;加载低电平检测次数(连续3次相同才开始有效数据)
dec temp1 ;高电平检测
nop
breq USBBeginPacket ;SOP 数据完成,开始数据移位
rjmp DetectSOPEnd
Increment0:
ldi temp1,2 ;加载高电平检测次数(连续2次相同才开始有效数据)
dec temp0 ;低电平检测
nop
brne DetectSOPEnd ;ak nenastal SOF - pokracuj
rjmp EndInt0HandlerPOP2
;
EndInt0Handler: ;结束中断0处理
pop ACC
pop RS232BufptrX
pop temp3
pop temp2
EndInt0HandlerPOP: ;结束中断0处理
pop USBBufptrY
pop ByteCount
mov bitcount,backupbitcount ;恢复 bitcount
EndInt0HandlerPOP2: ;结束中断0处理
pop temp1
pop temp0
out SREG,backupSREG ;恢复 SREG
ldi shiftbuf,1<<INTF0 ;znulovat flag interruptu INTF0
out GIFR,shiftbuf
reti ;inak skonci (bol iba SOF - kazdu milisekundu)
USBBeginPacket: ;SOP 数据完成,开始数据移位
mov backupbitcount,bitcount ;保存 bitcount (在中断返回时恢复)
;(读入第0位)
in shiftbuf,inputport ;读入 USB 通讯口到移位缓冲区
USBloopBegin:
push ByteCount ;保护字节计数
push USBBufptrY
ldi bitcount,6 ;初始化移位计数器
ldi ByteCount,MAXUSBBYTES ;初始化到 USB 输入最大的字节数
ldi USBBufptrY,InputShiftBufferBegin ;将输入缓冲区用作 USB 输入缓冲区
USBloop1_6: ;(读入第1-6位)
in inputbuf,inputport ;读入 USB 通讯口到输入缓冲区
cbr inputbuf,USBpinmask ;保留 USB 通讯口的2Bit,其余的清0
breq USBloopEnd ;是否挂起(同时为0)
ror inputbuf ;将D-移到CY中
rol shiftbuf ;将CY中的数据移到移位缓冲区
dec bitcount ;移位计数减1
brne USBloop1_6 ;继续移位
nop ;inak bude nutne skopirovat shift 寄存器 bo 缓冲区
USBloop7: ;(读入第7位)
in inputbuf,inputport ;读入 USB 通讯口到输入缓冲区
cbr inputbuf,USBpinmask ;保留 USB 通讯口的2Bit,其余的清0
breq USBloopEnd ;是否挂起(同时为0,数据中途中断或完成)
ror inputbuf ;将D-移到CY中
rol shiftbuf ;将CY中的数据移到移位缓冲区
;保存已经接受到的8Bit数据
ldi bitcount,7 ;初始化 pocitadla bitov v bajte
st Y+,shiftbuf ;将移位缓冲区中的数据存入输入缓冲区
USBloop0: ;(读入第0位)
in shiftbuf,inputport ;读入 USB 通讯口到输入缓冲区
cbr shiftbuf,USBpinmask ;保留 USB 通讯口的2Bit,其余的清0
breq USBloopEnd ;是否挂起(同时为0,数据中途中断或完成)
dec bitcount ;移位计数减1
nop ;
dec ByteCount ;移字节计数减1
brne USBloop1_6 ;将剩下的数据接收完成
rjmp EndInt0HandlerPOP ;结束中断0处理
USBloopEnd: ;挂起(同时为0,数据中途中断或完成)
cpi USBBufptrY,InputShiftBufferBegin+3 ;接收到的数据是否少于3字节
brcs EndInt0HandlerPOP ;少于3字节,结束中断0处理
lds temp0,InputShiftBufferBegin+0 ;identifikator paketu do temp0
lds temp1,InputShiftBufferBegin+1 ;adresa do temp1
brne TestDataPacket ;接收到的数据大于3字节时,只能是DATA0 a DATA1 包
;接收到的数据等于3字节,可能是 SETUP、OUT、IN、DATA0 或 DATA1 包
TestIOPacket:
; cp temp1,MyInAddress ;ak to nie je urcene (adresa) pre mna
; brne TestDataPacket ;tak to moze byt este Data Packet
TestSetupPacket:;检测是不是 SETUP 包
cpi temp0,nNRZISETUPPID ;是不是 SETUP 包
brne TestOutPacket
cp temp1,MyInAddress ;是不是本机地址(IN) ;ENG;if this isn't assigned (address) for me
brne TestDataPacket
ldi State,SetupState ;标记为设置状态
rjmp EndInt0HandlerPOP ;结束中断0处理 ak je Setup PID - prijimaj nasledny Data paket
TestOutPacket: ;检测是不是 OUT 包
cpi temp0,nNRZIOUTPID ;是不是 OUT 包
brne TestInPacket
cp temp1,MyOutAddress ;是不是本机地址(OUT) ;ENG;if this isn't assigned (address) for me
brne TestDataPacket
ldi State,OutState ;标记为 OUT 状态
rjmp EndInt0HandlerPOP ;结束中断0处理 ak je Out PID - prijimaj nasledny Data paket
TestInPacket: ;检测是不是 IN 包
cpi temp0,nNRZIINPID ;是不是 IN 包
brne TestDataPacket
cp temp1,MyInAddress ;是不是本机地址(IN) ;ENG;if this isn't assigned (address) for me
breq AnswerToInRequest ;tak to moze byt este Data Packet ;ENG;then this can be still DataPacket
TestDataPacket: ;检测是不是 DATA0 或 DATA1 包
cpi temp0,nNRZIDATA0PID ;是不是 DATA0 包
breq Data0Packet
cpi temp0,nNRZIDATA1PID ;是不是 DATA1 包
brne NoMyPacked ;不是本机能识别的包
Data0Packet: cpi State,SetupState ;是不是设置状态的 DATA 包
breq ReceiveSetupData
cpi State,OutState ;是不是 OUT 状态的 DATA 包
breq ReceiveOutData
NoMyPacked: ;不是本机能识别的包(主机只能使用 SETUP 和 OUT 包向终端发送数据)
ldi State,BaseState ;
rjmp EndInt0HandlerPOP ;结束中断0处理
AnswerToInRequest: ;IN 包处理
push temp2 ;保护数据
push temp3
push RS232BufptrX
push ACC
cpi ActionFlag,DoReadySendAnswer ;是否发送已经准备就绪,发送回应
brne NoReadySend ;发送 NAK
rcall SendPreparedUSBAnswer ;发送准备就绪的回应数据
cpi State,AddressChangeState;是否要求改变地址
breq SetMyNewUSBAddress ;设置新的本机地址
ldi State,InState ;输入状态
ldi ActionFlag,DoPrepareOutContinuousBuffer ;从缓冲区输出连续数据动作标志,主程序中将剩余的数据发送出去
rjmp EndInt0Handler ;结束中断0处理
ReceiveSetupData: ;设置状态的 DATA 包处理
push temp2 ;保护数据
push temp3
push RS232BufptrX
push ACC
rcall SendACK ;响应 SETUP 包,发送 ACK
rcall FinishReceiving ;ukonci prijem
ldi ActionFlag,DoReceiveSetupData ;收到配置数据工作标志,主程序中处理配置数据
rjmp EndInt0Handler ;结束中断0处理
ReceiveOutData: ;OUT 状态的 DATA 包处理
push temp2 ;保护数据
push temp3
push RS232BufptrX
push ACC
cpi ActionFlag,DoReceiveSetupData ;配置数据工作状态?
breq NoReadySend ;发送 NAK
rcall SendACK ;发送 ACK
clr ActionFlag ;清除动作标志
rjmp EndInt0Handler ;结束中断0处理
NoReadySend:
rcall SendNAK ;发送 NAK
rjmp EndInt0Handler ;结束中断0处理
;------------------------------------------------------------------------------------------
SetMyNewUSBAddress: ;设置新的本机地址
lds MyInAddress,MyInAddressSRAM
lds MyOutAddress,MyOutAddressSRAM
rjmp EndInt0Handler ;结束中断0处理
;------------------------------------------------------------------------------------------
FinishReceiving: ;将接收缓冲区中不满8Bit的数据填满
cpi bitcount,7 ;prenes do 缓冲区 aj posledny necely byte
breq NoRemainingBits ;ak boli vsetky byty prenesene, tak neprenasaj nic
inc bitcount
ShiftRemainingBits:
rol shiftbuf ;填充数据
dec bitcount
brne ShiftRemainingBits
st Y+,shiftbuf ;将移位缓冲区中的数据存入输入缓冲区
NoRemainingBits:
mov ByteCount,USBBufptrY ;取出输入缓冲区当前指针
subi ByteCount,InputShiftBufferBegin-1 ;取得接收到的数据量
mov InputBufferLength,ByteCount ;保存接收到的数据量
ldi USBBufptrY,InputShiftBufferBegin ;指针指向 USB 输入缓冲区首址
ldi RS232BufptrX,InputBufferBegin+1 ;将输入缓冲区+1用作 RS232 缓冲区
MoveDataBuffer:
ld temp0,Y+ ;将数据移到 RS232 缓冲区
st X+,temp0
dec ByteCount
brne MoveDataBuffer
ldi ByteCount,nNRZISOPbyte
sts InputBufferBegin,ByteCount ;ako keby sa prijal SOP - nekopiruje sa zo shift 缓冲区
ret
;------------------------------------------------------------------------------------------
;********************************************************************
;* Other procedures
;********************************************************************
;------------------------------------------------------------------------------------------
USBReset: ;初始化 USB stavoveho stroja
ldi temp0,nNRZIADDR0 ;初始化 USB adresy
mov MyOutAddress,temp0
mov MyInAddress,temp0
clr State ;初始化 stavoveho stroja
clr BitStuffInOut
clr OutBitStuffNumber
clr ActionFlag
clr RAMread ;bude sa vycitavat z ROM-ky
clr ConfigByte ;nenakonfiguravany stav
ret
;------------------------------------------------------------------------------------------
SendPreparedUSBAnswer: ;poslanie kodovanim NRZI OUT buffer s dlzkou OutputBufferLength do USB
mov ByteCount,OutputBufferLength ;dlzka odpovede
SendUSBAnswer: ;poslanie kodovanim NRZI OUT buffer do USB
ldi USBBufptrY,OutputBufferBegin ;指针 na zaciatok vysielacieho 缓冲区
SendUSBBuffer: ;poslanie kodovanim NRZI dany buffer do USB
ldi temp1,0 ;zvysovanie pointra (pomocna premenna)
mov temp3,ByteCount ;pocitadlo bytov: temp3 = ByteCount
ldi temp2,0b00000011 ;maska na xorovanie
ld inputbuf,Y+ ;nacitanie prveho bytu do inputbuf a zvys 指针 do 缓冲区
;USB ako vystup:
cbi outputport,DATAplus ;zhodenie DATAplus : kludovy stav portu USB
sbi outputport,DATAminus ;nahodenie DATAminus : kludovy stav portu USB
sbi USBdirection,DATAplus ;DATAplus ako vystupny
sbi USBdirection,DATAminus ;DATAminus ako vystupny
in temp0,outputport ;kludovy stav portu USB do temp0
SendUSBAnswerLoop:
ldi bitcount,7 ;pocitadlo bitov
SendUSBAnswerByteLoop:
nop ;oneskorenie kvoli casovaniu
ror inputbuf ;do carry vysielany bit (v smere naskor LSB a potom MSB)
brcs NoXORSend ;ak je jedna - nemen stav na USB
eor temp0,temp2 ;inak sa bude stav menit
NoXORSend:
out outputport,temp0 ;vysli von na USB
dec bitcount ;zmensi pocitadlo bitov - podla carry flagu
brne SendUSBAnswerByteLoop ;ak pocitadlo bitov nie je nulove - opakuj vysielanie s dalsim bitom
sbrs inputbuf,0 ;ak je vysielany bit jedna - nemen stav na USB
eor temp0,temp2 ;inak sa bude stav menit
NoXORSendLSB:
dec temp3 ;zniz pocitadlo bytov
ld inputbuf,Y+ ;nacitanie dalsieho bytu a zvys 指针 do 缓冲区
out outputport,temp0 ;vysli von na USB
brne SendUSBAnswerLoop ;opakuj pre cely buffer (pokial temp3=0)
mov bitcount,OutBitStuffNumber ;pocitadlo bitov pre bitstuff
cpi bitcount,0 ;ak nie je potrebny bitstuff
breq ZeroBitStuf
SendUSBAnswerBitstuffLoop:
ror inputbuf ;do carry vysielany bit (v smere naskor LSB a potom MSB)
brcs NoXORBitstuffSend ;ak je jedna - nemen stav na USB
eor temp0,temp2 ;inak sa bude stav menit
NoXORBitstuffSend:
out outputport,temp0 ;vysli von na USB
nop ;oneskorenie kvoli casovaniu
dec bitcount ;zmensi pocitadlo bitov - podla carry flagu
brne SendUSBAnswerBitstuffLoop ;ak pocitadlo bitov nie je nulove - opakuj vysielanie s dalsim bitom
ld inputbuf,Y ;oneskorenie 2 cykly
ZeroBitStuf:
nop ;oneskorenie 1 cyklus
cbr temp0,3
out outputport,temp0 ;vysli EOP na USB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -