热度 17
2014-1-17 06:44
3203 次阅读|
0 个评论
主函数操作流程: 时钟设置 清中断标志 ECAN1初始化,DMA0,2初始化,使能中断 ECAN2初始化,DMA1初始化 ,使能中断 ECAN2写信息,ECAN1写信息,发送请求 主循环为空,等待中断 ECAN1初始化 void ecan1Init(void){ C1CTRL1bits.REQOP=4; while(C1CTRL1bits.OPMODE!=4); //进入配置模式 ecan1ClkInit(); //时钟初始化,配置TQ C1FCTRLbits.FSA=0b10000;//设置FIFO从buffer16开始 C1FCTRLbits.DMABS=0b000;//DMA中开辟32个BUFFER // FILTER设置 //下面FILTER的设置参数含义为:设置FILTER1,ID为0X1FFFFFFF,拓展模式,指向缓存1,MASK选择0 ecan1WriteRxAcptFilter(1,0x1FFEFFFF,1,1,0); // MASK设置 //下面MASK的设置参数含义为:设置MASK1,所有的位都要比较,模式看后面,模式为拓展模式 ecan1WriteRxAcptMask(1,0x1FFFFFFF,1,1); //设置完FILTER和MASK,回到常规模式 C1CTRL1bits.REQOP=0; while(C1CTRL1bits.OPMODE!=0); //定义BUFFER0和BUFFER1的方向,以及优先级 C1RXFUL1=C1RXFUL2=C1RXOVF1=C1RXOVF2=0x0000; C1TR01CONbits.TXEN0=1; /* ECAN1, Buffer 0 is a Transmit Buffer */ C1TR01CONbits.TXEN1=0; /* ECAN1, Buffer 1 is a Receive Buffer */ C1TR01CONbits.TX0PRI=0b11; /* Message Buffer 0 Priority Level */ C1TR01CONbits.TX1PRI=0b11; /* Message Buffer 1 Priority Level */ } ECAN2初始化 void ecan2Init(void){ C2CTRL1bits.REQOP=4; //进入配置模式 while(C2CTRL1bits.OPMODE!=4); ecan2ClkInit(); //配置时钟TQ C2FCTRLbits.FSA=0b10000;//FIFO首地址 C2FCTRLbits.DMABS=0b000; //缓存数量 //下面FILTER的设置参数含义为:设置FILTER1,ID为0X1FFFFFFF,拓展模式,指向缓存0,MASK选择0 ecan2WriteRxAcptFilter(1,0x1FFEFFFF,1,0,0); //下面MASK的设置参数含义为:设置MASK1,所有的位都要比较,模式看后面,模式为拓展模式 ecan2WriteRxAcptMask(1,0x1FFFFFFF,1,1); C2CTRL1bits.REQOP=0; while(C2CTRL1bits.OPMODE!=0);//进入常规模式 C2RXFUL1=C2RXFUL2=C2RXOVF1=C2RXOVF2=0x0000; C2TR01CONbits.TXEN0=1; //ECAN2发送 C2TR01CONbits.TX0PRI=0b11; //优先级设置 } DMA初始化 void dma0init(void){ DMACS0=0; //冲突检测清零 DMA0CON=0x2020; //方向为发送,外设直接地址 DMA0PAD=0x0442; /发送地址 DMA0CNT=0x0007; //发送计数 DMA0REQ=0x0046; //写入请求好 DMA0STA= __builtin_dmaoffset(ecan1msgBuf); //地址指向 DMA0CONbits.CHEN=1; //使能通道0 } void dma1init(void){ DMA1CON=0x2020; //方向为发送,外设直接地址 DMA1PAD=(int)C2TXD; //C2TXD为发送数据寄存器 DMA1CNT=0x0007; //发送计数 DMA1REQ=0x0047; //请求号 DMA1STA= __builtin_dmaoffset(ecan2msgBuf); //DPRAM偏置,地址指向 DMA1CONbits.CHEN=1; //使能CH1 } void dma2init(void){ DMACS0=0; //冲突检测清零 DMA2CON=0x0020; //接收,外设直接地址 DMA2PAD=0x0440; //接收地址 DMA2CNT=0x0007; //接收计数 DMA2REQ=0x0022; //请求号 DMA2STA= __builtin_dmaoffset(ecan1msgBuf); //地址指向 DMA2CONbits.CHEN=1; //使能通道2 } void dma3init(void){ DMACS0=0; DMA3CON=0x0020; DMA3PAD=(int)C2RXD; /* ECAN 2 (C2RXD) */ DMA3CNT=0x0007; DMA3REQ=0x0037; /* ECAN 2 Receive */ DMA3STA=__builtin_dmaoffset(ecan2msgBuf); DMA3CONbits.CHEN=1; } ECAN1写消息 void ecan1WriteMessage(void){ ecan1WriteTxMsgBufId(0,0x1FFEFFFF,1,1); ecan1WriteTxMsgBufData(0,8,0,0,0,0); } //第一个函数:第一个参数,BUFFER号,第二个参数ID号,第三个,拓展ID标志,第四个,是否是远程帧 //上面的调用,写到缓存0,ID号是0X1FFFFFFF,是拓展帧,是远程帧 void ecan1WriteTxMsgBufId(unsigned int buf, long txIdentifier, unsigned int ide, unsigned int remoteTransmit){ unsigned long word0=0, word1=0, word2=0; unsigned long sid10_0=0, eid5_0=0, eid17_6=0,a; eid5_0 = (txIdentifier 0x3F); //取得ID号 eid17_6 = (txIdentifier6) 0xFFF; sid10_0 = (txIdentifier18) 0x7FF; word1 = eid17_6; if(remoteTransmit==1) { // 如果是远程帧,将远程帧的标志写入到WORD0和WORD2中 word0 = ((sid10_0 2) | ide | 0x2); word2 = ((eid5_0 10)| 0x0200);} else { word0 = ((sid10_0 2) | ide); word2 = (eid5_0 10); } ecan1msgBuf = word0;//将合成的WORD写入到BUFFER中 ecan1msgBuf = word1; ecan1msgBuf = word2; } 如果是数据帧,则继续写入数据,如果是远程帧,也可以写入一些无效数据,比如: ecan1WriteTxMsgBufId(0,0x1FFEFFFF,1,1); ecan1WriteTxMsgBufData(0,8,0,0,0,0);: void ecan1WriteTxMsgBufData(unsigned int buf, unsigned int dataLength, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4){ ecan1msgBuf = ((ecan1msgBuf 0xFFF0) + dataLength) ; ecan1msgBuf = data1; ecan1msgBuf = data2; ecan1msgBuf = data3; ecan1msgBuf = data4; } 中断函数的处理 上面的程序中,中断有6个,两个为ECAN1和ECAN2的中断,另外四个为DMA0~DMA3的四个中断 ECAN1和ECAN2的中断处理是一样的,具体接收子程序不同。 void __attribute__((interrupt, no_auto_psv))_C1Interrupt(void) { IFS2bits.C1IF = 0; //清零ECAN1中断标志 if(C1INTFbits.TBIF) { C1INTFbits.TBIF = 0; //发送中断?清空就行 } if(C1INTFbits.RBIF) { if(C1RXFUL1bits.RXFUL1==1) //接收?则需要接收程序 { rx_ecan1message.buffer=1; //设置一个缓存中有数据的标志 C1RXFUL1bits.RXFUL1=0; //清零接收中断标志 } rxECAN1(rx_ecan1message); //缓存有数据,则开始接收,然后清零标志 C1INTFbits.RBIF = 0; } } ECAN1的接收程序: void rxECAN1(mID *message) { unsigned int ide=0; unsigned int srr=0; unsigned long id=0,d; ide=ecan1msgBuf 0x0001; //将收到的帧的IDE和SRR读出来 srr=ecan1msgBuf 0x0002; // if(ide==0) { message-id=(ecan1msgBuf 0x1FFC) 2; //如果是标准帧,则将ID读出来,并且标记为标准帧 message-frame_type=CAN_FRAME_STD; } else //如果是扩展帧,将ID也读出来,放到BUFFER 0/1/2中 { id=ecan1msgBuf 0x1FFC; message-id=id 16; id=ecan1msgBuf 0x0FFF; message-id=message-id+(id 6); id=(ecan1msgBuf 0xFC00) 10; message-id=message-id+id; message-frame_type=CAN_FRAME_EXT; } //判断是不是远程帧,如果是远程帧,则将远程帧标志置位 if(srr==1) { message-message_type=CAN_MSG_RTR; } //如果为常规数据帧,则先标志帧类型为数据帧,然后将数据读入DMA的缓存,并且将数据长度也读入到BUFFER2中。 else { message-message_type=CAN_MSG_DATA; message-data =(unsigned char)ecan1msgBuf ; message-data =(unsigned char)((ecan1msgBuf 0xFF00) 8); message-data =(unsigned char)ecan1msgBuf ; message-data =(unsigned char)((ecan1msgBuf 0xFF00) 8); message-data =(unsigned char)ecan1msgBuf ; message-data =(unsigned char)((ecan1msgBuf 0xFF00) 8); message-data =(unsigned char)ecan1msgBuf ; message-data =(unsigned char)((ecan1msgBuf 0xFF00) 8); message-data_length=(unsigned char)(ecan1msgBuf 0x000F); } } 四个DMA的中断程序都很简单,就是单纯的清标志。 /***************************************************/ 2013年是移动互联网的元年,移动互联网大大提高了我们工作和生活的效率。 罗辑思维用互联网思维网络了大量的会员,最近又在召集用互联网思维来吃霸王餐。 我们不需要那么牛气哄哄,互联网思维既然能够解决这样的大事,那小事当然更没问题。 利用互联网思维做一个晨型人,也应该不是一件难事吧。 操作模式如下:申请一个微信公众号,分享作为晨型人一天的收获。 以及在遇到困难的时候,如果克服自己,解决问题。 如果有兴趣,扫一扫下面的公众号 吧,让我们一起轻松的做一个快乐的晨型人。 /***************************************************/