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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 第十四篇,STM32的CAN总线通信 -> 正文阅读

[嵌入式]第十四篇,STM32的CAN总线通信

1.CAN总线的概念

????CAN指的是控制器局域网网络(Controller?Area?Network),由德国博世汽车电子厂商开发出来。

????CAN使用差分信号,具有较强的抗干扰能力和传输稳定性

????CAN属于多主通信,网络中所有的节点都可以作为主设备进行通信

????CAN的网络扩展极其方便,CAN网络中扩展了新的通信单元,网络中旧的单元和硬件无需任何改变。

????CAN具有较强的纠错能力,可以发现传输中出现的错误,并对错误节点进行隔离;所有的单元都可以检测错误;检测出错误的单元会立即同时通知其他所有单元;正在发送消息的单元一旦检测出错误,会强制结束当前的发送。被强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止。

2.CAN的差分信号

模分信号使用电平的绝对值来表示逻辑的差别;

差分信号使用两个电平的差值来表示逻辑值。CAN传输使用两根数据线?-------------?CANH和CANL

CAN总线高速ISO11898标准:

如果CANH(3.5V)和CANL(1.5V)的电压差?=?2V,此时表示逻辑0,叫做显性电平 ;

如果CANH(2.5V)和CANL(2.5V)的电压差?=?0V,此时表示逻辑1,叫做隐性电平

//如果多个节点同时控制总线电平,由总线仲裁最终显示的是显性电平(0)

3.CAN通信协议

?CAN使用5种通信帧,下面以数据帧为例来介绍帧结构

数据帧的分析:

????数据帧分为标准数据帧扩展数据帧l两种格式。

????D?--- 表示显性电平

? ? R?--- 表示隐性电平

?数据帧由7部分组成:

数据帧七个部分的实现

标准格式中标识符(ID)有11bit,从ID28到ID18被依次发送,禁止高7位都为隐性(禁止设定:ID = 1111 111X XXX);

扩展格式的ID有29bit,基本ID从ID28到ID18,扩展ID由ID17到ID0表示,禁止高7位都为隐性(禁止设定:ID = 1111 111X XXX)。
RTR位用于标识是否是远程帧(0:数据帧;1:遥控帧);

IDE位用于标识符选择位(0:使用标准标识符;1:使用扩展标识符);

SRR位代替遥控帧请求位,为隐性位,代替了标准帧中的RTR位。

(1)帧起始

显示1位显性电平

(2)仲裁段

????用来实现帧的优先级帧的过滤

1.标准帧 ????

标准数据帧的仲裁段由11位ID1位RTR位组成,RTR用来区分数据帧(显性电平)和遥控帧 ????

2.扩展帧 ????

扩展数据帧由 29位ID,1位RTR,1位SRR1位IDE组成;

RTR用来区分数据帧(显性电平)遥控帧 ????

SRR用来代替标准帧中的RTR位,由于SRR是隐性电平,相同ID的标准帧优先级高于扩展帧 ??

IDE用来区分标准帧(显性电平)和扩展帧,显性电平表示标准帧,隐性电平表示扩展帧 ????

报文的优先级由总线通过ID仲裁来判断,当总线上同时出现显性电平和隐形电平时,最终显示为显性电平;当多个节点同时竞争总线占有权时,谁先出现隐形电平,将失去总线占有权,转为接收状态???

(3)控制段

表数据帧里数据段的字节数,r0,r1为保留位,默认是显性电平 ;

4位DLC表示数据段的长度(0~8)

(4)数据段

用户需要发送的数据内容,可一次性发送0–8个字节的数据(每个数据占用一个字节)

长度0~8字节,高位先出

(5)CRC段

CRC错误校验,由15位CRC校验码和1位CRC界定符组成, 校验出了错误信息,可利用错误帧请求重发,重发次数可设定;用于检查帧传输错误(检查范围:起始端,仲裁段,控制段,数据段)。

(6)ACK段

由1位ACK槽和1位ACK界定符组成,发送方的ACK槽是隐性电平 ,接收方确认收到正确的数据后以显性电平应答

(7)帧结束

?7位隐形电平,由7个隐形位(逻辑1)组成,因此ID仲裁断禁止出现1111111****形式的格式

4.CAN的位时序

CAN传输1位由4段组成:同步段,传播段,相位缓冲段1,相位缓冲段2

1位结束后会使用再同步补偿宽度(SJW)进行再补偿。这样设计的原因是让发送方和接收方的时序保持一致(消除误差)

(1)同步段(SS)

同步段用于实现实训的调整,完成显性/隐形电平的转换,也就是准备该位要发送的电平

(2)传播时间段(PTS)

用于吸收网络上的物理延迟,物理延迟包括发送的延迟,接收的延迟和信号传播的延迟

(3)相位缓冲段(PBS)

对于电平转换未被包含的部分进行补偿,同时和SJW一起补偿各单位的时钟误差,电平的读取在该段完成。

(4)再同步补偿宽度(SJW)

补偿前面同步的误差

????接收方的采样一定在PBS1和PBS2之间,由于SS和PTS误差的变动,PBS的补偿也会随着误差的变化而变化,实现传输1位时间的固定,SJW对PBS的补偿进行二次补偿。

1位时间?=?8?~?25Tq, SS?=?1Tq ,PTS?=?1?~?8Tq ,PBS?=?2?~?8Tq ,SKW?=?1?~?4Tq

5.stm32f407的CAN控制器

????stm32芯片带有bxCAN控制器,支持CAN协议的2.0A和2.0B,最快速度1Mbps,能够自动发送CAN报文,支持标准和扩展数据帧,控制器带有三个发送邮箱存储发送的报文,还有两个FIFO,支持ID过滤,可配置自动重发等功能。

(1)工作模式

????初始化模式:初始化CAN控制器

????正常模式:正常收发数据

????睡眠模式:低功耗

(2)测试模式

????静默模式:停止对外发送报文

????环回模式:报文不发往总线,直接发给自己

????环回和静默组合模式

????测试模式

(3)传输速率

波特率?=?42MHz/分频系数/(tbs1+tbs2+sjw)

(4)接收中断

FMPx表示收到了报文

6.原理图

?查看原理图可知

CAN总结的接口最终连接到了CPU的PD0和PD1,具有CAN的复用功能。

7.CAN总线通信的库函数实现

?添加CAN通信的库函数源码

(1)开启时钟

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);

(2)将GPIO配置为CAN复用功能

GPIO_Init(...); GPIO_PinAFConfig(...);

(3)初始化CAN

uint8_t?CAN_Init(CAN_TypeDef*?CANx,?CAN_InitTypeDef*?CAN_InitStruct);

参数: ????

CANx?-?哪个CAN ????

CAN_InitStruct?-?CAN初始化结构 ????

typedef?struct

{ ??

? uint16_t?CAN_Prescaler;???/*!<?预分频系数?1?to?1024.?*/ ?? ??

? uint8_t?CAN_Mode;?????????/*!<?工作模式?@ref?CAN_operating_mode?*/ ??uint8_t?CAN_SJW;??????????/*!<?再同步补偿宽度极限值?@ref?CAN_synchronisation_jump_width?*/ ??uint8_t?CAN_BS1;??????????/*!<?相位缓冲段1长度?@ref?CAN_time_quantum_in_bit_segment_1?*/ ??uint8_t?CAN_BS2;??????????/*!<?相位缓冲段2长度?@ref?CAN_time_quantum_in_bit_segment_2?*/ ?? ??FunctionalState?CAN_TTCM;?/*!<?时间触发使能?ENABLE?or?DISABLE.?*/ ?? ??FunctionalState?CAN_ABOM;??/*!<?自动离线使能?ENABLE?or?DISABLE.?*/ ??FunctionalState?CAN_AWUM;??/*!<?自动唤醒使能?ENABLE?or?DISABLE.?*/ ??FunctionalState?CAN_NART;??/*!<?自动重发使能?ENABLE?or?DISABLE.?*/ ??FunctionalState?CAN_RFLM;??/*!<?接收FIFO锁定使能?ENABLE?or?DISABLE.?*/ ??FunctionalState?CAN_TXFP;??/*!<?发送FIFO优先级使能?ENABLE?or?DISABLE.?*/ }?CAN_InitTypeDef;????

(4)初始化过滤器

void?CAN_FilterInit(CAN_FilterInitTypeDef*?CAN_FilterInitStruct);

//参数就是过滤器初始化结构

typedef?struct

{ ??

? uint16_t?CAN_FilterIdHigh;?????????/*!<?过滤器ID寄存器高16位?0x0000?and?0xFFFF?*/ ??uint16_t?CAN_FilterIdLow;??????????/*!<?过滤器ID寄存器低16位?0x0000?and?0xFFFF?*/ ??uint16_t?CAN_FilterMaskIdHigh;?????/*!<?过滤器ID掩码寄存器高16位?0x0000?and?0xFFFF?*/ ??uint16_t?CAN_FilterMaskIdLow;??????/*!<?过滤器ID掩码寄存器低16位?0x0000?and?0xFFFF?*/ ??uint16_t?CAN_FilterFIFOAssignment;?/*!<?接收FIFO的选择?@ref?CAN_filter_FIFO?*/ ?? ??uint8_t?CAN_FilterNumber;??????????/*!<?过滤器编号?0?to?13.?*/ ??

? uint8_t?CAN_FilterMode;????????????/*!<?过滤模式?@ref?CAN_filter_mode?*/ ??uint8_t?CAN_FilterScale;???????????/*!<?过滤器长度?@ref?CAN_filter_scale?*/ ??FunctionalState?CAN_FilterActivation;?/*!<?使能/禁止?ENABLE?or?DISABLE.?*/ }?CAN_FilterInitTypeDef;

(5)配置发送/接收的结构体

//发送数据结构体

typedef?struct

{ ??uint32_t?StdId;??/*!<?标准帧ID?0?to?0x7FF.?*/ ??

? ? uint32_t?ExtId;??/*!<?扩展帧ID?0?to?0x1FFFFFFF.?*/? ?

? ? uint8_t?IDE;?????/*!<?IDE标志?标准帧/扩展帧?@ref?CAN_identifier_type?*/ ??

? ? uint8_t?RTR;?????/*!<?RTR标志?数据帧/遥控帧?@ref?CAN_remote_transmission_request?*/? ? ? ? ? ? ? ? uint8_t?DLC;?????/*!<?数据段长度?0?to?8?*/ ??uint8_t?Data[8];?/*!<?发送的数据?0?to?0xFF.?*/ }?CanTxMsg;

//接收数据结构体 typedef?struct { ??uint32_t?StdId;??/*!<?标准帧ID?0?to?0x7FF.?*/ ??

? uint32_t?ExtId;??/*!<?扩展帧ID?0?to?0x1FFFFFFF.?*/ ??

? uint8_t?IDE;?????/*!<?IDE标志?标准帧/扩展帧?@ref?CAN_identifier_type?*/ ??

? uint8_t?RTR;?????/*!<?RTR标志?数据帧/遥控帧?@ref?CAN_remote_transmission_request?*/ ??uint8_t?DLC;?????/*!<?数据段长度?0?to?8?*/ ??uint8_t?Data[8];?/*!<?接收的数据?0?to?0xFF.?*/ ??uint8_t?FMI;?????/*!<?过滤器放入的内容?0?to?0xFF?*/ }?CanRxMsg;

(6)初始化CAN的接收中断

NVIC_Init(...); CAN_ITConfig(CAN1,?CAN_IT_FMP0,?ENABLE);

(7)发送和接收数据

接收: ????void?CAN_Receive(CAN_TypeDef*?CANx,?uint8_t?FIFONumber,?CanRxMsg*?RxMessage);

发送: ????

? ? uint8_t?CAN_Transmit(CAN_TypeDef*?CANx,?CanTxMsg*?TxMessage); ????uint8_t?CAN_TransmitStatus(CAN_TypeDef*?CANx,?uint8_t?TransmitMailbox);

8.上位机的使用

????打开软件

(1)串口设置

打开后会读到当前模块的配置

(2)将CAN模块设置为环回模式,波特率500Kbps

?(4)测试模块的发送和接收

9.连接模块和开发板

下一步需要编写程序实现CAN总线的通信 ,如果没有can模块进行测试,可以在初始化can 的时候把模式设置为环回模式,把数据发送给自己进行数据收发的测试。

#include <stm32f4xx.h>
#include <can.h>
#include <stdio.h>

void can1_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	CAN_InitTypeDef CAN_InitStruct;
	CAN_FilterInitTypeDef CAN_FilterInitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	
	//1.开启GPIOD和CAN1时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
	
	//2.初始化GPIO为CAN功能
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//复用模式
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//高速
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上下拉
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	GPIO_Init(GPIOD,&GPIO_InitStruct);
	
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_CAN1);
	GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_CAN1);
	
	//3.初始化CAN 42M / 4 /(1+12+8) = 500Kbps
	CAN_InitStruct.CAN_Prescaler = 4;//4分频
	CAN_InitStruct.CAN_SJW = CAN_SJW_1tq;//SJW宽度
	CAN_InitStruct.CAN_BS1 = CAN_BS1_12tq;//PBS1宽度
	CAN_InitStruct.CAN_BS2 = CAN_BS2_8tq;//PBS2宽度
	CAN_InitStruct.CAN_Mode = CAN_Mode_LoopBack;//CAN_Mode_Normal;//正常模式
	CAN_InitStruct.CAN_ABOM = DISABLE;//自动离线
	CAN_InitStruct.CAN_AWUM = DISABLE;//自动唤醒
	CAN_InitStruct.CAN_NART = DISABLE;//自动重发
	CAN_InitStruct.CAN_RFLM = DISABLE;//锁定接收
	CAN_InitStruct.CAN_TTCM = DISABLE;//时间触发
	CAN_InitStruct.CAN_TXFP = DISABLE;//发送报文优先级
	CAN_Init(CAN1,&CAN_InitStruct);
	
	//4.初始化过滤器
	CAN_FilterInitStruct.CAN_FilterActivation = ENABLE;//使能过滤器
	CAN_FilterInitStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//安装过滤器到FIFO0
	CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdMask;//过滤器模式 --- 掩码
	CAN_FilterInitStruct.CAN_FilterNumber = 0;//过滤器0
	CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_16bit;//过滤器长度
	CAN_FilterInitStruct.CAN_FilterIdHigh = 0x0000;
	CAN_FilterInitStruct.CAN_FilterIdLow = 0x0000;
	CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0x0000;
	CAN_FilterInitStruct.CAN_FilterMaskIdLow = 0x0000;
	CAN_FilterInit(&CAN_FilterInitStruct);
	
	//5.初始化CAN接收中断
	NVIC_InitStruct.NVIC_IRQChannel = CAN1_RX0_IRQn;//CAN1 FIFO0接收中断通道
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x2;//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x2;//响应优先级
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
	NVIC_Init(&NVIC_InitStruct);
	
	CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}

CanTxMsg CAN1_TX_MSG;
CanRxMsg CAN1_RX_MSG;

//can1发送函数 0 - 成功  非0 - 失败
u8 can1_send_message(u8 *data,u8 len,u32 message_id)
{
	u8 i,mailbox;
	u32 cnt = 0;
	
	if(len>8)
		return 1;
	
	//根据id选择标准帧/扩展帧
	if(message_id>0x7ff){//扩展帧
		CAN1_TX_MSG.IDE = CAN_Id_Extended;
	}
	else{
		CAN1_TX_MSG.IDE = CAN_Id_Standard;
	}
	
	CAN1_TX_MSG.RTR = CAN_RTR_Data;//数据帧
	CAN1_TX_MSG.DLC = len;//数据长度
	CAN1_TX_MSG.ExtId = message_id;//扩展帧ID
	CAN1_TX_MSG.StdId = message_id;//标准帧ID
	//发送的数据
	for(i=0;i<len;i++){
		CAN1_TX_MSG.Data[i] = data[i];
	}
	
	//发送数据等待发送成功
	mailbox = CAN_Transmit(CAN1,&CAN1_TX_MSG);
	do{
		cnt++;
	}while(CAN_TransmitStatus(CAN1,mailbox)!=CAN_TxStatus_Ok&&cnt<1000);
	
	if(cnt<1000)
		return 0;
	else
		return 1;
}

//CAN FIFO1中断处理函数
void CAN1_RX0_IRQHandler(void)
{
	if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)==SET){//收到数据
		CAN_Receive(CAN1,CAN_FIFO0,&CAN1_RX_MSG);
		/*
		//原路发回
		if(CAN1_RX_MSG.IDE==CAN_Id_Standard){//标准帧
			can1_send_message(CAN1_RX_MSG.Data,CAN1_RX_MSG.DLC,CAN1_RX_MSG.StdId);
		}
		else if(CAN1_RX_MSG.IDE==CAN_Id_Extended){
			can1_send_message(CAN1_RX_MSG.Data,CAN1_RX_MSG.DLC,CAN1_RX_MSG.ExtId);
		}
		*/
		printf("%s\r\n",CAN1_RX_MSG.Data);
		
		//清除标志
		CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
	}
}

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:39:38  更:2022-07-17 16:41:00 
 
开发: 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年11日历 -2024/11/25 22:56:42-

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