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)

CH549/CH548学习笔记7 - USB Device初始化_第1张图片

CH549/CH548学习笔记7 - USB Device初始化_第2张图片

 设置USB为设备模式,即

USB_CTRL = 0;

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

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

CH549/CH548学习笔记7 - USB Device初始化_第3张图片

 设置位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字节。

CH549/CH548学习笔记7 - USB Device初始化_第4张图片

#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字节

CH549/CH548学习笔记7 - USB Device初始化_第5张图片

6. 初始化地址

CH549/CH548学习笔记7 - USB Device初始化_第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初始化_第7张图片

你可能感兴趣的:(MCU编程,单片机,嵌入式硬件)