第四章-CAN通信-CAN协议解析 CAN协议报文dbc解析实例 hal库例程 CAN总线协 ...

打印 上一主题 下一主题

主题 562|帖子 562|积分 1686

第四章-CAN通信

4.3-实际编程

4.3.1-回环测试

软件初始化设置

CAN频率相干设置

打开接收中断

为了方便调试,我们初始化一下串口-PA9 PA10

添加一下重映射

  1. /**
  2. * @brief 重定向printf (重定向fputc),
  3.                                         使用时候记得勾选上魔法棒->Target->UseMicro LIB
  4.                                         可能需要在C文件加typedef struct __FILE FILE;
  5.                                         包含这个文件#include "stdio.h"
  6. * @param
  7. * @return
  8. */
  9. int fputc(int ch,FILE *stream)
  10. {
  11.         HAL_UART_Transmit(&huart1,( uint8_t *)&ch,1,0xFFFF);
  12.         return ch;
  13. }
复制代码
添加一些头文件

  1. #include "main.h"
  2. #include "gpio.h"
  3. #include "can.h"
  4. #include "usart.h"
  5. #include "bsp_CAN.h"
  6. #include "stdio.h"
复制代码
还有MDK的设置

我们先编程发送功能相干配置和函数
新建bsp_CAN.c和bsp_CAN.h文件
bsp_CAN.c内容
  1. //uint8_t CAN_SendData[8] = {1,2,3,4,5,6,7,8};//发送的八个字节数组
  2. uint8_t CAN_SendData[8] = "1234567";//发送的八个字符
  3. uint8_t CAN_RecData[8] = {0};//接收的缓冲区
  4. uint8_t CAN_RxFlag = 0;//CAN消息接收标志位,1-表示为接收到正确ID的消息,0-表示未接收到正确ID消息
复制代码
bsp_CAN.c内容
  1. /*******************
  2. *  @brief  CAN过滤器设置、接收使能、启动CAN
  3. *  @param  
  4. *  @return  
  5. *
  6. *******************/
  7. void CAN_Config(void)
  8. {
  9.         CAN_FilterTypeDef CAN_Filter;//定义一个CAN过滤器结构体
  10.        
  11.         //设定CAN过滤器参数
  12.         CAN_Filter.FilterBank = 0;//配置过滤器0
  13.         CAN_Filter.FilterScale = CAN_FILTERSCALE_16BIT;//16位过滤器
  14.         CAN_Filter.FilterMode = CAN_FILTERMODE_IDMASK;//标识符屏蔽模式
  15.         //这里不做任何过滤,所以设置都是00
  16.         CAN_Filter.FilterIdLow = 0x00;  //这是FR1的设置
  17.         CAN_Filter.FilterMaskIdLow = 0X00;
  18.         CAN_Filter.FilterIdHigh = 0X00;                //这是FR2的设置
  19.         CAN_Filter.FilterMaskIdHigh = 0x00;
  20.        
  21.         CAN_Filter.FilterFIFOAssignment = CAN_RX_FIFO0;//过滤器关联到FIFO
  22.         CAN_Filter.FilterActivation = ENABLE;//设置过滤器0、
  23.         CAN_Filter.SlaveStartFilterBank = 14;
  24.        
  25.         HAL_CAN_ConfigFilter(&hcan, &CAN_Filter);//配置过滤器
  26.        
  27.         //使能FIFO接收到新的报文中断
  28.         HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);
  29.        
  30.         //启动CAN,这个不能少
  31.         HAL_CAN_Start(&hcan);
  32. }
复制代码
bsp_CAN.c内容
  1. /*******************
  2. *  @brief  发送CAN报文设置
  3. *  @param  
  4. *  @return  
  5. *
  6. *******************/
  7. void CAN_SetMsg(void)
  8. {
  9.         uint32_t  TxMailBox;//暂存HAL_CAN_AddTxMessage 函数使用那个邮箱进行发送的
  10.    CAN_TxHeaderTypeDef CAN_TxHeader;
  11.    CAN_TxHeader.StdId = 0X88;   //这是标准标识符
  12.    CAN_TxHeader.ExtId = 0x00;   //设置扩展标识符,并没有使用
  13.    CAN_TxHeader.IDE = CAN_ID_STD;//设置标识符为标准帧模式
  14.    CAN_TxHeader.RTR = CAN_RTR_DATA;//设置消息的帧类型为数据帧
  15.    CAN_TxHeader.DLC = 8;//设置要传送的帧长度 为8 字节(就是数据段有多少字节)
  16.    
  17.    //通过邮箱发送数据
  18.    HAL_CAN_AddTxMessage(&hcan,&CAN_TxHeader,CAN_SendData,&TxMailBox);
  19.    
  20. }
