📄 新建 文本文档.txt
字号:
inc temp0 ;pocet moznych dodanych bajtov (plus byte dlzky 缓冲区)
cp ACC,temp0 ;ak sa neziada viac ako mozem dodat
brcc NoShortGetRS232Buffer ;vysli tolko kolko sa ziada
mov temp0,ACC
NoShortGetRS232Buffer:
dec temp0 ;uber byte dlzky
lds temp1,RS232BufferBegin+1 ;zisti ukazovatel citania 缓冲区 RS232 kodu : 2.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
add temp1,temp0 ;zisti kde je koniec
cpi temp1,RS232BufferBegin+MAXRS232LENGTH+1 ;ak by mal pretiect
brcs ReadNoOverflow
subi temp1,RS232BufferBegin+MAXRS232LENGTH+1 ;vypocitaj kolko sa neprenesie
sub temp0,temp1 ;a o to skrat dlzku citania
ldi temp1,RS232BufferBegin+4 ;a zacni od nuly
ReadNoOverflow:
lds ZL,RS232BufferBegin+1 ;zisti ukazovatel citania 缓冲区 RS232 kodu : 2.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
sts RS232BufferBegin+1,temp1 ;zapis novy ukazovatel citania 缓冲区 RS232 kodu : 2.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
dec ZL ;priestor pre udaj dlky - prenasa sa ako prvy bajt
sub RS232BufferFull,temp0 ;zniz dlzku 缓冲区
st Z,RS232BufferFull ;a uloz skutocnu dlzku do paketu
inc temp0 ;a o tento jeden bajt zvys pocet prenasanych bajtov (dlzka 缓冲区)
inc RAMread ;RAMread=1 - cita sa z RAM-ky
rjmp ComposeEndXXXDescriptor ;a priprav data
;----------------------------- END USER FUNCTIONS ----------------------------------
OneZeroAnswer: ;posle jednu nulu
ldi temp0,1 ;pocet mojich bytovych odpovedi do temp0
rjmp ComposeGET_STATUS2
StandardRequest:
cpi temp1,GET_STATUS ;00 主机请求设备、接口、或终端的特性状态
breq ComposeGET_STATUS ;
cpi temp1,CLEAR_FEATURE ;01 主机请求使一个设备、接口、或终端的一个特性不可用
breq ComposeCLEAR_FEATURE ;
cpi temp1,SET_FEATURE ;03 主机请求使能一个设备、接口、或终端
breq ComposeSET_FEATURE ;
cpi temp1,SET_ADDRESS ;05 主机指定以后与设备通讯的地址
breq ComposeSET_ADDRESS ;nastav adresu
cpi temp1,GET_DESCRIPTOR ;06 主机请求一个特定的描述符
breq ComposeGET_DESCRIPTOR ;vygeneruj ho
cpi temp1,SET_DESCRIPTOR ;07 主机增加一个描述符或更新一个存在的描述符
breq ComposeSET_DESCRIPTOR ;
cpi temp1,GET_CONFIGURATION ;08 主机请求目前设备的配置值
breq ComposeGET_CONFIGURATION ;
cpi temp1,SET_CONFIGURATION ;09 引导设备使用所选择的配置
breq ComposeSET_CONFIGURATION ;
cpi temp1,GET_INTERFACE ;0A 主机请求当前的接口号
breq ComposeGET_INTERFACE ;
cpi temp1,SET_INTERFACE ;0B 主机请求使用一个接口
breq ComposeSET_INTERFACE ;
cpi temp1,SYNCH_FRAME ;0C 设备设置和报告一个终端同步帧的序号
breq ComposeSYNCH_FRAME ;
;ak sa nenasla znama poziadavka
rjmp ZeroDATA1Answer ;ak to bolo nieco nezname, tak priprav nulovu odpoved
ComposeSET_ADDRESS: ;05 主机指定以后与设备通讯的地址
lds temp1,InputBufferBegin+4 ;取得新地址
rcall SetMyNewUSBAddresses ;ENG;and compute NRZI and bitstuffing coded adresses
ldi State,AddressChangeState ;改变地址状态
rjmp ZeroDATA1Answer ;返回一个0长度数据包
ComposeSET_CONFIGURATION: ;09 引导设备使用所选择的配置
lds ConfigByte,InputBufferBegin+4 ;取得主机要求的配置
ComposeCLEAR_FEATURE: ;01 主机请求使一个设备、接口、或终端的一个特性不可用
ComposeSET_FEATURE: ;03 主机请求使能一个设备、接口、或终端
ComposeSET_INTERFACE: ;0B 主机请求使用一个接口
ZeroStringAnswer:
rjmp ZeroDATA1Answer ;posli nulovu odpoved
ComposeGET_STATUS: ;00 主机请求设备、接口、或终端的特性状态
TwoZeroAnswer:
ldi temp0,2 ;pocet mojich bytovych odpovedi do temp0
ComposeGET_STATUS2:
ldi ZH, high(StatusAnswer<<1) ;加载ROM指针(设备、接口、或终端的状态)
ldi ZL, low(StatusAnswer<<1)
rjmp ComposeEndXXXDescriptor
ComposeGET_CONFIGURATION: ;08 主机请求目前设备的配置值
and ConfigByte,ConfigByte ;是否为0(为0表示还没有配置)
breq OneZeroAnswer ;
ldi temp0,1 ;pocet mojich bytovych odpovedi do temp0
ldi ZH, high(ConfigAnswerMinus1<<1) ;加载ROM指针
ldi ZL, low(ConfigAnswerMinus1<<1)+1
rjmp ComposeEndXXXDescriptor ;a dokonci
ComposeGET_INTERFACE: ;0A 主机请求当前的接口号
ldi ZH, high(InterfaceAnswer<<1) ;ROM指针 na odpoved
ldi ZL, low(InterfaceAnswer<<1)
ldi temp0,1 ;pocet mojich bytovych odpovedi do temp0
rjmp ComposeEndXXXDescriptor ;a dokonci
ComposeSYNCH_FRAME: ;0C 设备设置和报告一个终端同步帧的序号
ComposeSET_DESCRIPTOR: ;07 主机增加一个描述符或更新一个存在的描述符
rcall ComposeSTALL ;不支持
ret
ComposeGET_DESCRIPTOR: ;06 主机请求一个特定的描述符
lds temp1,InputBufferBegin+5 ;DescriptorType do temp1
cpi temp1,DEVICE ;设备描述符(DeviceDescriptor)
breq ComposeDeviceDescriptor ;
cpi temp1,CONFIGURATION ;配置描述符(ConfigurationDescriptor)
breq ComposeConfigDescriptor ;
cpi temp1,STRING ;字符串描述符(StringDeviceDescriptor)
breq ComposeStringDescriptor ;
ret
ComposeDeviceDescriptor:
ldi ZH, high(DeviceDescriptor<<1) ;ROM指针 na descriptor
ldi ZL, low(DeviceDescriptor<<1)
ldi temp0,0x12 ;pocet mojich bytovych odpovedi do temp0
rjmp ComposeEndXXXDescriptor ;a dokonci
ComposeConfigDescriptor:
ldi ZH, high(ConfigDescriptor<<1) ;ROM指针 na descriptor
ldi ZL, low(ConfigDescriptor<<1)
ldi temp0,9+9+7 ;pocet mojich bytovych odpovedi do temp0
ComposeEndXXXDescriptor:
lds TotalBytesToSend,InputBufferBegin+8 ;取得回应给主机的最大字节数
cp TotalBytesToSend,temp0
brcs HostConfigLength ;当前回应的数据量大于最大字节数,不允许回应的数据超量
mov TotalBytesToSend,temp0 ;当前回应的数据量少于最大字节数,有多少回应多少
HostConfigLength:
mov temp0,TotalBytesToSend
clr TransmitPart ;传送的次数(每次传送8字节)
andi temp0,0b00000111 ;字节数模8
breq Length8Multiply ;是否为8字节的整数
inc TransmitPart ;不是,就得多传送1次
Length8Multiply:
mov temp0,TotalBytesToSend ;
lsr temp0 ;右移3次(除以8)
lsr temp0
lsr temp0
add TransmitPart,temp0 ;得到总共需要传输的次数
ldi temp0,DATA0PID ;开始PID为DATAO,以后就是DATA1/DATA0变换
sts OutputBufferBegin+1,temp0 ;送入到输出缓冲区+1
rjmp ComposeNextAnswerPart
ComposeStringDescriptor:
ldi temp1,4+8 ;ak RAMread=4(vkladaj nuly z ROM-koveho citania) + 8(za prvy byte nevkldadaj nulu)
mov RAMread,temp1
lds temp1,InputBufferBegin+4 ;DescriptorIndex do temp1
cpi temp1,0 ;LANGID String
breq ComposeLangIDString ;
cpi temp1,2 ;DevNameString
breq ComposeDevNameString ;
brcc ZeroStringAnswer ;ak je DescriptorIndex vyssi nez 2 - posli nulovu odpoved
;inak to bude VendorString
ComposeVendorString:
ldi ZH, high(VendorStringDescriptor<<1) ;ROM指针 na descriptor
ldi ZL, low(VendorStringDescriptor<<1)
ldi temp0,(VendorStringDescriptorEnd-VendorStringDescriptor)*4-2 ;pocet mojich bytovych odpovedi do temp0
rjmp ComposeEndXXXDescriptor ;a dokonci
ComposeDevNameString:
ldi ZH, high(DevNameStringDescriptor<<1) ;ROM指针 na descriptor
ldi ZL, low(DevNameStringDescriptor<<1)
ldi temp0,(DevNameStringDescriptorEnd-DevNameStringDescriptor)*4-2 ;pocet mojich bytovych odpovedi do temp0
rjmp ComposeEndXXXDescriptor ;a dokonci
ComposeLangIDString:
clr RAMread
ldi ZH, high(LangIDStringDescriptor<<1) ;ROM指针 na descriptor
ldi ZL, low(LangIDStringDescriptor<<1)
ldi temp0,(LangIDStringDescriptorEnd-LangIDStringDescriptor)*2;pocet mojich bytovych odpovedi do temp0
rjmp ComposeEndXXXDescriptor ;a dokonci
;------------------------------------------------------------------------------------------
ZeroDATA1Answer:
rcall ComposeZeroDATA1PIDAnswer
ret
;------------------------------------------------------------------------------------------
SetMyNewUSBAddresses: ;nastavi nove USB adresy v NRZI kodovani ;ENG;set new USB addresses in NRZI coded
mov temp2,temp1 ;address to temp2 and temp1 and temp3
mov temp3,temp1 ;
cpi temp1,0b01111111 ;ENG;if address contains less than 6 ones
brne NewAddressNo6ones ;ENG;then don't add bitstuffing
ldi temp1,0b10111111 ;ENG;else insert one zero - bitstuffing
NewAddressNo6ones:
andi temp3,0b00000111 ;ENG;mask 3 low bits of Address
cpi temp3,0b00000111 ;ENG;and if 3 low bits of Address is no all ones
brne NewAddressNo3ones ;ENG;then no change address
;ENG;else insert zero after 3-rd bit (bitstuffing)
sec ;set carry
rol temp2 ;ENG;rotate left
andi temp2,0b11110111 ;ENG;and inserted zero after 3-rd bit
NewAddressNo3ones:
sts MyOutAddressSRAM,temp2 ;ENG;store new non-coded address Out (temp2)
;ENG;and now perform NRZI coding
rcall NRZIforAddress ;ENG;NRZI for AddressIn (in temp1)
sts MyInAddressSRAM,ACC ;ENG;store NRZI coded AddressIn
lds temp1,MyOutAddressSRAM ;ENG;load non-coded address Out (in temp1)
rcall NRZIforAddress ;ENG;NRZI for AddressOut
sts MyOutAddressSRAM,ACC ;ENG;store NRZI coded AddressOut
ret ;ENG;and return
;------------------------------------------------------------------------------------------
NRZIforAddress:
clr ACC ;vychodzi stav odpovede - mojej nNRZI USB adresy ;ENG;original answer state - of my nNRZI USB address
ldi temp2,0b00000001 ;maska na xorovanie ;ENG;mask for xoring
ldi temp3,8 ;pocitadlo bitov ;ENG;bits counter
SetMyNewUSBAddressesLoop:
mov temp0,ACC ;zapamatat si koncovu odpoved ;ENG;remember final answer
ror temp1 ;do carry vysielany bit LSB (v smere naskor LSB a potom MSB) ;ENG;to carry transmitting bit LSB (in direction firstly LSB then MSB)
brcs NoXORBits ;ak je jedna - nemen stav ;ENG;if one - don't change state
eor temp0,temp2 ;inak sa bude stav menit podla posledneho bitu odpovede ;ENG;otherwise state will be changed according to last bit of answer
NoXORBits:
ror temp0 ;posledny bit zmenenej odpovede do carry ;ENG;last bit of changed answer to carry
rol ACC ;a z carry do koncovej odpovede na miesto LSB (a sucasne prehodenie LSB a MSB poradia) ;ENG;and from carry to final answer to the LSB place (and reverse LSB and MSB order)
dec temp3 ;zmensi pocitadlo bitov ;ENG;decrement bits counter
brne SetMyNewUSBAddressesLoop ;ak pocitadlo bitov nie je nulove opakuj vysielanie s dalsim bitom ;ENG;if bits counter isn't zero repeat transmitting with next bit
ret
;------------------------------------------------------------------------------------------
;------------------------------------------------------------------------------------------
PrepareOutContinuousBuffer:
rcall PrepareContinuousBuffer
rcall MakeOutBitStuff
ret
;------------------------------------------------------------------------------------------
PrepareContinuousBuffer:
mov temp0,TransmitPart
cpi temp0,1
brne NextAnswerInBuffer ;ak uz je buffer prazdny
rcall ComposeZeroAnswer ;priprav nulovu odpoved
ret
NextAnswerInBuffer:
dec TransmitPart ;znizit celkovu dlzku odpovede
ComposeNextAnswerPart:
mov temp1,TotalBytesToSend ;发送的总字节
subi temp1,8 ;是否大于8字节
ldi temp3,8 ;不够8字节也发送1次
brcc Nad8Bytov
mov temp3,TotalBytesToSend ;剩下发送的总字节<8字节
clr TransmitPart
inc TransmitPart ;发送1次
Nad8Bytov:
mov TotalBytesToSend,temp1 ;保存发送的总字节-8
rcall LoadXXXDescriptor ;加载XXX描述符
ldi ByteCount,2 ;dlzka vystupneho 缓冲区 (iba SOP a PID)
add ByteCount,temp3 ;+ pocet bytov
rcall AddCRCOut ;输出缓冲区 CRC 校验
inc ByteCount ;增加2个CRC16的发送字节数
inc ByteCount
ret ;skonci
;------------------------------------------------------------------------------------------
.equ USBversion =0x0101 ;pre aku verziu USB je to (1.01)
.equ VendorUSBID =0x03EB ;identifikator dodavatela (Atmel=0x03EB)
.equ DeviceUSBID =0x21FE ;identifikator vyrobku (USB to RS232 converter AT90S2313=0x21FE)
.equ DeviceVersion =0x0002 ;cislo verzie vyrobku (verzia=0.02)
.equ MaxUSBCurrent =46 ;prudovy odber z USB (46mA)
;------------------------------------------------------------------------------------------
DeviceDescriptor: ;设备描述符
.db 0x12,0x01 ;0 byte - 描述符长度
;1 byte - 固定设备(01)
.dw USBversion ;2,3 byte - USB 发布号 (1.01版)
.db 0x00,0x00 ;4 byte - 类代码
;5 byte - 子类代码
.db 0x00,0x08 ;6 byte - 协议代码
;7 byte - 终端0最大包大小
.dw VendorUSBID ;8,9 byte - 销售商ID (Cypress=0x04B4)
.dw DeviceUSBID ;10,11 byte - 产品ID (teplomer=0x0002)
.dw DeviceVersion ;12,13 byte - 设备发布号BCD (verzia=0.01)
.db 0x01,0x02 ;14 byte - 给制造商的字符串描述符的指针 "vyrobca"
;15 byte - 给产品的字符串描述符的指针 "vyrobok"
.db 0x00,0x01 ;16 byte - 包括了序列号的字符串描述符的指针 "seriove cislo"
;17 byte - 可能的配置的号码
DeviceDescriptorEnd:
;------------------------------------------------------------------------------------------
ConfigDescriptor: ;配置描述符
.db 0x9,0x02 ;0 byte - 描述符长度
;1 byte - 固定配置(02)
ConfigDescriptorLength:
.dw 9+9+7 ;这个配置返回的所有数据的字节大小
ConfigAnswerMinus1:
.db 1,1 ;支持的接口号,SET_CONFIGURATION和GET_CONFIGURATION请求的标示符
.db 0,0x80 ;这个配置的字符串描述符的指针,自供电/总线供电和远程唤醒设置
.db MaxUSBCurrent/2,0x09 ;需要的总线电能, 接口描述符长度
.db 0x04,0 ;固定接口(04); 识别这个接口的号
InterfaceAnswer:
.db 0,1 ;用于选择一个替换设置的值,支持的终端号码
StatusAnswer:
.db 0,0 ;类代码,子类代码
.db 0,0 ;协议代码,接口的字符串描述符的指针
.db 0x07,0x5 ;终端描述符的长度,固定终端(05)
.db 0x81,0 ;终端号和方向,支持
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -