【嵌入式】HC32F07X CAN通讯配置和使用

目录

一 背景说明

二 原理分析

三 CAN通讯硬件设计

四 CAN通讯软件配置

五 CAN通讯测试


一 背景说明

        使用小华(华大)的MCU HC32F07X实现 CAN 通讯配置和使用

二 原理分析

【1】CAN原理说明(参考文章《CAN通信详解》):

        CAN是控制器局域网络(Controller Area Network, CAN)的简称,是一种能够实现分布式实时控制的串行通信网络。

        (i)CAN通信形式:CAN 使用称为 CANH / CANL 的通信线路执行传输和接收。电位差较小的电信号称为隐性信号,其逻辑值为1。电位差较大的电信号称为显性信号,其逻辑值0。如果通信总线上发生显性和隐性冲突,则显性优先。总线空闲时保持隐性。

        (ii)CAN数据格式:CAN的数据定义了有5种帧类型:

        (ii)CAN数据帧:数据帧一般由 7 个段构成,即:

(1) 帧起始。表示数据帧开始的段。
(2) 仲裁段。表示该帧优先级的段。
(3) 控制段。表示数据的字节数及保留位的段。
(4) 数据段。数据的内容,一帧可发送 0~8 个字节的数据。
(5) CRC 段。检查帧的传输错误的段。
(6) ACK 段。表示确认正常接收的段。
(7) 帧结束。表示数据帧结束的段

        图中 D 表示显性电平, R 表示隐形电平。

        更多具体内容不再赘述,可以参考上面的文章链接或者自行搜索。

【2】HC32F07X的CAN外设

        芯片CAN外设的主要特性:

■ 完全支持 CAN2.0A/CAN2.0B 协议。
■ 向上兼容 CAN-FD 协议。
■ 支持最高通信波特率 1Mbit/s
■ 支持 1~1/256 的波特率预分频, 灵活配置波特率。
■ 10 个接收缓冲器
- FIFO 方式
- 错误或者不被接收的数据不会覆盖存储的消息
■ 1 个高优先主发送缓冲器 PTB
■ 4 个副发送缓冲器 STB
- FIFO 方式
- 优先级仲裁方式
■ 8 组独立的筛选器
- 支持 11 位标准 ID 和 29 位扩展 ID
- 可编程 ID CODE 位以及 MASK 位
■ PTB/STB 均支持支持单次发送模式
■ 支持静默模式
■ 支持回环模式
■ 支持捕捉传输的错误种类以及定位仲裁失败位置
■ 可编程的错误警告值
■ 支持 ISO11898-4 规定时间触发 CAN 以及接收时间戳

        系统框图如下:

        更多详细的内容可以参考HC32F07X芯片的DATASHEET。

三 CAN通讯硬件设计

        以下推荐了两个CAN收发的硬件电路,可以将外部的 CANH/CANL 差分信号,转换为 CAN_TX/CAN_RX 信号用以内部MCU处理。一个是官方提供的,一个是开发板提供的,都可以正常使用。

        注意CAN通信需要5V,用以给收发器供电

【1】推荐电路1

        参考官方的硬件设计指南《AN_HC32L072_HC32L073_HC32F072系列硬件开发指南_Rev1.1》,里面对于CAN通信收发的硬件电路有如下推荐电路,其中使用了NXP的 TJA1042 作为收发器

【2】推荐电路2

        使用的周立功开发板中也引出了CAN功能,其中使用了NXP的TJA1051T作为收发器

四 CAN通讯软件配置

        选用引脚 PD00(CAN_RX)、PD01(CAN_TX)、PC12(CAN_STB)实现CAN通信功能,使用时钟频率为48MHz(官方例程使用的是外部8M晶振),CAN通讯波特率为1M,标准帧ID号为1。

【1】系统时钟配置

