STM32-CAN总线通信文档
- 格式:pdf
- 大小:288.42 KB
- 文档页数:12
stm32 can iap原理STM32是一款广泛应用于嵌入式系统开发的微控制器,其中的CAN (Controller Area Network)接口是一种常用的通信协议,用于在不同的设备之间进行数据传输。
而IAP(In-Application Programming)则是一种在设备中实现程序的在线更新的技术。
本文将介绍STM32中的CAN IAP原理,从而帮助读者更好地理解和应用这一技术。
CAN IAP原理的核心思想是通过CAN总线将新的程序代码传输到目标设备,并在设备中进行更新。
这种更新方式具有很高的灵活性和可靠性,能够使设备在不中断正常工作的情况下完成程序的更新。
下面将分别介绍CAN和IAP的基本原理,以及二者结合的实现方法。
我们来了解一下CAN接口。
CAN是一种串行通信协议,常用于工业控制系统和汽车电子领域。
它具有高速、可靠的特点,能够在多个节点之间进行数据传输。
在STM32中,CAN接口由硬件模块实现,可以通过编程配置其参数,如波特率、滤波器等。
CAN总线上的设备可以作为发送方或接收方,通过标识符来标识自己发送的数据。
通过CAN总线,设备之间可以实现快速的数据交换和通信。
我们来了解一下IAP技术。
IAP是一种在线更新程序的技术,能够在设备中更新程序代码,而无需将设备连接到计算机或使用外部编程器。
在STM32中,IAP技术可以通过修改存储器中的程序代码来实现程序的更新。
通过IAP技术,我们可以在设备中加载新的程序代码,实现功能的升级或修复bug等操作。
将CAN和IAP结合起来,就可以实现CAN IAP技术。
具体实现的步骤如下:1. 首先,需要将新的程序代码打包成BIN文件,并将其发送到目标设备。
可以通过计算机上的CAN工具或其他CAN设备发送程序代码。
2. 目标设备接收到BIN文件后,将其保存在存储器中的指定位置。
可以使用STM32提供的存储器编程接口来实现数据的写入。
3. 在存储器中保存了新的程序代码后,需要进行程序的更新。
STM32扩展6路CAN简介STM32是一款由STMicroelectronics公司推出的32位ARM Cortex-M系列微控制器。
它具有高性能、低功耗和丰富的外设资源,被广泛应用于各种嵌入式系统中。
其中,CAN(Controller Area Network)是一种常用的通信协议,用于在嵌入式系统中实现设备之间的高速通信。
本文将介绍如何通过扩展6路CAN来进一步增强STM32的通信能力。
我们将详细介绍扩展6路CAN的硬件连接和软件配置,以及如何在STM32上编写代码实现CAN通信。
硬件连接在扩展6路CAN之前,首先需要确认所选的STM32开发板是否支持CAN功能。
如果不支持,可以考虑更换支持CAN功能的开发板。
扩展6路CAN需要使用外部CAN模块来实现。
常用的外部CAN模块有MCP2515和SN65HVD232,它们可以通过SPI或UART接口与STM32连接。
具体的硬件连接方式取决于所选的外部CAN模块和STM32开发板的引脚分配。
通常,外部CAN模块的连接方式如下:1.将外部CAN模块的VCC引脚连接到STM32开发板的3.3V电源引脚。
2.将外部CAN模块的GND引脚连接到STM32开发板的地引脚。
3.将外部CAN模块的CS引脚(如果有)连接到STM32开发板的某个GPIO引脚,用于片选信号。
4.将外部CAN模块的SCK引脚连接到STM32开发板的SPI时钟引脚。
5.将外部CAN模块的MISO引脚连接到STM32开发板的SPI MISO引脚。
6.将外部CAN模块的MOSI引脚连接到STM32开发板的SPI MOSI引脚。
7.将外部CAN模块的INT引脚(如果有)连接到STM32开发板的某个GPIO引脚,用于中断信号。
请注意,具体的硬件连接方式可能因外部CAN模块和STM32开发板的型号而异。
在进行硬件连接之前,请务必仔细查阅外部CAN模块和STM32开发板的引脚定义和连接方式。
软件配置在进行软件配置之前,需要确保已经安装了适用于STM32的开发环境,例如Keil MDK或STM32CubeIDE。
stm32 canopen 例子摘要:1.引言2.STM32微控制器简介3.CANopen协议简介4.STM32 CANopen例子概述5.硬件设计6.软件设计7.总结正文:1.引言随着工业自动化和物联网技术的不断发展,嵌入式系统在各领域得到了广泛应用。
其中,STM32系列微控制器凭借出色的性能和低功耗特点,成为了嵌入式领域的热门选择。
CANopen协议作为一种基于CAN总线的通信协议,具有良好的实时性和可靠性,在工业自动化领域有着广泛的应用。
本文将介绍一个基于STM32的CANopen例子,以供参考。
2.STM32微控制器简介STM32系列微控制器是意法半导体公司推出的一款基于ARM Cortex-M 内核的32位闪存微控制器。
它具有高性能、低功耗、多功能、易扩展等特点,广泛应用于嵌入式系统领域。
3.CANopen协议简介CANopen协议是基于CAN总线的通信协议,由德国的Robert Bosch GmbH公司开发。
它是一种用于实时控制的开放式串行通信协议,具有多主控制结构、高可靠性、实时性好等特点。
CANopen协议在工业自动化领域得到了广泛应用,特别是在工业控制器和现场设备之间的通信。
4.STM32 CANopen例子概述本文将以一个简单的STM32 CANopen例子为例,介绍如何实现基于STM32的CANopen通信。
该例子采用STM32F103C8T6微控制器,具备两个CAN通道,分别用于发送和接收数据。
硬件方面,通过扩展CAN收发器及相关的外围器件,实现CANopen通信;软件方面,编写相应的程序实现CANopen协议的帧传输、数据处理等功能。
5.硬件设计硬件设计主要包括微控制器、CAN收发器、外围器件等的选型和连接。
首先,选用STM32F103C8T6微控制器作为核心控制器,通过SPI接口与CAN 收发器(如TJA1020)进行通信。
其次,根据需要选择其他外围器件,如电源模块、晶振模块、复位模块等。
stm32常见通信方式(TTL、RS232、RS485、CAN)总结
一、TTL电平:全双工(逻辑1: 2.4V--5V 逻辑0: 0V--0.5V)
1、硬件框图如下,TTL用于两个MCU间通信
2、‘0’和‘1’表示
二、RS-232电平:全双工(逻辑1:-15V--5V 逻辑0:+3V--+15V)
1、硬件框图如下,TTL用于MCU与PC机之间通信需要加电平转换芯片
2、‘0’和‘1’表示
三、RS-485:半双工、(逻辑1:+2V--+6V 逻辑0:-6V---2V)这里的电平指AB 两线间的电压差
1、硬件框图如下
2、‘0’和‘1’表示
四、CAN总线:逻辑1:-1.5V--0V 逻辑0:+1.5V--+3V)这里的电平指CAN_High、CAN_Low 两线间的电压差
1、硬件框图如下
2、‘0’和‘1’表示
以上总结:
1、从单片机软件编程角度来说,RS23
2、RS-485最终结果都是转换为TTL电平方式与单片机通信(CAN收发器把差分信号转化为TTL-->CAN控制器(MCU))。
其目的都是提高通信质量,提高抗干扰能力。
2、TTL、RS232是逻辑电平信号。
RS-485、CAN为差分信号。
五、I2C
5.1 I2C物理层
5.2 I2C协议层
5.3 数据的起始信号与停止信号
5.4数据有效性
I2C 协议在SCL 高电平时对SDA 信号采样,SCL 低电平时SDA准备下一个数据。
在STM32中都是有标准的数据结构和函数供大家使用,那么对于具体的每一部分对应那些数据、每一位代表什么意思都没有具体说明。
特别在使用某些协议,需要辨别该部分的具体信息时,就必须对数据结构中的每位的意义清楚才能提取出具体的含义。
先来看一下下面的东西吧。
CAN帧结构。
这个就不具体介绍了,不过先提一点疑问:在STM32中直接给结构体中各成员直接赋值或读取,那么其实际的发送或接收的最底层的结构又是怎么样的呢?typedef struct{uint32_t StdId;uint32_t ExtId;uint8_t IDE;uint8_t RTR;uint8_t DLC;uint8_t Data[8];uint8_t FMI;} CanRxMsg; 接受结构体和发送结构体一样,就只是结构体名不一样而已(CanTxMsg)。
对于上面的问题,在一些协议中进行解析时,如何将这些标识符与协议的具体项对应呢?由于在做J1939协议的编程,所以就以这个为例说明一下。
如上所示,在J1939中CAN帧结构为32位,包含优先级、PDU格式(PF)、PS、SA。
而在STM32的结构体中却是32位的ID,8位的IDE、RTR、DLC。
如果要单独提取标识符中的某一个有如何提取呢?这就涉及到STM32的收发邮箱的寄存器存储结构了。
来看一下其标识符寄存器结构吧(接收和发送寄存器结构除0位外都一样)对于J1939协议来说,必须对帧数据和优先级、PF、PS、SA进行双向解析。
所以我们在发送数据或收到数据时必须做一定的处理。
在STM32的固件库函数中该寄存器中的各个部分的值提取出来赋给其结构体中个部分的值。
发送数据时:u32 Id_Ext = 0x00000000;Id_Ext = Id_Ext|Priority<<26;Id_Ext = ((Id_Ext>>16)|Pdu_PF)<<16;Id_Ext = ((Id_Ext>>8)|Pdu_Ps)<<8;Id_Ext = Id_Ext|Pdu_Sa;接收数据时:PDU_PF = (RxMessage.ExtId&0x00ff0000)>>16;PDU_PS = (RxMessage.ExtId&0x0000ff00)>>8;PDU_SA = RxMessage.ExtId&0x000000FF;注意:在帧结构图中我们看到PF被分成了两部分,而在上面的处理中PF却是连在一起的8位。
图1 系统总体框图是一款带隔离的高速CAN收发器芯片,该芯片内部集成了所有必需的CAN隔离及CAN收发器件。
芯片的主要功能是将CAN控制器的逻辑电平转换为CAN总线的差分电平,并且具有DC 2500V的隔离功能及ESD保护作用,其是CAN收发器的理想选择[2]。
2 CAN总线收发模块的硬件设计CAN总线收发模块的硬件结构如图2所示。
CAN总线(1978-),男,江西宜春人,研究生,工程师。
研究方向:汽车电子项目管理。
公飞(1989-),男,山东临沂人,本科,助理工程师。
研究方向:汽车电子硬件设计。
收发模块的主要功能是控制开关和与RS232进行数据通信,开关可以用来控制现场设备的运行,后者可以方便与外界进行通信,提供通讯接口。
其硬件结构节点可以划分为最小系统模块、功能模块。
电源STM32的工作电压(VDD)为2.0~3.6V[3]。
通过内置的电压调节器提供所需的1.8V电源。
当主电源VDD掉电后,通过VBAT脚为实时时钟(RTC)和备份寄存器提供电源。
使用电池或其他电源连接到VBAT脚上,当VDD断电时,可以保存备份寄存器的内容和维持RTC的功能。
VBAT脚也图3 设置时钟流程图2.2 开关和RS232功能模块该节点具有两个功能,控制开关状态和与RS232通讯,开关选用八个TX2-5V继电器,两片MC1413作为驱动芯片,MC1413可以实现单片机端口电压到12V电平的转换。
与RS232通讯部分选用MAX232做为电平转换芯片。
2.3 CAN收发模块CAN收发模块主要是CAN收发器,CAN收发器的常用型号有CTM1050,CTM1050是一款带隔离的高速CAN收发器芯片,该芯片内部集成了所有必需的CAN隔离及CAN发器件。
芯片的主要功能是将CAN控制器的逻辑电平转换为CAN总线的差分电平,并且具有DC 2500V的隔离功能及ESD保护作用。
该芯片符合ISO 11898标准,因此,它可以和图2 节点硬件结构图图4 CAN初始化流程图选用的测试模式是环回模式,该模式下数据是自发自收的,即在发送成功的同时就接收到数据了。
STM32 CAN总线通信CAN总线通信详细学习的话这里有个视频教程可以推荐看看,/programs/view/IIuJjM2RIxc做电子的一定要多练勤于动手,做多了就自然而然就手到擒来。
Can.h文件如下:#ifndef __CAN_H#define __CAN_H#include "sys.h"////////////////////////////////////////////////////////////////////////////////////CAN接收RX0中断使能#define CAN_RX0_INT_ENABLE 0 //0,不使能;1,使能.u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode);//CAN初始化u8 Can_Send_Msg(u8* msg,u8 len); //发送数据u8 Can_Receive_Msg(u8 *buf); //接收数据#endifCan.c文件如下:#include "can.h"#include "led.h"#include "delay.h"#include "usart.h"//CAN初始化//tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tqCAN_SJW_3tq CAN_SJW_4tq//tbs2:时间段2的时间单元.范围:1~8;//tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq//brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1//注意以上参数任何一个都不能设为0,否则会乱.//波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);//mode:0,普通模式;1,回环模式;//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1); //则波特率为:36M/((1+8+7)*5)=450Kbps//返回值:0,初始化OK;// 其他,初始化失败;u8 CAN_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 CAN_RX0_INT_ENABLENVIC_InitTypeDef NVIC_InitStructure;#endifRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA 时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IOGPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化IO//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; //模式设置: mode:0,普通模式;1,回环模式; ////设置波特率CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tqCAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tqCAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tqCAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;////32位IDCAN_FilterInitStructure.CAN_FilterIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASKCAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化#if CAN_RX0_INT_ENABLECAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);#endifreturn 0;}#if CAN_RX0_INT_ENABLE //使能RX0中断//中断服务函数void USB_LP_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 Can_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<8;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 Can_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<8;i++)buf[i]=RxMessage.Data[i];return RxMessage.DLC;}关于CAN总线的滤波等一系列设置可以参考:stm32的can总线的配置如下:????? CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式?????CAN_InitStructure.CAN_ABOM=DISABLE;?????CAN_InitStructure.CAN_AWUM=DISABLE;?????CAN_InitStructure.CAN_NART=DISABLE;//CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失)?????? CAN_InitStructure.CAN_RFLM=DISABLE;????? CAN_InitStructure.CAN_TXFP=DISABLE;?????CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;????? //CAN_Mode_LoopBack????? //CAN_Mode_Normal????? CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;?????CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;//1--16?????CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//1--8?????CAN_InitStructure.CAN_Prescaler=2;????? CAN_Init(&CAN_InitStructure);?????? /* CAN filter init */????? CAN_FilterInitStructure.CAN_FilterNumber=0;//选择过滤器0????? CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//指定过滤器被设置为标识符屏蔽模式?????CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;//给出过滤器位宽为32位?下面根据设置的参数不同来决定can总线can总线的配置情况:1、对扩展数据帧进行过滤:(只接收扩展数据帧)?????CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<3)&0xFFFF0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;(注:标准帧数据帧、标准远程帧和扩展远程帧均被过滤)2、对扩展远程帧过滤:(只接收扩展远程帧)?????CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<3)&0xFFFF0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<3)|CAN_ID_EXT|CAN_RTR_REMOTE)&0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;3、对标准远程帧过滤:(只接收标准远程帧)?????CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<21)&0xffff0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_REMOTE)&0xffff;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;4、对标准数据帧过滤:(只接收标准数据帧)????? CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<21)&0xffff0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<21)|CAN_ID_STD|CAN_RTR_DATA)&0xffff;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFF;5、对扩展帧进行过滤:(扩展帧不会被过滤掉)?????CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<3)&0xFFFF0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<3)|CAN_ID_EXT)&0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFC;6、对标准帧进行过滤:(标准帧不会被过滤掉)????? CAN_FilterInitStructure.CAN_FilterIdHigh?? =(((u32)slave_id<<21)&0xffff0000)>>16;?????CAN_FilterInitStructure.CAN_FilterIdLow?? =(((u32)slave_id<<21)|CAN_ID_STD)&0xffff;?????CAN_FilterInitStructure.CAN_FilterMaskIdHigh? = 0xFFFF;?????CAN_FilterInitStructure.CAN_FilterMaskIdLow?? = 0xFFFC;注:slave_id为要过滤的id 号。