一个CAN的发送报文花费了快三天的时间,以前没有接触过CAN也没使用过DMA,因此遇上不少阻力,还好终于整出来了。
CAN的帧格式太多了不再说明。可以自己网上下载看看帧结构。这里只说一点,最长的帧是扩展数据帧。计算如下:
1sof + 29id + 1ide + 1rtr + 1srr + 2r + 4dlc + 8*8data+ 16crc + 2ack + 7eof = 128bit
1:由于选用的单片机有一个增强型CAN也就是ECAN因此我们必须使用DMA了,原因看下图:
数据手册有这么一句话:ECAN 报文缓冲区位于器件 RAM 中。它们不是 ECAN SFR。用户应用程序必须直接写入为 ECAN报文缓冲区配置的器件 RAM 区。缓冲区的位置和大小由用户应用程序定义。
因此我们必须看看DMA是怎么回事了。在众多的DMA配置中莫过于“存储器地址初始化”最让人纠结了。这东西还的可能看编译器的指令。。。。东西太多实在是不能一一列举了。我们只看看DMA缓冲区位置和大小的配置吧,下面的声明写在main函数之前就行。其中的语句都是什么意思这得看编译器了。这里的大概意思就是设置缓冲区的大小和对其方式!
__eds__ ECAN1MSGBUF ecan1msgBuf __attribute__((eds,aligned(ECAN1_MSG_BUF_LENGTH*16)));
其中ECAN1MSGBUF是自己定义的类型 是unsigned int [32][8] 也就是32个缓冲区,每个缓冲区大小是8字。
我们根据寄存器设置把缓冲区0(大小是8个字)设置为发送缓冲区,那么就是ecan1msgBuf[0][0]到ecan1msgBuf[0][7]就是发送缓冲区了。把请求发送的标志位至1就可以发送了。
下面的代码是在DMA配置中写的,作用就是设置DMA缓冲区的位置。
DMA0STAL = __builtin_edsoffset(ecan1msgBuf);
DMA0STAH = 0x0000;
2:DMA还有很多设置,比较简单就不再说了。下面看看CAN的一些注意事项:
CAN的数据帧分为标准格式和扩展格式,虽然我们发送的是标准格式,但是我们还是得写上EID。什么意思呢?看看下面的代码
ecan1msgBuf[buf][0] = word0; //SID<10:0>+RTR+IDE 11+1+1=13位
ecan1msgBuf[buf][1] = word1;//EID<17:6>
ecan1msgBuf[buf][2] = ((ecan1msgBuf[buf][2] & 0xFFF0) + dataLength) ;//EID<5:0>+RTR+RB1+RB0+DLC 6+1+1+1+4
无论是不是扩展格式都必须发送上面的值 3个字 只是数据不同而已。如果是标准格式那么
ecan1msgBuf[buf][0]就是SID<10:0>+RTR(0)+IDE(0) 如FFFC SID是0b1111 1111 111
ecan1msgBuf[buf][1] 就是EID<17:6> 0b0000 0000 0000
ecan1msgBuf[buf][2] 就是EID<5:0>0b0000 00 +RTR 0b0+RB1 0b0+RB0 0b0+ DLC 0b1000(数据长度8字节)
ecan1msgBuf[buf][3] = data1;//真正的数据段data1=0x1111 16位
ecan1msgBuf[buf][4] = data2;//data2=0x2222 16位
ecan1msgBuf[buf][5] = data3;//data3=0x3333 16位
ecan1msgBuf[buf][6] = data4;//data4=0x4444 16位 共64位 8个字节!!!!CAN的数据段最多8字节
代码太多就不上传了,寄存器的配置也不难。不知道的可以看看官方的例程。例程可以再单片机的说明页下载也可以在代码示例中找相近的单片机示例代码。
示例代码下载页面链接:http://www.microchip.com/TechDoc.aspx?type=CodeExamples