📄 usb.c
字号:
unsigned char DMA_EOT :1;
unsigned char not_use :7;
}Interrupt;
}Interrupt_Register; //中断寄存器
union
{
unsigned int Register;
struct
{
unsigned char bus_reset :1; //总线复位标志
unsigned char suspend :1; //挂起标志
unsigned char remote_wakeup :1;
unsigned char int_isr :1;
unsigned char not_end :1; //上次访问未结束标志
unsigned char usb_idle :1; //总线空闲
unsigned char usb_busy :1; //总线忙
unsigned char setup_packet_in :1; //setup包输入标志
unsigned char setup_packet_out :1; //setup包输出标志
unsigned char set_addr :1; //设置地址标志 ,如果为1,表明USB的地址已经设置,为0,则没有设置
unsigned char usb_endp0_in :1; //端点0输入标志
unsigned char usb_endp2_in :1; //端点2输入标志
unsigned char usb_endp2_out :1; //端点2输出标志
}flags;
}usb_flags; //定义USB标志寄存器
union //端点最后处理状态
{
unsigned char Register;
struct
{
unsigned char successful :1;
unsigned char error_code :4;
unsigned char setup_packet :1;
unsigned char data_1 :1;
unsigned char prestatus_not_read :1;
}Status;
}Last_Status;
union
{
unsigned char Register;
struct
{
unsigned char Command :1; //命令
unsigned char Data :1; //数据
}Status;
}SCSI; //定义SCSI状态寄存器
//***************** 延时x毫秒函数 ***********
void Delay(unsigned int x)
{
unsigned int i;
unsigned int j;
for(i=0;i<x;i++)
for(j=0;j<230;j++);
}
//********************************************
/********************************************************************************/
unsigned int SWAP(unsigned int temp) //高低字节交换
{
unsigned int i;
i=temp;
i<<=8;
temp>>=8;
i|=temp;
return i;
}
void error(unsigned char number) //出错处理
{
// unsigned char Error[]={"ERROR: "};
// prints(Error);
// printc(number);
number=0;
}
unsigned char Get_MSB(unsigned int temp) //取高8位
{
return (unsigned char)(temp>>8);
}
unsigned char Get_LSB(unsigned int temp) //取低8位
{
return (unsigned char)(temp);
}
void Write_Usb_CMD(unsigned char CMD) //写USB命令
{
USB_A0 = USB_COMMAND_ADD;
USB_DATA = CMD;
USB_WR = 0;
USB_WR = 1;
USB_DATA=0XFF;
}
void Write_A_Usb_DAT(unsigned char DAT) //写一个USB数据
{
USB_A0 = USB_DATA_ADD;
USB_DATA = DAT;
USB_WR = 0;
USB_WR = 1;
USB_DATA=0XFF;
}
unsigned char Read_A_Usb_DAT(void) //读一个USB数据
{
unsigned char temp;
USB_A0 = USB_DATA_ADD;
USB_RD = 0;
temp = USB_DATA;
USB_RD = 1;
return temp;
}
/****************************************************************************
函数名称:void Read_Intrrupt_Register(void)
函数作用:读D12 中断寄存器,并将读出的值存到中断标志全局共用体变量Intrrupt_Register中
改变全局变量:Intrrupt_Register
说明:外部设备读取D12的 中断寄存器之后,回根据Intrrupt_Register中相应的值,做相应的
响应,比如:如果此时读取的值中,bus_reset =1,则说明USB主机发送的是一个总线复位命令,
那么USB设备就必须进行总线复位,换句话说,主机要求你做什么,你就得做什么,不然主机可能不会识别你
*****************************************************************************/
void Read_Interrupt_Register(void) //读中断寄存器
{
Write_Usb_CMD(READ_INTERRUPT_REGISTER);
Interrupt_Register.Register[0] = Read_A_Usb_DAT();
Interrupt_Register.Register[1] = Read_A_Usb_DAT();
}
void Set_Usb_Addr(unsigned char addr) //设置D12地址
{
Write_Usb_CMD(SET_ADDR);
Write_A_Usb_DAT(0X80|addr); //最高位为1,则使地址有效
}
/***************
void Set_Usb_DMA()
{}
*****************/
/***********8以下是一些关于端点操作的函数*********************************/
void Set_Endp_Enable(void)
{
Write_Usb_CMD(SET_ENDPOINT_ENABLE );
Write_A_Usb_DAT(0X01); //1为普通,0为同步
}
/*************************************************************************8*****
函数名称:unsigned char Chioce_Endpoint(unsigned char endp)
函数功能:端点选择,并返回端点状态(空、满)
传递参数:端点 endp
返回数据:端点状态
*******************************************************************************/
unsigned char Chioce_Endp(unsigned char endp) //端点选择
{
Write_Usb_CMD(SELECT_ENDPOINT+endp );
return Read_A_Usb_DAT(); //读出数据为0,则该缓冲区空,为1,满
}
unsigned char Read_Endp_Status(unsigned char endp) //读端点状态
{
Write_Usb_CMD(READ_ENDPOINT_STATUS+endp );
return Read_A_Usb_DAT(); //返回端点状态字,根据状态做响应处理
}
unsigned char Read_Endp_Last_Status(unsigned char endp) //读端点最后状态,同时复位中断寄存器相应位。
{
Write_Usb_CMD(READ_LAST_STATUS+endp );
return Read_A_Usb_DAT(); //返回最后处理状态
}
void Set_Endp_Status(unsigned char endp, unsigned char status) //设置端点状态
{
Write_Usb_CMD(0x40+endp );
Write_A_Usb_DAT(!status );
}
/***********************以下是一些关于buffer缓冲区的操作函数***********************/
void Clear_Buffer(void) //清端点缓冲区
{
Write_Usb_CMD(CLEAR_BUFFER);
}
void Validate_Buffer(void) //使缓冲区合法。
{
Write_Usb_CMD(VALIDATE_BUFFER );
}
void Ack_Setup(unsigned char endp) //建立应答包
{
Chioce_Endp(endp); //选择端点
Write_Usb_CMD(ACK_SETUP ); //设置应答
}
/******************************************************************************************
函数名称:unsigned char Read_Endp_Buffer(unsigned char endp, unsigned char len, unsigned char *buff)
函数功能:读取指定端点的缓冲区数据且长度指定,数据放入buff中
传递参数:endp:端点
len :数据长度
*buff :缓冲区首地址
返回参数:实际读取数据长度
********************************************************************************************/
unsigned char Read_Endp_Buffer(unsigned char endp, unsigned char len, unsigned char *buff)
{
unsigned char i,buflen;
Read_Endp_Last_Status(endp); // 读端点最后状态:作用不是很清楚,估计是清除某些位。可删除试试
if(!Chioce_Endp(endp)&0x01){return 0;}//如果缓冲区为空,则返回 0;
Read_Endp_Status(endp); //为什么这里要读/???
Write_Usb_CMD(READ_BUFFER);
Read_A_Usb_DAT(); //读取的第一个字节为任意值,因此不要;
buflen=Read_A_Usb_DAT(); //第二字节为缓冲区数据长度
if(buflen>len)buflen=len; //需要读取的数据长度可能小于实际要求的数据长度,但是在读的时候是把数据读完。
for(i=0;i<buflen;i++) //读取数据
{
USB_RD=0;
*(buff+i)=USB_DATA;
USB_RD=1;
}
Clear_Buffer(); //数据读完之后,清缓冲区
return buflen; //如果成功读取,则返回读取数据的实际长度
}
unsigned char Write_Endp_Buffer(unsigned char endp, unsigned char len, unsigned char *buff)
{
unsigned char i;
Read_Endp_Last_Status(endp); //清除中断某些标志
Chioce_Endp(endp); // Read_Endp_Status(endp);就是这句话,使得每局过程出错
Write_Usb_CMD(WRITE_BUFFER);
Write_A_Usb_DAT(0);
Write_A_Usb_DAT(len);
for(i=0;i<len;i++)
{
USB_DATA=*(buff+i);
USB_WR=0;
USB_WR=1;
}
USB_DATA=0XFF;
Validate_Buffer();
return len;
}
/********************************************************************************
以下两个函数是USB的连接、断开及初始化函数。详细注释见下面
*********************************************************************************/
void Disconnect_Usb(void)
{
Write_Usb_CMD(0XF3); //设置USB—D12的模式命令;连续写两个字节。第一个为配置信息,第二个为分频系数。
Write_A_Usb_DAT(0x0E); //7-6=00:模式0,非同步模式;5=0:保留,写0;4=0;不连接;3=1:所有都报告,2=1;1=0;0=0。
Write_A_Usb_DAT(0x47); //分频系数计算公式:48/((3:0)+1),那么这里就是48/(7+1)=6MHz
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -