📄 d12_hard.h
字号:
/*USB D12程序代码*/
#define D12_COMMAND 0x0003
#define D12_DATA 0x0002
#define clrsuspend *PEDATDIR=*PEDATDIR&0XFFFB
#define setsuspend *PEDATDIR=*PEDATDIR|0X0004
#define clrd12reset *PEDATDIR=*PEDATDIR&0XFFFD
#define setd12reset *PEDATDIR=*PEDATDIR|0X0002
#define insuspend *PEDATDIR=*PEDATDIR|0X0404
#define outsuspend *PEDATDIR=*PEDATDIR|0x0004
#define readsuspend *PEDATDIR&0X0004
#define DISABLE (" setc INTM")
#define ENABLE (" clrc INTM")
/*********D12宏定义*************/
////----
//d12ci.c 使用部分
////----
#define D12_NOLAZYCLOCK 0x02
#define D12_CLOCKRUNNING 0x04
#define D12_INTERRUPTMODE 0x08
#define D12_SOFTCONNECT 0x10
#define D12_ENDP_NONISO 0x00
#define D12_ENDP_ISOOUT 0x40
#define D12_ENDP_ISOIN 0x80
#define D12_ENDP_ISOIO 0xC0
#define D12_CLOCK_12M 0x03
#define D12_CLOCK_4M 0x0b
#define D12_SETTOONE 0x40
#define D12_SOFONLY 0x80
#define D12_DMASINGLE 0x00
#define D12_BURST_4 0x01
#define D12_BURST_8 0x02
#define D12_BURST_16 0x03
#define D12_DMAENABLE 0x04
#define D12_DMA_INTOKEN 0x08
#define D12_AUTOLOAD 0x10
//==============================================
#define D12_NORMALPLUSSOF 0x20
#define D12_ENDP4INTENABLE 0x40
#define D12_ENDP5INTENABLE 0x80 // bug fixed in V2.1
#define D12_INT_ENDP0OUT 0x01
#define D12_INT_ENDP0IN 0x02
#define D12_INT_ENDP1OUT 0x04
#define D12_INT_ENDP1IN 0x08
#define D12_INT_ENDP2OUT 0x10
#define D12_INT_ENDP2IN 0x20
#define D12_INT_BUSRESET 0x40
#define D12_INT_SUSPENDCHANGE 0x80
#define D12_INT_EOT 0x0100
#define D12_SETUPPACKET 0x20
#define D12_BUFFER0FULL 0x20
#define D12_BUFFER1FULL 0x40
#define D12_FULLEMPTY 0x01
#define D12_STALL 0x02
typedef union _epp_flags
{
struct _flags
{
uchar timer:1;
uchar bus_reset:1;
uchar suspend:1;
uchar setup_packet:1;
uchar remote_wakeup:1;
uchar in_isr:1;
uchar control_state:2;
uchar configuration:1;
uchar verbose:1;
uchar ep1_rxdone:1;
uchar setup_dma:1;/*uchar read_flash:1;/*读FLASH标志*/
uchar dma_state:2;
/*uchar power_down:1;*/
uchar main_rxdone:1;/*主端点读 */
uchar main_txdone:1;/*主端点写 */
} bits;
unsigned int value;
} EPPFLAGS;
EPPFLAGS bEPPflags;
/***********D12底层写子程序**************/
void outportb(int portaddr,uchar val)
{
outport(portaddr,val);
}
/***********D12底层写命令子程序**************/
void SendD12Com(uchar val)
{
outport(D12_COMMAND,val);
}
/***********D12底层写数据子程序**************/
void SendD12Dat(uchar val)
{
outport(D12_DATA,val);
}
/***********D12底层读数据子程序**************/
uchar ReadD12Dat(void)
{
uint Ddata;
uchar indata;
inport(D12_DATA,&Ddata);
indata=Ddata&0x00ff;
return (indata);
}
/***********D12底层读子程序**************/
uchar inportb(int portaddr)
{
uint Ddata;
uchar indata;
inport(portaddr,&Ddata);
indata=Ddata&0x00ff;
return (indata);
}
/***********读取D12'sID子程序**************/
uint D12_ReadChipID(void)
{
uchar high,low;
uint D12_ID;
outportb(D12_COMMAND,0xfd);
low=inportb(D12_DATA);
high=inportb(D12_DATA);
D12_ID=high;
D12_ID=high<<8;
D12_ID+=low;
return D12_ID;
}
/***********D12底层读子程序**************/
/****************************************
段名: D12初始化函数
个数: 4
D12_SetAddressEnable(uchar) 设置地址寄存器
D12_SetEndpointEnable(uchar) 使能普通/同步端点
D12_SetMode(uchar , uchar) 设置D12使用模式
D12_SetDMA(uchar) ....
****************************************
函数名:D12_SetAddressEnable
输入参数:uchar Address
功能:设置地址并使能
注意事项:Address是从PC分配过来的
使用情况:D12基本通信函数
***************************************/
void D12_SetAddressEnable(uchar Address,uchar bEnable)
{
if(bEPPflags.bits.in_isr == 0)
asm(" setc INTM");
outportb(D12_COMMAND,0xD0);
if(bEnable)
Address |= 0x80; //使能位
outportb(D12_DATA,Address); //地址位
if(bEPPflags.bits.in_isr == 0)
asm(" clrc INTM");
// senddis("set address enable",buf,(long)Address);
}
/****************************************
//函数名:D12_SetEndpointEnable
//输入参数:uchar bEnable
//功能:端点使能,置1后就使能普通/同步端点
//注意事项:
//使用情况:D12基本通信函数
***************************************/
void D12_SetEndpointEnable(uchar bEnable)
{
if(bEPPflags.bits.in_isr == 0)
asm(" setc INTM");
outportb(D12_COMMAND,0xD8);
if(bEnable)
outportb(D12_DATA,1);
else
outportb(D12_DATA,0);
if(bEPPflags.bits.in_isr == 0)
asm(" clrc INTM");
// senddis("set endpoint enable ",buf,(long)bEnable);
}
/****************************************
//函数名:D12_SetMode
//输入:模式,时钟字节
//功能:设置LAZYCLOCK,时钟运行,中断模式,SOFTCONNECT,端点配置
//注意事项: 命令后要写入两个字节,如下
// 7 6 5 4 3 2 1 0
// 端点配置 留 SoftConnect 中断模式 时钟运行 无LAZYCLOCK 留
//
// 7 6 5 4 3210
// SOF_ONLY SET_TO_ONE 保留 时钟分频系数
//使用情况:D12基本通信函数
***************************************/
void D12_SetMode(uchar bConfig, uchar bClkDiv)//设置模式,在usb.c里设置的
{
if(bEPPflags.bits.in_isr == 0)
asm(" setc INTM");
outportb(D12_COMMAND,0xF3);
outportb(D12_DATA,bConfig);
outportb(D12_DATA,bClkDiv);
if(bEPPflags.bits.in_isr == 0)
asm(" clrc INTM");
// senddis("set d12 mode ",buf,(long)bConfig);
}
/****************************************
//函数名:D12_SetDMA
//输入:
//功能:
//注意事项:在命令后跟一个字节数据的写入或读出 (P35)
// 7 6 5 4 3 2 10
// 端点索引5 端点索引4 中断脚模式 自动重装 DMA方向 DMA使能 DAM突发串
// 中断使能 中断使能
//
***************************************/
void D12_SetDMA(uchar bMode)
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0xFB);
outportb(D12_DATA,bMode);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
// sendstring("set dma.\r\n");
}
/***************************************
//函数名:D12_ReadInterruptRegister
//功能:读中断状态寄存器
//注意事项:(P36) 连续读取两个字节
// 7 6 5 4 3 2 1 0
// 挂起改变 总线复位 主输入端点 主输出端点 端点1输入 端点1输出 控制端点输入 控制端点输出
// D12->PC PC->D12
***************************************/
unsigned short D12_ReadInterruptRegister(void) //读中断寄存器
{
uchar b1;
uchar b2;
unsigned int j;
outportb(D12_COMMAND,0xF4);
b1=inportb(D12_DATA);
b2=inportb(D12_DATA);
j=(b2<<8);
j=j|b1; //第一字节在前,第二字节在后
return j;
}
/***************************************
//函数名:D12_SelectEndpoint
//功能:选择端点,选择后可以读出端点缓冲是否已经满
//注意事项:
//输入:端点索引
***************************************/
uchar D12_SelectEndpoint(uchar bEndp)//选择端点
{
uchar c;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,bEndp);
c = inportb(D12_DATA);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
// senddis("select end point",buf,(long)bEndp);
return c;
}
/***************************************
//功能:读端点状态
//返回当前端点的状态
/***************************************/
uchar D12_ReadEndpointStatus(uchar bEndp)
{
uchar c;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0x80 + bEndp);
c = inportb(D12_DATA);
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return c;
}
/***************************************
//函数名:D12_ReadLastTransactionStatus
//功能:读最后处理状态寄存器状态
//注意事项:读一次后会复位中断寄存器中的响应位并将状态清0.读出1个字节,参看(P38),
//输入:40H+端点索引
/***************************************/
uchar D12_ReadLastTransactionStatus(uchar bEndp)//读最后处理状态寄存器
{
uchar i;
outportb(D12_COMMAND,0x40 + bEndp);
i=inportb(D12_DATA);
return i;
}
/***************************************
//函数名:D12_SetEndpointStatus
//输入: bEndp bStalled
// 选择端点 响应的状态,只能是第一位有效,1就为停止
//功能:设置断点的状态,
//注意事项:(P40) 应该仔细看看书
/***************************************/
void D12_SetEndpointStatus(uchar bEndp , uchar bStalled)//设置端点状态
{
if(bEPPflags.bits.in_isr == 0)
DISABLE;
outportb(D12_COMMAND,0x40 + bEndp); //端点索引
outportb(D12_DATA,bStalled); //1表示停止,写0表示初始化端点
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
/***************************************
//函数名:D12_SendResume
//功能:传输恢复
/***************************************/
void D12_SendResume(void)
{
outportb(D12_COMMAND,0xf6);
}
/***************************************
//函数名:D12_AcknowledgeEndpoint
//功能:应答SETUP包
//注意事项:P(40),SETUP包到后要有应答才能继续继续允许对IN,OUT端点的缓冲区操作
// 要先选择了端点再应答
/***************************************/
void D12_AcknowledgeEndpoint(uchar endp)//应答端点
{
outportb(D12_COMMAND,endp); //选择端点
outportb(D12_COMMAND,0xF1); //应答设置
// senddis("ack end point:",buf,(long)endp);
if(endp == 0)
outportb(D12_COMMAND,0xF2); //缓冲区清零
}
/***************************************
//写端点缓冲 端点索引 长度 所写数据缓冲区
/***************************************/
uchar D12_WriteEndpoint(uchar endp, uchar len, uchar * buf)
{
uchar i;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
//---------------------
outportb(D12_COMMAND,endp); //选择端点
i=inportb(D12_DATA); //读入满/空状态
outportb(D12_COMMAND,0xF0); //写缓冲区命令
outportb(D12_DATA,0); //第一个字节必须写0
outportb(D12_DATA,len);
for(i=0; i<len; i++)
outportb(D12_DATA,*(buf+i));
outportb(D12_COMMAND,0xFA); //使缓冲区有效
//--------------------------------
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return len;
}
/***************************************
//用途和上面相同,但只写一个字节
/***************************************/
void D12_WriteEndpointByte(uchar endp, uchar buf)
{
uchar i;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
//---------------------
outportb(D12_COMMAND,endp); //选择端点
i=inportb(D12_DATA); //读入满/空状态
outportb(D12_COMMAND,0xF0); //写缓冲区命令
outportb(D12_DATA,0); //第一个字节必须写0
outportb(D12_DATA,1);
outportb(D12_DATA,buf);
outportb(D12_COMMAND,0xFA); //使缓冲区有效
//--------------------------------
if(bEPPflags.bits.in_isr == 0)
ENABLE;
}
/***************************************
//////////////读端点缓冲 端点索引 长度 数据缓冲区
/***************************************/
uchar D12_ReadEndpoint(uchar endp, uchar len, uchar * buf)
{
uchar i, j;
if(bEPPflags.bits.in_isr == 0)
DISABLE;
//--------------------------------
outportb(D12_COMMAND,endp);
i=inportb(D12_DATA); //选择端点,可选读一个字节,用于判断缓冲是否满,这里应该用下面的函数比较好
if((i& D12_FULLEMPTY) == 0)
{ //如果缓冲区为空,则返回
if(bEPPflags.bits.in_isr == 0)
ENABLE;
return 0;
}
outportb(D12_COMMAND,0xF0); //读缓冲区命令
j = inportb(D12_DATA); //第一个字节无效的,
j = inportb(D12_DATA); //第二个为长度
if(j > len) //实际长度大于需要读的长度
j = len; //
for(i=0; i<j; i++)
*(buf+i) = inportb(D12_DATA);
outportb(D12_COMMAND,0xF2); //缓冲区清空
//-------------------------------
if(bEPPflags.bits.in_isr == 0)
ENABLE;
// senddis("read end point ",buf,(long)endp);
return j;
}
/***************************************/
/***************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -