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