当前位置: 首页 > news >正文

基于STM32F105系列使用CAN总线实现双机通信代码

基于STM32F105系列使用CAN总线实现双机通信代码,包含初始化、发送和接收功能。这里使用标准外设库,并假设使用CAN1。

1. CAN总线初始化

#include"stm32f10x.h"#include"stm32f10x_can.h"#include"stm32f10x_gpio.h"#include"stm32f10x_rcc.h"#include"misc.h"// CAN初始化结构体CAN_InitTypeDef CAN_InitStructure;CAN_FilterInitTypeDef CAN_FilterInitStructure;CanTxMsg TxMessage;CanRxMsg RxMessage;voidCAN_GPIO_Config(void){GPIO_InitTypeDef GPIO_InitStructure;// 使能GPIO和CAN时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);// 配置CAN引脚: PA11->RX, PA12->TXGPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;// TXGPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;// 推挽复用输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;// RXGPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;// 上拉输入GPIO_Init(GPIOA,&GPIO_InitStructure);}voidCAN_NVIC_Config(void){NVIC_InitTypeDef NVIC_InitStructure;// 配置CAN接收中断NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN1_RX0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);}voidCAN_Mode_Config(void){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;// 禁止FIFO锁定CAN_InitStructure.CAN_TXFP=DISABLE;// 禁止发送FIFO优先级// 配置波特率// CAN波特率 = APB1时钟 / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)// 假设APB1时钟为36MHz,波特率设为500kbpsCAN_InitStructure.CAN_BS1=CAN_BS1_9tq;// 时间段1CAN_InitStructure.CAN_BS2=CAN_BS2_4tq;// 时间段2CAN_InitStructure.CAN_Prescaler=6;// 分频系数// 总时间片 = 1 + 9 + 4 = 14// 波特率 = 36MHz / (14 * 6) = 428.57kHz (接近500k)CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;// 正常工作模式CAN_Init(CAN1,&CAN_InitStructure);// 配置CAN过滤器CAN_FilterInitStructure.CAN_FilterNumber=0;// 使用过滤器0CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;// 掩码模式CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;// 32位模式CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;// 要过滤的ID高位CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;// 要过滤的ID低位CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;// 掩码高位CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;// 掩码低位CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;// 关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;// 启用过滤器CAN_FilterInit(&CAN_FilterInitStructure);// 使能CAN接收中断CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);}

2. CAN数据发送函数

