CH549/CH548学习笔记7 - USB Device初始化

2024-01-11 13:10

本文主要是介绍CH549/CH548学习笔记7 - USB Device初始化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

​​​​​​​1. 中断使能位 

 2. USB 控制寄存器(USB_CTRL)

3.  USB 设备物理端口控制寄存器(UDEV_CTRL)

4. 初始化端点0

5. 初始化其他端点

6. 初始化地址

 7. 启动USB设备

8. 允许USB端口

9. 初始化中断


1. 中断使能位 

在初始化前需要先关闭USB中断。

IE_USB = 0;

该位位于扩展中断使能寄存器(IE_EX)中

 2. USB 控制寄存器(USB_CTRL)

 设置USB为设备模式,即

USB_CTRL = 0;

位7为0表示设备模式, 其他位清零。

3.  USB 设备物理端口控制寄存器(UDEV_CTRL)

 设置位7位1,禁止DP/DM下拉电阻;位2为0,选择12Mbps全速模式。

UDEV_CTRL = bUD_PD_DIS;

4. 初始化端点0

CH549/CH548一共支持5个双向端点。除了端点0是发送和接收共用数据缓冲区,其他4个端点需要单独空间,而且也是最大支持64字节。而端点1~3支持DMA和双数据缓冲区(单向时),端点4不支持双数据缓冲区,而且它的缓冲区在端点0缓冲区的后面。

端点 0 是默认端点,必须是控制传输,发送和接收共用一个 64 字节数据缓冲区,支持DMA传输。

#define EP0_IN_MEM_SIZE             (64)
#define EP0_OUT_MEM_SIZE            (64)
#define USBEP_BUFFER_ADDR_START     0x0000

端点的大小最大64字节,可以小于64字节,当小于64字节时需要多留2个字节。比如设置端点0的大小为32个字节,那么分配的buffer大小要为32+2 = 34字节。不过当端点为双向时,大小必须为64字节,对于端点0,如果要用到端点4,大小必须为64字节。

#ifdef __SDCC
EXTERN xdata uint8_t _at_ (USBEP_BUFFER_ADDR_START) usbEp0Buffer[EP0_IN_MEM_SIZE + EP4_OUT_MEM_SIZE + EP4_IN_MEM_SIZE];
#else
EXTERN xdata uint8_t usbEp0Buffer[EP0_IN_MEM_SIZE + EP4_OUT_MEM_SIZE + EP4_IN_MEM_SIZ] _at_ (USBEP_BUFFER_ADDR_START);
#endif

另外,buffer的起始地址必须2字节对齐(偶地址)。

初始化端点0的DMA地址即可完成初始化

UEP0_DMA = (uint16_t)usbEp0Buffer;

5. 初始化其他端点

 根据实际的应用定义对应的端点,以端点1为例,假设端点1作为IN端点。

#define EP1_OUT_MEM_SIZE    0
#define EP1_IN_MEM_SIZE     4

 定义端点1用到的缓存空间。

#if (EP1_OUT_MEM_SIZE > 0 || EP1_IN_MEM_SIZE > 0)
#define USBEP1_BUFFER_ADDR_START    (USBEP_BUFFER_ADDR_START + sizeof(usbEp0Buffer))
#ifdef __SDCC
EXTERN xdata uint8_t _at_ USBEP1_BUFFER_ADDR_START usbEp1Buffer[EP1_OUT_MEM_SIZE + EP1_IN_MEM_SIZE];
#else
EXTERN xdata uint8_t usbEp1Buffer[EP1_OUT_MEM_SIZE + EP1_IN_MEM_SIZE] _at_ USBEP1_BUFFER_ADDR_START;
#endif
#endif

 将usbEp1Buffer的起始地址定义在端点0的缓冲区的后面(端点0和端点4的缓冲区大小)。

而端点1的缓存空间分OUT和IN2个空间,前面是OUT空间,后面是IN空间(如果只是IN,则OUT空间为0)。

#if (EP1_OUT_MEM_SIZE > 0 || EP1_IN_MEM_SIZE > 0)
UEP1_DMA = (uint16_t)usbEp1Buffer;
UEP1_CTRL = 0;
#if(EP1_OUT_MEM_SIZE > 0)
UEP1_CTRL |= bUEP_AUTO_TOG | UEP_R_RES_ACK;
UEP4_1_MOD |= bUEP1_RX_EN;                                      //OUT Enable
#endif
#if(EP1_IN_MEM_SIZE > 0)
UEP1_CTRL |= bUEP_AUTO_TOG | UEP_T_RES_NAK;
UEP4_1_MOD |= bUEP1_TX_EN;                                      //IN Enable
#endif
UEP1_T_LEN = 0;
#endif

同样,端点1也支持DMA,初始化DMA地址,然后根据IN还是OUT初始化UEP1_CTRL和UEP4_1_MOD,设置bUEP_AUTO_TOG的目的是让芯片在发送成功或者接收成功后自动翻转相应的同步触发位(不理解为什么端点0没有这样设置),最后发送长度清空,即将UEP1_T_LEN清0。

端点2和端点3的初始化与端点1类似。而端点4比较特殊,它的收发缓存区的地址在端点0后面,这里就只定义一个指针

#if(EP4_OUT_MEM_SIZE > 0 || EP4_IN_MEM_SIZE > 0)
EXTERN xdata uint8_t *usbEp4Buffer;
#endif

 然后在初始化这个指针指向usbEp0Buffer中端点4部分的缓冲区即可。

#if (EP4_OUT_MEM_SIZE > 0 || EP4_IN_MEM_SIZE > 0)
usbEp4Buffer = usbEp0Buffer + EP0_IN_MEM_SIZE;
UEP4_CTRL = 0;
#if(EP4_OUT_MEM_SIZE > 0)
UEP4_CTRL |= bUEP_AUTO_TOG | UEP_R_RES_ACK;
UEP1_4_MOD |= bUEP4_RX_EN;                                      //OUT Enable
#endif
#if(EP4_IN_MEM_SIZE > 0)
UEP4_CTRL |= bUEP_AUTO_TOG | UEP_T_RES_NAK;
UEP1_4_MOD |= bUEP4_TX_EN;                                      //IN Enable
#endif
UEP4_T_LEN = 0;
#endif

注意,当端点(1 - 4)为双向时, OUT的大小必须为64字节。当使用端点4时,,端点0的缓冲区大小必须为64字节。而端点1-3为双向双缓冲区时,缓冲区大小必须是256字节

6. 初始化地址

默认地址为0

USB_DEV_AD = 0x00;

 7. 启动USB设备

USB_CTRL |= bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN;         // 启动USB设备及DMA,在中断期间中断标志未清除前自动返回NAK

bUC_DEV_PU_EN: 使能 USB 设备传输并且启用内部上拉电阻

bUC_INT_BUSY:自动应答忙 NAK

bUC_DMA_EN:使能 USB 的 DMA 和 DMA 中断

8. 允许USB端口

UDEV_CTRL |= bUD_PORT_EN;                                      // 允许USB端口

bUD_PORT_EN:使能物理端口

9. 初始化中断

USB_INT_FG = 0xFF;                                             // 清中断标志
USB_INT_EN = bUIE_SUSPEND | bUIE_TRANSFER | bUIE_BUS_RST;
IE_USB = 1;

这篇关于CH549/CH548学习笔记7 - USB Device初始化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/594466

相关文章

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

Spring Bean初始化及@PostConstruc执行顺序示例详解

《SpringBean初始化及@PostConstruc执行顺序示例详解》本文给大家介绍SpringBean初始化及@PostConstruc执行顺序,本文通过实例代码给大家介绍的非常详细,对大家的... 目录1. Bean初始化执行顺序2. 成员变量初始化顺序2.1 普通Java类(非Spring环境)(

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

重新对Java的类加载器的学习方式

《重新对Java的类加载器的学习方式》:本文主要介绍重新对Java的类加载器的学习方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍1.1、简介1.2、符号引用和直接引用1、符号引用2、直接引用3、符号转直接的过程2、加载流程3、类加载的分类3.1、显示

C++类和对象之初始化列表的使用方式

《C++类和对象之初始化列表的使用方式》:本文主要介绍C++类和对象之初始化列表的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C++初始化列表详解:性能优化与正确实践什么是初始化列表?初始化列表的三大核心作用1. 性能优化:避免不必要的赋值操作2. 强

SpringIOC容器Bean初始化和销毁回调方式

《SpringIOC容器Bean初始化和销毁回调方式》:本文主要介绍SpringIOC容器Bean初始化和销毁回调方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录前言1.@Bean指定初始化和销毁方法2.实现接口3.使用jsR250总结前言Spring Bea

Spring实现Bean的初始化和销毁的方式

《Spring实现Bean的初始化和销毁的方式》:本文主要介绍Spring实现Bean的初始化和销毁的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Bean的初始化二、Bean的销毁总结在前面的章节当中介绍完毕了ApplicationContext,也就