📄 main.c
字号:
}
//函数原型: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;
i= *SJA_CANAdr;
// SJA_INT_IR= SJA_IR; //采集中断寄存器
switch(i)
{
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)
{
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]);
RecDataFromUsbLength= 0;
}
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));
RecDataFromUsbLength= 0;
}
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;
if(RecDataFromCanLength) //判断CAN是否有数据输入
{
j= EmptyData;
for(i= 0; i< RecDataFromCanLength; i++)
//将数据移入数据池
{
*EmptyData= RecDataFromCan[i];
EmptyData++;
}
EmptyData= j+ 0x0d;
if(EmptyData> &SumDataFromCan[datanum])
EmptyData= &SumDataFromCan[0];
RecDataFromCanLength= 0;
}
}
//开中断
void MCU_INT(void)
{
EA= 1;
EX0= 1; //外部中断0使能
IT0= 0; //外部中断0低电平触发
IE0= 0; //清外部中断0标志位
EX1= 1; //外部中断1使能
PX1= 1; //中断优先级为高
IT1= 0; //外部中断1低电平触发
IE1= 0; //清外部中断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)
{
CH375_Init( ); //USB初始化
SJA_Init(); //SJA初始化
MCU_INT(); //开中断
LED_Low= 0;
USBINFlag= 0;
}
//主函数
void main(void)
{
unsigned char i;
unsigned char *buf,*DataBufTemp; //定义指针
Main_Init(); //初始化
while(1) //循环
{
//判断是否有数据需要转发到CAN总线
if(RecDataFromUsbLength) //判断DataToCan是否有数据,该数据用于发送到CAN总线上;
{
SJA_CANAdr= SJA_SR; //采集SJA1000T状态
i= *SJA_CANAdr;
if((i&0xF8)==0x40) //判断SJA1000发送缓冲区是否锁定,逻辑1,未锁定;逻辑0,锁定
{
CAN_DATA_WRITE(RecDataFromUsb); //往SJA1000的发送缓冲区写入数据
RecDataFromUsbLength= 0; //归零标志位
}
}
//判断是否有数据需要转发到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锁定
}
}
else if(EmptyData!= CurrentData) //判断数据池,逻辑1,数据池还有数据;逻辑0,数据池空
{
if((*CurrentData&0x80)==0x80) //判断该帧数据长度
DataToUsbLength= (*CurrentData&0x0F)+ 5;
else
DataToUsbLength= (*CurrentData&0x0F)+ 3;
DataBufTemp= CurrentData; //保存当前数据指针
for(i= 0; i< DataToUsbLength; i++) //从数据池导出数据
{
DataToUsb[i]= *CurrentData;
CurrentData++;
}
CurrentData= DataBufTemp+ 0x0d; //数据池指针处理
if(CurrentData> SumDataFromCan[datanum])
CurrentData= &SumDataFromCan[0];
}
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_start(void)
{
SDA=1; //发送起始条件的数据信号
_Nop();
SCL=1;
_Nop(); //起始条件建立时间大于4.7us,延时
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; //发送起始信号
_Nop(); // 起始条件锁定时间大于4μs
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; /*钳住I2C总线,准备发送或接收数据 */
_Nop();
_Nop();
}
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;
}
//送八位数据
void i2c_send8bit(unsigned char b)
{
unsigned char a;
for(a=0;a<8;a++)
{
if ((b << a ) & 0x80)
SDA = 1;
else
SDA = 0;
SCL = 1;
_Nop();
_Nop(); //保证时钟高电平周期大于4μ
_Nop();
_Nop();
_Nop();
SCL = 0;
}
}
//接收八位数据
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;
}
//led test
void Led_display(void)
{
unsigned int i;
for(i=5000; i>0; i++) LED_Low= 0;
for(i=5000; i>0; i++) LED_Low= 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -