⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avr309-usb 到 uart 协议转换程序.txt

📁 AVR309-USB 到 UART 协议转换程序。
💻 TXT
📖 第 1 页 / 共 5 页
字号:
       sbi   UCR,RXCIE                  ;
       reti
;------------------------------------------------------------------------------------------
;********************************************************************
;* 初始化程序
;********************************************************************
;------------------------------------------------------------------------------------------
reset:       ;初始化AVR资源:堆栈、串行口、USB缓冲区、中断
       ldi   temp0,StackBegin           ;初始化堆栈
       out   SPL,temp0

       clr   XH                         ;RS232 指针
       clr   YH                         ;USB 指针
       clr   ZH                         ;ROM 指针
       sts   RS232BufferBegin+0,YH      ;znuluj dlzky RS232 kodu v bufferi
       ldi   temp0,RS232BufferBegin+4
       sts   RS232BufferBegin+1,temp0   ;znuluj ukazovatel citania
       sts   RS232BufferBegin+2,temp0   ;znuluj ukazovatel zapisu
       clr   RS232BufferFull

       rcall InitACKBufffer             ;初始化 ACK 缓冲区
       rcall InitNAKBufffer             ;初始化 NAK 缓冲区

       rcall USBReset                   ;初始化 USB 接口到默认值

       sbi   TSOPpullupPort,TSOPpin     ;上拉红外接收口

       ldi   temp0,(1<<LEDlsb0)+(1<<LEDlsb1)+(1<<LEDlsb2)
       out   LEDPortLSB,temp0           ;用户自定义 PD 输出高
       ldi   temp0,(1<<LEDmsb3)+(1<<LEDmsb4)+(1<<LEDmsb5)+(1<<LEDmsb6)+(1<<LEDmsb7)
       out   LEDPortMSB,temp0           ;用户自定义 PB 输出高

       sbi   PORTD,0                    ;上拉串行接收口 RxD
       ldi   temp0,InitBaudRate         ;串行通讯波特率
       out   UBRR,temp0
       sbi   UCR,TXEN                   ;允许串行发送
       sbi   UCR,RXEN                   ;允许串行接收
       sbi   UCR,RXCIE                  ;允许 interrupt od prijimania UART

       ldi   temp0,0x0F                 ;设置 INT0、INT1 上升沿中断
       out   MCUCR,temp0                ;
       ldi   temp0,1<<INT0              ;允许外部中断 INT0
       out   GIMSK,temp0
;
;********************************************************************
;* 主程序
;********************************************************************
       sei               ;允许全局中断
Main:
;主循环。检查动作标志,如果标志置位,执行请求的动作。另外,这个例程检查数据线上的USB
;复位,如果检测到则重新初始化USB 微控制器界面。
       sbis  inputport,DATAminus        ;测试 D- 是否为0
       rjmp  CheckUSBReset              ;如果为0检查 USB 复位

       cpi   ActionFlag,DoReceiveSetupData ;是否接收到配置数据
       breq  ProcReceiveSetupData
       cpi   ActionFlag,DoPrepareOutContinuousBuffer ;是否准备从缓冲区输出连续数据
       breq  ProcPrepareOutContinuousBuffer
       rjmp  Main

CheckUSBReset:
       ldi   temp0,255                  ;进入 USB 复位时间 (10ms - 100us),集线器发出至少10mS
WaitForUSBReset:
       sbic  inputport,DATAminus        ;测试 D+ 是否为0
       rjmp  Main
       dec   temp0                      ;等待复位
       brne  WaitForUSBReset            ;集线器开始重新设置本设备前,会复位本设备
       rcall USBReset                   ;USB 复位
       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
;
;********************************************************************
;* INT0 中断处理
;********************************************************************
INT0Handler:             ;处理 INT0
;这是INT0 外部中断的中断服务例程。主要的接收/发送引擎,从USB 数据线模仿,储存数据到缓
;冲,判断USB 包的所有者(USB 地址),包确认,发送回答到USB 主机。USB 引擎的主要基础。
       in    backupSREG,SREG            ;INT0 中断中的SREG备份
       push  temp0
       push  temp1

       ldi   temp0,3                    ;为下面检测低电平有效数据准备
       ldi   temp1,2                    ;为下面检测高电平有效数据准备
       ;测试信号沿,用来达到同步(中断响应可能延迟 +/-4 个周期)
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               ;继续检测起始包SOP 完成
       rjmp  EndInt0HandlerPOP2         ;起始包SOP 检测失败,退出中断服务程序
;
EndInt0Handler: ;结束中断0处理
       pop   ACC
       pop   RS232BufptrX
       pop   temp3
       pop   temp2
EndInt0HandlerPOP:                      ;结束中断0处理
       pop   USBBufptrY
       pop   ByteCount
       mov   bitcount,backupbitcount    ;恢复移位计数器
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    ;备份移位计数器 (在中断返回时恢复)
                ;(读入第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            ;准备将移位缓冲区中的数据存入输入缓冲区
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                 ;初始化移位计数器
       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 ;取出输入移位缓冲区第0字节
       lds   temp1,InputShiftBufferBegin+1 ;取出输入移位缓冲区第1字节
       brne  TestDataPacket             ;接收到的数据大于3字节时,只能是循环位(DATA0)或(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)  ;注:如果不是本机地址。可能是设置包后面的数据包
       brne  TestDataPacket             ;  所以跳转到数据包检测
       ldi   State,SetupState           ;标记为设置状态
       rjmp  EndInt0HandlerPOP          ;结束中断0处理
TestOutPacket:  ;检测是不是 OUT 包
       cpi   temp0,nNRZIOUTPID          ;是不是 OUT 包
       brne  TestInPacket
       cp    temp1,MyOutAddress         ;是不是本机地址(OUT)
       brne  TestDataPacket
       ldi   State,OutState             ;标记为 OUT 状态
       rjmp  EndInt0HandlerPOP          ;结束中断0处理
TestInPacket:   ;检测是不是 IN 包
       cpi   temp0,nNRZIINPID           ;是不是 IN 包
       brne  TestDataPacket
       cp    temp1,MyInAddress          ;是不是本机地址(IN)
       breq  AnswerToInRequest

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   ;是否要求改变地址

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -