?? usbfunctions.c
字號:
#include <msp430x14x.h>
#include "USBvariables.h"
#include "USBfunctions.h"
typedef unsigned char uchar;
typedef unsigned int uint;
//外部變量聲明
extern unsigned char KeyChar; //按鍵輸入數值
extern unsigned char SendFlag; //是否發送數據標志
void (*StandardDeviceRequest[])(void)=
{
Get_status,
Clr_feature,
Reserved,
Set_feature,
Reserved,
Set_addr,
Get_descriptor,
Reserved,
Get_config,
Set_config,
Get_interface,
Set_interface,
Reserved,
Reserved,
Reserved,
Reserved
};
/*******************************************
函數名稱: Delayus
功 能: 延時指定微秒(8M晶振)
參 數: US--延時的微秒數(大約,不是很精確)
返回值 : 無
********************************************/
void Delayus(uint US)
{
uint i;
US=US*5/4; // 5/4是在8MHz晶振下,通過軟件仿真反復實驗得到的數值
for( i=0;i<US;i++);
}
/*******************************************
函數名稱: Delayms
功 能: 延時指定毫秒(8M晶振)
參 數: MS--延時的毫秒數
返回值 : 無
********************************************/
void Delayms(uint MS)
{
uint i,j;
for(i=0;i<MS;i++)
for(j=0;j<1141;j++); // 1141是在8MHz晶振下,通過軟件仿真反復實驗得到的數值
}
/*******************************************
函數名稱: D12_init
功 能: 初始化D12接口(包括數據接口和控制接口)
參 數: 無
返回值 : 無
********************************************/
void D12_init(void)
{
USBDAT_DDR|=0xFF; //數據端口設置為輸出
USBCTL_DDR|=BIT(WR_N)|BIT(RD_N)|BIT(C_D)|BIT(D12_CS);//控制引腳設置為輸出
USBINT_DDR&=~BIT(D12_INT); //中斷引腳設置為輸入 //中斷引腳設置為輸入
USBINT_IES|=BIT(D12_INT); //選擇下降沿中斷
USBINT_SEL&=~BIT(D12_INT); //選擇IO端口
USBINT_IE|=BIT(D12_INT); //使能端口中斷
USBCTL_PORT|=BIT(WR_N)|BIT(RD_N)|BIT(D12_CS); //控制引腳無效
EN_GINT(); //使能全局中斷
USBCTL_PORT&=~BIT(D12_CS); //給出片選信號
}
/*******************************************
函數名稱: OutB
功 能: 向D12寫入一個字節數據或者命令
參 數: cmd--命令標識(為CMD是命令,為DAT是數據)
dat--要寫入的字節數據
返回值 : 無
********************************************/
void OutB(uchar cmd,uchar dat)
{
if(cmd==CMD)
{
USBCTL_PORT|=BIT(C_D);
Delayus(5);
USBCTL_PORT&=~BIT(WR_N);
Delayus(5);
USBDAT_PORT=dat;
Delayus(5);
USBCTL_PORT|=BIT(WR_N);
}
else
{
USBCTL_PORT&=~BIT(C_D);
Delayus(1);
USBCTL_PORT&=~BIT(WR_N);
Delayus(1);
USBDAT_PORT=dat;
Delayus(1);
USBCTL_PORT|=BIT(WR_N);
}
}
/*******************************************
函數名稱: InB
功 能: 從D12讀出一個字節數據
參 數: 無
返回值 : dat--讀出的字節數據
********************************************/
uchar InB(void)
{
uchar dat;
USBDAT_DDR=0x00;
USBDAT_PORT=0xFF;
USBCTL_PORT&=~BIT(C_D);
Delayus(1);
USBCTL_PORT&=~BIT(RD_N);
Delayus(1);
dat=USBDAT_PIN;
Delayus(1);
USBCTL_PORT|=BIT(RD_N);
USBDAT_DDR=0xFF;
return dat;
}
/*******************************************
函數名稱: Set_addren
功 能: 設置地址/使能
參 數: addr--設置的地址
enable--使能標志(為1使能,為0禁止)
返回值 : 無
********************************************/
void Set_addren(uchar addr, uchar enable)
{
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD, 0xD0); //輸出設置地址/使能指令
Delayus(1);
if(enable)
{
addr|=0x80; //bit7置1,使能
}
Delayus(1);
OutB(DAT,addr); //輸出設置值
if(USB_FLAG.in_isr == 0)
EN_GINT();
}
/*******************************************
函數名稱: Set_EPen
功 能: 設置端點使能
參 數: enable--使能標志(為1使能,為0禁止)
返回值 : 無
********************************************/
void Set_EPen(uchar enable)
{
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,0xD8); //輸出設置端點使能指令
Delayus(1);
if(enable)
OutB(DAT,1); //設置端點允許
else
OutB(DAT,0); //設置端點禁止
if(USB_FLAG.in_isr == 0)
EN_GINT();
}
/*******************************************
函數名稱: Set_mode
功 能: 設置模式
參 數: config--配置字節信息
clkdiv--分頻因子
返回值 : 無
********************************************/
void Set_mode(uchar config,uchar clkdiv)
{
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,0xF3); //輸出設置模式指令
Delayus(1);
OutB(DAT,config); //輸出配置字節信息
OutB(DAT,clkdiv); //輸出時鐘分頻因數字節
if(USB_FLAG.in_isr == 0)
EN_GINT();
}
/*******************************************
函數名稱: Set_DMA
功 能: 設置DMA工作方式設置
參 數: bMode--設置值
返回值 : 無
********************************************/
void Set_DMA(uchar bMode)
{
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD, 0xFB); //設置DMA工作方命令
Delayus(1);
OutB(DAT, bMode); //輸出設置值
if(USB_FLAG.in_isr == 0)
EN_GINT();
}
/*******************************************
函數名稱: Read_IntR
功 能: 讀取中斷寄存器值
參 數: 無
返回值 : intreg--16位中斷寄存器值
********************************************/
uint Read_IntR(void)
{
uchar regl;
uint intreg;
OutB(CMD,0xF4); //讀取中斷寄存器命令
Delayus(5);
regl=InB( ); //讀取低8位字節
intreg=InB( ); //讀取高8位字節
intreg<<=8;
intreg+=regl; //組合為16位
return intreg;
}
/*******************************************
函數名稱: Sel_EP
功 能: 端點選擇,將內部指針初始化到選擇的緩沖區起始位置
參 數: endp--端點索引號,取值0 ~ 5
返回值 : byte--一個字節的返回數據
********************************************/
uchar Sel_EP(uchar endp)
{
uchar byte;
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,endp); //端點選擇
Delayus(1);
byte=InB( ); //讀出一個字節
if(USB_FLAG.in_isr == 0)
EN_GINT();
return byte;
}
/*******************************************
函數名稱: Sel_EP
功 能: 讀取端點狀態
參 數: endp--端點索引號,取值0 ~ 5
返回值 : status--端點狀態
********************************************/
uchar Read_EPsta(uchar endp)//-----------------
{
uchar status;
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,0x80+endp); //讀取端點狀態命令
status=InB( ); //讀取端點狀態
if(USB_FLAG.in_isr == 0)
EN_GINT();
return status;
}
/*******************************************
函數名稱: Read_LttransSta
功 能: 讀取最后處理狀態寄存器
參 數: endp--端點索引號,取值0 ~ 5
返回值 : status--端點最后處理的狀態
********************************************/
uchar Read_LttransSta(uchar endp)
{
uchar status;
OutB(CMD,0x40+endp); //輸出讀取最后處理狀態寄存器命令
Delayus(5);
status=InB( );
return status; //讀取狀態
}
/*******************************************
函數名稱: Set_EPsta
功 能: 設置端點狀態
參 數: endp--端點索引號,取值0 ~ 5
stall--設置狀態值
返回值 : 無
********************************************/
void Set_EPsta(uchar endp,uchar stall)
{
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,0x40+endp); //發送設置端點狀態命令
Delayus(1);
OutB(CMD,stall); //設置端點狀態
if(USB_FLAG.in_isr == 0)
EN_GINT();
}
/*******************************************
函數名稱: Set_Sresume
功 能: 設置發送恢復
參 數: 無
返回值 : 無
********************************************/
void Set_Sresume(void)
{
OutB(CMD,0xF6); //設置發送恢復
}
/*******************************************
函數名稱: Read_EP
功 能: 讀取端點數據
參 數: endp--端點索引號,取值 0 ~ 5
len--要讀取的數據長度
buf--接收數據指針
返回值 : num--實際讀到的字節數
********************************************/
uchar Read_EP(uchar endp,uchar len,uchar * buf)
{
uchar i,num;
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,endp); //發送選擇端點命令
Delayus(1);
if((InB( )&FULLEMPTY)==0) //如果緩沖區為空
{
if(USB_FLAG.in_isr == 0)
EN_GINT();
return 0; //則返回讀到0字節
}
OutB(CMD,0xF0); //發送讀緩沖區命令
Delayus(1);
num=InB( ); //讀取保留字節
num=InB( ); //讀取數據字節的數目/長度
if(num>len) //如果大于要求讀的字節數目
{
num=len; //則只讀取要求的字節長度
}
for(i=0; i<num; i++)
*(buf+i)=InB( ); //讀取要求的字節數目/長度
OutB(CMD,0xF2); //清緩沖區,新的信息包才可以重新被接受
if(USB_FLAG.in_isr == 0)
EN_GINT();
return num; //返回讀到的字節數
}
/*******************************************
函數名稱: Write_EP
功 能: 將數據寫入端點
參 數: endp--端點索引號,取值 0 ~ 5
len--要寫入的數據長度
buf--發送數據指針
返回值 : num--實際寫入的字節數
********************************************/
uchar Write_EP(uchar endp,uchar len,uchar * buf)
{
uchar i;
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,endp); //發送選擇端點命令
Delayus(1);
i=InB( ); //可選地讀取一個字節
OutB(CMD,0xF0); //發送寫緩沖區命令
Delayus(1);
OutB(DAT,0); //寫入一個保留字節
Delayus(1);
OutB(DAT,len); //寫入即將寫入的字節數目
Delayus(1);
for(i=0; i<len; i++)
{
OutB(DAT,*(buf+i)); //寫入指定的字節
}
Delayus(1);
OutB(CMD,0xFA); //使緩沖區有效
if(USB_FLAG.in_isr == 0)
EN_GINT();
return len; //返回寫入的字節數
}
/*******************************************
函數名稱: Ack_EP
功 能: 應答Setup
參 數: endp--端點索引號,取值 0 ~ 5
返回值 : 無
********************************************/
void Ack_EP(uchar endp)
{
OutB(CMD,endp); //選擇端點
Delayus(1);
OutB(CMD,0xF1); //應答Setup指令
Delayus(1);
if(endp==0)
{
OutB(CMD,0xF2); //清空該端點緩沖區
}
}
/*******************************************
函數名稱: Clear_buf
功 能: 清指定端點的緩沖區(包括雙緩沖區)
參 數: endp--端點索引號,取值 0 ~ 5
返回值 : 無
********************************************/
void Clear_buf(uchar endp)
{
OutB(CMD,endp); //選擇端點
Delayus(1);
OutB(CMD,0xF2); //清空第1個緩沖區
if (endp>=4)
{
OutB(CMD,endp); //選擇端點
Delayus(1);
OutB(CMD,0xF2); //清空第2個緩沖區
}
}
/*******************************************
函數名稱: Stall_ep0
功 能: 使控制端點處于停止狀態
參 數: 無
返回值 : 無
********************************************/
void Stall_ep0(void)
{
Set_EPsta(0,1);
Set_EPsta(1,1);
}
/*******************************************
函數名稱: S_trans
功 能: 通過端點索引 1 發送數據(DATA 類型)
參 數: buf--發送數據指針
len--發送數據長度
返回值 : 無
********************************************/
void S_trans(uchar * buf, uchar len)
{
if(len<=EP0_PACKET_SIZE) //長度小于EP0最大信息包大小才允許發送
{
Write_EP(1,len,buf);
}
}
/*******************************************
函數名稱: Code_trans
功 能: 通過端點索引 1 發送數據(CODE類型)
參 數: buf--發送數據指針
len--發送數據長度
返回值 : 無
********************************************/
void Code_trans(uchar *pRomData, uint len)
{
ControlData.wCount = 0; //傳輸字節數計數器清0
if(ControlData.wLength > len)
ControlData.wLength = len; //傳輸數據總字節數不得超過len
ControlData.pData = pRomData; //傳輸數據指針指向pRomData
if( ControlData.wLength >= EP0_PACKET_SIZE) //傳輸數據總字節數大于端點0最大信息包大小
{
Write_EP(1, EP0_PACKET_SIZE, ControlData.pData);//發送端點0最大信息包大小個字節
ControlData.wCount += EP0_PACKET_SIZE; //統計已發送字節數
UEN_GINT();
USB_FLAG.control_state = USB_TRANSMIT; //標志數據發送狀態
EN_GINT();
}
else
{
Write_EP(1, ControlData.wLength, pRomData); //寫入傳輸數據總字節數
ControlData.wCount += ControlData.wLength; //統計已發送字節數
UEN_GINT();
USB_FLAG.control_state = USB_IDLE; //標志空閑狀態
EN_GINT();
}
}
/*******************************************
函數名稱: USB_INT1
功 能: D12中斷服務函數
參 數: 無
返回值 : 無
********************************************/
#pragma vector=PORT1_VECTOR
__interrupt void USB_INT1(void)
{
uint int_sta;
if((USBINT_IFG & BIT(D12_INT))==BIT(D12_INT))
{
USBINT_IFG&=~BIT(D12_INT); //清除中斷標志
USB_FLAG.in_isr = 1;
int_sta=Read_IntR(); //讀取PDIUSBD12中斷寄存器值
if(int_sta!=0)
{
if(int_sta&INT_BUSRESET)
USB_FLAG.bus_reset=1; //USB總線復位標志
if(int_sta&INT_ENDP0IN)
Ep0_txdone(); //控制端點發送數據處理
if(int_sta&INT_ENDP0OUT)
Ep0_rxdone(); //控制端點接收數據處理
if(int_sta&INT_ENDP1IN)
Ep1_txdone(); //端點 1發送數據處理
if(int_sta&INT_ENDP1OUT)
Ep1_rxdone(); //端點 1接收數據處理
if(int_sta&INT_ENDP2IN)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -