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

📄 usb_to_can.txt

📁 这个一个经调试可用的USB_TO_CAN的程序,希望对CAN总线开发,与USB接口的学习人士有用.
💻 TXT
📖 第 1 页 / 共 2 页
字号:
//***************************************************
//  filename: main.c
//  Author: wen
//  Rewrite:
//  Date: 2007-01-10
//  Version: V1.0
//  Description: ALL main.c file
//****************************************************

//****************************************************
//修改
//文小龙
//提供接收及发送BUFFER,USB数据改为中断上传和批量下传方式,即采用EP1IN,EP2OUT
//****************************************************

#include<include.h>
#include<reg52.h>
#include<string.h>

sbit LED_Low= P1^4;


//****************************************************
//CAN bus function

//函数原型:  bit   CAN_CREATE_COMMUNATION(void)
//           0: 表示SJA1000接口正常
//           1: 表示SJA1000与处理器接口不正常
//说明:该函数用于检测CAN控制器的接口是否正常
bit CAN_CREATE_COMMUNATION(void)
{
    SJA_CANAdr= SJA_TEST;                     //访问测试寄存器
    *SJA_CANAdr=0xaa;                     //写入测试值
    if(*SJA_CANAdr== 0xaa)                  //回读
       return  0;                          //读测试正确
    else
       return  1;
}

//函数原型:      bit   CAN_ENTER_RETMODEL(void)
//返回值:
//           0 ; 表示成功进入复位工作模式
//           1 ; 表示不能进入复位工作模式                                                                                                     *
//说明:      CAN控制器进入复位工作模式
bit CAN_ENTER_RETMODEL(void)
{
    INT8U TempData;
    SJA_CANAdr= SJA_MOD;			     //访问地址指向模式寄存器
    TempData=  *SJA_CANAdr;                          //保存原始值
    *SJA_CANAdr= (TempData|0x01);                     //置位复位请求
    if((*SJA_CANAdr&0x01)== 1)
       return   0;
    else
       return   1;
}

//函数原型:      bit   CAN_QUIT_RETMODEL(void)
//返回值:
//           0: 表示成功退出复位工作模式
//           1: 表示不能退出复位工作模式
//说明:      CAN控制器退出复位工作模式
bit CAN_QUIT_RETMODEL(void)
{
    INT8U TempData;
    SJA_CANAdr= SJA_MOD;                   //访问地址指向模式寄存器
    TempData= *SJA_CANAdr;                       //保存原始值
    *SJA_CANAdr=(TempData&0xfe);       		 //清除复位请求
    if((*SJA_CANAdr&0x01) == 0)
       return   0;                              //退出成功
    else
       return   1;                    	       //退出失败
}

//函数原型:  bit   CAN_DATA_WRITE(unsigned char *SendDataBuf)
//参数说明:  特定帧格式的数据发送
//返回值:
//           0    ; 表示将数据成功的发送至发送缓冲区
//           1	  ; 表示上一次的数据正在发送,
//                ; 表示发送缓冲区被锁定,不能写入数据
//                ; 表示写入数据错误
bit CAN_DATA_WRITE(unsigned char *SendDataBuf)
{
   INT8U TempCount;
   SJA_CANAdr= SJA_SR;      //访问地址指向状态寄存器
  if((*SJA_CANAdr&0x08)== 0)         //判断上次发送是否完成
      return  1;

   if((*SJA_CANAdr&0x04)== 0)          //判断发送缓冲区是否锁定
      return  1;

   SJA_CANAdr=  SJA_RXEFF;
   switch(SendDataBuf[0]&0xC0)	//对PelicCAN mode 数据格式进行判断
   {
   	case 0x40:		//标准远程帧
   		TempCount= 3;
   	break;
   	case 0x00:		//标准数据帧
   		TempCount= (SendDataBuf[0]&0x0f)+ 3;
   	break;
   	case 0xC0:		//扩展远程帧
   		TempCount= 5;
   	break;
   	case 0x80:		//扩展数据帧
   		TempCount= (SendDataBuf[0]&0x0f)+ 5;
        break;
   	default:		//退出,返回1
   		return 1;
   	break;
   }

    memcpy(SJA_CANAdr,SendDataBuf,TempCount);     //将数据传入SJA1000CAN数据发送缓冲区

    SJA_CANAdr= SJA_CMR;        //置位发送请求
    *SJA_CANAdr= 0x01;
    return 0;
}

//函数原型:  bit   CAN_DATA_RECEIVE(unsigned char *RcvDataBuf);
//参数说明:  RcvDataBuf,存放微处理器保存数据缓冲区
//返回值:    0;接收成功
//           1;接收失败
//说明:CAN控制器接收数据,仅限于接收数据
bit CAN_DATA_RECEIVE(INT8U *RcvDataBuf)
{
   INT8U TempCount;
   SJA_CANAdr= SJA_SR;     		//访问地址指向状态寄存器

   if((*SJA_CANAdr&0x01)==0)               //判断报文是否有效
      return 1;

   SJA_CANAdr= SJA_RXEFF;
   switch(*SJA_CANAdr&0xC0)
   {
	case 0x00:				//标准数据帧
		TempCount= (*SJA_CANAdr&0x0f)+ 3;

		TempCount= (*SJA_CANAdr&0x0f)+ 5;
    break;
	case 0xC0:				//扩展远程帧
		TempCount= 5;
    break;
	default: break;
   }
   memcpy(RcvDataBuf,SJA_CANAdr,TempCount);//读取接收缓冲区的报文
   RecDataFromCanLength= TempCount;            //置标志位
   return  0;
 }

