IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> (34)STM32——CAN通讯实验笔记 -> 正文阅读

[嵌入式](34)STM32——CAN通讯实验笔记

目录

学习目标

运行结果

内容

特点

物理层

数据帧?

帧起始

仲裁段

控制段

数据段

CRC 段

ACK 段

帧结束

位?

仲裁

bxCAN

特点

框图

模式

工作模式

测试模式

调试模式?

标识符筛选器

发送流程

接收流程

时序

中断

寄存器

配置

硬件连接

代码

总结?


学习目标

????????这个CAN通信实验比较的难,而且内容较多,并且大都是新的知识点(加上老师只念PPT),所以学习起来有亿点点困难,但是我们还是要来简单的介绍一下。

运行结果

?

内容

  • CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO 国际标准化的串行通信协议。1986 年德国电气商博世公司开发出面向汽车的 CAN 通信协议。
  • 此后,CAN 通过 ISO11898 及 ISO11519 进 行了标准化,现在在欧洲已是汽车网络的标准协议。
  • 现在,CAN 的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。

特点

  1. 多主控制。在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元 同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始 发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级 最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。
  2. 系统的柔软性。与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单 元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。
  3. 通信速度较快,通信距离远。最高 1Mbps(距离小于 40M),最远可达 10KM(速率低 于 5Kbps)。
  4. 具有错误检测、错误通知和错误恢复功能。所有单元都可以检测错误(错误检测功能), 检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单 元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新 发送此消息直到成功发送为止(错误恢复功能)。
  5. 故障封闭功能。CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等) 还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上 发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。
  6. 连接节点多。CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没 有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。

物理层

????????CAN 协议经过 ISO 标准化后有两个标准:ISO11898 标准和 ISO11519-2 标准。其中 ISO11898 是针对通信速率为 125Kbps~1Mbps 的高速通信标准,而 ISO11519-2 是针对通信速率为 125Kbps 以下的低速通信标准。 本章,我们使用的是 500Kbps 的通信速率,使用的是 ISO11898 标准,该标准的物理层特征如图所示:

????????从该特性可以看出,显性电平对应逻辑 0,CAN_H 和CAN_L 之差为 2.5V 左右。而隐性电平对应逻辑 1,CAN_H 和 CAN_L 之差为 0V。在总线上显性电平具有优先权,只要有一个单元输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强)。另外,在 CAN 总线的起止端都有一个120Ω的终端电阻,来做阻抗匹配,以减少回波反射。

????????CAN 协议是通过以下 5 种类型的帧进行的: 数据帧、 遥控帧 、 错误帧 、过载帧 、间隔帧另外,数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有 11 个位的标识符(ID), 扩展格式有 29 个位的 ID。

数据帧?

数据帧一般由 7 个段构成,即:

  1. 帧起始。表示数据帧开始的段。
  2. 仲裁段。表示该帧优先级的段。
  3. 控制段。表示数据的字节数及保留位的段。
  4. 数据段。数据的内容,一帧可发送 0~8 个字节的数据。
  5. CRC 段。检查帧的传输错误的段。
  6. ACK 段。表示确认正常接收的段。
  7. 帧结束。表示数据帧结束的段。

????????图中 D 表示显性电平,R 表示隐形电平(下同)。?

帧起始

????????这个比较简单,标准帧和扩展帧都是由 1 个位的显性电平表示帧起始。

仲裁段

????????表示数据优先级的段,标准帧和扩展帧格式在本段有所区别,如图所示:

  • 标准格式的 ID 有 11 个位。从 ID28 到 ID18 被依次发送。禁止高 7 位都为隐性(禁止设 定:ID=1111111XXXX)。扩展格式的 ID 有 29 个位。基本 ID 从 ID28 到 ID18,扩展 ID 由 ID17 到 ID0 表示。基本 ID 和标准格式的 ID 相同。禁止高 7 位都为隐性(禁止设定:基本 ID=1111111XXXX)。
  • 其中 RTR 位用于标识是否是远程帧(0,数据帧;1,远程帧),IDE 位为标识符选择位(0, 使用标准标识符;1,使用扩展标识符),SRR 位为代替远程请求位,为隐性位,它代替了标准帧中的 RTR 位。

控制段

由 6 个位构成,表示数据段的字节数。标准帧和扩展帧的控制段稍有不同,如图所示:?

数据段

????????该段可包含 0~8 个字节的数据。从最高位(MSB)开始输出,标准帧和扩展帧在这个段的定义都是一样的。

CRC 段

????????该段用于检查帧传输错误。由 15 个位的 CRC 顺序和 1 个位的 CRC 界定符(用 于分隔的位)组成,标准帧和扩展帧在这个段的格式也是相同的。此段 CRC 的值计算范围包括:帧起始、仲裁段、控制段、数据段。接收方以同样的算法计 算 CRC 值并进行比较,不一致时会通报错误。

ACK 段

????????此段用来确认是否正常接收。由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位组成。 标准帧和扩展帧在这个段的格式也是相同的。发送单元的 ACK,发送 2 个位的隐性位,而接收到正确消息的单元在 ACK 槽(ACK Slot) 发送显性位,通知发送单元正常接收结束,这个过程叫发送 ACK/返回 ACK。发送 ACK 的是 在既不处于总线关闭态也不处于休眠态的所有接收单元中,接收到正常消息的单元(发送单元 不发送 ACK)。所谓正常消息是指不含填充错误、格式错误、CRC 错误的消息。

帧结束

????????这个段也比较简单,标准帧和扩展帧在这个段格式一样,由 7 个位的隐性位组成。

位?

由发送单元在非同步的情况下发送的每秒钟的位数称为位速率。一个位可分为 4 段。

  • 同步段(SS)
  • 传播时间段(PTS)
  • 相位缓冲段 1(PBS1)
  • 相位缓冲段 2(PBS2)

这些段又由可称为 Time Quantum(以下称为 Tq)的最小时间单位构成。

仲裁

????????上图中,单元 1 和单元 2 同时开始向总线发送数据,开始部分他们的数据格式是一样的, 故无法区分优先级,直到 T 时刻,单元 1 输出隐性电平,而单元 2 输出显性电平,此时单元 1 仲裁失利,立刻转入接收状态工作,不再与单元 2 竞争,而单元 2 则顺利获得总线使用权,继续发送自己的数据。这就实现了仲裁,让连续发送显性电平多的单元获得总线使用权。

  1. 总线空闲时,最先发送的单元获得发送优先权,一但发送,其他单元无法抢占。
  2. 如果有多个单元同时发送,则连续输出显性电平多的单元,具有较高优先级。从ID开始比较,如果ID相同,还可能会比较RTR和SRR等位。

bxCAN

特点

  • 支持 CAN 协议 2.0A 和 2.0B 主动模式
  • 波特率最高达 1Mbps
  • 支持时间触发通信
  • 具有 3 个发送邮箱
  • 具有 3 级深度的 2 个接收 FIFO
  • 可变的过滤器组(28 个,CAN1 和 CAN2 共享)

框图

模式

工作模式

初始化模式

????????当硬件处于初始化模式时,可以进行软件初始化。为进入该模式,软件将 CAN_MCR 寄存 器的 INRQ 位置 1,并等待硬件通过将 CAN_MCR 寄存器的 INAK 位置 1 来确认请求。

正常模式

????????一旦初始化完成,软件必须向硬件请求进入正常模式,这样才能在 CAN 总线上进行同步, 并开始接收和发送。

睡眠模式(低功耗)

????????为降低能耗功耗,bxCAN 具有低功耗模式,称为睡眠模式。软件通过将 CAN_MCR 寄存器 的 SLEEP 位置 1 而发出请求后,即可进入该模式。该模式下,bxCAN 时钟停止,但软件仍 可访问 bxCAN 邮箱。

测试模式

静默模式

????????可以通过将 CAN_BTR 寄存器的 SILM 位置 1,将 bxCAN 置于静默模式。相当于可以接收外界和自身消息,不能发送消息给外界。

?环回模式

????????可以通过将 CAN_BTR 寄存器的 LBKM 位置 1,将 bxCAN 置于环回模式。在环回模式下, bxCAN 将其自身发送的消息作为接收的消息来处理并存储(如果这些消息通过了验收筛选) 在接收邮箱中。相当于可以给外界和自身发送数据,不能接收外界数据。

?环回与静默组合模式

????????顾名思义,就是上面两个模式之和,只能接收自己的数据。

调试模式?

????????当微控制器进入调试模式(Cortex?-M4F 内核停止)时,bxCAN 可以继续正常工作,也可以停止工作。

标识符筛选器

????????STM32F4 的过滤器(也称筛选器)组最多有 28 个,每个滤波器组 x 由 2 个 32 为寄存器, CAN_FxR1 和 CAN_FxR2 组成。

????????STM32F4 每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的 不同,每个过滤器组可提供:

  • 1 个 32 位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE 和 RTR 位
  • 2 个 16 位过滤器,包括:STDID[10:0]、IDE、RTR 和 EXTID[17:15]位

????????此外过滤器可配置为,屏蔽位模式和标识符列表模式。

????????在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按 照“必须匹配”或“不用关心”处理。 而在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用 2 个标识符寄存器。接收报文标识符的每一位都必须跟过滤 器标识符相同。

  • 为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。
  • 为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。
  • 应用程序不用的过滤器组,应该保持在禁用状态。
  • 过滤器组中的每个过滤器,都被编号为(叫做过滤器号,图 32.1.11 中的 n)从 0 开始,到某 个最大数值-取决于过滤器组的模式和位宽的设置。
  • 举个简单的例子,我们设置过滤器组 0 工作在:1 个 32 位过滤器-标识符屏蔽模式,然后 设置 CAN_F0R1=0XFFFF0000,CAN_F0R2=0XFF00FF00。其中存放到 CAN_F0R1 的值就是期 望收到的 ID,即我们希望收到的 ID(STID+EXTID+IDE+RTR)最好是:0XFFFF0000。而 0XFF00FF00 就是设置我们需要必须关心的 ID,表示收到的 ID,其位[31:24]和位[15:8]这 16 个 位的必须和 CAN_F0R1 中对应的位一模一样,而另外的 16 个位则不关心,可以一样,也可以 不一样,都认为是正确的 ID,即收到的 ID 必须是 0XFFxx00xx,才算是正确的(x 表示不关心)。

发送流程

????????CAN 发送流程为:程序选择 1 个空置的邮箱(TME=1)->设置标识符(ID),数据长度和 发送数据->设置 CAN_TIxR 的 TXRQ 位为 1,请求发送->邮箱挂号(等待成为最高优先级)-> 预定发送(等待总线空闲)->发送->邮箱空置。

接收流程

????????FIFO 空->收到有效报文->挂号_1(存入 FIFO 的一个邮箱,这个由硬件 控制,我们不需要理会)->收到有效报文->挂号_2->收到有效报文->挂号_3->收到有效报文-> 溢出。

?

FIFO锁定功能:如果应用程序未释放邮箱,下一条有效消息将存储在 FIFO 中,使其进入 Pending_2 状态 (FMP[1:0] = 10b)。下一条有效消息会重复该存储过程,同时将 FIFO 变为 Pending_3 状态 (FMP[1:0] = 11b)。此时,软件必须通过将 RFOM 位置 1 来释放输出邮箱,从而留出一个空 邮箱来存储下一条有效消息。否则,下一次接收到有效消息时,将导致消息丢失。

时序

????????这个是时序部分,其中BS1包括了PTS和PBS1。?

中断

????????bxCAN 共有四个专用的中断向量。每个中断源均可通过 CAN 中断使能寄存器 (CAN_IER) 来单独地使能或禁止。

?

?

寄存器

????????寄存器我就不讲解了,太多了,我自己都吃不消了。?

配置

1、配置相关引脚的复用功能(AF9),使能 CAN 时钟。

2、设置 CAN 工作模式及波特率等。

3、设置滤波器。

4、发送接受消息

5、CAN 状态获取

硬件连接

????????需要通过跳线帽将 PA11 和 PA12 分 别连接到 CRX(CAN_RX)和 CTX(CAN_TX)上面。

代码

// can.c
#include "can.h"
#include "led.h"
#include "delay.h"
#include "usart.h"	 

//CAN初始化
//tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
//则波特率为:42M/((6+7+1)*6)=500Kbps
//返回值:0,初始化OK;
//    其他,初始化失败; 


u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

  	GPIO_InitTypeDef       GPIO_InitStructure; 
	CAN_InitTypeDef        CAN_InitStructure;
  	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
#if CAN1_RX0_INT_ENABLE 
   	NVIC_InitTypeDef       NVIC_InitStructure;
#endif
    //使能相关时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	
	
    //初始化GPIO
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12
	
	  //引脚复用映射配置
	  GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1
	  GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1
	  
  	//CAN单元设置
   	CAN_InitStructure.CAN_TTCM = DISABLE;	//非时间触发通信模式   
  	CAN_InitStructure.CAN_ABOM = DISABLE;	//软件自动离线管理	  
  	CAN_InitStructure.CAN_AWUM = DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
  	CAN_InitStructure.CAN_NART = ENABLE;	//禁止报文自动传送 
  	CAN_InitStructure.CAN_RFLM = DISABLE;	//报文不锁定,新的覆盖旧的  
  	CAN_InitStructure.CAN_TXFP=DISABLE;	//优先级由报文标识符决定 
  	CAN_InitStructure.CAN_Mode= mode;	 //模式设置 
  	CAN_InitStructure.CAN_SJW=tsjw;	//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
  	CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
  	CAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tq
  	CAN_InitStructure.CAN_Prescaler=brp;  //分频系数(Fdiv)为brp+1	
  	CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1 
    
		//配置过滤器
 	  CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
  	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
   	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
  	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
  	CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
		
#if CAN1_RX0_INT_ENABLE
	
	  CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.		    
  
  	NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(&NVIC_InitStructure);
#endif
	return 0;
}   
 
#if CAN1_RX0_INT_ENABLE	//使能RX0中断
//中断服务函数			    
void CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
	for(i=0;i<8;i++)
	printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);
}
#endif

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 CAN1_Send_Msg(u8* msg,u8 len)
{	
  u8 mbox;
  u16 i=0;
  CanTxMsg TxMessage;
  TxMessage.StdId=0x12;	 // 标准标识符为0
  TxMessage.ExtId=0x12;	 // 设置扩展标示符(29位)
  TxMessage.IDE=0;		  // 使用扩展标识符
  TxMessage.RTR=0;		  // 消息类型为数据帧,一帧8位
  TxMessage.DLC=len;							 // 发送两帧信息
  for(i=0;i<len;i++)
  TxMessage.Data[i]=msg[i];				 // 第一帧信息          
  mbox= CAN_Transmit(CAN1, &TxMessage);   
  i=0;
  while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
  if(i>=0XFFF)return 1;
  return 0;		

}
//can口接收数据查询
//buf:数据缓存区;	 
//返回值:0,无数据被收到;
//		 其他,接收的数据长度;
u8 CAN1_Receive_Msg(u8 *buf)
{		   		   
 	u32 i;
	CanRxMsg RxMessage;
    if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;		//没有接收到数据,直接退出 
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据	
    for(i=0;i<RxMessage.DLC;i++)
    buf[i]=RxMessage.Data[i];  
	return RxMessage.DLC;	
}

// main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "can.h"

int main(void)
{ 
	u8 key;
	u8 i=0,t=0;
	u8 cnt=0;
	u8 canbuf[8];
	u8 res;
	u8 mode=1;//CAN工作模式;0,普通模式;1,环回模式
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);    //初始化延时函数
	uart_init(115200);	//初始化串口波特率为115200
	LED_Init();					//初始化LED 
	KEY_Init(); 				//按键初始化  
	CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);//CAN初始化环回模式,波特率500Kbps    	 
	printf("KEY0:Send WK_UP:Mode");//显示提示信息	 									  
while(1)
	{
		key=KEY_Scan(0);
		if(key==KEY0_PRES)//KEY0按下,发送一次数据
		{
			for(i=0;i<8;i++)
			{
				canbuf[i]=cnt+i;//填充发送缓冲区
				if(i<4){printf("Send Data:%d",canbuf[i]);	  //显示数据
				printf ("\r\n\r\n");}
				else {printf("Send Data:%d",canbuf[i]);
printf ("\r\n\r\n");}					//显示数据
 			}
			res=CAN1_Send_Msg(canbuf,8);//发送8个字节 
			if(res){printf("Failed");		//提示发送失败
				printf ("\r\n\r\n");}
			else {printf("OK    ");	 		//提示发送成功		
printf ("\r\n\r\n");}				
		}else if(key==WKUP_PRES)//WK_UP按下,改变CAN的工作模式
		{	   
			mode=!mode;
			CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,mode);	//CAN普通模式初始化,普通模式,波特率500Kbps 
			if(mode==0)//普通模式,需要2个开发板
			{
				printf("Nnormal Mode ");
				printf ("\r\n\r\n");				
			}else //回环模式,一个开发板就可以测试了.
			{
 				printf("LoopBack Mode");
				printf ("\r\n\r\n");
			}
		}		 
		key=CAN1_Receive_Msg(canbuf);
		if(key)//接收到有数据
		{			
 			for(i=0;i<key;i++)
			{									    
				if(i<4){printf("Receive Data:%d",canbuf[i]);	//显示数据
					printf ("\r\n\r\n");}
				else {printf("Receive Data:%d",canbuf[i]);	//显示数据
					printf ("\r\n\r\n");}
 			}
		}
		t++; 
		delay_ms(10);
		if(t==20)
		{
			LED0=!LED0;//提示系统正在运行	
			t=0;
			cnt++;
			printf("Count:%d",cnt);	//显示数据
			printf ("\r\n\r\n");
		}		   
	} 
	
}

总结?

? ? ? ? 本节CAN的知识特别多,而且特别难,测试也就测试了一下回环模式。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:27:45  更:2022-09-04 01:29:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 15:02:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码