news 2026/7/5 4:23:40

STM32如何实现多个设备的主从机CAN通讯?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32如何实现多个设备的主从机CAN通讯?

主从机can通讯(stm32)

基于STM32的CAN总线温度检测节点 的硬件设计与制作。1个主节点+3个从节点,每个节点均包含STM32最小系统、CAN通信模块、温度采集模块,能够稳定完成本地温度采集并通过CAN总线实现数据收发。

1、CAN 总线

CAN(Controller Area Network,控制器局域网),1983 年博世为汽车电子开发,是差分串行通信总线,多主仲裁、抗干扰强、实时性高,广泛用于汽车、工业 PLC、嵌入式设备。 核心特点:多主机、无主从区分;差分信号抗 EMI;硬件帧仲裁;错误自动检测重传;最远 10km 低速通信。

本系统选取的是闭环CAN总线网络。特点:高速、短距离,它的总线最大长度为40m,通信速度最高为1Mbps,总线的两端各要求有一个120 欧的电阻。如下图所示:

2、CAN 模块

CAN通信模块核心器件选用TJA1050 CAN收发器,该器件支持5kbps至1Mbps波特率,兼容CAN 2.0A/B协议,可将STM32内部CAN控制器的逻辑电平转换为总线差分信号,提升抗干扰能力。其具备热保护、短路保护功能,可避免总线故障损坏器件,且体积小、功耗低,适合节点模块化部署;总线两端配置120Ω终端电阻,抑制信号反射,保障长距离传输稳定性。

3、注意事项:

由于TJA1050 CAN收发器配置了120Ω终端电阻,在连接TJA1050 硬件之前,需要对其中两个TJA1050去掉120Ω终端电阻,保证是闭环CAN总线网络,这样信号传输就不会丢包。

4、器件清单

stm32f103c8t64
TJA10504
DS18B204
BEEP3
LED4
电源模块1
OLED 屏幕1
按键模块2

5、主机原理图

6、从机原理图

7、主机代码

#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "Key.h" #include "MyCAN.h" #include "STDIO.h" #include "ds18b20.h" #include "LED.h" uint8_t Keycount; uint8_t Keymode; uint32_t RxID; uint8_t RxLength; uint8_t RxData[8]; uint32_t TxID = 0x111; uint8_t TxLength = 8; uint8_t TxData[8] = {0x00, 0x00, 0x00}; float TA; float TB; float TC; float TD; char TA_buf[10]; char TB_buf[10]; char TC_buf[10]; char TD_buf[10]; uint8_t TA_s = 30; uint8_t TB_s = 30; uint8_t TC_s = 30; uint8_t TD_s = 30; void SHOW(void) { OLED_ShowString(1, 1, "A:"); OLED_ShowString(2, 1, "B:"); OLED_ShowString(3, 1, "C:"); OLED_ShowString(4, 1, "D:"); if(TA > TA_s) OLED_ShowString(1,10,"warning"); else OLED_ShowString(1,10,"normal "); if(TB > TB_s) OLED_ShowString(2,10,"warning"); else OLED_ShowString(2,10,"normal "); if(TC > TC_s) OLED_ShowString(3,10,"warning"); else OLED_ShowString(3,10,"normal "); if(TD > TD_s) OLED_ShowString(4,10,"warning"); else OLED_ShowString(4,10,"normal "); } float temp_data; float temp_data1[1]; int main(void) { OLED_Init(); Key_Init(); MyCAN_Init(); OLED_Clear(); DS18B20_Init(); BEEP_Init(); LED_Init(); while (1) { Keycount = Key_GetNum(); if(Keycount ==1){ OLED_Clear(); Keymode++; if(Keymode>4)Keymode = 0; } if(Keymode==0) { SHOW(); TD=(float)DS18B20_Get_Temp()/10.0f; TxData[0] = TA_s; TxData[1] = TB_s; TxData[2] = TC_s; MyCAN_Transmit(0X111, TxLength,TxData); MyCAN_Transmit(0X222, TxLength,TxData); MyCAN_Transmit(0X333, TxLength,TxData); if(TD > (float)TD_s){ LED_ON();BEEP_ON(); Delay_ms(10); } else{ LED_OFF();BEEP_OFF(); Delay_ms(10); } if (MyCAN_ReceiveFlag()) { MyCAN_Receive(&RxID, &RxLength, RxData); if(RxID == 0x111)//从机A TA = RxData[0] *10 + RxData[1] + (float)RxData[2]*0.1; if(RxID == 0x222)//从机B TB = RxData[0] *10 + RxData[1] + (float)RxData[2]*0.1; if(RxID == 0x333)//从机C TC = RxData[0] *10 + RxData[1] + (float)RxData[2]*0.1; sprintf(TA_buf,"%.1fC",TA);OLED_ShowString(1,3,TA_buf); Delay_ms(2); sprintf(TB_buf,"%.1fC",TB);OLED_ShowString(2,3,TB_buf); Delay_ms(2); sprintf(TC_buf,"%.1fC",TC);OLED_ShowString(3,3,TC_buf); Delay_ms(2); sprintf(TD_buf,"%.1fC",TD);OLED_ShowString(4,3,TD_buf); Delay_ms(2); } } Delay_ms(2); if(Keymode>0) { OLED_ShowString(1,3,"TA_H:"); OLED_ShowString(2,3,"TB_H:"); OLED_ShowString(3,3,"TC_H:"); OLED_ShowString(4,3,"TD_H:"); OLED_ShowNum(1,8,TA_s ,2); OLED_ShowNum(2,8,TB_s ,2); OLED_ShowNum(3,8,TC_s ,2); OLED_ShowNum(4,8,TD_s ,2); } if(Keymode==1) { OLED_ShowString(1,11,"<"); if(Keycount ==2){ TA_s++; if(TA_s>40)TA_s=20;} } if(Keymode==2) { OLED_ShowString(2,11,"<"); if(Keycount ==2){ TB_s++; if(TB_s>40)TB_s=20;} } if(Keymode==3) { OLED_ShowString(3,11,"<"); if(Keycount ==2){ TC_s++; if(TC_s>40)TC_s=20;} } if(Keymode==4) { OLED_ShowString(4,11,"<"); if(Keycount ==2){ TD_s++; if(TD_s>40)TD_s=20;} } } }

8、从机代码

下面是从机A代码。从机B、C、D代码只需将CAN的ID改成不同的即可。

#include "stm32f10x.h" // Device header #include "Delay.h" #include "LED.h" #include "MyCAN.h" #include "ds18b20.h" #include <stdio.h> #include <stdlib.h> uint32_t RxID; uint8_t RxLength; uint8_t RxData[8]; uint32_t TxID = 0x222; uint8_t TxLength = 8; uint8_t TxData[8] = {0x00, 0x00, 0x00}; int Ttens, Tunits, Tdecimal; float temp_data; float temp_data1[1]; int temp_data_H; void extract_digits(float num, int *tens, int *units, int *decimal) { float abs_num = (num < 0) ? -num : num; int scaled = (int)(abs_num * 10.0f + 0.5f); *decimal = scaled % 10; // 小数位 *units = (scaled / 10) % 10; // 个位 *tens = (scaled / 100) % 10; // 十位 } int main(void) { DS18B20_Init(); LED_Init(); BEEP_Init(); MyCAN_Init(); while (1) { temp_data=(float)DS18B20_Get_Temp()/10.0f; if(temp_data > temp_data_H){ LED_ON();BEEP_ON(); Delay_ms(10); } else{ LED_OFF();BEEP_OFF(); Delay_ms(10); } temp_data1[0]=temp_data; extract_digits(temp_data1[0], &Ttens, &Tunits, &Tdecimal); TxData[0] = Ttens; TxData[1] = Tunits; TxData[2] = Tdecimal; MyCAN_Transmit(TxID, TxLength,TxData); if (MyCAN_ReceiveFlag()) { MyCAN_Receive(&RxID, &RxLength, RxData); if(RxID == 0x222)//从机A { temp_data_H = RxData[1]; } } Delay_ms(100); } }

9、实物图

指导

如果需要全套源码(器件清单、含原理图、pcb文件、代码)可以搜上面的号

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/5 4:22:18

AI 电动窗帘电机智能功率 低功耗、静音驱动 完整选型方案

2026年随着 AI 技术在智能家居中的普及&#xff08;如语音控制、光线自适应、场景联动&#xff09;&#xff0c;电动窗帘电机对功率 MOSFET 提出更高要求&#xff1a;低功耗、静音驱动、高可靠性。微碧半导体&#xff08;VBsemi&#xff09;基于 Trench 和 SGT 工艺&#xff0c…

作者头像 李华
网站建设 2026/7/5 4:21:45

如何高效使用DeepL Chrome扩展:5分钟快速入门终极指南

如何高效使用DeepL Chrome扩展&#xff1a;5分钟快速入门终极指南 【免费下载链接】deepl-chrome-extension A DeepL Translator Chrome extension 项目地址: https://gitcode.com/gh_mirrors/de/deepl-chrome-extension 你是否经常遇到看不懂的外文网页&#xff1f;想要…

作者头像 李华
网站建设 2026/7/5 4:17:23

从“搜得到“到“被推荐“:AI时代的营销新变量

一、一场悄悄发生的用户习惯迁移 有一件事&#xff0c;可能大多数企业还没完全意识到—— 用户找东西的方式&#xff0c;正在被AI重写。 三年前&#xff0c;一个人想找一家靠谱的公司&#xff0c;会打开百度输入关键词&#xff0c;翻两三页&#xff0c;对比几家官网&#xff0c…

作者头像 李华
网站建设 2026/7/5 4:17:15

[SCI论文写作素材]AI Agent 在不同领域的应用-可用于SCI论文写作

AI Agent 在不同领域的应用&#xff0c;特别适合Introduction** 可用于SCI论文写作&#xff0c;有参考文献格式和连接。** 应用领域核心智能体名称核心技术架构核心性能/实验数据核心研究结论连接高分子材料设计Polymer-Agent基于LLM推理能力&#xff0c;集成TransPolymer聚合…

作者头像 李华