//寄存器定义;
#include //宏定义;
#define uchar unsigned char //数据类型定义
#define uint unsigned int //数据类型定义
#pragma interrupt_handler INT1_17:3 //定义INT1的中断服务程序
#pragma interrupt_handler Timer0:10 //定义定时计数器0的中断服务程序
#pragma interrupt_handler Usart_receive:12 //定义接收中断服务程序
#define fosc 7372800 //晶振7.3728MHZ
#define CANSTAT 0x0E
#define CANCTRL 0x0F
#define BFPCTRL 0x0C
#define TEC 0x1C
#define REC 0x1D
#define CNF3 0x28
#define CNF2 0x29
#define CNF1 0x2A
#define CANINTE 0x2B
#define CANINTF 0x2C
#define EFLG 0x2D
#define TXRTSCTRL 0x0D
#define RXF0SIDH 0x00
#define RXF0SIDL 0x01
#define RXF0EID8 0x02
#define RXF0EID0 0x03
#define RXF1SIDH 0x04
#define RXF1SIDL 0x05
#define RXF1EID8 0x06
#define RXF1EID0 0x07
#define RXF2SIDH 0x08
#define RXF2SIDL 0x09
#define RXF2EID8 0x0A
#define RXF2EID0 0x0B
#define RXF3SIDH 0x10
#define RXF3SIDL 0x11
#define RXF3EID8 0x12
#define RXF3EID0 0x13
#define RXF4SIDH 0x14
#define RXF4SIDL 0x15
#define RXF4EID8 0x16
#define RXF4EID0 0x17
#define RXF5SIDH 0x18
#define RXF5SIDL 0x19
#define RXF5EID8 0x1A
#define RXF5EID0 0x1B
#define RXM0SIDH 0x20
#define RXM0SIDL 0x21
#define RXM0EID8 0x22
#define RXM0EID0 0x23
#define RXM1SIDH 0x24
#define RXM1SIDL 0x25
#define RXM1EID8 0x26
#define RXM1EID0 0x27
#define TXB0CTRL 0x30
#define TXB0SIDH 0x31
#define TXB0SIDL 0x32
#define TXB0EID8 0x33
#define TXB0EID0 0x34
#define TXB0DLC 0x35
#define TXB0D0 0x36
#define TXB0D1 0x37
#define TXB0D2 0x38
#define TXB0D3 0x39
#define TXB0D4 0x3A
#define TXB0D5 0x3B
#define TXB0D6 0x3C
#define TXB0D7 0x3D
#define TXB1CTRL 0x40
#define TXB1SIDH 0x41
#define TXB1SIDL 0x42
#define TXB1EID8 0x43
#define TXB1EID0 0x44
#define TXB1DLC 0x45
#define TXB1D0 0x46
#define TXB1D1 0x47
#define TXB1D2 0x48
#define TXB1D3 0x49
#define TXB1D4 0x4A
#define TXB1D5 0x4B
#define TXB1D6 0x4C
#define TXB1D7 0x4D
#define TXB2CTRL 0x50
#define TXB2SIDH 0x51
#define TXB2SIDL 0x52
#define TXB2EID8 0x53
#define TXB2EID0 0x54
#define TXB2DLC 0x55
#define TXB2D0 0x56
#define TXB2D1 0x57
#define TXB2D2 0x58
#define TXB2D3 0x59
#define TXB2D4 0x5A
#define TXB2D5 0x5B
#define TXB2D6 0x5C
#define TXB2D7 0x5D
#define RXB0CTRL 0x60
#define RXB0SIDH 0x61
#define RXB0SIDL 0x62
#define RXB0EID8 0x63
#define RXB0EID0 0x64
#define RXB0DLC 0x65
#define RXB0D0 0x66
#define RXB0D1 0x67
#define RXB0D2 0x68
#define RXB0D3 0x69
#define RXB0D4 0x6A
#define RXB0D5 0x6B
#define RXB0D6 0x6C
#define RXB0D7 0x6D
#define RXB1CTRL 0x70
#define RXB1SIDH 0x71
#define RXB1SIDL 0x72
#define RXB1EID8 0x73
#define RXB1EID0 0x74
#define RXB1DLC 0x75
#define RXB1D0 0x76
#define RXB1D1 0x77
#define RXB1D2 0x78
#define RXB1D3 0x79
#define RXB1D4 0x7A
#define RXB1D5 0x7B
#define RXB1D6 0x7C
#define RXB1D7 0x7D
#define TXREQ 0x08
#define TXP 0x03
#define RXM 0x60
#define BUKT 0x04
#define REQOP 0xE0
#define ABAT 0x10
#define OSM 0x08
#define CLKEN 0x04
#define CLKPRE 0x03
#define REQOP 0xE0
#define ICOD 0x0E
#define RX0IE 0x01
#define RX1IE 0x02
#define TX0IE 0x04
#define TX1IE 0x80
#define TX2IE 0x10
#define ERRIE 0x20
#define WAKIE 0x40
#define MERRE 0x80
#define RX0IF 0x01
#define RX1IF 0x02
#define TX0IF 0x04
#define TX1IF 0x80
#define TX2IF 0x10
#define ERRIF 0x20
#define WAKIF 0x40
#define MERRF 0x80
#define B1BFS 0x20
#define B0BFS 0x10
#define B1BFE 0x08
#define B0BFE 0x04
#define B1BFM 0x02
#define B0BFM 0x01
#define SJW 0xC0
#define BRP 0x3F
#define BTLMODE 0x80
#define SAM 0x40
#define PHSEG1 0x38
#define PRSEG 0x07
#define WAKFIL 0x40
#define PHSEG2 0x07
#define TXB2RTS 0x04
#define TXB1RTS 0x02
#define TXB0RTS 0x01
#define SJW_1TQ 0x40
#define SJW_2TQ 0x80
#define SJW_3TQ 0x90
#define SJW_4TQ 0xC0
#define BTLMODE_CNF3 0x80
#define BTLMODE_PH1_IPT 0x00
#define SMPL_3X 0x40
#define SMPL_1X 0x00
#define PHSEG1_8TQ 0x38
#define PHSEG1_7TQ 0x30
#define PHSEG1_6TQ 0x28
#define PHSEG1_5TQ 0x20
#define PHSEG1_4TQ 0x18
#define PHSEG1_3TQ 0x10
#define PHSEG1_2TQ 0x08
#define PHSEG1_1TQ 0x00
#define PRSEG_8TQ 0x07
#define PRSEG_7TQ 0x06
#define PRSEG_6TQ 0x05
#define PRSEG_5TQ 0x04
#define PRSEG_4TQ 0x03
#define PRSEG_3TQ 0x02
#define PRSEG_2TQ 0x01
#define PRSEG_1TQ 0x00
#define PHSEG2_8TQ 0x07
#define PHSEG2_7TQ 0x06
#define PHSEG2_6TQ 0x05
#define PHSEG2_5TQ 0x04
#define PHSEG2_4TQ 0x03
#define PHSEG2_3TQ 0x02
#define PHSEG2_2TQ 0x01
#define PHSEG2_1TQ 0x00
#define SOF_ENABLED 0x80
#define WAKFIL_ENABLED 0x40
#define WAKFIL_DISABLED 0x00
#define RX0IE_ENABLED 0x01
#define RX0IE_DISABLED 0x00
#define RX1IE_ENABLED 0x02
#define RX1IE_DISABLED 0x00
#define G_RXIE_ENABLED 0x03
#define G_RXIE_DISABLED 0x00
#define TX0IE_ENABLED 0x04
#define TX0IE_DISABLED 0x00
#define TX1IE_ENABLED 0x08
#define TX2IE_DISABLED 0x00
#define TX2IE_ENABLED 0x10
#define TX2IE_DISABLED 0x00
#define G_TXIE_ENABLED 0x1C
#define G_TXIE_DISABLED 0x00
#define ERRIE_ENABLED 0x20
#define ERRIE_DISABLED 0x00
#define WAKIE_ENABLED 0x40
#define WAKIE_DISABLED 0x00
#define IVRE_ENABLED 0x80
#define IVRE_DISABLED 0x00
#define RX0IF_SET 0x01
#define RX0IF_RESET 0x00
#define RX1IF_SET 0x02
#define RX1IF_RESET 0x00
#define TX0IF_SET 0x04
#define TX0IF_RESET 0x00
#define TX1IF_SET 0x08
#define TX2IF_RESET 0x00
#define TX2IF_SET 0x10
#define TX2IF_RESET 0x00
#define ERRIF_SET 0x20
#define ERRIF_RESET 0x00
#define WAKIF_SET 0x40
#define WAKIF_RESET 0x00
#define IVRF_SET 0x80
#define IVRF_RESET 0x00
#define REQOP_CONFIG 0x80
#define REQOP_LISTEN 0x60
#define REQOP_LOOPBACK 0x40
#define REQOP_SLEEP 0x20
#define REQOP_NORMAL 0x00
#define ABORT 0x10
#define OSM_ENABLED 0x08
#define CLKOUT_ENABLED 0x04
#define CLKOUT_DISABLED 0x00
#define CLKOUT_PRE_8 0x03
#define CLKOUT_PRE_4 0x02
#define CLKOUT_PRE_2 0x01
#define CLKOUT_PRE_1 0x00
#define OPMODE_CONFIG 0x80
#define OPMODE_LISTEN 0x60
#define OPMODE_LOOPBACK 0x40
#define OPMODE_SLEEP 0x20
#define OPMODE_NORMAL 0x00
#define RXM_RCV_ALL 0x60
#define RXM_VALID_EXT 0x40
#define RXM_VALID_STD 0x20
#define RXM_VALID_ALL 0x00
#define RXRTR_REMOTE 0x08
#define RXRTR_NO_REMOTE 0x00
#define BUKT_ROLLOVER 0x04
#define BUKT_NO_ROLLOVER 0x00
#define FILHIT0_FLTR_1 0x01
#define FILHIT0_FLTR_0 0x00
#define FILHIT1_FLTR_5 0x05
#define FILHIT1_FLTR_4 0x04
#define FILHIT1_FLTR_3 0x03
#define FILHIT1_FLTR_2 0x02
#define FILHIT1_FLTR_1 0x01
#define FILHIT1_FLTR_0 0x00
[page]
#define TXREQ_SET 0x08
#define TXREQ_CLEAR 0x00
#define TXP_HIGHEST 0x03
#define TXP_INTER_HIGH 0x02
#define TXP_INTER_LOW 0x01
#define TXP_LOWEST 0x00
#define DLC_0 0x00
#define DLC_1 0x01
#define DLC_2 0x02
#define DLC_3 0x03
#define DLC_4 0x04
#define DLC_5 0x05
#define DLC_6 0x06
#define DLC_7 0x07
#define DLC_8 0x08
#define CAN_RESET 0xC0
#define CAN_READ 0x03
#define CAN_WRITE 0x02
#define CAN_RTS 0x80
#define CAN_RTS_TXB0 0x81
#define CAN_RTS_TXB1 0x82
#define CAN_RTS_TXB2 0x84
#define CAN_RD_STATUS 0xA0
#define CAN_BIT_MODIFY 0x05
#define CAN_RX_STATUS 0xB0
#define CAN_RD_RX_BUFF 0x90
#define CAN_LOAD_TX 0X40
#define DUMMY_BYTE 0x00
#define TXB0 0x31
#define TXB1 0x41
#define TXB2 0x51
#define RXB0 0x61
#define RXB1 0x71
#define EXIDE_SET 0x08
#define EXIDE_RESET 0x00
uchar can_boud=0x07;//MCP2515在16M晶振情况,can_boud=0x00总线波特率为1M,0x01=500K,0x03=250K,0x07=125K;公式:16M/(16*(1+X))
uint bps=38400;//定义
avr单片机串口波特率
uchar eflag=0;//是不是扩展帧,为1则表示接收到的是扩展帧,0表示标准帧
uchar Tdate[10]={0};//存放要发送标准帧的数据,最大10位,前2位是ID号,后8位是数据位
uchar TID[2]={0,0};//存放要发送标准帧的ID号
uchar Rdate[8]={0};//存放接收到的数据
uchar RESID[4];//存放接收到的数据帧的ID号,标准帧只用到RESID[0],RESID[1],扩展帧全部用到
uchar bytetime;//232与CAN透明转换时,根据不同的波特率确定所要延时的时间,
uint usart_number=0;//计数当前所接收的串行数据的那一组数据流的数据个数,串口传来的数据存放在Tdate中等待用CAN标准帧发送
uchar state;//2515状态(包括发送接收中断标志位和各请求发送位),具体见数据手册
uchar DLC=8;//接收到数据的长度
//
//
void delay(uchar k)//
{uint i=0;
while(k--){for(i=0;i<8000;i++);}
}
//##############################################################################
void Set_CS(uchar level) //
{if(level) PORTB|=0x10; //
else PORTB&=0xef; //
}
//##############################################################################
//
//
void WriteSPI(uchar order)
{ uchar clear;
Set_CS(0); //
SPDR=order; //2515读指令为0x03
while(!(SPSR&0x80)); //等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR;//
Set_CS(1); //
}
//
uchar Read_state(uchar order)//读状态命令,order=0xa0,0xa1,
{ uchar clear;
Set_CS(0); //
SPDR=order; //
while(!(SPSR&0x80)); //等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR;//
SPDR=0; //空数据
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
Set_CS(1); //
return clear;
}
//
uchar Read_Byte(uchar Address)
{uchar clear;
uchar date;
Set_CS(0); //使能SPI器件
SPDR=0x03; //送2515读指令为0x03
while(!(SPSR&0x80)); //等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
SPDR=Address; //送地址
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
SPDR=0x00; //发空数据,启动数据发送以接收数据
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
date=SPDR; //接收数据
Set_CS(1); //关SPI器件DS1722
return date;
}
//
void Write_Byte(uchar Address,uchar Data)
{uchar clear;
Set_CS(0); //使能SPI器件2515
SPDR=0x02; //送2515写命令为0x02
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR;
SPDR=Address; //送地址,启动SPI时钟
while(!(SPSR&0x80));//等待SPIF置位,等数据发送完毕
clear=SPSR;
clear=SPDR; //通过先读SPSR,紧接着访问SPDR来对SPIF清零
SPDR=Data;
while(!(SPSR&0x80));
clear=SPSR;
clear=SPDR;
Set_CS(1); //关SPI器件
}
//
//###########################对CAN的一些操作####################################
//
void load_Standard_ID_dates(uchar num)//给标准帧装载ID和数据
//选用发送缓冲器0,num:要发送的个数(最大8个)
{
uchar i,j,T0=0x36;
uchar TIDH,TIDL;
i=TID[1]>>3;j=TID[0]<<5;j=j+i;i=TID[1]<<5;
TIDL=i;TIDH=j;//将数组TID中的值转化为TIDH,TIDL以便给TXB0SIDH,TXB0SIDL附值
Write_Byte(CANCTRL,0x80);//CAN工作在配置模式
Write_Byte(CNF1,can_boud);
Write_Byte(TXB0SIDH,TIDH);
Write_Byte(TXB0SIDL,TIDL);
Write_Byte(TXB0DLC,num);//
for(i=2;i
}
//##############################################################################
void Receive_all_ID_process(void)//结合MCP2515数据手册来看
{uchar k;
k=RESID[1];//先判断接收到的是不是标准帧,因为标准帧和扩展帧的ID处理不一样
if((k&0x08)==0)
{//如果是标准处理方法
RESID[1]=RESID[1]>>5;
k=RESID[0]&0x1f;//借用k
k=k<<3;
RESID[1]=RESID[1]+k;
RESID[0]=RESID[0]>>5;
}
else
{//扩展帧处理方法,RESID[3]、RESID[4]不变
k=k>>5;
k=k<<2;
RESID[1]=RESID[1]&0x03;
RESID[1]=RESID[1]+k;
k=RESID[0];
k=k<<5;
RESID[1]=RESID[1]+k;
RESID[0]=RESID[0]>>3;//将RXB0SIDH,RXB0SIDL转化
}
}
//##############################################################################
//##############################USART初始化程序###########################//
void usart_init(void)
{
UCSRB=(1<
UBRRL=(fosc/16/(bps+1))%6;
UBRRH=(fosc/16/(bps+1))/256;
UCSRC=(1<
bytetime=215983/bps;//215983=1000000*20/92.6,92.6=1024/11.0592,定时器分频为1024
bytetime=255-bytetime;//计算不同的波特率所要延时的初值,要附值给TCNT0,实现透明转换中用到
}
//##########################串行通信##########################//
void putchar(uchar c)
{while(!(UCSRA&(1<
UDR=c;}
//##############################中断服务程序##################################//
void INT1_17(void)
{
uchar i,j,k,R0=0x66;
GICR &=0x7f;
state=Read_state(0xa0);
//WriteSPI(0xa0);//读取2515状态指令,状态值附值给state
if((state&0x01)!=0)
{//判断是不是接收缓冲器0满产生的中断
k=Read_Byte(RXB0SIDL);//为了判断是标准帧还是扩展帧
if((k&0x08)==0)eflag=0;//置标准帧标志
else eflag=1;//置扩展帧标志
DLC=Read_Byte(RXB0DLC);
DLC &=0x0f;
RESID[0]=Read_Byte(RXB0SIDH);
RESID[1]=Read_Byte(RXB0SIDL);
RESID[2]=Read_Byte(RXB0EID8);
RESID[3]=Read_Byte(RXB0EID0);//先读取所有ID
Receive_all_ID_process();//处理RESID
if(eflag==0)
{//如果是标准帧
putchar(RESID[0]);
putchar(RESID[1]);//先送标准帧ID号
}
else
{//如果是扩展帧
putchar(RESID[0]);
putchar(RESID[1]);
putchar(RESID[2]);
putchar(RESID[3]);//先送扩展帧ID号
}
putchar(DLC);
}
Write_Byte(CANINTF,0x00);//接收完一次必须对中断标志位清0
GICR |=0x80;
}
//####################################
void Usart_receive(void)//定义接收中断服务程序
{Tdate[usart_number]=UDR;
usart_number++;
TIMSK=0x05;//打开T1,T0中断屏蔽
TCCR0=0x05;//设T0分频数为1024
TCNT0=bytetime;//设T0时间常数,从此值开始计数
}
//##############定时器中断0,串行数据流控制
void Timer0(void)
{TIMSK=0x00;//关T0中断屏蔽
TCNT0=0x00;//
TCCR0=0x00;//T0停止计数
if((usart_number>2)&&(usart_number<11))
{
TID[0]=Tdate[0];TID[1]=Tdate[1];
load_Standard_ID_dates(usart_number-2);//对2515发送缓冲器0和ID寄存器进行数据装载
usart_number=0;
Write_Byte(CANCTRL,0x00);//选定工作模式
WriteSPI(CAN_RTS_TXB0);//发送缓冲器0请求发送
}
else usart_number=0;
}
//##############################CAN(2515)初始化程序###########################//
void CAN_Initialize(void)
{
WriteSPI(CAN_RESET);
delay(20);
Write_Byte(CANCTRL,0x80);//CAN工作在配置模式
Write_Byte(CNF1,can_boud);
Write_Byte(CNF2,0x80 | PHSEG1_3TQ | PRSEG_1TQ);//Set CNF2
Write_Byte(CNF3,PHSEG2_3TQ);
//0x80+0x10+0x00,相位缓冲段2由CNF3确定,相位缓冲段1为3TQ,传播段为1TQ
Write_Byte(RXB0CTRL,0xf0);//接收类型选择,接收所有报文
Write_Byte(CANINTF,0x00);//接收完一次必须对中断标志位清0
Write_Byte(CANINTE,0x01);//接收缓冲器0满中断使能
Write_Byte(CANCTRL,0x00);//选定正常工作模式
}
//##############################系统初始化程序################################//
void AVR_Initialize(void) //初始化
{
DDRB=0xff; //SPI口
PORTB=0xff;
DDRD=0xf0;//将外部中断引脚设定为输入
PORTD=0x7f;
SPCR=0b01011100;//关中断(SPIE=0),使能SPI(SPE=1),MSB首先发送(DORD=0)
//选择微机为主机模式(MSTR=1)
//空闲时SCK 为高电平(CPOL=1)
//在SCK 的结束沿采样(CPHA=1)以保证数据稳定
//SPR1=0和SPR0=0,SCK=fosc/4
SPSR |=0x01;//SPI的速度加倍
MCUCR=0x0a;//设置外部中断的中断触发方式为下降沿触发
GICR=0xc0;//通用中断控制寄存器设置,打开中断INT0和INT1
SREG=0x80;//开全局中断
}
//##################################主程序####################################//
void main()
{
AVR_Initialize(); //I/O口及中断初始化
CAN_Initialize();
usart_init();
UCSRB |=0x80;//接收中断使能
}