📄 can_sja1000.c
字号:
#include <avr/io.h>
#include <stdio.h>
//#include <avr/signal.h>
#include <avr/interrupt.h>
#include <util/delay_basic.h>
#include "SJA_BcanConf.h"
#define nop asm("NOP")
#define FREQ 8 //时钟8M
unsigned char Rec_Flag = 0; //接受标志位
unsigned char Send_Flag = 0; //发送标志位
//volatile unsigned char *p;
/**** 定义发送,接受帧结构 ****/
struct BCAN_BUFstruct
{
unsigned char FrameID_H;
unsigned char FrameID_L3;
unsigned char FrameKIND;
unsigned char FrameLENGTH;
unsigned char Frame_Data[8];
}BCAN_FRAME,Receive_BUF,Send_BUF;
/**** 延时函数 ****/
void delayMs(unsigned int t)
{
unsigned int i;
for(i=0; i<t; i++)
_delay_loop_2(FREQ*250); //约1ms
}
/**** 写SJA1000寄存器 ****/
void CANREG_WRITE(unsigned int SJAREG_ADR,unsigned char Data)
{
unsigned char *aa;
aa=SJAREG_ADR;
*aa= Data;
}
/**** 读SJA1000寄存器 ****/
unsigned char CANREG_READ(unsigned int SJAREG_ADR)
{
unsigned char *p;
unsigned char SJAREG_data;
p= SJAREG_ADR;
SJAREG_data = *p;
return SJAREG_data;
}
/***** CAN控制器进入复位模式 ****/
unsigned char BCAN_ENTER_RETMODEL(void)
{
unsigned char TempData;
TempData = CANREG_READ(REG_CONTROL); //读控制寄存器
TempData = TempData | 0x01;
CANREG_WRITE(REG_CONTROL, TempData); //写控制寄存器
if((CANREG_READ(REG_CONTROL) & 0X01) == 1)
{
return 0; //置复位模式成功
}
else
{
return 1; //置复位模式失败
}
}
/***** CAN控制器进入正常模式 ****/
unsigned char BCAN_QUIT_RETMODE(void)
{
unsigned char TempData;
TempData = CANREG_READ(REG_CONTROL); //读控制寄存器
TempData = TempData & 0xfe;
CANREG_WRITE(REG_CONTROL, TempData); //写控制寄存
if((CANREG_READ(REG_CONTROL) & 0X01) == 0)
{
return 0; // 进入正常模式成功
}
else
{
return 1; //进入正常模式失败
}
}
/**** 设置CAN控制器验收代码寄存器ACR、验收屏蔽寄存器AMR ****/
unsigned char BCAN_SET_OBJECT(unsigned char BCAN_ACR,unsigned char BCAN_AMR)
{
CANREG_WRITE(REG_ACR, BCAN_ACR); //写验收代码寄存器
if(CANREG_READ(REG_ACR) != BCAN_ACR)
{
return 1; //写失败
}
CANREG_WRITE(REG_AMR, BCAN_AMR); //写验收屏蔽寄存器
if(CANREG_READ(REG_AMR) != BCAN_AMR)
{
return 1; //写失败
}
return 0;
}
/**** 设置CAN控制器通讯波特率 ****/
unsigned char BCAN_SET_BANDRATE(unsigned char BCAN_BTR0,unsigned char BCAN_BTR1)
{
CANREG_WRITE(REG_BTR0, BCAN_BTR0);
if(CANREG_READ(REG_BTR0) != BCAN_BTR0)
{
return 1;
}
CANREG_WRITE(REG_BTR1, BCAN_BTR1);
if(CANREG_READ(REG_BTR1) != BCAN_BTR1)
{
return 1;
}
return 0;
}
/**** 设置CAN输出控制器OCR、时钟分频器CDR ****/
unsigned char BCAN_SET_OUTCLK(unsigned char Out_Control,unsigned char Clock_Out)
{
CANREG_WRITE(REG_OCR, Out_Control);
if(CANREG_READ(REG_OCR) != Out_Control)
{
return 1;
}
CANREG_WRITE(REG_CDR, Clock_Out);
if(CANREG_READ(REG_CDR) != Clock_Out)
{
return 1;
}
return 0;
}
/**** 数据发送至发送缓冲区 ****/
unsigned char BCAN_DATA_SEND(void)
{
unsigned char i ;
if((CANREG_READ(REG_STATUS) & 0x08) == 0) //判断上次发送是否完成
{
return 1;
}
if((CANREG_READ(REG_STATUS) & 0x04) == 0) //判断发送缓冲区是否锁定
{
return 1;
}
CANREG_WRITE(REG_TxBuffer1,Send_BUF.FrameID_H); //写ID码10~3位
//写ID码2~0,帧类型,发送数据长度
CANREG_WRITE(REG_TxBuffer2,(Send_BUF.FrameID_L3<<5)|(Send_BUF.FrameKIND<<4)|(Send_BUF.FrameLENGTH));
if(Send_BUF.FrameKIND ==0 ) //数据帧,写数据缓冲区
{
for(i=0; i<Send_BUF.FrameLENGTH; i++)
{
CANREG_WRITE(REG_TxBuffer3+i,Send_BUF.Frame_Data[i]);
}
}
return 0;
}
/**** 从接受缓冲区接受数据 ****/
unsigned char BCAN_DATA_RECEIVE(void)
{
unsigned char i;
if((CANREG_READ(REG_STATUS) & 0x01) == 0) //判断接受缓冲区是否有报文
{
return 1;
}
Receive_BUF.FrameID_H = CANREG_READ(REG_RxBuffer1);
Receive_BUF.FrameLENGTH = (CANREG_READ(REG_RxBuffer2))&0x0f;
Receive_BUF.FrameKIND = (CANREG_READ(REG_RxBuffer2)&0x10)>>4;
Receive_BUF.FrameID_L3 = (CANREG_READ(REG_RxBuffer2)&0xE0)>>5;
if(Receive_BUF.FrameKIND == 0)
{
for(i=0;i<Receive_BUF.FrameLENGTH;i++)
{
Receive_BUF.Frame_Data[i] = CANREG_READ(REG_RxBuffer3+i);
}
}
return 0;
}
/**** 接受的CAN数据处理 ****/
void CanRcv_Prg(void)
{
unsigned char status;
status = BCAN_DATA_RECEIVE(); //接受数据
if(status ==0 )
{
if(Receive_BUF.FrameKIND == 1) //远程帧处理
{
nop;
}
else //数据帧处理
{
nop;
}
}
}
void SJA1000_Init(void)
{
unsigned char status;
cli();
CANREG_WRITE(REG_CONTROL,0x07); //接受中断使能
delayMs(1);
status=BCAN_ENTER_RETMODEL();
delayMs(1);
CANREG_WRITE(REG_COMMAND,0x0e); //工作在正常模式
delayMs(1);
status=BCAN_SET_OBJECT(0x00,0xff); //验收代码寄存器ACR、验收屏蔽寄存器AMR
delayMs(1);
status=BCAN_SET_BANDRATE(0x04,0x1C);//设置CAN控制器通讯波特 12M,100k/s
delayMs(1);
status=BCAN_SET_OUTCLK(0x1a,0x48);//设置CAN输出控制器OCR、时钟分频器CDR
delayMs(1);
status=BCAN_QUIT_RETMODE();
delayMs(1);
sei();
}
void MCU_Init(void)
{
cli();
MCUCR |= (1<<SRE); //使能外部存储器
XMCRA = 0x80; //外部存储器地址空间为一个大区,无等待周期
XMCRB = 0x00; //端口C全部用于高位地址
DDRD |=(1<<DDD0)|(1<<DDD1); //PD0,PD1输出
PORTD &=(~((1<<PD0)|(1<<PD1)));
DDRE &=(~(1<<DDE4)); //中断引脚输入上拉
cli();
EICRB &=(~((1<<ISC41)|(1<<ISC40))); //INT4低电平产生中断
EIMSK |=(1<<INTF4); //INT4中断使能
DDRB |= 1<<DDB0; //配置PB0为输出
PORTB &=(~(0<<PB0)); //pB0输出低电平,硬件复位sja1000
delayMs(200); // 延时200ms
PORTB |= (1<<PB0);
delayMs(200);
//sei(); //开总中断
}
int main(void)
{
unsigned char i,flag1=0;
unsigned char cmd_data,status;
MCU_Init();
SJA1000_Init();
while(1)
{
delayMs(100);
//PORTD &= (~(1<<PD1));
delayMs(100);
if(flag1==0)
{
Send_BUF.FrameID_H = 0;
Send_BUF.FrameLENGTH = 8;
Send_BUF.FrameKIND = 0;
Send_BUF.FrameID_L3 = 0;
if(Send_BUF.FrameKIND == 0)
{
for(i=0;i<Send_BUF.FrameLENGTH;i++)
{
Send_BUF.Frame_Data[i] = i;
}
}
BCAN_DATA_SEND();
cmd_data =0x01; //发送请求
CANREG_WRITE(REG_COMMAND,0X01);
delayMs(100);
status=CANREG_READ(REG_INTERRUPT);
if((status&0x02) == 0x02) PORTD |= (1<<PD1);
while(1);
// PORTD |= (1<<PD1);
}
if(Send_Flag ==1)
{
Send_Flag =0;
//PORTD |= (1<<PD1);
flag1=0;
}
}
return (0);
}
/**** 外部中断4中断处理函数 ****/
SIGNAL(SIG_INTERRUPT4)
{
unsigned char sta;
cli();
PORTD |= (1<<PD1);
while(1);
sta=CANREG_READ(REG_INTERRUPT);
if((sta & 0x10) == 0x10)
{
PORTD |= (1<<PD0);
delayMs(1000);
PORTD &= (~(1<<PD0));
while(1);
SJA1000_Init(); //唤醒中断处理
}
if((sta & 0x04) == 0x04)
{
PORTD |= (1<<PD0);
while(1);
SJA1000_Init(); //错误中断处理
}
if((sta & 0x80) == 0x80)
{
PORTD |= (1<<PD1);
while(1);
}
if((sta & 0x02) == 0x02)
{
Send_Flag = 1; //发送中断处理
// PORTD |= (1<<PD1);
//while(1);
}
if((sta & 0x01) == 0x01)
{
Rec_Flag = 1; //接受中断处理
PORTD |= (1<<PD1);
delayMs(1000);
PORTD &= (~(1<<PD1));
while(1);
}
sei();
}
// #asm("nop") //空操作的汇编代码,等待中断发生
//#define nop asm("NOP")
//#define NOP asm volatile ("nop")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -