CAN通信实验

18.1 can协议18.1.1 协议概述can是controller area network的缩写,最初是专门用于汽车网络的通信协议,与485协议相似,can也是一种2线制,采用两根线的电压差进行数据传输的协议,随着can协议的高性能与可靠性被认同,现在被广泛运用在工业自动化,船舶等当面,目前最热门的国六标准,j1939通信协议就是以can协议为基础设计的。
can协议最远通信距离可达10km,与485相似,can也有两种电平,分别为显性电平与隐性电平,当can_h与can_l电压一致的时候为隐性电平,反之为显性电平。实际上隐性电平代表逻辑电平1,显性电平代表逻辑电平0,can在通信的时候,也需要在每个设备输出端并联1个120ω的终端匹配电阻,用于进行阻抗匹配。18.1.2 通信组成can协议通过5种类型的帧进行数据通信:数据帧,遥控帧,错误帧,过载帧和间隔帧,其中数据帧与遥控帧具有标准格式与扩展格式两种,标准格式有11个位的标识符,扩展格式则有29个位的标识符,五种帧的功能如下所示。(1)数据帧:用于实际数据传输
(2)遥控帧:用于接收端向具有相同id的发送端请求数据
(3)错误帧:用于检测报错时通知其他设备
(4)过载帧:用于接收端通报尚未准备好接收准备
(5)间隔帧:用于将数据帧与遥控帧和前面的帧分割
完整的数据帧构成如下图所示。
数据帧一般由7段组成:
(1)帧起始:即数据帧开始的段,标准帧和扩展帧都是由1个位的显性电平表示帧起始
(2)仲裁段:表示该帧优先级,标准帧和扩展帧格式在这一段结构如下图所示。
其中rtr位用于标识是否是远程帧(0代表数据帧;1代表远程帧),ide位为标识符选择位(0表示使用标准标识符;1表示使用扩展标识符),srr位为代替远程请求位,为隐性位,代替了标准帧中的rtr位。
(3)控制段:表示数据的字节数即保留位,由6个位构成,表示数据段的字节数。标准帧和扩展帧的控制段结构如下图所示。
r0和r1为保留位,必须全部以显性电平发送,但是接收端可以接收显性、隐性及任意组合的电平。dlc段为数据长度表示段,高位在前,dlc段有效值为08,但是接收方接收到915的时候并不认为是错误。
(4)数据段:数据段内容,一段可以发送0~8个字节的数据,从最高位msb开始输出
(5)crc校验:crc校验数据完整性
(6)应答段:表示正常接收
(7)帧结束:表示该帧结束
18.1.3 通信参数由发送单元在非同步的情况下发送的每秒钟的位数称为位速率。一个位可分为4段。
(1)同步段(ss)
(2)传播时间段(pts)
(3)相位缓冲段1(pbs1)
(4)相位缓冲段2(pbs2)
这些段又由可称为tq的最小时间单位构成。1位分为4个段,每个段又由若干个tq构成,这称为位时序。1位由多少个tq构成、每个段又由多少个tq构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。各段的作用和tq数如下表所示。
18.1.4 总线仲裁在总线空闲态,最先开始发送消息的单元获得发送权。当多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平最多的单元可继续发送。实现过程如下图所示。
单元1和单元2同时开始向总线发送数据,开始部分他们的数据格式是一样的,故无法区分优先级,直到t时刻,单元1输出隐性电平,而单元2输出显性电平,此时单元1仲裁失利,立刻转入接收状态工作,不再与单元2竞争,而单元2则顺利获得总线使用权,继续发送自己的数据。这就实现了仲裁,让连续发送显性电平多的单元获得总线使用权
18.1.5 stm32 can模组简介stm32f1系列自带的是基本扩展can,支持can协议的2.0a和2.0b,支持报文发送的优先级要求可软件配置,最大通信速率1mbps,3个发送邮箱和3级深度的2个接收缓存器fifo,28个可变的滤波器组,stm32的can模组结构如下图所示。
从上面结构可以看出,两个can都分别具备自己的发送与接收邮箱,但是28个滤波器却是公用的,通过fmr寄存器可以设置滤波器的分配方式,stm32的每个滤波器组的位宽都可以独立配置,根据位宽的不同,每个滤波器组可以提供
(1)1个32位过滤器:包含stdid[10:0],extid[17:0],18位扩展id,ide和rtr位
(2)1个16位过滤器:包含stdid[10:0],ide,rtr和extid[17:15]
此外过滤器可以配置为屏蔽位模式与标识符列表模式。
(1)在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理
(2)标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。
18.1.6 can的发送流程第1步:程序选择1个空置的邮箱(tme=1),设置标识符(id),数据长度和发送数据
第2步:设置can_tixr的txrq位为1,请求发送
第3步:邮箱挂号(等待成为最高优先级)
第4步:预定发送(等待总线空闲)
第5步:发送
第6步:邮箱空置
整个发送流程如下图所示。
18.1.7 can的接收流程can接收到的有效报文,被存储在3级邮箱深度的fifo中。fifo完全由硬件来管理,从而节省了cpu的处理负荷,简化了软件并保证了数据的一致性。应用程序只能通过读取fifo输出邮箱,来读取fifo中最先收到的报文。这里的有效报文是指那些正确被接收的(直到eof都没有错误)且通过了标识符过滤的报文。前面我们知道can的接收有2个fifo,我们每个滤波器组都可以设置其关联的fifo,通过can_ffa1r的设置,可以将滤波器组关联到fifo0/fifo1。can接收流程为:
fifo空->收到有效报文->挂号1(存入fifo的一个邮箱,这个由硬件控制,我们不需要理会)->收到有效报文->挂号2->收到有效报文->挂号3->收到有效报文->溢出
这个流程里面,我们没有考虑从fifo读出报文的情况,实际情况是:我们必须在fifo溢出之前,读出至少1个报文,否则下个报文到来,将导致fifo溢出,从而出现报文丢失。每读出1个报文,相应的挂号就减1,直到fifo空,完整的接收流程图如下图所示。
fifo接收到的报文数,我们可以通过查询can_rfxr的fmp寄存器来得到,只要fmp不为0,我们就可以从fifo读出收到的报文。
18.1.8 通信速率计算根据通信参数小节我们可以知道1个位是由4个段组成,分别为同步段(ss),传播时间段(pts),相位缓冲段1(pbs1),相位缓冲段2(pbs2),stm32内部将传播时间段与相位缓冲段1合并为时间段1,这样1个位就是有3个段组成,即同步段ss,时间段1和时间段2(即相位缓冲段),由于波特率的定义是1秒内发送二进制位的个数,所以,can波特率的计算公式为
18.1.9 stm32f1系列can测试模式(1)静默模式
通过对can_btr寄存器的silm位置1,来选择静默模式。在静默模式下,can可以正常地接收数据帧和远程帧,但只能发出隐性位,而不能真正发送报文。如果bxcan需要发出显性位(确认位、过载标志、主动错误标志),那么这样的显性位在内部被接回来从而可以被can内核检测到,同时can总线不会受到影响而仍然维持在隐性位状态。因此,静默模式通常用于分析can总线的活动,而不会对总线造成影响-显性位(确认位、错误帧)不会真正发送到总线上,静默模式等效图如下图所示。
(2)环回模式
通过对can_btr寄存器的lbkm位置1,来选择环回模式。在环回模式下,can把发送的报文当作接收的报文并保存(如果可以通过接收过滤)在接收邮箱里,环回模式等效图如下图所示。
(3)环回静默模式
该模式可用于“热自测试”,即可以像环回模式那样测试can,但却不会影响cantx和canrx所连接的整个can系统。在环回静默模式下,canrx引脚与can总线断开,同时cantx引脚被驱动到隐性位状态,环回静默模式等效图如下图所示。
18.2 相关寄存器18.2.1 can主控制器:can_mcr31302928272625242322212019181716
- dbf
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
reset - ttcm abom awum nart rflm txfp sleep inrq
bit 16:dbf:调试冻结
0:在调试时,can照常工作
1:在调试时,冻结can的接收/发送。仍然可以正常地读写和控制接收fifo
bit 15:bxcan软件复位
0:本外设正常工作
1:对bxcan进行强行复位,复位后bxcan进入睡眠模式。此后硬件自动对该位清0
bit 7:时间触发通信模式
0:禁止时间触发通信模式
1:允许时间触发通信模式
bit 6:自动离线管理
0:离线状态的退出过程是,软件对inrq位进行置1随后清0后,一旦硬件检测到128次11位连续的隐性位,则退出离线状态
1:一旦硬件检测到128次11位连续的隐性位,则自动退出离线状态
bit 5:自动唤醒模式
0:睡眠模式通过清除can_mcr寄存器的sleep位,由软件唤醒
1:睡眠模式通过检测can报文,由硬件自动唤醒。唤醒的同时,硬件自动对sleep和slak位清0
bit 4:禁止报文自动重传
0:按照can标准,can硬件在发送报文失败时会一直自动重传直到发送成功
1:can报文只被发送1次,不管发送的结果如何
bit 3:接收fifo锁定模式
0:在接收溢出时fifo未被锁定,当接收fifo的报文未被读出,下一个收到的报文会覆盖原有的报文
1:在接收溢出时fifo被锁定,当接收fifo的报文未被读出,下一个收到的报文会被丢弃
bit 2:发送fifo优先级
0:优先级由报文的标识符来决定
1:优先级由发送请求的顺序来决定
bit 1:睡眠模式请求(在复位后该位被置1)
1:可以请求can进入睡眠模式,一旦当前的can活动结束,can就进入睡眠
0:使can退出睡眠模式
bit 0:初始化请求
0:当can在接收引脚检测到连续的11个隐性位后,can就达到同步,并为接收和发送数据作好准备了。为此,硬件相应地对inak位清0
1:一旦当前的can活动结束,can就进入初始化模式。相应地,硬件对inak位置1
18.2.2 can主状态寄存器:can_msr1514131211109876543210
- rx samp rxm txm - slaki wkui erri slak inak
bit 11:can接收电平,该位反映can接收引脚的实际电平
bit 10:上次采样值,can接收引脚的上次采样值(对应于当前接收位的值)
bit 9:接收模式,该位为1表示can当前为接收器
bit 8:发送模式,该位为1表示can当前为发送器
bit 4:睡眠确认中断,当slkie=1,一旦can进入睡眠模式硬件就对该位置1,紧接着相应的中断被触发软件可对该位清0,当slak位被清0时硬件也对该位清0
bit 3:唤醒中断挂号,当can处于睡眠状态,一旦检测到帧起始位,硬件就置该位为1
bit 2:出错中断挂号,当检测到错误时,can_esr寄存器的某位被置1,如果can_ier寄存器的相应中断使能位也被置1时,则硬件对该位置1
bit 1:睡眠模式确认
0:can退出睡眠模式
1:can模块正处于睡眠模式
bit 0:初始化确认
0:can退出初始化模式时
1:can模块正处于初始化模式
18.2.3 can位时序寄存器:can_btr31302928272625242322212019181716
silm lbkm - sjw[1:0] - ts2[2:0] ts1[3:0]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- brp[9:0]
bit 31:静默模式(用于调试)
0:正常状态
1:静默模式
bit 30:环回模式(用于调试)
0:禁止环回模式
1:允许环回模式
bit 25~bit 24:重新同步跳跃宽度,该位域定义了can硬件在每位中可以延长或缩短多少个时间单元的上限,t rjw =t can ×(sjw[1:0]+1)
bit 22~bit 20:时间段2,该位域定义了时间段2占用了多少个时间单元,t bs2 =t can ×(ts2[2:0]+1)
bit 19~bit 16:时间段1,该位域定义了时间段1占用了多少个时间单元,t bs1 =t can ×(ts1[3:0]+1)
bit 9bit 0:波特率分频器,该位域定义了时间单元tq的时间长度,t q =(brp[9:0]+1)×tpclk~
18.2.4 can发送状态寄存器:can_tsr31302928272625242322212019181716
low2 low1 low0 tme2 tme1 tme0 code[1:0] abrq2 - terr2 alst2 txok2 rqcp2
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
abrq1 - terr1 alst1 txok1 rqcp1 abrq0 - terr0 alst0 txok0 rqcp0
bit 31,bit30,bit 29:邮箱x最低优先级标志
当多个邮箱在等待发送报文,且邮箱x的优先级最低时,硬件对该位置1
bit 28,bit 27,bit 26:发送邮箱x空
bit 25~bit 24:邮箱号
当有至少1个发送邮箱为空时,表示下一个空的发送邮箱号。
当所有的发送邮箱都为空时,表示优先级最低的那个发送邮箱号
bit 23,bit 15,bit 7:邮箱x终止发送
bit 19,bit 11,bit 3:邮箱x发送失败
bit 18,bit 10,bit 2:邮箱x仲裁丢失
bit 17,bit 9,bit 1:邮箱x发送成功
bit 16,bit 8,bit 0:邮箱x请求完成
18.2.5 can接收fifox寄存器:can_rfxr1514131211109876543210
- rofm fovr full - fmp[1:0]
bit 5:释放接收fifo,输出邮箱软件通过对该位置1来释放接收fifo的输出邮箱。如果接收fifo为空,那么对该位置1没有任何效果,即只有当fifo中有报文时对该位置1才有意义。如果fifo中有2个以上的报文,由于fifo的特点,软件需要释放输出邮箱才能访问第2个报文,当输出邮箱被释放时,硬件对该位清0
bit 4:fifo溢出,当fifo0已满,又收到新的报文且报文符合过滤条件,硬件对该位置1,该位由软件清0
bit 3:fifo满,当fifo0中有3个报文时,硬件对该位置1,该位由软件清0
bit 1~bit 0:fifo报文数目,表示当前接收fifo0中存放的报文数目
每当1个新的报文被存入接收fifo0,硬件就对fmp0加1
每当软件对rfom位写1来释放输出邮箱,fmp就被减1,直到其为0
18.2.6 can过滤器主控寄存器:can_fmr1514131211109876543210
- finit
bit 0:过滤器初始化模式
0:过滤器组工作在正常模式
1:过滤器组工作在初始化模式
18.2.7 can过滤器模式寄存器:can_fm1r31302928272625242322212019181716
- fbm[27:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
fbm[15:0]
bit 29~bit 0:过滤器模式
0:过滤器组x的2个32位寄存器工作在标识符屏蔽位模式
1:过滤器组x的2个32位寄存器工作在标识符列表模式
18.2.8 can过滤器位宽寄存器:can_fs1r31302928272625242322212019181716
- fsc[27:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
fsc[15:0]
bit 29~bit 0:过滤器位宽设置
0:过滤器位宽为2个16位
1:过滤器位宽为单个32位
18.2.9 can过滤器fifo关联寄存器:can_ffa1r31302928272625242322212019181716
ffa[27:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
ffa[15:0]
bit 29~bit 0:过滤器关联设置
0:过滤器被关联到fifo0
1:过滤器被关联到fifo1
18.2.10 can过滤器激活寄存器:can_fa1r31302928272625242322212019181716
fact[27:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
fact[15:0]
bit 29~bit 0:过滤器激活
0:过滤器被禁用
1:过滤器被激活
18.2.11 发送邮箱标识符寄存器:can_tixr31302928272625242322212019181716
stid[10:0]/exid[28:18] exid[17:13]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
exid[12:0] ide rtr txrq
bit 31~bit 21:标准标识符或扩展标识符,依据ide位的内容,这些位或是标准标识符,或是扩展身份标识的高字节
bit 20~bit 3:扩展标识符,扩展身份标识的低字节
bit 2:标识符选择
0:使用标准标识符
1:使用扩展标识符
bit 1:远程发送请求
0:数据帧
1:远程帧
bit 0:发送数据请求,由软件对其置1,来请求发送邮箱的数据。当数据发送完成,邮箱为空时,硬件对其清0
18.2.12 发送邮箱数据长度和时间戳寄存器:can_tdtxr31302928272625242322212019181716
time[15:0]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- tgt - dlc[3:0]
bit 31~bit 16:报文时间戳,该域包含了,在发送该报文sof的时刻,16位定时器的值
bit 8:发送时间戳(只有在can处于时间触发通信模式才有效)
0:不发送时间戳time[15:0]
1:发送时间戳time[15:0]
注:在长度为8的报文中,时间戳time[15:0]是最后2个发送的字节:time[7:0]作为第7个字节,time[15:8]为第8个字节,替换了写入can_tdhxr[31:16]的数据。为了把时间戳的2个字节发送出去,dlc必须编程为8。
bit 3~bit 0:发送数据长度,指定数据报文的数据长度或者远程帧请求的数据长度
18.2.13 发送邮箱低字节数据寄存器:can_tdlxr31302928272625242322212019181716
data3[7:0] data2[7:0]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
data1[7:0] data0[7:0]
bit 31~bit 24:数据字节3
bit 23~bit 16:数据字节2
bit 15~bit 8:数据字节1
bit 7~bit 0:数据字节0
18.2.14 发送邮箱高字节数据寄存器:can_tdhxr31302928272625242322212019181716
data7[7:0] data6[7:0]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
data5[7:0] data4[7:0]
bit 31~bit 24:数据字节7
bit 23~bit 16:数据字节6
bit 15~bit 8:数据字节5
bit 7~bit 0:数据字节4
18.2.15 接收邮箱标识符寄存器:can_rixr31302928272625242322212019181716
stid[10:0]/exid[28:18] exid[17:13]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
exid[12:0] ide rtr -
bit 31~bit 21:标准标识符或扩展标识符,依据ide位的内容,这些位或是标准标识符,或是扩展身份标识的高字节
bit 20~bit 3:扩展标识符,扩展身份标识的低字节
bit 2:标识符选择
0:使用标准标识符
1:使用扩展标识符
bit 1:远程发送请求
0:数据帧
1:远程帧
18.2.16 接收邮箱数据长度和时间戳寄存器:can_rdtxr31302928272625242322212019181716
time[15:0]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
fmi[7:0] - dlc[3:0]
bit 31~bit 16:报文时间戳,该域包含了,在接收该报文sof的时刻,16位定时器的值
bit 15~bit 8:过滤器匹配序号
bit 3~bit 0:接收数据长度
18.2.17 接收邮箱低字节数据寄存器:can_rdlxr31302928272625242322212019181716
data3[7:0] data2[7:0]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
data1[7:0] data0[7:0]
bit 31~bit 24:数据字节3
bit 23~bit 16:数据字节2
bit 15~bit 8:数据字节1
bit 7~bit 0:数据字节0
18.2.18 接收邮箱高字节数据寄存器:can_rdhxr31302928272625242322212019181716
data7[7:0] data6[7:0]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
data5[7:0] data4[7:0]
bit 31~bit 24:数据字节7
bit 23~bit 16:数据字节6
bit 15~bit 8:数据字节5
bit 7~bit 0:数据字节4
18.3 实验例程实验内容:利用can的回环模式进行数据收发测试,通信速率500kbps。
(1)创建can.h文件,并输入以下代码。
/********************************************************************************************************* can 通 信 驱 动 文 件*********************************************************************************************************/#ifndef _can_h_#define _can_h_#include sys.h /********************************************************************************************************* 函 数 列 表*********************************************************************************************************/u8 can_init( u8 tsjw, u8 tbs2, u8 tbs1, u16 brp, u8 mode ) ; //can初始化u8 can_tx_msg( u32 id, u8 ide, u8 rtr, u8 len, u8 *dat ) ; //can发送数据void can_rx_msg( u8 fifox, u32 *id, u8 *ide, u8 *rtr, u8 *len, u8 *dat ) ; //can接收数据#endif(2)创建can.c文件,并输入以下代码。
/********************************************************************************************************* can 通 信 驱 动 程 序*********************************************************************************************************/#include can.h/*******************************************************name :can_mode_initfunction :can初始化paramater : tsjw:重新同步跳跃时间单元.范围:1~3 tbs2:时间段2的时间单元.范围:1~8 tbs1:时间段1的时间单元.范围:1~16 brp:波特率分频器.范围:1~1024 mode:工作模式 0:普通模式 1:回环模式return : 0:成功 其他:失败*******************************************************/u8 can_init( u8 tsjw, u8 tbs2, u8 tbs1, u16 brp, u8 mode ){ u16 i=0; if( ( tsjw==0 )||( tbs2==0 )||( tbs1==0 )||( brp==0 ) ) return 1 ; //先减去1.再用于设置 tsjw -= 1 ; tbs2 -= 1 ; tbs1 -= 1 ; brp -= 1 ; rcc->apb2enr |= 1crh |= 0x000b8000 ; gpioa->odr |= 3mcr |= 1100 ) return 2 ; //进入初始化模式失败 } can1->mcr |= 0btr |= mode0xfff0 ) return 3 ; //退出初始化模式失败 } //过滤器初始化 can1->fmr |= 1sfilterregister[ 0 ].fr2 = 0x00000000 ; //32位mask can1->fa1r |= 1stxmailbox[ mbox ].tir |= idestxmailbox[ mbox ].tdtr |= len ; //设置dlc //待发送数据存入邮箱 can1->stxmailbox[ mbox ].tdhr = ( ( (u32)dat[7]<<24 )|( (u32)dat[6]<<16 )|( (u32)dat[5]24 ; //tme0 break; //邮箱1 case 1: sta |= can1->tsr&( 1<>8 ; //rqcp1 sta |= can1->tsr&( 1<>8 ; //txok1 sta |= can1->tsr&( 1<>25 ; //tme1 break; //邮箱2 case 2: sta |= can1->tsr&( 1<>16 ; //rqcp2 sta |= can1->tsr&( 1<>16 ; //txok2 sta |= can1->tsr&( 1<>26 ; //tme2 break; //邮箱号不对 default: sta = 0x05 ; break ; } } if( i==0xfff ) mbox = 0xff ; return mbox ;}/*******************************************************name :can_rx_msgfunction :can接收数据paramater : fifox:邮箱号 id:标准id(11位)/扩展id(11位+18位) ide:id类型 0:标准帧 1:扩展帧 rtr:数据类型 0:数据帧 1:远程帧 len:要发送的数据长度 *dat:数据指针return :none*******************************************************/void can_rx_msg( u8 fifox, u32 *id, u8 *ide, u8 *rtr, u8 *len, u8 *dat ){ if( ( fifox==0 )&&( ( can1->rf0r&0x03 )==0 ) ) len = 0 ; else if( ( fifox==1 )&&( ( can1->rf1r&0x03 )==0 ) ) len = 0 ; else { //接收数据 *ide = can1->sfifomailbox[ fifox ].rir&0x04 ; //得到标识符选择位的值 if( *ide==0 ) *id = can1->sfifomailbox[ fifox ].rir>>21 ; //标准标识符 else *id = can1->sfifomailbox[ fifox ].rir>>3 ; //扩展标识符 *rtr = can1->sfifomailbox[ fifox ].rir&0x02 ; //得到远程发送请求值 *len = can1->sfifomailbox[ fifox ].rdtr&0x0f ; //得到dlc dat[ 0 ] = can1->sfifomailbox[ fifox ].rdlr&0xff ; dat[ 1 ] = ( can1->sfifomailbox[ fifox ].rdlr>>8 )&0xff ; dat[ 2 ] = ( can1->sfifomailbox[ fifox ].rdlr>>16 )&0xff ; dat[ 3 ] = ( can1->sfifomailbox[ fifox ].rdlr>>24 )&0xff ; dat[ 4 ] = can1->sfifomailbox[ fifox ].rdhr&0xff ; dat[ 5 ] = ( can1->sfifomailbox[ fifox ].rdhr>>8 )&0xff ; dat[ 6 ] = ( can1->sfifomailbox[ fifox ].rdhr>>16 )&0xff ; dat[ 7 ] = ( can1->sfifomailbox[ fifox ].rdhr>>24 )&0xff ; if( fifox==0 ) can1->rf0r |= 0x20 ; //释放fifo0邮箱 else if( fifox==1 ) can1->rf1r |= 0x20 ; //释放fifo1邮箱 }}(3)创建1.c文件,并输入以下代码。
#include sys.h#include delay.h#include usart1.h#include can.hint main(){ u32 id; u8 ide, rtr, len, canbuf[ 8 ] ; stm32_clock_init( 9 ) ; //stm32时钟初始化 systick_init( 72 ) ; //systick初始化 usart1_init( 72, 115200 ) ; //初始化串口1波特率115200 can_init( 1, 8, 9, 4, 1 ) ; //can初始化 can_tx_msg( 0x12, 0, 0, 8, can test ) ; //发送8个字节 while( 1 ) { can_rx_msg( 0, &id, &ide, &rtr, &len, canbuf ) ; //读取数据 }}

PeCS体系在人体菌群等领域的应用
笔记本电脑中应用的存储芯片
苹果15上市时间已定 苹果或将于9月13日举行秋季发布会 9月22日苹果15上市
专注人工智能芯片的寒武纪2020年净利润预计亏损3.5亿-5.2亿
iPhone8售价曝光:或成苹果史上最贵iPhone
CAN通信实验
土壤墒情监测站与传统方法的对比,它有哪些优势
南大光电全力推进ArF光刻胶
如何快速选择合适的电流测量仪器-钳表
微软与Intel联合开发双屏笔记本,抢占新一代产品的入口
美法院推翻英特尔因专利侵权赔偿VLSI 21.8亿美元的裁定
为什么在脑机接口中使用超声波?
【虹科案例】虹科数字化仪在激光雷达大气研究中的应用
易华录与航天科工壹进制共建国资信创灾备云
T-box系统解决方案紧急呼叫单元
使用定向耦合器和RF功率检测器来实现在线RF功率和回波损耗测量
智能家居镜面显示屏将掀起一股智能家居新潮流
机械硬盘不使用的时候应该如何保存提高使用寿命
搭载RFID技术的数字人民币有利于服务老年人
天永智能:备受追捧,欲做中国最大的汽车智能装备解决方案商