PDIUSBD12 USB 驅(qū)動(dòng)程序演示實(shí)驗(yàn)
一.實(shí)驗(yàn)?zāi)康?br>PDIUSBD12(簡(jiǎn)稱D12) USB 芯片符合USB1.1 協(xié)議,廣泛應(yīng)用于各種的USB 設(shè)備。
本實(shí)驗(yàn)程序展示了如何在Small RTOS51 操作系統(tǒng)中實(shí)現(xiàn)D12 驅(qū)動(dòng)程序的編寫。
示例主要實(shí)現(xiàn)了如下功能:USB 設(shè)備的枚舉,通過(guò)D12 的端點(diǎn)2 接受來(lái)自上位機(jī)的數(shù)
據(jù),并通過(guò)單片機(jī)的串口轉(zhuǎn)發(fā)回上位機(jī),同時(shí)驅(qū)動(dòng)ZLG7290 顯示0~9 的數(shù)字。
二.實(shí)驗(yàn)設(shè)備及器件
PC 機(jī) 一臺(tái)
DP-51PROC 單片機(jī)綜合仿真實(shí)驗(yàn)儀 一臺(tái)
USB D12 PARK 模塊 一臺(tái)
USB 連接線 一根
三.實(shí)驗(yàn)步驟
1. D12 PARK 插到A6 區(qū)的排針內(nèi);
2. 使用導(dǎo)線把A2 區(qū)的INT1 與A6 區(qū)的P1_INT0 相連;
3. 使用導(dǎo)線把A2 區(qū)的T0 與A6 區(qū)的P1_IO2 相連;
4. 使用導(dǎo)線把A2 區(qū)的T1 與A6 區(qū)的P1_IO5 相連;
5. 使用導(dǎo)線把A2 區(qū)的A15 與A6 區(qū)的P1_CS 1 相連;
6. 使用導(dǎo)線把A2 區(qū)的P16、P17 分別與D5 區(qū)的SCL、SDA 相連;
7. 使用導(dǎo)線把A2 區(qū)的P10 與D5 區(qū)的/RST 相連,并短接D5 區(qū)的JP1;
8. 使用導(dǎo)線連接A2 區(qū)的P14 與B10 區(qū)的ZDJ_A;
9. B10 區(qū)的ZDJ_B 連接到C1 的GND;
10. 短接B10 區(qū)JP18 的電機(jī)電源跳線
四.實(shí)驗(yàn)參考程序主要部分
/**************************************************************
Small RTOS(51)
The Real-Time Kernel(For Keil c51)
(c) Copyright 2002-2004, chenmingji
All Rights Reserved
V1.20
***************************************************************/
#include "config.h"
/**************************************************************
聲明全局變量
**********************************************************/
extern EPPFLAGS bEPPflags; /*USB 事件標(biāo)志*/
extern uint8 xdata GenEpBuf[]; /*信號(hào)包緩沖區(qū)(命令區(qū))*/
extern uint8 xdata EpBuf[]; /*信號(hào)包緩沖區(qū)(數(shù)據(jù)區(qū))*/
extern uint16 data D12_DATA; /*D12 數(shù)據(jù)的地址變量*/
extern uint16 data D12_COMMAND; /*D12 命令的地址變量*/
//指針的NULL 為0,這個(gè)變量占用0 地質(zhì)避免出現(xiàn)有效的NULL 指針
uint8 OS_Q_MEM_SEL NotUse _at_ 0x0000;
uint8 xdata ShowCase[8];
uint8 xdata PWMH; //高電平脈沖的個(gè)數(shù)
uint8 xdata PWM; //PWM 周期
uint8 xdata COUNTER;
uint8 key_buf[2];
void enumerate_task(void);
void USB_REC_task(void);
void change_speed_task(void);
void get_key_task(void);
void INTT1() interrupt 3
{
COUNTER++;
if(COUNTER < PWMH)
{
P1_4 = 1; //P1.4 變?yōu)楦唠娖?br>}
else
{
P1_4 = 0;
}
}
void usb_ISR(void) interrupt 2
{
OS_INT_ENTER();
EX1 = 0;
OSSemIntPost(D12_isr);
OSIntExit();
}
/**********************************************************
**名稱:init_port()
**功能:端口初始化,D12SUSPD 復(fù)位為0
****************************************************************/
void init_Hard()
{
P0 = 0XFF;
P1 = 0XFF;
P2 = 0XFF;
P3 = 0XFF;
D12SUSPD = 0;
}
/**************************************************************
** 函數(shù)名稱: init
** 功能描述: 初始化函數(shù),一般在多任務(wù)環(huán)境啟動(dòng)前調(diào)用
**************************************************888**************/
void init(void)
{
TMOD &= 0XF0;
TMOD |= 0X01;
// 每10ms 發(fā)生一次T0 中斷
TL0 = (65536 - (11059200 / 12) / 100) % 256;
TH0 = (65536 - (11059200 / 12) / 100) / 256;
ET0 = 1;
TR0 = 1;
PT0 = 0;
EA = 1;
}
void control_init(void)
{
PWMH=0x00;
COUNTER=0x01;
PWM=255;
TMOD = TMOD & 0x0f;
TMOD = TMOD | 0x20; //定時(shí)器1 在模式2 下工作
TL1=0x00;
TH1=0x00; //自動(dòng)重裝的值
TR1=1;
ET1 = 1;
}
/**************************************************************
** 函數(shù)名稱: void init_display(void)
** 功能描述: 初始化LED 顯示
*****************************************************************/
void init_display(void)
{
uint8 i;
ZLG7290_RST = 0;
_nop_();
_nop_();
ZLG7290_RST = 1;
for (i = 0; i < 8; i++)
{
ShowCase[i] = 31;
}
ZLG7290_SendBuf(ShowCase,8);
}
void main(void)
{
OSInit();
init_Hard(); /*初始化硬件*/
init();
control_init();
IT1 = 0;
EX1 = 1;
PX1 = 1;
init_display();
D12_DATA = 0x7002; /*定義數(shù)據(jù)地址*/
D12_COMMAND = 0x7003; /*定義命令地址*/
D12_SetDMA(0x0); /*不使用DMA 功能*/
bEPPflags.value = 0; /*初始化USB 寄存器*/
OSTaskCreate(USB_REC_task , NULL , 0); //創(chuàng)建USB 中斷處理任務(wù)
while(1)
{
PCON = PCON |0x01 ; /* CPU 進(jìn)入休眠狀態(tài) */
}
}
/*************************************************************
** 函數(shù)名稱: void enumerate(void)
** 功能描述: 完成USB 請(qǐng)求處理的任務(wù)
************************************************************/
void enumerate_task(void)
{
//創(chuàng)建其他優(yōu)先級(jí)低的任務(wù)
OSTaskCreate(get_key_task, NULL,2);
OSTaskCreate(change_speed_task, NULL,3);
while(1)
{
OSWait(K_TMO, 2);
IT1 = 0;
EX1 = 1;
reconnect_USB();
while(USB_VIN)
{
usbserve();
OSWait(K_TMO, 1);
}
}
}
/*******************************************************
** 函數(shù)名稱: void USB_REC(void)
** 功能描述: USB 中斷處理任務(wù)
**************************************************************/
void USB_REC_task(void)
{
OSSemCreate(D12_isr , 0);
OSSemCreate(D12_use , 1);
OSTaskCreate(enumerate_task , NULL ,1); //創(chuàng)建USB 請(qǐng)求處理任務(wù)
while(1)
{
OSSemPend(D12_isr , 0);
OSSemPend(D12_use , 0);
fn_usb_isr();
OSSemPost(D12_use);
EX1=1;
}
}
/*************************************************************
** 函數(shù)名稱: void change_speed_task(void)
** 功能描述: 修改馬達(dá)速度任務(wù)。
*************************************************************/
void change_speed_task(void)
{
while(1)
{
OS_ENTER_CRITICAL();
if( bEPPflags.bits.ep1_rxdone)
{
PWMH = GenEpBuf[0];
bEPPflags.bits.ep1_rxdone = 0;
}
OS_EXIT_CRITICAL();
ShowCase[0] = PWMH %10;
ShowCase[1] = (PWMH /10)%10;
ShowCase[2] = (PWMH /100)%10;
OS_ENTER_CRITICAL();
ZLG7290_SendBuf(ShowCase,8);
OS_EXIT_CRITICAL();
OSWait(K_TMO,9);
}
}
/***********************************************************
** 函數(shù)名稱: void get_key_task(void)
** 功能描述: 獲取按鍵值任務(wù)。
**************************************************************/
void get_key_task(void)
{
while(1)
{
OS_ENTER_CRITICAL();
key_buf[0] = ZLG7290_GetKey();
OS_EXIT_CRITICAL();
OSWait(K_TMO, 1);
if(key_buf[0] == 0)
{
continue;
}
OS_ENTER_CRITICAL();
key_buf[1] = ZLG7290_GetKey();
OS_EXIT_CRITICAL();
if(key_buf[0] != key_buf[1])
{
OS_ENTER_CRITICAL();
D12_WriteEndpoint(3, 1, &key_buf[0]);
OS_EXIT_CRITICAL();
}
}
}
五.實(shí)驗(yàn)示例程序簡(jiǎn)析
本由于驅(qū)動(dòng)程序中使用了USB51s.lib 庫(kù),故關(guān)于該庫(kù)的使用方法詳見(jiàn)實(shí)驗(yàn)儀配套光盤
中的《 PDIUSBD12 固件編程指南 》和書(shū)《 PDIUSBD12 固件編程與驅(qū)動(dòng)開(kāi)發(fā) 》。這里僅
僅就敘述如何在Small RTOS51 下編寫D12 USB 驅(qū)動(dòng)程序。
由于對(duì)PDIUSBD12 的操作是一種不能重入的操作,所以必須要在這一次操作完成后才
能進(jìn)行下一次對(duì)PDIUSBD12 的操作。因此,對(duì)PDIUSBD12 器件的操作采用了一個(gè)信號(hào)量
(D12_use)來(lái)管理。這種信號(hào)量管理的方法就像有很多個(gè)門共用一把鑰匙,必須一次只能
開(kāi)一個(gè)門,而開(kāi)這個(gè)門的先后則由任務(wù)的優(yōu)先級(jí)來(lái)決定。
在驅(qū)動(dòng)中使用了2 個(gè)信號(hào)量,其含義如下:
?? D12_use: 不為0,表示PDIUSBD12 處于空閑狀態(tài),可以使用;為0,則表示
PDIUSBD12 正在使用中。不允許其他任務(wù)對(duì)PDIUSBD12 進(jìn)行操作。此信號(hào)量在
創(chuàng)建時(shí)被初始化為1。
?? D12_isr: 不為0,表示檢測(cè)到PDIUSBD12 產(chǎn)生的USB 中斷請(qǐng)求;為0,表示
沒(méi)有USB 中斷請(qǐng)求或者USB 中斷請(qǐng)求已被執(zhí)行處理。,此信號(hào)量在創(chuàng)建時(shí)被初始
化為0。
控制馬達(dá)轉(zhuǎn)速的方法很多,PWM(脈寬調(diào)制)方式是比較常見(jiàn)的一種,實(shí)現(xiàn)較簡(jiǎn)單并
且效果好。在DP-51PRO.NET 中可以實(shí)現(xiàn)PWM 控制馬達(dá)轉(zhuǎn)速實(shí)驗(yàn),其馬達(dá)控制電路參見(jiàn)
綜合實(shí)驗(yàn)7 電機(jī)實(shí)驗(yàn).。
本例程中,PWM 波形由定時(shí)器1 的周期性中斷產(chǎn)生。其代碼實(shí)現(xiàn)見(jiàn)程序清單5.4。定
時(shí)器1 中斷服務(wù)函數(shù)(INTT1)對(duì)全局變量COUNTER 進(jìn)行自增計(jì)數(shù),并與PWMH 進(jìn)行比
較,根據(jù)比較結(jié)果控制P1_4(波形輸出引腳)輸出電平的高低,從實(shí)現(xiàn)PWM 的輸出。馬達(dá)的
轉(zhuǎn)速與PWM 波形中的高電平之占空比成正比。
六.程序演示
由于本示例程序需要跟PC 機(jī)進(jìn)行數(shù)據(jù)通訊,故必須與PC 機(jī)相關(guān)軟件配合使用才能實(shí)
現(xiàn)所有的功能。上位機(jī)軟件可以使用配套光盤中的usb 調(diào)試助手(1.2 版)(有關(guān)usb 調(diào)試助
手的使用請(qǐng)見(jiàn)其幫助文件),該軟件用于向?qū)嶒?yàn)儀發(fā)送控制數(shù)據(jù)和接收發(fā)上來(lái)的按鍵值數(shù)據(jù)。
使用usb 調(diào)試助手軟件之前還必須安裝D12 驅(qū)動(dòng)程序方可正常使用。
首先將USB_D12.hex 文件下載到實(shí)驗(yàn)儀中,運(yùn)行單片機(jī)中的程序。單片機(jī)將配置
PDIUSBD12 并進(jìn)行USB 枚舉,USB D12PARK 模塊上的LED 燈將閃爍幾次。、兩、三秒后,
若USB 枚舉成功,模塊上的LED 將常亮,表示USB 連接正常。此時(shí)打開(kāi)usb 調(diào)試助手,
選擇名稱為Philips PDIUSBD12 Smart Evaluation Board 的設(shè)備,設(shè)置接收端點(diǎn)和發(fā)送端點(diǎn)都
為端點(diǎn)1,設(shè)置接收和發(fā)送管道大小為16 字節(jié)。按下啟動(dòng)按扭,這樣便與實(shí)驗(yàn)儀建立的USB
連接。向發(fā)送區(qū)填入1 個(gè)字節(jié)的數(shù)據(jù),然后發(fā)送到實(shí)驗(yàn)儀,這樣便可實(shí)現(xiàn)馬達(dá)的變速。按下
實(shí)驗(yàn)儀中D7 區(qū)的按鍵,在PC 上便可接收到該按鍵的鍵值。
評(píng)論
查看更多