//函数原型:void SJA_Init(void);
//无参数,无返回值
//说明:SJA初始化
 void SJA_Init(void)
 {
 	INT8U i,j;             //数据缓存

 	EA= 0;

 	//进入复位模式
 	for(i= 0; i< 500; i++)
 		if(!CAN_ENTER_RETMODEL())   break;

        SJA_CANAdr= SJA_IER;
        *SJA_CANAdr= 0x00;         //清除所有中断

        SJA_CANAdr= SJA_CDR;
        *SJA_CANAdr= 0xC8;          //设定PeliCAN模式,禁止CLKOUT,使能CBP



        //设定波特率
	SJA_CANAdr= SJA_BTR0;
	j= *SJA_CANAdr= i2c_read(0x01);
	SJA_CANAdr= SJA_BTR1;
	j= *SJA_CANAdr= i2c_read(0x02);

	//配置CAN输出 TX1悬空 TX0推免
	SJA_CANAdr= SJA_OCR;
	*SJA_CANAdr= 0x1A;        //0x00|0x18|0x02

	SJA_CANAdr= SJA_RBSA;
	*SJA_CANAdr= 0x00;       //接收缓冲地址置零

	SJA_CANAdr= SJA_RXERR;
	*SJA_CANAdr= 0x00;      //接收错误计数器置零

	SJA_CANAdr= SJA_TXERR;
	*SJA_CANAdr= 0x00;      //发送错误计数器置零

	//读取错误代码器,器件自动将错误代码器归零
  SJA_CANAdr= SJA_ECC;
  i= *SJA_CANAdr;

	SJA_CANAdr= SJA_IER;
	*SJA_CANAdr= 0xFF;      //设置SJA1000中断使能

   	//清除复位模式
	//关闭自我测试及仅听模式
	//清除休眠模式
	//选择单滤波模式
      SJA_CANAdr= SJA_MOD;
     *SJA_CANAdr= 0x08;
      EA= 1;

      SJA_CANAdr= SJA_CMR;
      *SJA_CANAdr= 0x0c;        //释放接收/发送缓存区
}
//CAN bus function end
//****************************************************

//***************************************************
//USB function define
#define DELAY_START_VALUE		1	  //根据单片机的时钟选择延时初值

//IO位置定义
IOPORT CH375_CMD_PORT _at_ 0xFD00;		// CH375命令端口的I/O地址
IOPORT CH375_DAT_PORT _at_ 0xFC00;		// CH375数据端口的I/O地址

//延时1微秒,不精确
void	Delay1us( )
{
#if DELAY_START_VALUE!= 0
	INT8U i;
	for ( i=DELAY_START_VALUE; i!=0; i-- );
#endif
}

//延时2微秒,不精确
void	Delay2us( )
{
	INT8U i;
	for ( i=DELAY_START_VALUE*2+1; i!=0; i-- );
}

//与CH372/CH375有关的基本I/O操作
void CH375_WR_CMD_PORT(INT8U cmd) {   //向CH372/CH375写入命令
	Delay2us();
	CH375_CMD_PORT= cmd;
	Delay2us();
}

void CH375_WR_DAT_PORT(INT8U dat) {  //向CH372/CH375写入数据
	CH375_DAT_PORT= dat;
	Delay1us();
}

INT8U CH375_RD_DAT_PORT( void ) {      //读CH372/CH375内部数据
	Delay1us();
	return(CH375_DAT_PORT);
}

//CH375初始化子程序
void CH375_Init( void )
{
	INT8U i;

	#ifdef MY_USB_VENDOR_ID
	#ifdef MY_USB_PRODUCT_ID
		CH375_WR_CMD_PORT( CMD_SET_USB_ID );
		CH375_WR_DAT_PORT( (UINT8)MY_USB_VENDOR_ID );

	#endif
	#endif  

        // 设置USB工作模式
	CH375_WR_CMD_PORT( CMD_SET_USB_MODE );
	CH375_WR_DAT_PORT( 2 );     // 设置为使用内置固件的USB设备方式
	for (i= 100; i!= 0; i--)
		if(CH375_RD_DAT_PORT()== CMD_RET_SUCCESS)   break;  // 等待操作成功

	#ifdef ENABLE_USB_SUSPEND
	// 设置检查USB总线挂起状态,便于在USB总线挂起时使CH375也进入低功耗状态
		CH375_WR_CMD_PORT( CMD_CHK_SUSPEND );  // 设置检查USB总线挂起状态的方式

	#endif 
}
//USB function define end
//********************************************************

//********************************************************
//others function define

//函数原型:void USB_INT1(void) interrupt 2
//无参数,无返回值
//说明:外部中断1服务函数
void USB_INT1(void) interrupt 2
{
	INT8U			IntStatus;
	INT8U			cnt;
	PINT8U			buf;
  EA= 0;
	CH375_WR_CMD_PORT(CMD_GET_STATUS);  //获取中断状态并取消中断请求
	IntStatus = CH375_RD_DAT_PORT( );     // 获取中断状态
	IE0 = 0;                              //清中断标志
	switch(IntStatus)
        {    
		case USB_INT_EP2_IN:  // 批量端点上传成功,数据发送成功
			CH375_WR_CMD_PORT( CMD_UNLOCK_USB );  //释放当前USB缓冲区,收到上传成功中断后,必须解锁USB缓冲区,以便继续收发
		break;
		case USB_INT_EP1_IN:  // 中断端点上传成功,中断数据发送成功
			CH375_WR_CMD_PORT( CMD_UNLOCK_USB );  // 释放当前USB缓冲区
		break;
		case USB_INT_EP1_OUT:  // 辅助端点下传成功,接收到辅助数据
			CH375_WR_CMD_PORT( CMD_UNLOCK_USB );  // 释放当前USB缓冲区
		break;
                #ifdef ENABLE_USB_SUSPEND   //总线挂起状态查询

⌨️ 快捷键说明

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