背景
需求為實現一個鍵盤產品,於是將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