背景
需求为实现一个键盘产品,于是将C8051F340
作为主控制器。本篇记录C8051F340
的USB控制器
相关知识点,阅读本篇文章需要读者具有最基本的USB相关知识。
正文
-
C8051F340
结构
C8051F340
,以下简称F340
,为silicon公司出品的8位单片机,具有USB接口,可支持USB全速/低速两种模式,USB功能控制器包括一个串行接口引擎(SIE),一个USB收发器,1k FIFO块,该控制器物理层遵循USB2.0通信协议,架构图如下:
此处可以将USB看做一个独立于F340
的外设,F340
通过USB控制器提供的寄存器来控制USB控制器,其内部共含有4个物理端点,端点0可同时含有IN/OUT双向通道,端点1-端点3为单向通道,但可将对应的3个端点模拟为双向通道,只需将对应端点的FIFO部分配置为两部分——IN/OUT,在USB运行中,改变对应方向寄存器即可。
F340
只能作为USB从设备。 -
C8051F340
之USB寄存器读写方式
USB所有的寄存器都通过两组特殊功能寄存器(SFR)访问:
USB0 Address(USB0ADR)
:对应的要读写寄存器的地址;
USB0 Data(USB0DAT)
:对应寄存器读或写的数据。
即先将要访问的寄存器地址写入USB0ADR
,下一步操作USB0DAT
则完成对对应寄存器读/写操作,对应读写宏定义如下:
#define POLL_READ_BYTE(addr, target) while(USB0ADR & 0x80);
READ_BYTE(addr, target);
#define READ_BYTE(addr, target) USB0ADR = (0x80 | addr);
while (USB0ADR & 0x80); target = USB0DAT
#define POLL_WRITE_BYTE(addr, data) while(USB0ADR & 0x80);
WRITE_BYTE(addr, data);
#define WRITE_BYTE(addr, data) USB0ADR = (addr); USB0DAT = data;
C8051F340
USB时钟配置
USB可通过寄存器USB0XCN
配置USB为全速/低速模式。当选择为低速模式时,USB0的时钟必须为6MHZ,当工作在全速模式时,USB0必须工作在48MHZ,时钟的配置方法在另一篇博客Silicon C8051F340之时钟系统中已详述。注意配置CLKREC(Clock Recovery Control)
寄存器,Clock Recovery circuitry的作用是用来将USB数据流与控制器内部时钟相同步,使USB控制器能准确读取到USB主机输入的USB数据流,配置方法文档内已说的很明白,不再重复。以下为配置USB为全速模式的示例代码:
void USB0_Init (void)
{
POLL_WRITE_BYTE (POWER, 0x08); // Force Asynchronous USB Reset
POLL_WRITE_BYTE (IN1IE, 0x07); // Enable Endpoint 0-1 in interrupts
POLL_WRITE_BYTE (OUT1IE,0x07); // Enable Endpoint 0-1 out interrupts
POLL_WRITE_BYTE (CMIE, 0x07); // Enable Reset, Resume, and Suspend interrupts
USB0XCN = 0xE0; // Enable transceiver; select full speed
POLL_WRITE_BYTE (CLKREC,0x89); // Enable clock recovery,
// single-step mode disabled
EIE1 |= 0x02; // Enable USB0 Interrupts
// Enable USB0 by clearing the USB
POLL_WRITE_BYTE (POWER, 0x01); // Inhibit Bit and enable suspend
// detection
}
C8051F340
USB中断
作为一个用户(单片机的编程者),在USB0中断中,我们只需要关心3大类中断寄存器即可,CMINT(Common interrupt)
(公共中断寄存器),IN1INT
(输入端点中断寄存器),OUT1INT
(输出端点中断寄存器)。USB的通信协议规定,端点0通常用来传递配置信息,其他端点根据端点类型(大容量或是中断或是同步)来传递不同的端点数据,USB通信细节本篇不再赘述,会在博客USB通信详解系列中详述。以下贴出USB0中断处理代码,会更加直观些:
void Usb_ISR (void) interrupt 8 // USB中断入口
{
unsigned char bCommon, bIn, bOut;
POLL_READ_BYTE (CMINT, bCommon); // USB0公共中断寄存器
POLL_READ_BYTE (IN1INT, bIn); // USB0输入端点中断寄存器
POLL_READ_BYTE (OUT1INT, bOut); // USB0输出端点中断寄存器
{
if (bCommon & rbRSUINT) { // 恢复
Usb_Resume ();
}
if (bCommon & rbRSTINT) { // 复位
Usb_Reset ();
}
if (bCommon & rbSUSINT) { // 挂起
Usb_Suspend ();
}
if (bIn & rbEP0) { // 端点0中断处理
Handle_Control ();
}
if (bIn & rbIN1) { // 端点1输入中断处理
Handle_In1 ();
}
if (bOut & rbOUT1) { // 端点1输出中断处理
Handle_Out1 ();
}
}
}
从以上代码可以看出,当有数据来或是需要写的时候,使能了对应中断,则SIE即会产生相关中断,通知MCU来处理对应的USB数据。具体如何处理对应的数据会在博客USB通信详解系列中详述。
至此,记录完毕。
参考链接:
C8051F340数据手册。
记录时间:2017-4-6
记录地点:深圳WZ