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

相关文章

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

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

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

Spring组件初始化扩展点BeanPostProcessor的作用详解

《Spring组件初始化扩展点BeanPostProcessor的作用详解》本文通过实战案例和常见应用场景详细介绍了BeanPostProcessor的使用,并强调了其在Spring扩展中的重要性,感... 目录一、概述二、BeanPostProcessor的作用三、核心方法解析1、postProcessB

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::