/* derivative information */ #pragma LINK_INFO DERIVATIVE \"mc9s12dp512\"void Transmission_CAN1(void); void InitCAN0(void) ; void InitCAN1(void) ; void delay(void); void InitCRG(void);
unsigned char txdata[8]; //如果要方便观察它们的值可以设为全局变量 unsigned char rxdata[8]; //现在是局部变量,但也能从BUFFER中观察0X160,0X170附近
void main(void) {
/* put your own code here */
InitCRG(); //这是LOOP BACK模式 DDRB=0XFF; //复位
PORTB=0xff; //初始化方向设置为输入,随后pb的状态将被实际状态代替
InitCAN0(); //实际应用时要改到正常模式,并确定硬件连接正确 InitCAN1();
EnableInterrupts ; //CCR中的I位清零 for(;;) {
Transmission_CAN1(); delay();
} /* wait forever */
/* please make sure that you never leave this function */ }
void InitCRG(void) { //clock and reset generation
SYNR=0; //PLLCLK=2*OCCLK*(SYNR+1)/(REFDIV+1)
REFDV=0; //当外部晶振为16M的时侯,PLL的输出频率为32M,单片机为了提高cpu
//运行速度,降低外部时钟频率,提高整个系统的电磁兼容能力,采用锁相环技术
CRGFLG=0Xf2; //清CRG模块的各个标志位
//第7位是实时中断标志位。写1,清标志位 //第6位是上电复位标志位。写1,清标志位
//第4位是PLL锁定状态改变标志位。写1,请标志位。 //第1位是自时钟模式中断标志位。写1,清标志位 PLLCTL=0XF1; //设置锁相环PLL控制寄存器
//第7位是时钟监控使能位。写1,使能对时钟的监控 //第6位是PLL使能位。写1,使能PLL //第5位是自动带宽使能位。写1,自动选择带宽 //第4位是带宽选择位,在选择了自动带宽时这一位无效 //第0位是自时钟模式使能位。写1,在晶振失效时进入自时钟模式
CRGINT=0x00; //清非法地址复位中断标志位
while(CRGFLG_LOCK==1) ; //等待PLL输出始终达到稳定
CLKSEL= 0XFB; // 设置总线始终选择寄存器
//第7位是总线时钟选择位。写1,总线时钟频率=PLL输出时钟频率/2
//第3位是WAIT模式PLL停止位。写1,PLL在WAIT模式下停止工作
//第1位是WAIT模式实时中断停止位。写1,实时中断在WAIT模式停止工作
//第0位是WAIT模式看门狗停止位。写1,看门狗在WAIT模式停止工作
COPCTL=0; //设置看门狗控制寄存器,为零是禁用看门狗 }
void InitCAN0(void) //can的初始化主要是对can通道控制寄存器,波特率,id
滤波寄存器,接受寄存器等设置 {
/*DS上说在设定INITRQ之前最好能先进入睡眠模式以确保安全*/
CAN0CTL0=0x01; //进入CAN 初始化模式 while(CAN0CTL1_INITAK==0); //等待确认进入初始化模式
CAN0CTL1=0X80; //CAN 使能,选用晶振时钟,频率为16M ,loop back mode
CAN0BTR1=0X3A; // One sample per bit,time segment2=4, // time segment1=11;时间量=1+11+4=16
CAN0BTR0=0xC9;
//Synchronization
Jump
With=4Tq,Prescaler=10;
//得到位速率为100K, Bit Rate=(Frequence of CANCLK)/(Prescalar*Number of Time Quanta)
CAN0IDAC=0X10; //验收标志寄存器4X16 bits Identifier Acceptance Filters
/*To receive standard identifiers in 32 bit filter mode, it is required to
program the last three bits (AM2 - AM0) in the mask registers CANIDMR1 and CANIDMR5 to \"don’t
care\". To receive standard identifiers in 16 bit filter mode, it is required to program the last three bits (AM2
- AM0) in the mask registers CANIDMR1, CANIDMR3, CANIDMR5 and CANIDMR7 to \"don’t car\". */
CAN0IDAR0=0x20; CAN0IDMR0=0xff;
CAN0IDAR1=0x00; CAN0IDMR1=0Xff;
CAN0IDAR2=0X21;
CAN0IDMR2=0X00; //此处将Recieve_Filter0只用CAN0IDAR0来判断保报文
//优先级,不过每一位都要参与判断 CAN0IDAR3=0x12; CAN0IDMR3=0X00;
CAN0IDAR4=0X00; CAN0IDMR4=0X00;
CAN0IDAR5=0x00; CAN0IDMR5=0X0f;
//此处将Recieve_Filter只用CAN0IDAR0来判断保报文 //优先级,不过每一位都要参与判断 CAN0IDAR6=0X00;
CAN0IDMR6=0X00;
CAN0IDAR7=0x00; CAN0IDMR7=0X00;
CAN0CTL0=0x00; //退出初始化模式,回到正常模式 while(CAN0CTL1_INITAK==1) ;
while(CAN0CTL0_SYNCH==1);
CAN0RFLG=0XC3;
//清
CAN
STATUS
CHANGE
INTERRUPT,OVERRUN INTERRUPT,
//BUFFER FULL 的标志位
CAN0RIER=0x01; //开RECIEVER FULL 中断 }
void InitCAN1(void) {
/*DS上说在设定INITRQ之前最好能先进入睡眠模式以确保安全*/
CAN1CTL0=0x01; //进入CAN 初始化模式 while(CAN1CTL1_INITAK==0); //等待确认进入初始化模式
CAN1CTL1=0X80; //CAN 使能,选用晶振时钟,频率为16M ,loop back mode
CAN1BTR1=0X3A; // One sample per bit,time segment2=4, // time segment1=11;时间量=1+11+4=16
CAN1BTR0=0xC9;
//Synchronization
Jump
With=4Tq,Prescaler=10;
//得到位速率为100K, Bit Rate=(Frequence of CANCLK)/(Prescalar*Number of Time Quanta)
CAN1IDAC=0X10; //4X 16 bits Identifier Acceptance Filters
/*To receive standard identifiers in 32 bit filter mode, it is required to
program the last three bits (AM2 - AM0) in the mask registers CANIDMR1 and CANIDMR5 to \"don’t
care\". To receive standard identifiers in 16 bit filter mode, it is required to program the last three bits (AM2
- AM0) in the mask registers CANIDMR1, CANIDMR3, CANIDMR5 and CANIDMR7 to \"don’t car\". */
CAN1IDAR0=0x20; //IDAM1 IDAM0 标识符接受模式 CAN1IDMR0=0xff; 0 0 2*32 0 1 4*16 CAN1IDAR1=0X00; 1 0 8*8 CAN1IDMR1=0Xff; 1 1 过滤器关闭
CAN1IDAR2=0X80;
CAN1IDMR2=0Xff; //此处将Recieve_Filter0只用CAN0IDAR0来判断保报文
//优先级,不过每一位都要参与判断 CAN1IDAR3=0X00; CAN1IDMR3=0Xff;
CAN1IDAR4=0X90; CAN1IDMR4=0Xff;
CAN1IDAR5=0X00; CAN1IDMR5=0Xff;
//此处将Recieve_Filter只用CAN0IDAR0来判断保报文 //优先级,不过每一位都要参与判断 CAN1IDAR6=0Xa0; CAN1IDMR6=0Xff;
CAN1IDAR7=0X00; CAN1IDMR7=0Xff;
CAN1CTL0=0; //退出初始化模式,回到正常模式 while(CAN1CTL1_INITAK==1) ;
while(CAN1CTL0_SYNCH==1);
CAN1RFLG=0XC3;
//清
CAN
STATUS
CHANGE
INTERRUPT,OVERRUN INTERRUPT,
//BUFFER FULL 的标志位
CAN1RIER=0x00; //开RECIEVER FULL 中断 } void
Transmission_CAN1(void/*unsigned
char
txbuffer,unsigned
char
ID,unsigned char priority,unsigned char length, unsigned char txdata[8],int index*/) {
unsigned char txbuffer;
unsigned char ID_0,ID_1,ID_2,ID_3; unsigned char priority;
unsigned char length; unsigned char txdata[8]; int index;
//以查询方式发送数据
while(CAN1TFLG==0) ; //如果BUFFER都是满的,等待
CAN1TBSEL=CAN1TFLG; //选择BUFFER
txbuffer=CAN1TBSEL; //备份选择的BUFFER,其实也不一定需要,只要以后直接写CAN0TBSEL就好了
ID_0=0x20; //把ID 值写入要传送的帧 ID_1=0X79; //IDE=0,RTR=0.数据帧,标准格式的标识符 ID_2=0X21; ID_3=0X12; //*((unsigned
long*)((unsigned
long)(&CAN0TXIDR0)))=0x2000; //不过在本例中IDMR已经设定了只辨识前8位标识符 CAN1TXIDR0=ID_0; CAN1TXIDR1=ID_1; CAN1TXIDR2=ID_2; CAN1TXIDR3=ID_3;
length=0x07; //把数据长度写入要传送的帧 CAN1TXDLR=length;
priority=0; //当有传送缓冲竞争时,此数据帧所写入的缓冲有最高优先级
CAN1TXTBPR=priority;
txdata[0]=1; txdata[1]=2; txdata[2]=3; txdata[3]=4; txdata[4]=5; txdata[5]=6; txdata[6]=7; txdata[7]=8;
for(index=0;index<=length;index++) {
*(&CAN1TXDSR0+index)=txdata[index]; //把DATA读入帧 }
CAN1TFLG=txbuffer; //开始传送
while((CAN1TFLG&txbuffer)!=txbuffer) ; //等待传送结束
//标志位会在传送结束或者ABORT的时候自动清除
//PTM可编程定时器 programmable timer module }
void delay(void) { int a;
for(a=1000;a>0;a--) ; }
#pragma TRAP_PROC void CAN0_Recieve(void) {
unsigned char length,index; //unsigned char rxdata[8]; PORTB=0; //delay(); //PORTB=0XFF; //delay();
length=(CAN0RXDLR&0X0F);
for(index=0;index} }