static void App_SysClkInit(void)
{stc_sysctrl_clk_cfg_t stcCfg;stc_sysctrl_pll_cfg_t stcPLLCfg;Sysctrl_SetPeripheralGate(SysctrlPeripheralFlash, TRUE);    ///< 使能FLASH模块的外设时钟Flash_WaitCycle(FlashWaitCycle1);Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz);             ///< PLL使用RCH作为时钟源,因此需要先设置RCHstcPLLCfg.enInFreq    = SysctrlPllInFreq4_6MHz;     ///< RCH 4MHzstcPLLCfg.enOutFreq   = SysctrlPllOutFreq36_48MHz;  ///< PLL 输出48MHzstcPLLCfg.enPllClkSrc = SysctrlPllRch;              ///< 输入时钟源选择RCHstcPLLCfg.enPllMul    = SysctrlPllMul12;            ///< 4MHz x 12 = 48MHzSysctrl_SetPLLFreq(&stcPLLCfg);///< 选择PLL作为HCLK时钟源;stcCfg.enClkSrc  = SysctrlClkPLL;///< HCLK SYSCLK/2stcCfg.enHClkDiv = SysctrlHclkDiv1;///< PCLK 为HCLK/8stcCfg.enPClkDiv = SysctrlPclkDiv1;///< 系统时钟初始化Sysctrl_ClkInit(&stcCfg);
}

【2】CAN初始化GPIO

//CAN通信引脚定义
#define CAN_RX_PORT     (GpioPortD)
#define CAN_RX_PIN      (GpioPin0)
#define CAN_TX_PORT     (GpioPortD)
#define CAN_TX_PIN      (GpioPin1)
#define CAN_STB_PORT    (GpioPortC)
#define CAN_STB_PIN     (GpioPin12)#define  APB1_CLK       48000000    //CAN 的输入时钟
#define  CAN_BAUD       1000000     //CAN 的波特率/**************************************************************************
* 函数名称: COM_Init
* 功能描述: CAN通信初始化GPIO
**************************************************************************/
void COM_Init(void)
{stc_gpio_cfg_t stcGpioCfg;Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);stcGpioCfg.enDir = GpioDirIn;       ///< 端口方向配置->输入stcGpioCfg.enDrv = GpioDrvL;        ///< 端口驱动能力配置->高驱动能力stcGpioCfg.enPu  = GpioPuDisable;   ///< 端口上下拉配置->无stcGpioCfg.enPd  = GpioPdDisable;stcGpioCfg.enOD  = GpioOdDisable;   ///< 端口开漏输出配置->开漏输出关闭stcGpioCfg.enCtrlMode = GpioAHB;    ///< 端口输入/输出值寄存器总线控制模式配置->AHBGpio_Init(CAN_RX_PORT, CAN_RX_PIN, &stcGpioCfg);stcGpioCfg.enDir = GpioDirOut;Gpio_Init(CAN_TX_PORT, CAN_TX_PIN, &stcGpioCfg);Gpio_Init(CAN_STB_PORT, CAN_STB_PIN, &stcGpioCfg);///<CAN RX\TX复用功能配置Gpio_SetAfMode(CAN_RX_PORT, CAN_RX_PIN, GpioAf1);Gpio_SetAfMode(CAN_TX_PORT, CAN_TX_PIN, GpioAf1);///<STB 低-PHY有效Gpio_ClrIO(CAN_STB_PORT, CAN_STB_PIN);
}

【3】CAN波特率自适应配置接口

/**************************************************************************
* 函数名称: COM_BaudCfg
* 功能描述: CAN通信波特率自动配置
* 其他说明: 48MHz主频,1M波特率计算得到:SJW=2, PRESC=1-1, SEG_2=15, SEG_1=30若输入500K波特率,PRESC为2-1; 输入250K波特率,PRESC为4-1
**************************************************************************/
void COM_BaudCfg(stc_can_init_config_t *p_stcCanInitCfg, uint32_t src_clk, uint32_t baud)
{uint32_t i,value = baud,record = 1;uint32_t remain = 0,sum_prescaler = 0;while(( baud == 0 )||( src_clk == 0 ));sum_prescaler = src_clk / baud;for ( i = 73; i > 3; i-- ) {remain = sum_prescaler - ((sum_prescaler / i)*i);if( remain == 0 ) {record = i;break;} else {if (remain < value) {value = remain;record = i;}}}/* 设置重新同步跳跃宽度为2个时间单位 */p_stcCanInitCfg->stcCanBt.SJW = 2;p_stcCanInitCfg->stcCanBt.PRESC = (sum_prescaler/record) - 1;p_stcCanInitCfg->stcCanBt.SEG_2 = (record - 3) / 3;p_stcCanInitCfg->stcCanBt.SEG_1 = (record - 3) - p_stcCanInitCfg->stcCanBt.SEG_2;
}