复制代码
然后在bsp_CAN.h中声明一下
  1. void CAN_Config(void);//设置过滤器和其他设置的激活
  2. void CAN_SetMsg(void);//这个是设置发送器
复制代码
我们要在main.c中使用下面变量就先声明,一下
  1. extern uint8_t CAN_RxFlag ;   //接收标识位
  2. extern uint8_t CAN_SendData[8] ;//发送的八个字节数组
  3. extern uint8_t CAN_RecData[8];//接收的缓冲区
复制代码
初始化加上

  1.   CAN_Config();//CAN过滤器设置、接收使能、启动CAN
复制代码
然后main的循环时如许的
  1.   while (1)
  2.   {
  3.     /* USER CODE END WHILE */
  4.     /* USER CODE BEGIN 3 */
  5.         HAL_Delay(500);
  6.         HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
  7.         CAN_SetMsg();
  8.         if(CAN_RxFlag == 1){
  9.                 CAN_RxFlag = 0;
  10.                 printf("发送的是:%s\r\n",CAN_SendData);       
  11.                 printf("接收的是:%s\r\n",CAN_RecData);       
  12.         }
  13.         else printf("没有接收,没有发送\r\n");       
  14.        
  15.   }
复制代码
打开串口助手,波特率115200

上面我们测试的环回模式,数据是发送回被自己收到,而且也发送到外面,但是自己不能收别人的

以是我们可以用逻辑分析仪测试一下
这里说逻辑分析仪测试CAN的方法

  • 接线
    CAN模块按要求供电
    单片机PA11是CAN_RX—>CAN模块的CAN_RX
    单片机PA12是CAN_TX—>CAN模块的CAN_TX
    ​ CAN模块的CAN_H—>逻辑分析仪通道0
    ​ CAN模块的CAN_L—>逻辑分析仪GND
  • 然后设置CAN上位机
    采样率一定要高,最高CAN速率1Mbps我们刚才软件初始化的是500Kbps 我们设置分析仪20MHz 够用了。

  • 然后就可以开启单片机,让后逻辑分析仪单次采样

4.3.2-环回模式和筛选器

我们把CAN设置环回模式

我们主要更改CAN筛选器设置、
标识符屏蔽–ID是设置要频闭的ID、然后通过标识符掩码指定对应位相等完成屏蔽。
标识符列表–就是设置可以通过的白名单,必须与设置ID完全相等才可以通过

下面是具体设置位置
下面的第三步一定要注意!!!

  1. uint8_t CAN_RxFlag = 0;//CAN消息接收标志位,1-表示为接收到正确ID的消息,0-表示未接收到正确ID消息
  2. #define PASS_ID  ((uint32_t)0X89)   //接收过滤ID,因为我们是标准帧格式所以数值0X0-0X7FF之间
复制代码
  1. void CAN_Config(void)
  2. {
  3.         CAN_FilterTypeDef CAN_Filter;//定义一个CAN过滤器结构体
  4.         //设定CAN过滤器参数
  5.         CAN_Filter.FilterBank = 0;//配置过滤器0
  6.         CAN_Filter.FilterScale = CAN_FILTERSCALE_16BIT;//16位过滤器
  7.         CAN_Filter.FilterMode = CAN_FILTERMODE_IDMASK;//标识符屏蔽模式
  8.         //使能筛选器,硬件控制器回按照筛选器内容进行对比筛选,不满足消息就会丢弃,满足存入FIFO中
  9.         //这里设置过滤
  10.         CAN_Filter.FilterIdHigh = (PASS_ID <<5)|CAN_RTR_DATA|CAN_ID_STD;        //这是设置第一个16位筛选器ID
  11.         CAN_Filter.FilterMaskIdHigh = 0xFF;                              //这是设置第一个16位筛选器掩码
  12.        
  13.         CAN_Filter.FilterIdLow = 0XFF;      //第二个16位筛选器ID
  14.         CAN_Filter.FilterMaskIdLow = 0XFF;  //第二个16位筛选器掩码必须是FF,如果是00 任何ID都会通过筛选
  15.        
  16.         CAN_Filter.FilterFIFOAssignment = CAN_RX_FIFO0;//过滤器关联到FIFO
  17.         CAN_Filter.FilterActivation = ENABLE;//设置过滤器0、
  18.         CAN_Filter.SlaveStartFilterBank = 14;
  19.        
  20.         HAL_CAN_ConfigFilter(&hcan, &CAN_Filter);//配置过滤器
  21.         //使能FIFO接收到新的报文中断
  22.         HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);
  23.         //启动CAN,这个不能少
  24.         HAL_CAN_Start(&hcan);
  25. }
