STM32学习笔记(十) CAN通讯测试(环回模式)

发布者:TechGuru123最新更新时间:2019-09-30 来源: eefocus关键字:STM32  CAN通讯测试  环回模式 手机看文章 扫描二维码
随时随地手机看文章

1.CAN通讯的理解

 想学习CAN通讯,那么要对通讯协议有一定的认知。通讯协议是指通信双方对数据传送控制的一种约定。约定中包括对数据格式,同步方式,传输速度,传送步骤,检纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守。 


 CAN通讯全称控制器局域网通讯,是用来在局域网中高效传输,处理信息的一种通讯方式。它采用数据块编码的方式,数据块根据帧类型的不同有四种格式,可使不同的节点接收到相同的数据,然后再根据各节点内CAN配置选择处理还是丢弃该信息(这与TCP/IP协议栈的链路层的MAC地址过滤很相似,是可以互通理解的),CAN的位流是按照非归零(NRZ)码方式编码,一个完整的位电平有显性和隐性两种方式。显性和隐性是根据CAN总线上的差分电压VCAN1H-VCAN1L, 若小于阈值则为隐性位,代表逻辑1,大于阈值则为显性位,代表逻辑0,这种将单电平转换成两根差分线的方式提高了电路的可靠性,不过也决定局域网里同时只能有一路数据传输,因此CAN通讯是半双工的。


2.CAN通讯帧格式

 CAN报文有四种不同的帧类型:

 (1).数据帧:数据帧将数据从发送器传输到接收器。

 数据帧和可以使用标准帧和扩展帧两种格式。它们用一个帧间空间与前面的帧分隔。

       1).帧起始(SOF) 标志帧的开始,由一个“显性(0)”位构成。只有在总线空闲时才允许节点发送(信号),其它所有节点必须同步于首先开始发送报文的节点的帧起始前沿。

     2).仲裁场 由标识符和传送帧类型(RTR)组成的仲裁场

     标准帧格式:

    

    扩展帧格式:

    

           对于数据帧 RTR恒为0,SRR恒为1,因此可以根据仲裁场起始第12个字符数判断是标准帧还是扩展帧。

    3).控制场 保留位R1,R0(恒为0),以及帧长度选择位DLC(4位)构成的。

    4).数据场 由数据帧里的发送数据组成,长度由DLC控制,但小于等于8字节。

    5).CRC场 由CRC序列(CRC Sequence),以及CRC界定符(CRC Delimiter)构成。CRC序列之后是CRC界定符,它包含一个单独的“隐性(1)”位。

    6).应答场(ACK Field) 2位,包含应答间隙(ACK Slot)和应答界定符(ACK Delimiter),当接收器正确地接收到有效的报文,接收器就会在应答间隙(ACK Slot)中写入显性位(0),在返回给发送器,完成一次通讯(半双工).

      ① 应答间隙

     所有接收到匹配CRC序列的节点会在应答间隙期间用“显性(0)”的位写入发送器的“隐性(1)”位来组成应答数据。

      ② 应答界定符

    应答界定符是应答场的第二位,并且必须为“隐性(1)”的位。因此,应答间隙(ACK Slot)被两个“隐性”的位所包围,也就是CRC界定符和应答界定符。

        7).帧结束  由7个隐性位构成,代表帧的结束。

  (2).远程帧:总线节点发出远程帧,请求发送具有同一识别符的数据帧。

          

             远程帧除了RTR位默认为1,没有数据场外,其它与数据帧相同,不在赘述。

  (3).错误帧:报文发送过程中,检测到任一节点出错,即于下一位发送出错帧,通知发送端停止发送。

           

           错误标志:有两种形式的错误标志:激活错误标志和认可错误标志。

    1).激活错误”标志由6个连续的“显性”位组成

    2).“认可错误”标志由6个连续的“隐性”的位组成,除非被其他节点的“显性”位重写。

           错误界定符:错误界定符包括8个“隐性”的位。

    错误标志传送了以后,每一个节点就发送一个“隐性”的位,并一直监视总线直到检测出一个“隐性”的位为止,然后就开始发送其余7个“隐性”位。

 (4).过载帧:接收端用于要求发送端延缓发送下一个数据帧或者远程帧。

          

         1).超载标志: 过载标志由6个“显性”的位组成。过载标志的所有形式和“激活错误”标志的一样

       2).过载界定符包括8个“隐性”的位,具体动作与错误界定符一致

  CAN通讯是数据块编码的半双工通讯方式,没有主从设备区别,因此发出报文的节点为该报文的发送器,该节点在总线空闲或丢失仲裁前恒为发送器;如果一个节点不是报文发送器,并且总线不处于空闲状态,则该节点为接收器。

