CAN通信模块的滤波器设置
2013-08-31 10:21
507 查看
昨天好不容调试通了CAN模块,首先是滤波器不能关闭,关了机不接受任何帧数据了,跟我想象中的完全部不一样啊,另外通信的是标准帧,到现在扩展帧怎么弄的还没搞清楚,先记录下标准帧的东西;相关的寄存器设置这个不用说了,我没有搞清楚的就是这个滤波器设置问题,后来研究了半天,16为滤波器标准帧总算勉强懂了一点。
基本原理就是MR+AR的方式,在标准帧中ID有11为,ID10-ID0;所以如果想要通信的帧ID=0B001 0000 0000 =0x100的话,那么应该将这11个bit放入寄存器(AR0-AR1)组成的16为寄存器中,于是得到得到AR=001 0000 0000 00000(在最后面添加5个0)得到16bit,于是AR=0x2000;MR设置为全部比较,MR=0x0007;又例如,假设通信的ID=0B 0001 0000 000=0x080(最前面补0,这个数不变
),那么将这个11bit放入寄存器中(AR0-AR1)组成的16为寄存器中,于是得到得到AR=0001 0000 000 00000(在最后面添加5个0)得到16bit,于是AR=0x1000;MR设置为全部比较,MR=0x0007;一次类推;
接下来在讲一下MR的问题,MR也就是屏蔽的意义,因为在标准帧中只有11为有效;假如要通信的ID=0B 001 0000 000X,那么应该将这11个bit放入寄存器(AR0-AR1)组成的16为寄存器中,于是得到得到AR=001 0000 000X 00000(在最后面添加5个0)得到16bit,于是AR=0x2000(或者0x2020),MR=0B 000 0000 0001 + 00111(补5位,最后三个必须为111)=0x0027.
标准帧中当设置应该是这样额。附一个网上的程序:
MSCAN学习
//////////////////////////////////////////////////////////////////////////////
// MSCAN初始化
//////////////////////////////////////////////////////////////////////////////
/*******************CAN0******************************/
void MSCAN0_Init()
{
// If MSCAN peripheral is not in Initialization Mode, enables the Inizialization Mode Request
if(!(CAN0CTL1&CAN0CTL1_INITAK_MASK))
{
CAN0CTL0 = CAN0CTL0_INITRQ_MASK; //进入初始化模式(必须!)
while(!(CAN0CTL1&CAN0CTL1_INITAK_MASK));//wait进入
}
// Enables MSCAN peripheral and chooses Oscillator Clock, Loop Disabled and Normal Operation
CAN0CTL1 = 0x80;
// Configures SJW = 3Tq and Prescaler = 3
CAN0BTR0=0x43;//每位1个采样,设置时钟分频。同步跳跃宽度SJW =2和时间原子TIMSEG的选择设置见下一个寄存器CAN0BTR1,下图。DATASHEET,P338页
// Configures One Sample, Time Segment 1 = 5Tq and Time Segment 2 = 2Tq
CAN0BTR1=0x94;//设置波特率
//上图为波特率计算公式,再求倒数即为波特率。见DATASHEET(P305)
CAN0IDAC=0x01; //设置为16位接收过滤器
CAN0IDMR0=0Xff; //不匹配,也即总线上所有数据都可以接收
CAN0IDMR1=0Xff;
CAN0IDMR2=0Xff;
CAN0IDMR3=0Xff;
//设置接收ID标识符过滤器,当屏蔽寄存器开启之后(CAN0IDMRx = 0x00),这些寄存器才有用。
// CAN0IDAR0=0X57;
// CAN0IDAR1=0X60;
// CAN0IDAR2=0X55;
// CAN0IDAR3=0X54;
CAN0CTL0 = 0x00; //退出初始化模式进入正常模式
while(CAN0CTL1&CAN0CTL1_INITAK_MASK); //等待退出
while(!(CAN0CTL0&CAN0CTL0_SYNCH_MASK));//同步时钟
CAN0RIER=1; //CAN0接收中断使能
}
//////////////////////////////////////////////////////////////////////////////
// MSCAN发送
//////////////////////////////////////////////////////////////////////////////
//can结构体
struct can_msg {
unsigned int id;
Bool RTR;
unsigned char data[8];
unsigned char len;
unsigned char prty;
};
Bool MSCAN0_SendMsg(struct can_msg msg)
{
unsigned char i;
unsigned char txbuffer = 0;
if (!CAN0TFLG)
return 0;
CAN0TBSEL = CAN0TFLG;
//CAN0TBSEL = 0X01;
txbuffer = CAN0TBSEL;
CAN0TXIDR0 = (msg.id>>3)&0x0ff;
CAN0TXIDR1 = (msg.id<<5)&0x0ff;
//CAN0TXIDR0 = 0x55;
// CAN0TXIDR1 = 0x40;//配置成扩展帧格式29位ID发送SRR=1 IDE=1
CAN0TXIDR2 = 0x55;
CAN0TXIDR3 = 0x53;
for(i = 0; i < msg.len; i++)
*(&CAN0TXDSR0+i) = msg.data[i]; //发送数据到发送邮箱
CAN0TXDLR = msg.len; //发送数据长度
CAN0TXTBPR = msg.prty; //本地发送优先级
CAN0TFLG = txbuffer;
while ( (CAN0TFLG & txbuffer) == txbuffer); //等待数据发送到总线
return 1;
}
/**********************************************************
**名称:void interrupt 38 CAN0RxISR()
**描述:CAN0接收中断,接收can总线上的匹配ID号的数据
**
**********************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 38 CAN0RxISR()
{
if(CAN0RXIDR0==userID0)&&CAN0RXIDR1==(userID0)
{//判断总线上该数据帧的ID号是否与设定值匹配。
length = (CAN0RXDLR & 0x0F);
for (index=0; index<length; index++)
{
rxdata0[index] = *(&CAN0RXDSR0 + index);
}
}
else if(CAN0RXIDR0==userID1&&CAN0RXIDR1==userID1)
{
length = (CAN0RXDLR & 0x0F);
for (index=0; index<length; index++)
{
rxdata1[index] = *(&CAN0RXDSR0 + index);
}
}
}
#pragma CODE_SEG DEFAULT
基本原理就是MR+AR的方式,在标准帧中ID有11为,ID10-ID0;所以如果想要通信的帧ID=0B001 0000 0000 =0x100的话,那么应该将这11个bit放入寄存器(AR0-AR1)组成的16为寄存器中,于是得到得到AR=001 0000 0000 00000(在最后面添加5个0)得到16bit,于是AR=0x2000;MR设置为全部比较,MR=0x0007;又例如,假设通信的ID=0B 0001 0000 000=0x080(最前面补0,这个数不变
),那么将这个11bit放入寄存器中(AR0-AR1)组成的16为寄存器中,于是得到得到AR=0001 0000 000 00000(在最后面添加5个0)得到16bit,于是AR=0x1000;MR设置为全部比较,MR=0x0007;一次类推;
接下来在讲一下MR的问题,MR也就是屏蔽的意义,因为在标准帧中只有11为有效;假如要通信的ID=0B 001 0000 000X,那么应该将这11个bit放入寄存器(AR0-AR1)组成的16为寄存器中,于是得到得到AR=001 0000 000X 00000(在最后面添加5个0)得到16bit,于是AR=0x2000(或者0x2020),MR=0B 000 0000 0001 + 00111(补5位,最后三个必须为111)=0x0027.
标准帧中当设置应该是这样额。附一个网上的程序:
MSCAN学习
//////////////////////////////////////////////////////////////////////////////
// MSCAN初始化
//////////////////////////////////////////////////////////////////////////////
/*******************CAN0******************************/
void MSCAN0_Init()
{
// If MSCAN peripheral is not in Initialization Mode, enables the Inizialization Mode Request
if(!(CAN0CTL1&CAN0CTL1_INITAK_MASK))
{
CAN0CTL0 = CAN0CTL0_INITRQ_MASK; //进入初始化模式(必须!)
while(!(CAN0CTL1&CAN0CTL1_INITAK_MASK));//wait进入
}
// Enables MSCAN peripheral and chooses Oscillator Clock, Loop Disabled and Normal Operation
CAN0CTL1 = 0x80;
// Configures SJW = 3Tq and Prescaler = 3
CAN0BTR0=0x43;//每位1个采样,设置时钟分频。同步跳跃宽度SJW =2和时间原子TIMSEG的选择设置见下一个寄存器CAN0BTR1,下图。DATASHEET,P338页
// Configures One Sample, Time Segment 1 = 5Tq and Time Segment 2 = 2Tq
CAN0BTR1=0x94;//设置波特率
//上图为波特率计算公式,再求倒数即为波特率。见DATASHEET(P305)
CAN0IDAC=0x01; //设置为16位接收过滤器
CAN0IDMR0=0Xff; //不匹配,也即总线上所有数据都可以接收
CAN0IDMR1=0Xff;
CAN0IDMR2=0Xff;
CAN0IDMR3=0Xff;
//设置接收ID标识符过滤器,当屏蔽寄存器开启之后(CAN0IDMRx = 0x00),这些寄存器才有用。
// CAN0IDAR0=0X57;
// CAN0IDAR1=0X60;
// CAN0IDAR2=0X55;
// CAN0IDAR3=0X54;
CAN0CTL0 = 0x00; //退出初始化模式进入正常模式
while(CAN0CTL1&CAN0CTL1_INITAK_MASK); //等待退出
while(!(CAN0CTL0&CAN0CTL0_SYNCH_MASK));//同步时钟
CAN0RIER=1; //CAN0接收中断使能
}
//////////////////////////////////////////////////////////////////////////////
// MSCAN发送
//////////////////////////////////////////////////////////////////////////////
//can结构体
struct can_msg {
unsigned int id;
Bool RTR;
unsigned char data[8];
unsigned char len;
unsigned char prty;
};
Bool MSCAN0_SendMsg(struct can_msg msg)
{
unsigned char i;
unsigned char txbuffer = 0;
if (!CAN0TFLG)
return 0;
CAN0TBSEL = CAN0TFLG;
//CAN0TBSEL = 0X01;
txbuffer = CAN0TBSEL;
CAN0TXIDR0 = (msg.id>>3)&0x0ff;
CAN0TXIDR1 = (msg.id<<5)&0x0ff;
//CAN0TXIDR0 = 0x55;
// CAN0TXIDR1 = 0x40;//配置成扩展帧格式29位ID发送SRR=1 IDE=1
CAN0TXIDR2 = 0x55;
CAN0TXIDR3 = 0x53;
for(i = 0; i < msg.len; i++)
*(&CAN0TXDSR0+i) = msg.data[i]; //发送数据到发送邮箱
CAN0TXDLR = msg.len; //发送数据长度
CAN0TXTBPR = msg.prty; //本地发送优先级
CAN0TFLG = txbuffer;
while ( (CAN0TFLG & txbuffer) == txbuffer); //等待数据发送到总线
return 1;
}
/**********************************************************
**名称:void interrupt 38 CAN0RxISR()
**描述:CAN0接收中断,接收can总线上的匹配ID号的数据
**
**********************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 38 CAN0RxISR()
{
if(CAN0RXIDR0==userID0)&&CAN0RXIDR1==(userID0)
{//判断总线上该数据帧的ID号是否与设定值匹配。
length = (CAN0RXDLR & 0x0F);
for (index=0; index<length; index++)
{
rxdata0[index] = *(&CAN0RXDSR0 + index);
}
}
else if(CAN0RXIDR0==userID1&&CAN0RXIDR1==userID1)
{
length = (CAN0RXDLR & 0x0F);
for (index=0; index<length; index++)
{
rxdata1[index] = *(&CAN0RXDSR0 + index);
}
}
}
#pragma CODE_SEG DEFAULT
相关文章推荐
- CAN通信中地址设置的问题
- 基于STM32的CAN网络开发笔记之滤波器配置和ID设置
- CAN总线通信:实现MIC-3680与F28335 CAN总线通信的设置
- CAN接口芯片MCP2515的波特率和滤波器设置问题
- STM32 CAN 通信 滤波设置问题
- 设置 NULL DACL 权限描述符解决ASP.NET 通过 FileMapping 与其他进程通信问题
- 5000米433M透明传输模块,远距离无线数传模块 通信模块
- STM32407 网络通信模块
- Mycat 网络通信模块源码
- thinkPHP 学习记录 一个站点下模块设置
- 蓝牙模块与手机通信
- 【ST学习小组】STM32F103的CAN 通信之主控器
- 基于STC15F2K08S2单片机和JDY-10蓝牙模块的串行通信
- drupal8 模块设置
- 用C#开发.NET CF 蓝牙通信模块
- 学生信息系统学习心得六、课程设置模块的创建
- Android--Recovery模块之恢复出厂设置
- DESTOON系统文章模块默认设置第一张图片为标题图的方法
- Python:使用threading模块实现多线程编程八[使用Event实现线程间通信]
- 关于webrtc里面的opengl设置坐标系的问题,解决ios和android通信图像是反的问题