uint8_tCAN_Send_Msg(uint8_t*msg,uint8_tlen,uint32_tid){uint8_ti=0;uint8_ttransmit_mailbox=0;TxMessage.StdId=id;// 标准IDTxMessage.ExtId=0x00;// 扩展IDTxMessage.IDE=CAN_Id_Standard;// 标准帧TxMessage.RTR=CAN_RTR_Data;// 数据帧TxMessage.DLC=len;// 数据长度(最大8字节)// 填充数据for(i=0;i<len;i++){TxMessage.Data[i]=msg[i];}// 发送数据transmit_mailbox=CAN_Transmit(CAN1,&TxMessage);// 等待发送完成i=0;while((CAN_TransmitStatus(CAN1,transmit_mailbox)!=CANTXOK)&&(i<0xFF)){i++;}if(i>=0xFF){return1;// 发送失败}return0;// 发送成功}

3. CAN数据接收中断服务函数

voidUSB_LP_CAN1_RX0_IRQHandler(void){staticuint8_treceive_buffer[8];if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)!=RESET){// 读取接收到的数据CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);// 清除中断标志CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);// 处理接收到的数据if(RxMessage.IDE==CAN_Id_Standard){uint8_ti;// 复制接收到的数据for(i=0;i<RxMessage.DLC;i++){receive_buffer[i]=RxMessage.Data[i];}// 在这里处理接收到的数据// 例如:将数据发送到串口或进行其他处理// Process_Received_Data(receive_buffer, RxMessage.DLC, RxMessage.StdId);}}}

4. 主函数示例

intmain(void){uint8_tsend_data[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};uint32_tmessage_id=0x123;// CAN消息ID// 初始化系统时钟SystemInit();// 配置GPIOCAN_GPIO_Config();// 配置NVIC中断CAN_NVIC_Config();// 配置CAN模式CAN_Mode_Config();// 主循环while(1){// 每隔1秒发送一次数据Delay(1000);// 自定义延时函数// 发送CAN消息CAN_Send_Msg(send_data,8,message_id);// 可以在这里添加其他处理逻辑}}

参考代码 stm32f105系列使用can总线实现双机通信源代码www.youwenfan.com/contentcsv/70917.html

5. 双机通信配置说明

设备A配置(发送设备):

// 设置设备A的ID为0x100uint32_tdevice_a_id=0x100;

设备B配置(接收设备):

// 配置过滤器只接收来自设备A的消息CAN_FilterInitStructure.CAN_FilterIdHigh=0x0100<<5;// ID高16位CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;// ID低16位CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFFFF;// 掩码高位CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;// 掩码低位

6. 完整的工程配置步骤

  1. 硬件连接

    • CAN_H 连接 CAN_H
    • CAN_L 连接 CAN_L
    • 两个设备的GND相连
    • 在总线的两端接120Ω终端电阻
  2. 软件配置

    // 波特率计算// 假设系统时钟为72MHz,APB1时钟为36MHz// 500kbps配置:BS1=9, BS2=4, Prescaler=6// 1Mbps配置:BS1=9, BS2=4, Prescaler=3
  3. 编译和下载

    • 使用Keil MDK或STM32CubeIDE
    • 确保包含正确的头文件
    • 配置正确的系统时钟

注意事项

  1. 终端电阻:必须在CAN总线的两端各接一个120Ω的终端电阻
  2. 波特率:两个设备的波特率必须相同
  3. 中断优先级:根据实际应用需求合理配置中断优先级
  4. 错误处理:在实际应用中应添加错误检测和重发机制
  5. ID冲突:确保每个设备的CAN ID唯一,避免冲突
http://www.cnnetsun.cn/news/2485045.html

相关文章:

  • 鸿蒙支付模块构建:快捷充值选项与缴费记录的时间线设计
  • VSCode Mermaid Preview:面向技术团队的实时图表协作解决方案
  • [明道云实战] 流程一多就开始乱,怎样把明道云工作流整理成可维护的工程系统?
  • 深度测评2026年日本工程塑料厂家最佳代理服务排行榜,解锁高精尖材料新选择
  • 告别Keil!在VSCode里用PlatformIO+CubeMX+HAL库玩转STM32(保姆级配置流程)
  • 从CUDA_VISIBLE_DEVICES到Docker:聊聊GPU资源隔离的几种‘姿势’
  • MiniMax-M2.7-W8A8 双机 DP=2 部署
  • 树莓派摄像头detected=0?别急着重装系统,先检查这个新手常插错的接口
  • 考前终极口诀合集,30秒过一遍
  • 错过申报期等于白干:政策信息平台的时效性保障技术方案
  • 从Multisim仿真到理论验证:一个实际案例带你吃透结点电压法的‘自导’与‘互导’
  • 从IMC层到应力点:手把手教你用SEM/EDS给BGA焊点做一次‘体检’
  • 从6DOF到近场动力学:多物理场耦合仿真的技术跃迁与工程实践
  • 创业公司如何利用Taotoken以可控成本开展每日AI创意生成活动
  • k8s集群网络层碎碎念
  • 硬件研发必看:钡特电源 DF2-15S03XT 与金升阳 F1503XT-2WR3 属工业标准模块电源封装与性能
  • LobeHub推出CAO调度系统,理想丰满现实骨感,AI全自动化办公仍待探索
  • 如何判断杉木桩品牌的选型标准?
  • 嵌入式开发必备:Linux下ELF文件查看与交叉编译验证全攻略
  • LabVIEW 2021 + 树莓派4B:从镜像烧录到点亮第一个LED的保姆级避坑指南
  • HPM6750双核RISC-V开发实战:从固件合并到双核启动全流程解析
  • HsMod终极指南:55项功能打造你的个性化炉石传说体验
  • 想买AI漫剧制作服务?先了解这3个价格档位和真实案例
  • MCU工程迁移实战:从STM32到MSPM0L1306的完整指南
  • Perplexity作家搜索≠简单关键词匹配:从NLP意图识别到跨平台身份对齐的9层专业验证体系
  • CentOS 7服务器上NVIDIA驱动和CUDA 11.x的保姆级安装避坑指南(含Nouveau禁用与版本选择)
  • 2026年免费商用音乐素材网站TOP5深度评测:从版权合规到项目适配的全方位指南
  • 从Vue/React到移动端:用Cordova 12把你的Web项目打包成Android App实战
  • 注册培训师、咨询师——杨刚老师简介
  • 初创团队如何利用 Taotoken 以最小成本验证多个大模型能力