3.CAN通讯的STM32实现

      CAN协议是比较复杂的一种通讯协议,因此需要在学习如何使用stm32实现前了解协议本身的很多内容,下面就可以开始stm32中CAN协议环回测试,用来简单的理解CAN协议的测试。既然是要STM32实现,那么步骤的设计如下:

   (1).工作原理图

  了解了CAN通讯,下面进入正题,CAN通讯连接首先看原理图如下:

         

      从上面可以看出CAN1_TX: PD1    CAN1_RX PD0

  (2).CAN硬件驱动配置

  CAN通讯端口配置还是比较简单的:


 GPIO_InitTypeDef GPIO_InitStructure;

    

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);

    

 GPIO_InitStructure.GPIO_Pin = CAN1_TX_Pin;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //将CAN1输出端PD1配置为推挽输出模式  

 GPIO_Init(CAN1_TX_Port,&GPIO_InitStructure);    

    

 GPIO_InitStructure.GPIO_Pin = CAN1_RX_Pin;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //将CAN1输入端PD0配置为浮空输入

 GPIO_Init(CAN1_RX_Port, &GPIO_InitStructure);


     CAN通讯模式配置(因为是简单的测试,因此配置为环回模式,过滤器配置为屏蔽位模式)


void CAN1_MODE_Config(void)
{
    CAN_InitTypeDef CAN_InitStructure;                                
    CAN_FilterInitTypeDef CAN_FilterInitStructure;        
    NVIC_InitTypeDef NVIC_InitStructure;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
    CAN_DeInit(CAN1);
    
    CAN_InitStructure.CAN_ABOM = DISABLE;                     //离线模式由软件实现
    CAN_InitStructure.CAN_AWUM = DISABLE;                     //软件唤醒
    CAN_InitStructure.CAN_TTCM = DISABLE;                     //禁止时间触发通信模式
    CAN_InitStructure.CAN_NART = ENABLE;                      //禁止自动重传
    CAN_InitStructure.CAN_TXFP = DISABLE;                     //优先级由报文的标识符来决定
    CAN_InitStructure.CAN_RFLM = DISABLE;                     //接受溢出时FIFO不锁定,下一个收到的报文覆盖原有报文
   CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;           //CAN硬件工作环回模式
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;                  //重新同步跳跃宽度为2个时间单位
    CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq;                  //时间段为8个时间单位
    CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;                  //时间段为7个时间单位
   CAN_InitStructure.CAN_Prescaler = 5;                      //设定一个时间单位的长度为5,范围(1~1024)
    CAN_Init(CAN1, &CAN_InitStructure);
    
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;             //设定过滤器组为屏蔽位模式
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;            //过滤器位宽为32位过滤器一个
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;                          //设定过滤器标识符高位(32为高位段,16位为第一个)
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;                           //设定过滤器标识符低位(32为低位段,16位为第二个)
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0x0000;                       //设定过滤器标识符高位(32为高位段,16位为第一个)
    CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0x0000;                        //设定过滤器标识符低位(32为低位段,16位为第二个)
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;        //过滤器FIFO0指向过滤器0
    CAN_FilterInitStructure.CAN_FilterNumber = 1;                               //指定待初始化的过滤器,范围1~13
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;                      //使能过滤器
    CAN_FilterInit(&CAN_FilterInitStructure);
    
    CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //FIF0消息挂号中断允许
    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;   
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;             //CAN1_RX0中断向量表中开启
    NVIC_Init(&NVIC_InitStructure);
}


完成了驱动方面的配置,下面要进行的就是发送CAN数据和接收CAN数据的生成和实现了:


//CAN发送帧构成

void CAN_TxMessageInit(uint32_t std_id, uint32_t ext_id, uint8_t ide, uint8_t rtr, uint8_t dlc, uint8_t *pdata)

{

    uint8_t i;

    assert_param(dlc>8);      

    CanTxMessage.StdId = std_id&0x7ff; //设定标准标识符0~0x7ff  11位

    CanTxMessage.ExtId = ext_id&0x3ffff; //设定额外标识符0~0x3ffff 18位

    CanTxMessage.IDE = ide; //输出标识符类型,STD(标准标识符)或EXT(额外标识符)

    CanTxMessage.RTR = rtr; //输出帧类型,DATA(数据帧)或者REMOTE(远程帧)

    CanTxMessage.DLC = dlc; //帧长度,0~8

   for(i=0; i    {

        CanTxMessage.Data[i] = *(pdata+i);

    }

}


//CAN中断接收函数

void CAN1_RX0_IRQHandler(void)

{

    ITStatus Status;

    

[1] [2]
关键字:STM32  CAN通讯测试  环回模式 引用地址:STM32学习笔记(十) CAN通讯测试(环回模式)

上一篇:STM32F105 CAN总线数据收发调试
下一篇:stm32f103 学习笔记 —— 07 CAN通讯协议

推荐阅读最新更新时间:2024-11-17 07:26

STM32输入捕获--“PWM输入模式”(可拓展多路同时捕获)
前言 博文基于STM32F103ZET6和标准固件库V3.5.0在MDK5环境下开发; 本博文只讨论输入捕获的PWM输入模式,这个模式是STM32输入捕获检测脉宽和频率的一种硬件处理机制,说白了就是STM32芯片专门用来进行对PWM进行捕获的一个功能;此方法相比较于传统的PWM的捕获方法,大大减小了代码量,提高了检测效率,而实际上对于PWM信号的检测还有其他方法(下面我会介绍,就是原子教程提供的方法),并且关于繁琐的寄存器的介绍这里就不多说了,有兴趣的话可以直接去我的另外一个博客里去看: https://blog.csdn.net/wuyuzun/article/details/73135662 ;(备注:此链接里的博客里有一个配
[单片机]
<font color='red'>STM32</font>输入捕获--“PWM输入<font color='red'>模式</font>”(可拓展多路同时捕获)
STM32 Cubemax(三)——时序读写完成称重传感器+HX711的使用
前言 因为在一个项目中使用到了称重传感器,在此记录一下其使用方法还有一些需要注意的地方。 首先介绍一下使用的传感器 HX711——一款专用于电子秤的A/D转换芯片 称重传感器(使用的这一款量程200KG) 一、接线 买到传感器后,可以看到后面尾巴引出了5条线 **其中黄线在单片机处理里面是不需要的,不需要接。 ** 如果大家买的是我上图的那一款HX711,那么可以直接按照上面的英文指示接线。 照着颜色接就完事了,RED接红线,BLK接黑线。 但还有几款HX711上面没有这个颜色提示,那也没有关系。 一般如下 接完了HX711和称重传感器,下一步就是接HX711和单片机 这里 DAT和CLK为自己
[单片机]
<font color='red'>STM32</font> Cubemax(三)——时序读写完成称重传感器+HX711的使用
stm32使用usart1串口通信以及truestudio重定向printf踩的坑
刚接触stm32,这些天一直被stm32的串口通信困扰,先是收不到数据,后来收到数据了但printf函数不能通过串口发送到上位机。问题来自于多方面,有硬件上的也有软件上的,我在这里总结一下,希望能对大家有帮助避免踩坑。 我使用的是stm32f103rct6的板子,使用hal库在turestudio9.3环境下开发,主机是ubuntu18系统。 硬件问题: 1、有一个usb转ttl线有问题,短接rx和tx后,用cutecom发送和接收的数据会不一致,换成其他线则没问题。 2、usb转ttl线的rx端要接stm32板子的rx端,usb转ttl线的rx端接板子的tx端,我之前刚好是rx-rx、tx-tx,因些收不到数据。
[单片机]
<font color='red'>stm32</font>使用usart1串口通信以及truestudio重定向printf踩的坑
STM32中断没有子优先级?
看到一个交流群在讨论关于【关于STM32中断优先级的话题】,其中就有小伙伴提到:为什么有些STM32中断没有【子优先级】? 比如,有时候你在使用STM32CubeMX配置时,你会发现只有Preemption Priority【抢占优先级】,而没有Sub Priority【次优先级】: 然而,有时候你会发现又有Sub Priority【次优先级】: 这个问题就牵涉到STM32,准确的来说的是 Cortex-M NVIC嵌套向量中断控制器的问题。 下面就展开来说说关于ARM单片机NVIC的内容。 关于Cortex-M的NVIC NVIC:Nested Vectored Interrupt Controller,嵌套向量中断
[单片机]
<font color='red'>STM32</font>中断没有子优先级?
STM32 | MCU错误代码自动追踪库的使用经验分享
大家在用STM32的时候有没有遇到过HardFault的问题呢: 下面针对这个问题做个小总结。 现象还原:在debug模式下进行仿真调试,全速运行再停止运行,程序会跑到 HardFault_Handler函数中,产生 HardFault,即硬错。其产生的原因大概有如下几类: (1)数组越界操作; (2)内存溢出,访问越界; (3)堆栈溢出,程序跑飞; (4)中断处理错误; 针对HardFault问题的定位,网上有几种方法,大概都是围绕着:在debug模式下,查看一些地址,分析寄存器、函数调用栈等,这是很让人头疼的事情。这里分享一种简单的、直观的HardFault错误定位的方法,使用开源库: CmBacktrace 。这
[单片机]
<font color='red'>STM32</font> | MCU错误代码自动追踪库的使用经验分享
STM32 堆和栈知识
简介:堆和栈的区别:stack的空间由操作系统自动分配/释放,heap上的空间手动分配/释放。stack的空间有限,heap是很大的自由存储区。程序在编译期和函数分配内存都是在栈上进行,且程序运行中函数调用时参数的传递也是在栈上进行。 关于堆和栈已经是程序员的一个月经话题,大部分有是基于os层来聊的。 那么,在赤裸裸的单片机下的堆和栈是什么样的分布呢?以下是网摘: 刚接手STM32时,你只编写一个 int main() { while(1); } BUILD://Program Size: Code=340 RO-data=252 RW-data=0 ZI-data=1632 编译后,就会发现这
[单片机]
STM32开发 -- patch生成和使用
领导给我一个.patch文件,“去打一下patch!” emmmm,有点懵。不是说不知道,其实在linux下有用到过的。 参看:如何制作LINUX的patch文件及如何打patch But,那么该如何通过git命令生成Patch和打Patch?? 开始讲解! 一、啥是patch? 首先你的了解一下什么时候patch? 参看:维基百科 – patch 计算机工具补丁(patch)是一个Unix 程序,它根据单独文件(称为补丁文件)中包含的指令更新文本文件。补丁文件(也称为补丁)是一个由差异列表组成的文本文件,通过运行相关的diff程序并将原始和更新的文件作为参数来生成。使用补丁更新文件通常被称为应用补丁或只是修补文件。
[单片机]
基于STM32的单通道示波器制作成功
终于把基于STM32的示波器做出来啦!本来想用外部高速AD做一个1Mhz采样率的示波器,由于自己没有制作示波器经验,手头上也没现成的IC,于是就先利用STM32内部的12位AD做了一个简易示波器,小练一下示波器的制作,以后有时间再继续做一个实用性较强的便携式示波器吧。 该示波器的硬件配置为:3.7V锂电池供电,显示屏为带触摸的16位3.2寸TFT液晶,主控芯片为STM32F103VC。为了省事,信号触发采用软件触发,幅值、周期、XY轴偏移都是通过触控屏来设置。(由于宿舍没有函数发生器,下面演示图片中的波形是由LM358搭出来的简易信号发生器,波形非常不规则) 下为示波器的实物图(后面那块小小的东西为简陋的波形发生器):
[单片机]
基于<font color='red'>STM32</font>的单通道示波器制作成功
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多每日新闻

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved