⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch372.c

📁 该源码与书本配套
💻 C
字号:
#include <reg51.h>
#include <intrins.h>
#include "ch372.h"

byte UsbReBuf[2];    //USB接收两个加数的缓冲区
byte UsbSendBuf[2];  //USB返回加法和的缓冲区
byte IsSend=0;       //是否有数据需要发送  0-没有   1-有
/**************************************************************************
发送加法和
**************************************************************************/
void SendSum()
{
   if(IsSend==1)
   {
      IsSend=0;
      WrPoint2(UsbSendBuf,2);
   }
}

/**************************************************************************
初始化
返回值:1:初始化成功  0:不成功
**************************************************************************/
byte Ch372Init()
{
	byte q0;
//	CH372_PORT |= CH372_INT;
//	EIMSK |= CH372_INT;
	if(Test372()==0)
		return 0;
	q0=SetUSB_Mod372(2);
	if(q0!=100)
		return 1;
	else
		return 0;
}

/**************************************************************************
执行硬件复位
**************************************************************************/
void Rst372()
{
	SendCommand372(RST_ALL);
	__delay_cycles(6250);	//延时	
}

/**************************************************************************
设置USB 的厂商识别码Vendor-ID 和产品识别码Product-ID。该命令必须在
SET_USB_MODE 命令之前执行。
VID:厂商识别码Vendor-ID
PID:产品识别码Product-ID
**************************************************************************/
void SetUSB_ID372(word16 VID,word16 PID)
{
	byte q0[4];
	q0[0]=VID>>8;
	q0[1]=VID&0xFF;
	q0[2]=PID>>8;
	q0[3]=PID&0xFF;
	SendCommand372(SET_USB_ID);	
	WriteData372(q0,4);
	__delay_cycles(160);	//延时
}

/**************************************************************************
设置USB工作模式
mod:工作模式。 0:未启用的USB 设备方式(上电或复位后的默认方式)
				   1:已启用外部固件模式
				   2:已启用内部固件模式
返回值:启用方式。 100:设置失败				  
**************************************************************************/
byte SetUSB_Mod372(byte mod)
{
	byte q0,q1;
	SendCommand372(SET_USB_MOD);
	WriteData372(&mod,1);
	//等待操作成功,通常需要等待10uS~20uS
	for ( q0=100;q0!=0;q0--) 
	{
		ReadData372(&q1,1);
		if ( q1 == CMD_SUCCESS ) 
			return mod;  
	}
	return 100;
}

/**************************************************************************
对CH372的中断进行处理,本函数应当被中断函数调用。
**************************************************************************/
void DoInt372()
{
	byte q0;
	word16 sum;       //加法和
	SendCommand372(GET_STA);//写读CH372的中断状态的命令,并通知CH372取消中断请求
	ReadData372(&q0,1);     //读CH372的中断状态
	switch(q0)              //根据CH372的中断状态进行处理
	{
		case 0x03:
		case 0x07:
		case 0x0B:
		case 0xFF:
			//检测到USB总线复位,内部固件模式时不需要处理
		break;
		case 0x0C:
			//端点0 的接收器接收到数据,SETUP 事务成功,内部固件模式时不需要处理
		break;
		case 0:
			//端点0 的接收器接收到数据,OUT 事务成功,内部固件模式时不需要处理
		break;
		case 0x08:
			//端点0 的发送器发送完数据,IN 事务成功,内部固件模式时不需要处理
		break;
		case 0x01:
			//端点1 接收到数据,OUT 事务成功,内部固件模式时不需要处理
		break;
		case 0x09:
			//端点1(中断端点)发送完数据,IN 事务成功
			SendCommand372(ULK_USB);         //释放当前USB缓冲区
		break;
		case 0x02:
			//端点2(批量端点)接收到数据,OUT 事务成功
			SendCommand372(R_USB_DATA);   //写读端点2数据的命令
			ReadData372(&q0,1);           //读端点2收到数据的字节数
			if(q0!=0)
			{
			   ReadData372(UsbReBuf,q0);  //读取数据,释放缓冲区
   			if(q0==2)                       
   			{
   				 //收到字节数为2,为两个加数
   				sum=UsbReBuf[0]+UsbReBuf[1];
               UsbSendBuf[0]=sum&0xFF;
               UsbSendBuf[1]=sum>>8;
               IsSend=1;
   			}
			}
		break;
		case 0x0A:
			//端点2(批量端点)发送完数据,IN 事务成功
			SendCommand372(ULK_USB);    //释放当前USB缓冲区
		break;
	}
}

/**************************************************************************
测试工作状态
返回值:1:正常  0:不正常
**************************************************************************/
byte Test372()
{
	byte q0,q1=0;
	SendCommand372(CHK_EXIST);
	q0=0xF0;
	WriteData372(&q0,1);
	ReadData372(&q1,1);
	q1=~q1;
	if(q0==q1)
		return 1;
	else 
		return 0;
}

/**************************************************************************
向USB 端点1 的上传缓冲区写入数据块。数据块长度的有效值是0~8,
如果长度不为0,则单片机必须将后续数据逐个写入CH372。
psrc:要写的数据。
**************************************************************************/
void WrPoint1(byte* psrc,byte n_byte)
{
	SendCommand372(W_USB_DATA5);
	WriteData372(&n_byte,1);
	WriteData372(psrc,n_byte);
}

/**************************************************************************
向USB 端点2 的上传缓冲区写入数据块。数据块长度的有效值是0~64,
如果长度不为0,则单片机必须将后续数据逐个写入CH372。
psrc:要写的数据。
**************************************************************************/
void WrPoint2(byte* psrc,byte n_byte)
{
	SendCommand372(W_USB_DATA7);
	WriteData372(&n_byte,1);
	WriteData372(psrc,n_byte);
}

/**************************************************************************
底层命令
**************************************************************************/
/**************************************************************************
发送命令
command:命令
**************************************************************************/
void SendCommand372(byte command)
{
	*((byte*)USB_CMD_ADR)=command;
	__delay_cycles(20);
}

/**************************************************************************
发送数据
psrc:数据
n_byte:数据字节数。范围:0~64
**************************************************************************/
void WriteData372(byte* psrc,byte n_byte)
{
	byte q0;
	for(q0=0;q0<n_byte;q0++)
	{
		*((byte*)USB_DATA_ADR)=(*psrc);
		__delay_cycles(15);
		psrc++;
	}
}

/**************************************************************************
读数据
pdest:数据
n_byte:数据字节数。范围:0~64
**************************************************************************/
void ReadData372(byte* pdest,byte n_byte)
{
	byte q0;
	for(q0=0;q0<n_byte;q0++)
	{
		*pdest=*((byte*)USB_DATA_ADR);
		__delay_cycles(15);
		pdest++;
	}	
}

/****************************************************************************
延时
n:延时循环次数
****************************************************************************/
void __delay_cycles(word16 n)
{
   word16 q0;
   for(q0=n;q0>0;q0--)
   {
      _nop_();
      _nop_();
      _nop_();
      _nop_();
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -