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

📄 usb_to_can.txt

📁 这个一个经调试可用的USB_TO_CAN的程序,希望对CAN总线开发,与USB接口的学习人士有用.
💻 TXT
📖 第 1 页 / 共 2 页
字号:
		case USB_INT_USB_SUSPEND:
                {
			CH375_WR_CMD_PORT( CMD_UNLOCK_USB );
			CH375_WR_CMD_PORT( CMD_ENTER_SLEEP );
                 }
		break;
		case USB_INT_WAKE_UP:
			CH375_WR_CMD_PORT( CMD_UNLOCK_USB );
		break;
                #endif
		default:
			CH375_WR_CMD_PORT( CMD_UNLOCK_USB );  // 释放当前USB缓冲区
			break;
	}
	EA= 1;
}

//函数原型:void CAN_INT1(void) interrupt 0
//无参数,无返回值
//说明:外部中断0服务函数
void CAN_INT0(void) interrupt 0
{
	INT8U SJA_INT_IR;
	INT8U i;

	EA= 0;
  SJA_CANAdr= SJA_IR;
  SJA_INT_IR= *SJA_CANAdr;
	SJA_INT_IR= SJA_IR;			//采集中断寄存器
	switch(SJA_INT_IR)
	{
		case 0x01:						//SJA1000接收中断
				CAN_DATA_RECEIVE(RecDataFromCan);  //CAN bus接收数据,存入RecDataFromCan; 
		break;
		case 0x02:						//SJA1000发送中断
					;			
	  break;	
	  default:							//其他中断,如仲裁丢失、唤醒等
	  		SJA_Init();
	  break; 
	}
	SJA_CANAdr= SJA_RMC;			//将报文计数器减1
	i= *SJA_CANAdr;                        
	SJA_CANAdr= SJA_CMR;								//释放接收缓冲器
	*SJA_CANAdr= 0x04;
  EA= 1;
}

//数据池处理
//USB数据先接收,接收后判别,如果前两个字节是30 aa,这表明是参数配置数据
//其他数据直接是CAN BUS数据,转发到CAN bus上去
void RecDataFromUSBDeal(void)
{
	INT8U i, j, k;
	//判断是否有数据输入
	if(RecDataFromUsbLength>1)
	{
	    if((RecDataFromUsb[0]==0x30)&&(RecDataFromUsb[1]==0xaa))   //如果USB总线上输入得数据头两字节是:30 aa,并且数据长度是13,则数据是CAN参数设置数据
	    {
			  i2c_write(0x01, RecDataFromUsb[2]);
              i2c_write(0x02, RecDataFromUsb[3]);
              i2c_write(0x05, RecDataFromUsb[4]);
              i2c_write(0x06, RecDataFromUsb[5]);
              i2c_write(0x07, RecDataFromUsb[6]);
              i2c_write(0x08, RecDataFromUsb[7]);
              i2c_write(0x09, RecDataFromUsb[8]);
              i2c_write(0x0A, RecDataFromUsb[9]);
              i2c_write(0x0B, RecDataFromUsb[10]);
              i2c_write(0x0C, RecDataFromUsb[11]);
	    }
	    else if((RecDataFromUsb[0]==0x30)&&(RecDataFromUsb[1]==0x55)&&(RecDataFromUsbLength==2))  //如果USB总线输入数据为:30 55,表明上位机是在查询CAN总线参数
	    {
	    	RecDataFromCanLength= 12;
	    	RecDataFromCan[0]= 0x30;
	    	RecDataFromCan[1]= 0x55;
	    	for(i=0;i<10;i++)
	    	  RecDataFromCan[(2+i)]=  i2c_read((0x02+ i));
	    }
	    else                     //其他数据均为需要转发到CAN bus上得数据
	    {
				if((datanum- DataNum1)> 0x0D)		//判断SumDataFromUsb数据池空间是否足够
				{
						for(i= 0; i< RecDataFromUsbLength; i++)				//将数据移入数据池
							SumDataFromUsb[DataNum1+i]= RecDataFromUsb[i];
						FrameNumFromUsb++;														//置标志位
						DataNum1= DataNum1+ RecDataFromUsbLength;
						RecDataFromUsbLength= 0x00;     //清标志位
				}
				else   //数据池满时处理,将最先进数据池的数据清除
				{
						k= SumDataFromUsb[0];
						for(i= 0; i< k; k++)
						for(j= 0; j< datanum; j++)
									SumDataFromUsb[j]= SumDataFromUsb[j+1];
				}
	    }
	}
	
}

//数据池数据处理 RecDataFromCAN
void RecDataFromCANDeal(void)
{
		unsigned char i,j,k;
		if(RecDataFromCanLength)		//判断CAN是否有数据输入
		{
			if((datanum- DataNum2)> 0x0d)			//判断数据池是否为满
			{
							for(i= 0; i< RecDataFromCanLength; i++)							//将数据移入数据池
										SumDataFromCan[DataNum2+ i]= RecDataFromCan[i];
							FrameNumFromCan++;
							DataNum2= DataNum2+ RecDataFromCanLength;						//置标志位
							RecDataFromCanLength= 0x00;     //清标志位
			}
			
		}

}

