📄 新建 文本文档.txt
字号:
ret
;------------------------------------------------------------------------------------------
CheckCRC: ;vstup: USBBufptrY = zaciatok spravy ,ByteCount = dlzka spravy
add ByteCount,USBBufptrY ;ByteCount ukazuje na koniec spravy
inc USBBufptrY ;nastav 指针 na zaciatok spravy - vynechat SOP
ld temp0,Y+ ;nahraj PID do temp0
;a nastav 指针 na zaciatok spravy - vynechat aj PID
cpi temp0,DATA0PID ;ci je DATA0 pole
breq ComputeDATACRC ;pocitaj CRC16
cpi temp0,DATA1PID ;ci je DATA1 pole
brne CRC16End ;ak nie tak skonci
ComputeDATACRC:
ser temp0 ;初始化 zvysku LSB na 0xff
ser temp1 ;初始化 zvysku MSB na 0xff
CRC16Loop:
ld temp2,Y+ ;nahraj spravu do temp2 a zvys 指针 do 缓冲区
ldi temp3,8 ;pocitadlo bitov v byte - temp3
CRC16LoopByte:
bst temp1,7 ;do T uloz MSB zvysku (zvysok je iba 16 bitovy - 8 bit vyssieho byte)
bld bitcount,0 ;do bitcount LSB uloz T - MSB zvysku
eor bitcount,temp2 ;XOR bitu spravy a bitu zvysku - v LSB bitcount
rol temp0 ;posun zvysok dolava - nizsi byte (dva byty - cez carry)
rol temp1 ;posun zvysok dolava - vyssi byte (dva byty - cez carry)
cbr temp0,1 ;znuluj LSB zvysku
lsr temp2 ;posun spravu doprava
ror bitcount ;vysledok XOR-u bitov z LSB do carry
brcc CRC16NoXOR ;ak je XOR bitu spravy a MSB zvysku = 0 , tak nerob XOR
ldi bitcount,CRC16poly>>8 ;do bitcount CRC polynom - vrchny byte
eor temp1,bitcount ;a urob XOR zo zvyskom a CRC polynomom - vrchny byte
ldi bitcount,CRC16poly ;do bitcount CRC polynom - spodny byte
eor temp0,bitcount ;a urob XOR zo zvyskom a CRC polynomom - spodny byte
CRC16NoXOR:
dec temp3 ;boli uz vsetky bity v byte
brne CRC16LoopByte ;ak nie, tak chod na dalsi bit
cp USBBufptrY,ByteCount ;bol uz koniec spravy
brne CRC16Loop ;ak nie tak opakuj
CRC16End:
ret ;inak skonci (v temp0 a temp1 je vysledok)
;------------------------------------------------------------------------------------------
LoadDescriptorFromROM:
lpm ;nahraj z pozicie ROM pointra do R0
st Y+,R0 ;R0 uloz do 缓冲区 a zvys buffer
adiw ZH:ZL,1 ;zvys ukazovatel do ROM
dec ByteCount ;pokial nie su vsetky byty
brne LoadDescriptorFromROM ;tak nahravaj dalej
rjmp EndFromRAMROM ;inak skonci
;------------------------------------------------------------------------------------------
LoadDescriptorFromROMZeroInsert:
lpm ;nahraj z pozicie ROM pointra do R0
st Y+,R0 ;R0 uloz do 缓冲区 a zvys buffer
bst RAMread,3 ;ak je 3 bit jednotkovy - nebude sa vkladat nula
brtc InsertingZero ;inak sa bude vkladat nula
adiw ZH:ZL,1 ;zvys ukazovatel do ROM
lpm ;nahraj z pozicie ROM pointra do R0
st Y+,R0 ;R0 uloz do 缓冲区 a zvys buffer
clt ;a znuluj
bld RAMread,3 ;treti bit v RAMread - aby sa v dalsom vkladali nuly
rjmp InsertingZeroEnd ;a pokracuj
InsertingZero:
clr R0 ;na vkladanie nul
st Y+,R0 ;nulu uloz do 缓冲区 a zvys buffer
InsertingZeroEnd:
adiw ZH:ZL,1 ;zvys ukazovatel do ROM
subi ByteCount,2 ;pokial nie su vsetky byty
brne LoadDescriptorFromROMZeroInsert ;tak nahravaj dalej
rjmp EndFromRAMROM ;inak skonci
;------------------------------------------------------------------------------------------
LoadDescriptorFromSRAM:
ld R0,Z ;nahraj z pozicie RAM pointra do R0
st Y+,R0 ;R0 uloz do 缓冲区 a zvys buffer
inc ZL ;zvys ukazovatel do RAM
dec ByteCount ;pokial nie su vsetky byty
brne LoadDescriptorFromSRAM ;tak nahravaj dalej
rjmp EndFromRAMROM ;inak skonci
;------------------------------------------------------------------------------------------
LoadDescriptorFromEEPROM:
out EEAR,ZL ;nastav adresu EEPROM
sbi EECR,EERE ;vycitaj EEPROM do registra EEDR
in R0,EEDR ;nahraj z EEDR do R0
st Y+,R0 ;R0 uloz do 缓冲区 a zvys buffer
inc ZL ;zvys ukazovatel do RAM
dec ByteCount ;pokial nie su vsetky byty
brne LoadDescriptorFromEEPROM;tak nahravaj dalej
rjmp EndFromRAMROM ;inak skonci
;------------------------------------------------------------------------------------------
LoadXXXDescriptor:
ldi temp0,SOPbyte ;加载SOP到输出缓冲区
sts OutputBufferBegin,temp0
ldi ByteCount,8 ;8 bytov nahrat
ldi USBBufptrY,OutputBufferBegin+2 ;Y指针指向发送缓冲区+2
and RAMread,RAMread ;RAMread 是否为0
brne FromRAMorEEPROM ;0=ROM,1=RAM,2=EEPROM,4=ROM s vkladanim nuly
FromROM:
rjmp LoadDescriptorFromROM ;从 ROM 中加载数据
FromRAMorEEPROM:
sbrc RAMread,2 ;RAMread=4
rjmp LoadDescriptorFromROMZeroInsert ;从 ROM 中加载数据
sbrc RAMread,0 ;RAMread=1
rjmp LoadDescriptorFromSRAM ;从 SRAM 中加载数据
rjmp LoadDescriptorFromEEPROM ;从 EEPROM 中加载数据
EndFromRAMROM:
sbrc RAMread,7 ;ak je najvyssi bit v premennej RAMread=1
clr RAMread ;znuluj RAMread
rcall ToggleDATAPID ;循环DATA1/DATA0
ldi USBBufptrY,OutputBufferBegin+1 ;do vysielacieho 缓冲区 - pozicia DATA PID
ret
;------------------------------------------------------------------------------------------
PrepareUSBOutAnswer: ;pripravenie odpovede do 缓冲区
rcall PrepareUSBAnswer ;根据配置数据进行进一步的处理
MakeOutBitStuff:
inc BitStuffInOut ;vysielaci buffer - vkladanie bitstuff bitov
ldi USBBufptrY,OutputBufferBegin ;do vysielacieho 缓冲区
rcall BitStuff ;安排填充位
mov OutputBufferLength,ByteCount ;dlzku odpovede zapamatat pre vysielanie
clr BitStuffInOut ;prijimaci buffer - mazanie bitstuff bitov
ret
;------------------------------------------------------------------------------------------
PrepareUSBAnswer: ;pripravenie odpovede do 缓冲区
clr RAMread ;nulu do RAMread premennej - cita sa z ROM-ky
lds temp0,InputBufferBegin+2 ;取出 bmRequestType
lds temp1,InputBufferBegin+3 ;取出 bRequest
cbr temp0,0b10011111 ;保留 bmRequestType 第6位和第5位(请求类型)
brne VendorRequest ;tak to nie je Vendor Request
rjmp StandardRequest ;00 是 USB 的11种标准请求
;--------------------------
DoSetInfraBufferEmpty:
rjmp OneZeroAnswer ;potvrd prijem jednou nulou
;--------------------------
DoSetRS232Baud:
lds temp0,InputBufferBegin+4 ;prvy parameter - hodnota baudrate na RS232
out UBRR,temp0 ;nastav rychlost UART-u
rjmp OneZeroAnswer ;potvrd prijem jednou nulou
;--------------------------
DoGetRS232Baud:
in R0,UBRR ;vrat rychlost UART-u v R0
rjmp DoGetIn ;a ukonci
;--------------------------
DoRS232Send:
lds temp0,InputBufferBegin+4 ;prvy parameter - hodnota vysielana na RS232
out UDR,temp0 ;vysli data na UART
WaitForRS232Send:
sbis UCR,TXEN ;ak nie je povoleny UART vysielac
rjmp OneZeroAnswer ;tak skonci - ochrana kvoli zacykleniu v AT90S2323/2343
sbis USR,TXC ;pockat na dovysielanie bytu
rjmp WaitForRS232Send
rjmp OneZeroAnswer ;potvrd prijem jednou nulou
;--------------------------
DoRS232Read:
rjmp TwoZeroAnswer ;iba potvrd prijem dvoma nulami
;--------------------------
VendorRequest:
clr ZH ;pre citanie z RAM alebo EEPROM
cpi temp1,1 ;
breq DoSetInfraBufferEmpty ;restartne infra prijimanie (ak bolo zastavene citanim z RAM-ky)
cpi temp1,2 ;
breq DoGetInfraCode ;vysle prijaty infra kod (ak je v bufferi)
cpi temp1,3 ;
breq DoSetDataPortDirection ;nastavi smer toku datovych bitov
cpi temp1,4 ;
breq DoGetDataPortDirection ;zisti smer toku datovych bitov
cpi temp1,5 ;
breq DoSetOutDataPort ;nastavi datove bity (ak su vstupne, tak ich pull-up)
cpi temp1,6 ;
breq DoGetOutDataPort ;zisti nastavenie datovych out bitov (ak su vstupne, tak ich pull-up)
cpi temp1,7 ;
breq DoGetInDataPort ;vrati hodnotu datoveho vstupneho portu
cpi temp1,8 ;
breq DoEEPROMRead ;vrati obsah EEPROM od urcitej adresy
cpi temp1,9 ;
breq DoEEPROMWrite ;zapise EEPROM na urcitu adresu urcite data
cpi temp1,10 ;
breq DoRS232Send ;vysle byte na seriovy linku
cpi temp1,11 ;
breq DoRS232Read ;vrati prijaty byte zo seriovej linky (ak sa nejaky prijal)
cpi temp1,12 ;
breq DoSetRS232Baud ;nastavi prenosovu rychlost seriovej linky
cpi temp1,13 ;
breq DoGetRS232Baud ;vrati prenosovu rychlost seriovej linky
cpi temp1,14 ;
breq DoGetRS232Buffer ;vrati RS232 buffer
cpi temp1,USER_FNC_NUMBER+0 ;
breq DoUserFunction0 ;vykona uzivatelsku rutinu0
cpi temp1,USER_FNC_NUMBER+1 ;
breq DoUserFunction1 ;vykona uzivatelsku rutinu1
cpi temp1,USER_FNC_NUMBER+2 ;
breq DoUserFunction2 ;vykona uzivatelsku rutinu2
rjmp ZeroDATA1Answer ;ak to bolo nieco nezname, tak priprav nulovu odpoved
;----------------------------- USER FUNCTIONS --------------------------------------
;------------------------------TEMPLATE OF YOUR FUNCTION----------------------------
;------------------ BEGIN: This is template how to write own function --------------
;free of use are 寄存器s:
;temp0,temp1,temp2,temp3,ACC,ZH,ZL
;寄存器s are destroyed after execution (use push/pop to save content)
;at the end of routine you must correctly set 寄存器s:
;RAMread - 0=reading from ROM, 1=reading from RAM, 2=reading from EEPROM
;temp0 - number of transmitted data bytes
;ZH,ZL - 指针 to buffer of transmitted data (指针 to ROM/RAM/EEPROM)
;to transmit data (preparing data to buffer) :
;to transmit data you must jump to "ComposeEndXXXDescriptor"
;to transmit one zero byte you can jump to "OneZeroAnswer" (commonly used as confirmation of correct processing)
;to transmit two zero byte you can jump to "TwoZeroAnswer" (commonly used as confirmation of error in processing)
DoUserFunctionX:
DoUserFunction0: ;send byte(s) of RAM starting at position given by first parameter in function
lds temp0,InputBufferBegin+4 ;prvy parameter Lo do temp0
;lds temp1,InputBufferBegin+5 ;prvy parameter Hi do temp1
;lds temp2,InputBufferBegin+6 ;druhy parameter Lo do temp2
;lds temp3,InputBufferBegin+7 ;druhy parameter Hi do temp3
;lds ACC,InputBufferBegin+8 ;pocet pozadovanych bytov do ACC
;Tu si pridajte vlastny kod:
;-------------------------------------------------------------------
nop ;priklad na kod - nic nerobi
nop
nop
nop
nop
;-------------------------------------------------------------------
mov ZL,temp0 ;bude sa posielat hodnota RAM adresy ulozena v temp0 (prvy parameter funkcie)
inc RAMread ;RAMread=1 - cita sa z RAM-ky
ldi temp0,RAMEND+1 ;posli max pocet byte - celu RAM
rjmp ComposeEndXXXDescriptor ;a priprav data
DoUserFunction1:
rjmp OneZeroAnswer ;potvrd prijem jednou nulou
DoUserFunction2:
rjmp TwoZeroAnswer ;potvrd prijem dvoma nulami
;------------------ END: This is template how to write own function ----------------
;----------------------------- USER FUNCTIONS --------------------------------------
DoGetInfraCode:
rjmp OneZeroAnswer ;potvrd prijem jednou nulou
DoEEPROMRead:
lds ZL,InputBufferBegin+4 ;prvy parameter - offset v EEPROM-ke
ldi temp0,2
mov RAMread,temp0 ;RAMread=2 - cita sa z EEPROM-ky
ldi temp0,E2END+1 ;pocet mojich bytovych odpovedi do temp0 - cela dlzka EEPROM
rjmp ComposeEndXXXDescriptor ;inak priprav data
DoEEPROMWrite:
lds ZL,InputBufferBegin+4 ;prvy parameter - offset v EEPROM-ke (adresa)
lds R0,InputBufferBegin+6 ;druhy parameter - data, ktore sa maju zapisat do EEPROM-ky (data)
rjmp EEPROMWrite ;zapis do EEPROM a aj ukonci prikaz
DoSetDataPortDirection:
lds ACC,InputBufferBegin+4 ;prvy parameter - smer datovych bitov
rcall SetDataPortDirection
rjmp OneZeroAnswer ;potvrd prijem jednou nulou
DoGetDataPortDirection:
rcall GetDataPortDirection
rjmp DoGetIn
DoSetOutDataPort:
lds ACC,InputBufferBegin+4 ;prvy parameter - hodnota datovych bitov
rcall SetOutDataPort
rjmp OneZeroAnswer ;potvrd prijem jednou nulou
DoGetOutDataPort:
rcall GetOutDataPort
rjmp DoGetIn
DoGetInDataPort:
rcall GetInDataPort
DoGetIn:
ldi ZL,0 ;posiela sa hodnota v R0
ldi temp0,0x81 ;RAMread=1 - cita sa z RAM-ky
mov RAMread,temp0 ;(najvyssi bit na 1 - aby sa hned premenna RAMread znulovala)
ldi temp0,1 ;posli iba jeden byte
rjmp ComposeEndXXXDescriptor ;a priprav data
DoGetRS232Buffer:
mov temp0,RS232BufferFull ;zisti dlzku 缓冲区 RS232 kodu
cpi temp0,0 ;ak je RS232 Buffer prazdny
breq OneZeroAnswer ;tak nic neposli a potvrd prijem jednou nulou
lds ACC,InputBufferBegin+8 ;pocet pozadovanych bytov do ACC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -