“通俗易懂:轻松掌握STM32F103上的CAN通信“ 您所在的位置:网站首页 CAN通信模块NC “通俗易懂:轻松掌握STM32F103上的CAN通信“

“通俗易懂:轻松掌握STM32F103上的CAN通信“

2024-07-14 09:18| 来源: 网络整理| 查看: 265

CAN(Controller Area Network)是一种常用的通信协议,广泛应用于汽车、工业控制等领域。本文将向初学者介绍CAN的基本概念、工作原理以及如何在STM32F103微控制器上使用标准库进行CAN通信。同时,将提供一个完整的示例代码,帮助你更好地理解和应用CAN协议。

一、CAN的基本概念和工作原理

CAN的基本概念

CAN是一种串行通信协议,最初是由德国Bosch公司开发用于汽车电子系统的通信协议。它使用了差分信号传输方式,具有高噪声抑制能力和较高的可靠性。CAN通信协议采用了两线制(CAN_H和CAN_L)的物理层接口,能够实现多个节点之间的高速、实时通信。

CAN的工作原理

CAN通信是基于事件触发的机制。每个节点在总线上以相同的速率进行数据传输,节点之间通过标识符(Identifier)进行消息的识别和过滤。CAN协议分为两种传输模式:数据帧(Data Frame)和远程帧(Remote Frame)。数据帧用于节点之间的数据传输,而远程帧用于请求节点发送特定数据。

在CAN通信中,每个节点都具有唯一的标识符。当一个节点发送一帧数据时,其他节点可以通过检查标识符来确定是否接收该数据。CAN总线上的节点可以处于发送模式或接收模式。发送节点通过发送数据帧将数据发送到总线上,而接收节点通过接收数据帧来获取数据。

二、STM32F103上使用CAN的步骤

接下来,将介绍如何在STM32F103微控制器上使用标准库进行CAN通信。请确保你已经安装了适当的开发环境和STM32Cube库。

初始化CAN总线

首先,需要初始化CAN总线。以下是使用STM32标准库进行CAN初始化的示例代码:

#include "stm32f10x.h" void CAN_Configuration(void) { CAN_InitTypeDef CAN_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 使能CAN和GPIO时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置CAN引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // CAN初始化 CAN_DeInit(CAN1); CAN_StructInit(&CAN_InitStructure); // 配置CAN参数 CAN_InitStructure.CAN_TTCM = DISABLE; CAN_InitStructure.CAN_ABOM = DISABLE; CAN_InitStructure.CAN_AWUM = DISABLE; CAN_InitStructure.CAN_NART = DISABLE; CAN_InitStructure.CAN_RFLM = DISABLE; CAN_InitStructure.CAN_TXFP = DISABLE; CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq; CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq; CAN_InitStructure.CAN_Prescaler = 6; CAN_Init(CAN1, &CAN_InitStructure); }

在上述代码中,使用了RCC_APB1PeriphClockCmd函数和RCC_APB2PeriphClockCmd函数分别使能了CAN和GPIOA的时钟。然后,通过GPIO_InitStructure结构体配置了CAN引脚(GPIO_Pin_11和GPIO_Pin_12)的工作模式(GPIO_Mode_AF_PP表示复用推挽输出)和速度。

首先使用CAN_DeInit函数将CAN1外设恢复到默认值。然后,使用CAN_StructInit函数初始化CAN_InitStructure结构体为默认值。

接下来,根据需求设置CAN_InitStructure结构体的各个参数。例如,将CAN的传输模式设置为正常模式(CAN_Mode_Normal),将同步跳转宽度(SJW)设置为1个时间单位(CAN_SJW_1tq),位时序参数(BS1和BS2)设置为4和3个时间单位(CAN_BS1_4tq和CAN_BS2_3tq),预分频器(Prescaler)设置为6。最后,通过调用CAN_Init函数将配置应用到CAN1外设。

通过以上步骤,成功地初始化了CAN总线。接下来,可以发送和接收CAN消息。

下面是一个简单的示例代码,演示如何通过CAN总线发送消息:

void CAN_SendMessage(uint8_t data) { CanTxMsg TxMessage; // 设置消息ID和长度 TxMessage.StdId = 0x123; TxMessage.IDE = CAN_Id_Standard; TxMessage.RTR = CAN_RTR_Data; TxMessage.DLC = 1; // 设置消息数据 TxMessage.Data[0] = data; // 发送消息 CAN_Transmit(CAN1, &TxMessage); }

在这段代码中,首先创建了一个名为TxMessage的CanTxMsg结构体变量,用于存储要发送的CAN消息。

使用了StdId字段设置了消息的标识符(ID)。在这个示例中,将标识符设置为0x123。

IDE字段用于指定消息的标识符类型。在这个示例中,使用了CAN_Id_Standard表示使用标准标识符。

RTR字段用于指定消息的传输类型。在这个示例中,使用了CAN_RTR_Data表示数据帧传输。

DLC字段用于指定消息的数据长度。在这个示例中,将数据长度设置为1字节。

然后,使用Data数组设置了要发送的消息数据。在这个示例中,将数据设置为data变量的值。

最后,使用CAN_Transmit函数将消息发送到CAN总线上。

接收CAN消息

以下是一个简单的示例代码,演示如何通过CAN总线接收消息:

void CAN_ReceiveMessage(void) { CanRxMsg RxMessage; // 等待接收到消息 while (CAN_MessagePending(CAN1, CAN_FIFO0) == 0); // 接收消息 CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); // 处理接收到的消息 if (RxMessage.StdId == 0x123 && RxMessage.IDE == CAN_Id_Standard && RxMessage.DLC == 1) { uint8_t data = RxMessage.Data[0]; // 处理接收到的数据 } }

在这段代码中,首先创建了一个名为RxMessage的CanRxMsg结构体变量,用于存储接收到的CAN消息。

通过使用CAN_MessagePending函数,等待接收到消息。只有当有消息到达时,该函数才会返回非零值,否则会一直等待。

接下来,使用CAN_Receive函数从CAN总线上接收消息,并将其存储在RxMessage变量中。

最后,通过检查RxMessage结构体中的标识符(ID)、标识符类型和数据长度,来判断接收到的消息是否符合预期。在这个示例中,检查标识符是否为0x123、标识符类型是否为标准标识符、数据长度是否为1字节。如果满足条件,可以将数据提取出来并进行进一步的处理。

主函数

最后,在主函数中调用上述函数以初始化CAN总线并发送/接收CAN消息:

int main(void) { CAN_Configuration(); // 发送CAN消息 CAN_SendMessage(0xAA); // 接收CAN消息 CAN_ReceiveMessage(); while (1) { // 主循环 } }

三、总结

本文向初学者介绍了CAN的基本概念和工作原理,以及如何在STM32F103微控制器上使用标准库进行CAN通信。希望本文能够对初学者在学习和应用CAN通信方面提供帮助。如果你对CAN有更多的疑问或需要进一步的指导,请随时提问。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有