复制代码
我们可以先测试设置过滤器ID不是我们发送的

然后编译烧录,发现单片机没有收到,阐明成功了

我们更改为0x88就可以正常收到消息了
  1. #define PASS_ID  ((uint32_t)0X88)   //接收过滤ID,因为我们是标准帧格式所以数值0X0-0X7FF之间
复制代码
4.3.3-正常模式-双机通信




设备1 单片机主要发送


设备2单片机接收


这是接线方法

然后串口软件接设备2单片机

我们的IAP.c内容如下
  1. /* Includes ------------------------------------------------------------------*/
  2. #include "MyApp.h"
  3. /* Private define-------------------------------------------------------------*/
  4. /* Private variables----------------------------------------------------------*/
  5. /* Public variables-----------------------------------------------------------*/
  6. /* Private function prototypes------------------------------------------------*/      
  7. /*******************
  8. *  @brief  这是 C语言内嵌汇编
  9. //MSR MSP, r0 意思是将r0寄存器中的值加载到MSP(主栈寄存器,
  10. //复位时默认使用)寄存器中,r0中保存的是参数值,即addr的值
  11. //BX r14 跳转到连接寄存器保存的地址中,即退出函数,跳转到函数调用地址
  12. *  @param  
  13. *  @return  
  14. *
  15. *******************/
  16. __asm void MSR_MSP (uint32_t ulAddr)
  17. {
  18.         MSR MSP,r0 //set Main Stack value
  19.         BX r14
  20. }
  21. /*******************
  22. *  @brief  跳转到应用程序
  23. *  @param  ulAddr_App:应用程序的起始端地址
  24. *  @return  
  25. *
  26. *******************/
  27. void IAP_ExecuteApp(uint32_t ulAddr_App)
  28. {
  29.         void (*pFunApp)(void);//定义一个函数指针
  30.        
  31.         //检查栈顶地址是否合法
  32.         //if(((*(__IO uint32_t*)ulAddr_App) & 0x2FFE0000) == 0x20000000)       
  33.         if(((*(__IO uint32_t *)ulAddr_App) & 0x2FFF5000) == 0x20000000)
  34.         {
  35.                 printf("地址合法开始跳转\r\n");
  36.                 pFunApp = (iapfun) *(__IO uint32_t *)(ulAddr_App + 4); //赋值函数指针、指向新APP的复位中断函数地址
  37.                 MSR_MSP(*(__IO uint32_t *)ulAddr_App);                                        //初始化APP堆栈指针,对APP程序的堆栈进行重构,就是重新分配RAM
  38.                 pFunApp();                            //执行APP的复位中断函数,最终便会跳转到APP的main函数
  39.         }
  40.         else
  41.         {
  42.                 printf("地址不合法\r\n");
  43.                 //错误栈顶地址不合法!
  44.         }
  45. }
  46. /********************************************************
  47.   End Of File
  48. ********************************************************/
复制代码
我们的IAP.h
  1. #ifndef  __IAP_H_
  2. #define  __IAP_H_
  3. /* Includes ------------------------------------------------------------------*/
  4. #include "main.h"
  5. #include "gpio.h"
  6. typedef void (* iapfun)(void);     //定义一个函数指针(指向一个返回为空形参为空的函数)
  7. #define APP_Start                        FLASH_BASE+0x400          //这是APP开始位置
  8. void IAP_ExecuteApp(uint32_t ulAddr_App);
  9. #endif
  10. /********************************************************
  11.   End Of File
  12. ********************************************************/
复制代码




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张裕

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表