H8/300H系列带内部CAN控制器的单片机,广泛应用在各种环境恶劣的通信系统里,如炼油厂,汽车通信等。我们以Tiny系列为例,其内部集成一个TinyCAN控制器,其规格如下:
BOSCH 2.0B active
最高速率1Mbps
数据长度:0~8bytes
4个数据缓存mailbox(可配置为接收或者发送)
CAN总线硬件电路组成:
MCU + CAN控制器 + CAN的物理层收发器
所以我们必须在外面加上一个CAN的收发器,典型的如飞利浦的TJA1050系列。不同的收发器支持不同的速率。如果你的CAN控制器支持1M的速率,那么相应的收发器必须支持1M的速率。
CAN控制器根据2根线上的电位差来判断总线电平。总线电平分为显性电平和隐形电平,二者必居其一。发送方通过使总线电平发生变化,将消息发送给接受方。
具体的CAN规格可以参考“瑞萨开发工具”板块里的《瑞萨提供的CAN通信入门手册》。
下面以瑞萨产的HA13721收发器为例,典型电路如下:
CAN通信编程介绍:
首先我们来初始化CAN控制器。
TinyCAN.MCR.BIT.RSTRQ = 1;
while(TinyCAN.GSR.BIT.RESET == 0);
TinyCAN.TCMSC.BIT.PMR97 = 1; // 设置发送引脚
TinyCAN.TCMSC.BIT.PMR96 = 1; // 设置接收引脚
TinyCAN.MCR.BIT.RSTRQ = 0;
// TCIRR0 clear
TinyCAN.TCIRR0.BIT.RHI = 1;
// 设置接收中断源
TinyCAN.TCIMR0.BIT.DFRIM = 0; // 数据帧请求中断
TinyCAN.TCIMR0.BIT.RFRIM = 0; // 远程帧请求中断
TinyCAN.MBIMR.BIT.MB3 = 0; // 发送邮箱3中断
// 设置发送中断源
TinyCAN.TCIMR1.BIT.EMPIM = 0; // Mailbox empty interrupt enable
// 邮箱设置:设置为发送或者接收
TinyCAN.MBCR.BIT.MB0 = 1; // 该缓存默认为接收
TinyCAN.MBCR.BIT.MB1 = 0; // 设置为发送
TinyCAN.MBCR.BIT.MB2 = 0; // 设置为发送
TinyCAN.MBCR.BIT.MB3 = 0; // 设置为接收
// 下面我们用邮箱0作为接收,邮箱1作为发送。每个邮箱是一个CAN节点,分别设置这2个节点
// MBOX0 setup Receive Mailbox
TinyCAN.MC[0][0] = 8; // 数据长度为8字节
TinyCAN.MC[0][4] = 10; // 设置低ID
TinyCAN.MC[0][5] = 5; // 设置高ID
// MBOX3 setup Transmit Mailbox
TinyCAN.MC[1][0] = 8; // 数据长度为8字节
TinyCAN.MC[1][4] = 11; // 设置低ID
TinyCAN.MC[1][5] = 6; // 设置高ID
// 下面设置CAN控制器的接收滤波器
// 如果设置为0的话,表示节点的ID匹配时,才接收数据
TinyCAN.LAFM[0] = 0x00000000; // Acceptance filter mask enable
TinyCAN.LAFM[1] = 0x00000000;
// CAN通信波利率,这里我们设置为1Mbps
TinyCAN.BCR1.BIT.TSG1 = 5; // 6 Tq
TinyCAN.BCR1.BIT.TSG2 = 2; // 3 Tq
TinyCAN.BCR0.BIT.SJW = 1; // 2 time quantum
TinyCAN.BCR0.BIT.BRP = 1; // 2 system clocks XMB Added 2007.07.23
while(TinyCAN.GSR.BIT.RESET != 0); // wait until GSR3 is reset
OK,CAN控制器已经被初始化,下面我们就可以发送数据了。
首先往数据缓存里填充要发送的数据,数据长度为8个字节。
TinyCAN.MD[1][0] = 0x11;
TinyCAN.MD[1][1] = 0x22;
TinyCAN.MD[1][2] = 0x33;
TinyCAN.MD[1][3] = 0x44;
TinyCAN.MD[1][4] = 0x55;
TinyCAN.MD[1][5] = 0x66;
TinyCAN.MD[1][6] = 0x77;
TinyCAN.MD[1][7] = 0x88;
然后发送数据
while(TinyCAN.TXACK.BIT.MB1); // 等待该标志
TinyCAN.TXPR.BIT.MB1 = 1; // 发送数据
如果一桢数据全部发送完毕,则会产生一个发送中断,如下:
__interrupt(vect=34) void INT_TinyCAN(void)
{
if(TinyCAN.TXACK.BIT.MB1) //发送数据完成
{
TinyCAN.TXACK.BIT.MB1 = 1; // 清除该标志
}
}
这个CAN控制器的中断全部共享一个中断向量34,所以我们只能采用软件中断的方式来判断产生了哪个中断源。
CAN接收的过程是在接收中断里读取接收缓冲的数据。
总结:
CAN通信是一种典型的串行通信协议,以抗干扰性强出名,适用于各种恶劣的环境。
在应用上要注意一些问题,比如总线仲裁,广播,错误帧等。有兴趣的朋友可以深入研究一下。
文章评论(0条评论)
登录后参与讨论