【4】CAN初始化配置(其中,波特率配置为1M,滤波器配置标准帧ID为1

/**************************************************************************
* 函数名称: COM_Cfg
* 功能描述: CAN通信初始化配置
**************************************************************************/
void COM_Cfg(void)
{stc_can_init_config_t   stcCanInitCfg;stc_can_filter_t        stcFilter;Sysctrl_SetPeripheralGate(SysctrlPeripheralCan, TRUE);///<CAN 波特率配置COM_BaudCfg(&stcCanInitCfg, APB1_CLK, CAN_BAUD);    //48MHz主频,1M波特率stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 16-1;stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 10;stcCanInitCfg.enCanRxBufAll  = CanRxNormal;stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;CAN_Init(&stcCanInitCfg);///<CAN 滤波器配置stcFilter.enAcfFormat = CanAllFrames;stcFilter.enFilterSel = CanFilterSel1;stcFilter.u32CODE     = 0x00000001;stcFilter.u32MASK     = 0x1FFFFFFF;CAN_FilterConfig(&stcFilter, TRUE);CAN_IrqCmd(CanRxIrqEn, TRUE);EnableNvic(CAN_IRQn, IrqLevel0, TRUE);
}

【5】CAN中断服务子程序(用于CAN接收)

stc_can_rxframe_t       stcRxFrame;
stc_can_txframe_t       stcTxFrame;
uint8_t                 u8RxFlag = FALSE;/**************************************************************************
* 函数名称: Can_IRQHandler
* 功能描述: CAN中断服务函数
**************************************************************************/
void Can_IRQHandler(void)
{if(TRUE == CAN_IrqFlgGet(CanRxIrqFlg)){CAN_IrqFlgClr(CanRxIrqFlg);CAN_IrqCmd(CanRxIrqEn, FALSE);CAN_Receive(&stcRxFrame);u8RxFlag = TRUE;}
}

【6】CAN发送接口(用于CAN发送)

/**************************************************************************
* 函数名称: COM_Tx
* 功能描述: CAN通信发送测试
**************************************************************************/
void COM_Tx(void)
{//中断接收,循环发送uint8_t u8Idx = 0;if(TRUE == u8RxFlag){u8RxFlag = FALSE;if(1 == stcRxFrame.Cst.Control_f.RTR){return;}//<<Can TxstcTxFrame.StdID         = stcRxFrame.StdID;stcTxFrame.Control_f.DLC = stcRxFrame.Cst.Control_f.DLC;stcTxFrame.Control_f.IDE = stcRxFrame.Cst.Control_f.IDE;stcTxFrame.Control_f.RTR = stcRxFrame.Cst.Control_f.RTR;for(u8Idx=0; u8Idx<stcRxFrame.Cst.Control_f.DLC; u8Idx++){stcTxFrame.Data[u8Idx] = stcRxFrame.Data[u8Idx];}CAN_SetFrame(&stcTxFrame);CAN_TransmitCmd(CanPTBTxCmd);CAN_IrqCmd(CanRxIrqEn, TRUE);}
}

【7】主函数调用

int32_t main(void)
{//系统时钟App_SysClkInit();//通信模块COM_Init();COM_Cfg();while(1){//通信COM_Tx();delay1ms(10);}
}

五 CAN通讯测试

        进行CAN测试的方法很多,如果没有USB-CAN通信转换工具/CAN协议分析工具,可以增加CAN外部回环或者内部回环的配置,配合Log串口输出或者仿真器Debug进行测试。我这边使用了USB-CAN通信转换工具(CAN-II)/CAN协议分析工具(CANTest)直接进行收发测试:

【1】选择 CANTest 中的对应设备 USBCAN2:

【2】匹配软件中的波特率为1M,确定并启动CAN:

【3】修改帧ID为1,点击发送,可以看到上位机发送数据到测试板,经由测试板返回相同长度及内容的数据

        以上配置及测试成功。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/155019.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux】centos安装配置及远程连接工具的使用

【Linux】centos安装配置及远程连接工具的使用 1.使用vmware创建虚拟机&#xff0c;因为过程比较简单就没有截图了&#xff0c;根据下面步骤来就行。2.网络配置3.MobaXterm连接CentOS1.new session2.点击ssh&#xff0c;输入虚拟机的IP地址即可 4.进行阿里云换源1.进入2.下载wg…

一年时间如何能掌握 C++ ?

一年时间如何能掌握 C &#xff1f; 建议不要把掌握c作为一个一年的目标。 C的外延太广&#xff0c;就是应用领域、面向对象、设计模式等等。C语法和标准库本身是有限的。 最近很多小伙伴找我&#xff0c;说想要一些C资料&#xff0c;然后我根据自己从业十年经验&#xff0c;…

二叉树问题——对称二叉树

摘要 101. 对称二叉树 一、对称二叉树解析 1.1 递归思路分析 首先想清楚&#xff0c;判断对称二叉树要比较的是哪两个节点&#xff0c;要比较的可不是左右节点&#xff01;对于二叉树是否对称&#xff0c;要比较的是根节点的左子树与右子树是不是相互翻转的&#xff0c;理解…

3ds Max2022安装教程(最新最详细)

目录 一.简介 二.安装步骤 网盘资源见文末 一.简介 3DS Max是由Autodesk公司开发的一款专业三维建模、动画和渲染软件&#xff0c;广泛应用于影视、游戏、建筑和工业设计等领域。 3DS Max的主要特点和功能包括&#xff1a; 三维建模&#xff1a;3DS Max提供了各种强大的建…

关于c++unique后会打乱顺序

这为什么加上注释这三行输出就会多个4 5 吗 还是a已经发生了变化? 疑问? 解决: unique要求容器有序&#xff0c;而且执行完以后会把重复的放在后面 因为unique后可能无序所以要排序一下,代码如下 。 源代码 #include <iostream> #include <algorithm> #…

C++前缀和算法的应用:预算内的最多机器人数目

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 单调双向队列 滑动窗口 题目 你有 n 个机器人&#xff0c;给你两个下标从 0 开始的整数数组 chargeTimes 和 runningCosts &#xff0c;两者长度都为 n 。第 i 个机器…

Java进阶(List)——面试时List常见问题解读 结合源码分析

前言 List、Set、HashMap作为Java中常用的集合&#xff0c;需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中List集合的面试问题&#xff0c;结合源码分析题目背后的知识点。 关于的Set的博客文章如下&#xff1a; Java进阶&#xff08;Set&#xff09;——面试时…

【C语言_题库】C语言:编写一个程序,输入一组字符串,将字符串中的小写字母转换为大写字母,其它字符不变,并输出。

把键盘输入的一行字符串的小写字母转换成大写字母,其余字符不变,进行输出,直到遇到回车为止。 具体说明 【问题描述】 从键盘输入一行英文字符串,把所有小写字母变成大写字母,其他字母和字符保持不变。 【输入形式】 输入一行字符串,含大小写。 【输出形式】 输出大写字…

linux后台运行python脚本

前言 我们在运行程序时&#xff0c;有的程序花费时间较多&#xff0c;但我们总不能一直看着程序运行&#xff0c;所以我在这里记录一下&#xff0c;Linux服务器如何后台运行我们的脚本程序 实现后台运行程序 我们登录到服务器&#xff0c;切换至目录到我们所要运行的程序下 …

弱覆盖栅格图层制作

栅格边界生成及图层制作 栅格边界polygon生成 提取的弱覆盖栅格数据中包含了栅格中心经度和栅格中心维度&#xff0c;我们根据栅格中心经纬度生成对应的栅格边界POLYGON&#xff08;20米*40米&#xff09; 计算公式&#xff1a;polygon(栅格中心经度-0.00017 栅格中心纬度0.00…

自主查询成绩

今天我们来揭秘如何制作成绩查询系统&#xff0c;让学生可以自行查看成绩&#xff01; 成绩查询系统可以帮助学生和老师轻松管理、发布、查看成绩。无论是期中考试、期末考试&#xff0c;作业查询还是平时的课堂表现&#xff0c;都可以通过成绩查询系统来及时掌握。 让我们一起…

qt-gui

C常用GUI开发框架Qt&#xff0c;开始支持Python 2018-12-24 12:49 C的GUI接口开发框架Qt宣布&#xff0c;在5.12版本中开始支持Python&#xff0c;Python开发人员现在可以使用所有的Qt API&#xff0c;目前仍在技术预览版的阶段&#xff0c;但官方也承诺&#xff0c;正式版将…