📄 usb_to_can.txt
字号:
//***************************************************
// 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 + -