//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//描述://INT0按键程序+显示程序+CAN自收发程序&//数码管1-2(从右至左)显示本节点计数结果,数码管3-4显示接收到的数据&//十进制显示&//CAN主要参数:PeliCAN模式,扩展帧EFF模式&//29位标示码结构:&//发送数据结构:计数结果,0x02,0x03,0x04,0x05,0x06,0x07,0x08&//接收数据结构:待显示数据+其它7个字节的数据&//本节点的地址:0x11,0x22,0x33,0x00;可以接收全部节点的数据&//目的节点地址:0x01,0x02,0x03,0x00;可以被能接收全部节点数据的节点接收&//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!&//【声明】作者:PIAE小组includereg52.h#includeintrins.h#includecan_selfdef.hvoidINT0_Counter(void)interrupt0using1{//INT0按键为计数按键EA=0;Txd_data++;//存储计数结果,并为待发送的数据TXD_flag=1;//要发送数据标志位EA=1;}voidCAN_RXD(void)interrupt2{//接收数据函数,在中断服务程序中调用uchardataJudge;EA=0;//关CPU中断IE0=0;Judge=IR;if(Judge&0x01){//IR.0=1接收中断RX_buffer[0]=RBSR;RX_buffer[1]=RBSR1;RX_buffer[2]=RBSR2;RX_buffer[3]=RBSR3;RX_buffer[4]=RBSR4;RX_buffer[5]=RBSR5;RX_buffer[6]=RBSR6;RX_buffer[7]=RBSR7;RX_buffer[8]=RBSR8;RX_buffer[9]=RBSR9;RX_buffer[10]=RBSR10;RX_buffer[11]=RBSR11;RX_buffer[12]=RBSR12;RXD_flag=1;//置有接收标志CMR=0X04;Judge=ALC;//释放仲裁随时捕捉寄存器Judge=ECC;//释放错误代码捕捉寄存器}IER=0x01;//.0=1--接收中断使能;EA=1;//打开CPU中断}voidmain(void){//CPU初始化SJA_RST=1;//CAN总线复位管脚,复位无效SJA_CS=0;//CAN总线片选有效EX1=1;IT1=0;//CAN总线接收中断IT0=1;//外部中断0负边沿触发EX0=1;//打开外部中断0EA=1;//打开总中断SJA_CS=1;//CAN总线片选无效,使对数据总线的操作不会影响SJA1000。//CPU初始化CAN_init();//SJA1000初始化,对SJA1000寄存器的读写是采用外部寄存器寻址方式,所以不需要程序单独控制片选有效无效_nop_();_nop_();while(1){_nop_();_nop_();Rxd_deal();//接收处理程序Txd_deal();//发送处理程序led_seg7(1,Txd_data);led_seg7(3,Rxd_data);}}//*********************处理函数********************************voidRxd_deal(void){////////接收处理程序//////////////if(RXD_flag){EA=0;//关闭CPU中断RXD_flag=0;Rxd_data=RX_buffer[5];EA=1;}}////////接收处理程序//////////////voidTxd_deal(void){//发送处理函数,主要是准备数据,并且调用发送函数if(TXD_flag==1){_nop_();TXD_flag=0;TX_buffer[5]=Txd_data;//CAN_TXD();_nop_();_nop_();}}//*********************处理函数********************************//*********************CAN子函数***********************voidCAN_init(void){//SJA1000的初始化ucharbdataJudge;ucharACRR[4];ucharAMRR[4];ACRR[0]=0x11;ACRR[1]=0x22;ACRR[2]=0x33;ACRR[3]=0x44;//接收代码寄存器,节点1AMRR[0]=0xff;AMRR[1]=0Xff;AMRR[2]=0xff;AMRR[3]=0xff;//接收屏蔽寄存器。只接收主机发送的信息do{//.0=1---resetMODRe,进入复位模式,以便设置相应的寄存器//防止未进入复位模式,重复写入MODR=0x09;Judge=MODR;}while(!(Judge&0x01));CDR=0x88;//CDR.3=1--时钟关闭,.7=0---basicCAN,.7=1---PeliCANBTR0=0x31;BTR1=0x1c;//总线波特率设定IER=0x01;//.0=1--接收中断使能;.1=0--关闭发送中断使能OCR=0xaa;//配置输出控制寄存器CMR=0x04;//释放接收缓冲器ACR=ACRR[0];ACR1=ACRR[1];ACR2=ACRR[2];ACR3=ACRR[3];//初始化标示码AMR=AMRR[0];AMR1=AMRR[1];AMR2=AMRR[2];AMR3=AMRR[3];//初始化掩码do{//确保进入自接收模式MODR=0x04;Judge=MODR;}while(!(Judge&0x04));}//SJA1000的初始化voidCAN_TXD(void){uchardataJudge;uchardataTX_buffer[N_can];//初始化标示码头信息TX_buffer[0]=0x88;//.7=0扩展帧;.6=0数据帧;.3=1数据长度TX_buffer[1]=0x01;//本节点地址TX_buffer[2]=0x02;//TX_buffer[3]=0x03;//TX_buffer[4]=0x00;////初始化标示码头信息//初始化发送数据单元TX_buffer[5]=Txd_data;TX_buffer[6]=0x22;TX_buffer[7]=0x33;TX_buffer[8]=0x44;//TX_buffer[9]=0x55;//TX_buffer[10]=0x66;//TX_buffer[11]=0x77;//TX_buffer[12]=0x88;////初始化数据信息EA=0;//关中断do{Judge=SR;LED_RED=0;//}while(Judge&0x10);//SR.4=1正在接收,等待do{Judge=SR;LED_RED=0;//}while(!(Judge&0x08));//SR.3=0,发送请求未处理完,等待do{Judge=SR;LED_RED=0;//}while(!(Judge&0x04));//SR.2=0,发送缓冲器被锁。等待LED_RED=!LED_RED;LED_GRE=!LED_GRE;//灯闪烁TBSR=TX_buffer[0];TBSR1=TX_buffer[1];TBSR2=TX_buffer[2];TBSR3=TX_buffer[3];TBSR4=TX_buffer[4];TBSR5=TX_buffer[5];TBSR6=TX_buffer[6];TBSR7=TX_buffer[7];TBSR8=TX_buffer[8];TBSR9=TX_buffer[9];TBSR10=TX_buffer[10];TBSR11=TX_buffer[11];TBSR12=TX_buffer[12];CMR=0x10;//置位自发送接收请求EA=1;}voidDelay(uchardelay_time){//延时程序while(delay_time--){}}//*********************CAN子函数*************************voidled_seg7(ucharfrom,ucharnumber)//from(1_4):数码管显示起始位置(从右到左),number:显示的数{uchardigit,temp_l;uchartemp_h=0x7f;temp_h=_cror_(temp_h,from-1);//确定从哪一位开始显示,即确定高四位temp_h=temp_h&0xf0;//取高四位temp_l=P2&0x0f;//取P2的低四位P2=temp_h|temp_l;//设定P2口if(number==0){P0=led[0];Delay(5);P0=0xff;}else{while(number){digit=number%10;number/=10;P0=led[digit];Delay(5);temp_h=P2&0xf0;//取P2的高四位temp_h=temp_h|0x0f;//拼装temp_h,进行位选temp_h=_cror_(temp_h,1);temp_h=temp_h&0xf0;//取高四位temp_l=P2&0x0f;//取P2的低四位P0=0xff;P2=temp_h|temp_l;//设定P2口}//while结束}//else结束}------------------------------//对管脚分配进行了定义//对子函数进行了声明#defineucharunsignedchar#defineuintunsignedint#defineNOP5{_nop_();_nop_();_nop_();_nop_();_nop_();}/*延时5us*/#defineN_can13//一帧字节数bitTXD_flag=0;//若为1,要求发送处理bitRXD_flag=0;//有无数据可以接收;0无,1有ucharcodeled[]={0xC0,0xDE,0xA2,0x8A,0x9C,0x89,0x81,0xDA,0x80,0x88,0xFF,0xBF};//0,1,2,3,4,5,6,7,8,9,off//编码规则是gfedcba,其中g为小数点,控制dp,这里都设为1,不亮ucharRX_buffer[13];//接收的数据ucharTX_buffer[13];//接收的数据ucharTxd_data=0;//CAN总线要发送的数据,也是要在数码管1-2位置显示的数据ucharRxd_data=0;//CAN总线要接收的数据,也是要在数码管3-4位置显示的数据/*P1口分配*//*P2口分配*/sbitLED_RED=P2^1;sbitLED_GRE=P2^2;sbitSJA_RST=P2^3;//SJA1000复位管脚sbitSJA_CS=P2^0;//SJA1000片选管脚/*CAN总线SJA1000寄存器地址定义(用的是PeliCAN模式,扩展帧EFF模式)*///为什么地址上0xFE00。FE是因为我们有16位的地址线。P0口是低8位地址,P2口是高8位地址。而P20是接的CS端一定要是为0,所以地址是FE.ucharxdataMODR_at_0xFE00;//模式寄存器ucharxdataCMR_at_0xFE01;//命令寄存器ucharxdataSR_at_0xF