//开中断
void MCU_INT(void)
{
	EA= 1;
	EX0= 1;         //外部中断0使能
        IT0= 0;		//外部中断0低电平触发
        IE0= 0;		//清外部中断0标志位

	EX1= 1;			//外部中断1使能
	PX1= 1;			//中断优先级为高

	//串口设置
	//串口操作模式为2,波特率位9600bps/s
	//开串口接收跟发送中断
	TMOD= 0x20;      //选择定时器1,16位
	TL1= 0xfd;	     //定时器初值0xfdH
	TH1= 0xfd;
	SCON= 0x50; 	 //选择模式2
	PCON = 0x00;
   	TR1= 1;
	ES= 1;
}

//单片机初始化
void Main_Init(void)
{
	//USB初始化
	CH375_Init( );
    //SJA初始化
	SJA_Init();
	//开中断
	
	LED_Low= 0;
	USBINFlag= 1;
}

//主函数
void main(void)
{
	unsigned char CAN_Status;     //CAN总线状态
	unsigned char i,j;
	unsigned char *buf;						//定义指针
	//初始化
	Main_Init();

	//循环
	while(1)
	{
			
			else if(FrameNumFromUsb)							//判断数据池,逻辑1,数据池还有数据;逻辑0,数据池空
			{
				EA= 0;															//关中断,避免数据出错
				if((SumDataFromUsb[0]&0x80)==0x80)						//判断该帧数据长度
								DataToCanLength= SumDataFromUsb[0]+ 5;
				else
								DataToCanLength= SumDataFromUsb[0]+ 3;
				
				for(i=0; i<DataToCanLength; i++)			//从数据池导出数据
							 DataToCan[i]= SumDataFromUsb[0];				
				for(i=DataToCanLength; i> 0; i--)			//数据池数据排序
				{
					   for(j= 0;j<datanum; j++)
					    SumDataFromUsb[j]= SumDataFromUsb[j+1];
				}	
				EA= 1;
				FrameNumFromUsb--;										//设置标志位
				DataNum1= DataNum1- DataToCanLength;
			}	
			//判断是否有数据需要转发到USB总线
			if(DataToUsbLength)				//判断DataToUsb是否有数据,该数据用于发送到USB总线上;
			{
				if(USBINFlag==0)			 //查询USB发送Buffer是否占用,逻辑1,占用;逻辑0,未占用
				{
						CH375_WR_CMD_PORT(CMD_WR_USB_DATA7);  //向USB端点2的发送缓冲区写入数据块
	    			CH375_WR_DAT_PORT(DataToUsbLength);  //首先写入后续数据长度
            buf= DataToUsb;  //指向缓冲区
	   				do{
									CH375_WR_DAT_PORT(*buf);  //写入数据到CH375
									buf++;
	    			}while(--DataToUsbLength);

						//置标志位
						USBINFlag= 1;                  //表明CH372的发送BUFFER锁定
				}
			}
			
		 
		 RecDataFromCANDeal();
		 RecDataFromUSBDeal();
	}
}

//********************************************
//I2C function define
//i2c_write(地址,数据),写一个字节
void i2c_write(unsigned char Address,unsigned char WData)
{
	do{
		i2c_start();
		i2c_send8bit(0xA0);
	}while(i2c_ack());
	i2c_send8bit(Address);
	i2c_ack();
	i2c_send8bit(WData);
	i2c_ack();
	i2c_stop();
}
//i2c_read(地址,数据),读一个字节
unsigned char i2c_read(unsigned char Address)
{
	unsigned char c;
	do{
		i2c_start();
		i2c_send8bit(0xA0);
	}while(i2c_ack()); //=1,表示无确认,再次发送
	i2c_send8bit(Address);
	i2c_ack();

	do{
		i2c_start();
		i2c_send8bit(0xA1);
	}while(i2c_ack());
	c=i2c_receive8bit();
	i2c_ack();
	i2c_stop();
	return(c);
}


void i2c_stop(void)
{
  SDA=0;  /*发送结束条件的数据信号*/
  _Nop();   /*发送结束条件的时钟信号*/
  SCL=1;  /*结束条件建立时间大于4us*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();
  _Nop();
  SDA=1;  /*发送I2C总线结束信号*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();
}
//发送接收确认信号
bit i2c_ack(void)
{
	bit ack;
	SDA = 1;
	SCL = 1;
    _Nop();
    _Nop();               /*保证时钟高电平周期大于4μs*/
    _Nop();
    _Nop();
    _Nop();
	if(SDA==1)
		ack = 1;
	else
		ack = 0;
	SCL = 0;
	return ack;
}



//接收八位数据
unsigned char i2c_receive8bit(void)
{
	unsigned char a;
	unsigned char b= 0;
	for(a= 0; a< 8; a++)
	{
		SCL = 1;
		_Nop();
        _Nop();               //保证时钟高电平周期大于4μ
        _Nop();
        _Nop();
        _Nop();
		b=b<<1;
	if(SDA==1)
		b=b|0x01; 			//按位或
	SCL = 0;
	}
	return b;}

⌨️ 快捷键说明

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