历史上的今天
今天是:2024年09月30日(星期一)
2019年09月30日 | 利用CAN中断进行简单的数据接收
2019-09-30 来源:eefocus
CAN是控制器局域网络(Controller Area Network, CAN)的简称,是国际上应用最广泛的现场总线之一。 在北美和西欧,CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。

本例通过用MC9S12XS128MAA来实现CAN标准帧的接收。
以下为本例所用到的寄存器介绍(CAN初始化部分用到的寄存器此篇不再赘述,见“利用CAN进行简单的数据发送”)
CANRFLG寄存器

WUPIF (唤醒中断标志)= 1 时,MSCAN在CAN总线上检测到活动并请求唤醒
= 0 时,睡眠模式下未观察到唤醒活动
CSCIF(CAN状态改变中断标志) = 1 时, MSCAN更改了当前CAN总线状态
= 0 时,CAN总线状态未发生变化
RSTAT[1:0] (接收状态位)= 00 时,RxOK :0 ≤ 接收错误计数器 ≤ 96
= 01 时,RxWRN :96 < 接收错误计数器 ≤ 127
= 10 时,RxERR :127 < 接收错误计数器 ≤ 255
= 11 时,Bus-off : 传输错误计数器 > 255
TSTAT[1:0] (发送状态位) = 00 时,TxOK :0 ≤ 发送错误计数器 ≤ 96
= 01 时,TxWRN :96 < 发送错误计数器 ≤ 127
= 10 时,RxERR :127 < 发送错误计数器 ≤ 255
= 11 时,Bus-off : 传输错误计数器 > 255
OVRIF(溢出中断标志) = 1 时,数据溢出
= 0 时,没有溢出
RXF(接收缓冲区满标志) = 1 时,RxFG中有一条新消息
= 0 时,RxFG无可用新消息
CANRXIDR:用来存放CAN报文的ID、远程帧或数据帧状态、标准帧或扩展帧


CANRXDSR:用来存放数据长度用来存放数据(最多8个字节)

CAN0RXDLR:用来存放数据长度


以下为完整的CAN接收报文程序
#include #include "derivative.h" #define LED PORTB_PB0 //定义连接发光二级管的PORTB_PB0口数据寄存 //器为LED,写'0'亮,写'1' 灭 #define LED_dir DDRB_DDRB0 //定义连接发光二级管的PORTB_PB0口方向寄存器 //为LED_dir,写'0'做输入口,写'1'做输出口 struct can_msg //定义接收报文的结构体 { unsigned int id; //报文的ID号 Bool RTR; unsigned char data[8]; //报文的数据 unsigned char len; //数据长度 }; struct can_msg msg_get; //定义结构体变量 void INIT_PLL(void) //初始化锁相环 { CLKSEL_PLLSEL=0; //内部总线时钟来源于晶振 PLLCTL_PLLON=0; //关闭PLL SYNR=0x40 | 0x03; REFDV=0x80 | 0x01; POSTDIV=0x00; //PLL为64MHz PLLCTL_PLLON=1; //打开PLL _asm(nop); _asm(nop); //等待两个机器周期 while(CRGFLG_LOCK==0); //根据CRGFLG寄存器的LOCK位,确定PLL是否稳定 LOCK==1 稳定,==0 不稳定 CLKSEL_PLLSEL =1; //选择PLL作为时钟源 } void INIT_CAN0(void) //初始化CAN0 { if(CAN0CTL0_INITRQ==0) // 查询是否进入初始化状态 CAN0CTL0_INITRQ =1; // 进入初始化状态 while (CAN0CTL1_INITAK==0); //初始化握手标志 CAN0BTR0_SJW = 0; //设置同步 CAN0BTR0_BRP = 7; //设置波特率 CAN0BTR1 = 0x1c; //设置时段1和时段2的Tq个数 ,总线频率为250kb/s /* Bit Time = [(Prescaler value)*(1+TimeSegment1+TimeSegment2)]/fCANCLK f = 1 / Bit Time Prescaler value = 8 TimeSegment1 = 13 TimeSegment2 = 2 fcanclk = 32MHz f = 250kb/s */ CAN0IDMR0 = 0xFF; CAN0IDMR1 = 0xFF; CAN0IDMR2 = 0xFF; CAN0IDMR3 = 0xFF; CAN0IDMR4 = 0xFF; CAN0IDMR5 = 0xFF; CAN0IDMR6 = 0xFF; CAN0IDMR7 = 0xFF; // 关闭滤波器 CAN0CTL1 = 0xC0; //使能MSCAN模块,设置为一般运行模式、使用总线时钟源 CAN0CTL0 = 0x00; //返回一般模式运行 while(CAN0CTL1_INITAK); //等待回到一般运行模式 while(CAN0CTL0_SYNCH==0); //等待总线时钟同步 CAN0RIER_RXFIE = 1; //打开接收中断 } Bool MSCAN0GetMsg(struct can_msg *msg) //CAN0接收函数 { unsigned char sp2; if(!(CAN0RFLG_RXF)) // 检测接收标志 0没有新消息,1有新消息 return(FALSE); if(CAN0RXIDR1_IDE) // 检测 CAN协议报文模式 (标准帧/扩展帧) 0标准帧 1扩展帧 return(FALSE); msg->id = (unsigned int)(CAN0RXIDR0<<3) | (unsigned char)(CAN0RXIDR1>>5); //将ID通过移位放入相应的寄存器位置 if(CAN0RXIDR1&0x10) msg->RTR = TRUE; else msg->RTR = FALSE; // 读标识符 RTR0数据帧 1远程帧 msg->len = CAN0RXDLR; // 读取数据长度 for(sp2 = 0; sp2 < msg->len; sp2++) msg->data[sp2] = *((&CAN0RXDSR0)+sp2); // 读取数据 CAN0RFLG = 0x01; // 清 RXF 标志位 (缓冲器准备接收) return(TRUE); } #pragma CODE_SEG __NEAR_SEG NON_BANKED //中断接收函数 void interrupt VectorNumber_Vcan0rx CAN_receive(void) //通过中断向量VectorNumber_Vcan0rx来定义中断接收函数 { if(MSCAN0GetMsg(&msg_get)) //判断是否有合法的标准帧收到 { LED = ~LED; //接收到合法标准帧LED反相 } else //错误进入死循环 { for(;;); } } void main(void) { DisableInterrupts; //禁止打开所有中断 INIT_PLL(); //初始化PLL模块,设置busclock=32Mhz INIT_CAN0(); //初始化can0模块 LED_dir=1; //LED接口PB0设置为输出口 LED=0; //初始化LED初始状态为亮 EnableInterrupts; //允许打开所有中断 for(;;) { } } 注意:1.本例CAN初始化中 CAN0RIER_RXFIE 一定要赋值为1,打开接收中断,否则将无法接收到数据 2.中断向量可以通过查看Project -> Includes -> MC9S12XS128.h文件寻找 3.由于本单片机只有一路CAN,所以无法实现自发自收,因而选择通过CANTest进行发送,通过指示灯闪烁来判断是否收到数据 接线实物图见下方: 通过CANTest发送数据,数据内容可以通过下图粉色椭圆框起来的部分填写,点击发送就可以将所填写的信息发送出来了,此时开发板的指示灯将会由亮变暗或者由暗变亮
史海拾趣
|
小弟最近在搞一个无线传输的论文,就是用GPRS模块实现无线数据传输。但是不清楚如何操纵GPRS模块才能把数据发送到固定的IP地址。我现在知道的有如下知识:要是实现GPRS模块与Ethernet链接,需要先进行ppp拨号,但是拨号之后就不清楚怎么才把数据发 ...… 查看全部问答> |
|
各位大侠你们,最近在研究用单片机控制TC35模块发送短信的东西,自己在万能板上都焊接好了,用超级终端可以正常发送短信,但是我想通过单片机直接发送短信,就是程序弄不好,希望的大侠指点下,下面是我的程序。 #include //#include #include ...… 查看全部问答> |
|
最近打算在WINCE下开发一个天气预报软件, 资源就用http://www.webxml.com.cn所提供的提前预报资料..我上该网看了下, 那里有教如何使用函数来查询天气情况并且获得返回的字符数组.. 看了看实例代码, 那是VB.NET写的, 就其中一句 Imports cn.com.we ...… 查看全部问答> |
|
在skyeye上面启动uClinux的时候报段错误 [root@localhost uClinux-dist]# skyeye -e linux-2.4.x/linux arch: arm cpu info: armv3, arm7tdmi, 41007700, fff8ff00, 0 mach info: name at91, mach_init addr 0x8071ad4 can\'t find device mod ...… 查看全部问答> |
|
linux内核完全剖析 基于0.12内核 赵炯 的 200901的 txt doc pdf 的下载版本地址 谁有就给个链接吧 谢谢了哈 嘿嘿… 查看全部问答> |




