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

news2024/9/20 2:06:56

目录

一 背景说明

二 原理分析

三 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作为时钟源,因此需要先设置RCH

    stcPLLCfg.enInFreq    = SysctrlPllInFreq4_6MHz;     ///< RCH 4MHz
    stcPLLCfg.enOutFreq   = SysctrlPllOutFreq36_48MHz;  ///< PLL 输出48MHz
    stcPLLCfg.enPllClkSrc = SysctrlPllRch;              ///< 输入时钟源选择RCH
    stcPLLCfg.enPllMul    = SysctrlPllMul12;            ///< 4MHz x 12 = 48MHz
    Sysctrl_SetPLLFreq(&stcPLLCfg);

    ///< 选择PLL作为HCLK时钟源;
    stcCfg.enClkSrc  = SysctrlClkPLL;
    ///< HCLK SYSCLK/2
    stcCfg.enHClkDiv = SysctrlHclkDiv1;
    ///< PCLK 为HCLK/8
    stcCfg.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;    ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    Gpio_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 Tx
        stcTxFrame.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.coloradmin.cn/o/1153749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 puppeteer 库采集豆瓣音频简单代码示例

今天要给大家分享的采集代码&#xff0c;主要是使用 puppeteer 库进行编写的&#xff0c;用于采集豆瓣网相关音频。这段代码也是非常的简单实用&#xff0c;一起来看看吧。 // 引入 puppeteer 库 const puppeteer require(puppeteer);// 定义获取代理服务器的函数 function …

针灸养生服务预约小程序的效果如何

针灸服务的市场需求度很高&#xff0c;每个城市中都有不少相关品牌&#xff0c;对商家来说&#xff0c;如何引流拓客、打造品牌是生意开展的首要条件之一&#xff0c;且主要以同城用户为主&#xff0c;或连锁情况下为各店引流&#xff0c;但传统线下模式很难实现生意拓展。 那…

蓝桥杯每日一题2023.10.31

题目描述 全球变暖 - 蓝桥云课 (lanqiao.cn) 题目分析 果然有关连通块类的问题使用dfs都较为好写~~ 我们可以通过判断连通块的代码来加上部分条件算出被完全淹没的岛屿个数 在岛屿中如果有为"#"的a[i][j]上下左右全部是"#"则说明此岛屿一定不会被完全…

2023年【低压电工】找解析及低压电工模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 低压电工找解析是安全生产模拟考试一点通生成的&#xff0c;低压电工证模拟考试题库是根据低压电工最新版教材汇编出低压电工仿真模拟考试。2023年【低压电工】找解析及低压电工模拟考试 1、【单选题】()仪表可直接用…

VIVO应用商店评论数据抓取

VIVO应用商店的app评论数据抓取 每个应用的评论能获取到最新的 100页 数据 每页20条&#xff0c;也就是 2000条评论数据 接口&#xff1a; pl.appstore.vivo.com.cn/port/comments/ 爬取运行截图&#xff1a;

嵌入式应用选择正确的系统设计方法:第二部分

在设计嵌入式系统之前&#xff0c;我们需要知道我们在设计什么。在这种情况下&#xff0c;术语“要求”和“规范”以多种方式使用-有些人将它们用作同义词&#xff0c;而另一些人将它们用作不同的阶段。它们在这里用来表示设计过程中相关但截然不同的步骤。 需求 是对客户需求…

Leaflet地图工具

2023 年 5 月 18 日 — Leaflet 1.9.4 正式发布! Leaflet 是一个开源并且对移动端友好的交互式地图 JavaScript 库。 它大小仅仅只有 42 KB of JS, 并且拥有绝大部分开发者所需要的所有地图特性 。 Leaflet 简单、高效并且易用。 它可以高效的运行在桌面和移动平台, 拥有着大…

[Machine Learning][Part 7]神经网络的基本组成结构

这里我们将探索神经元/单元和层的内部工作原理。特别是,与之前学习的回归/线性模型和逻辑模型进行比较。最后接介绍tensorflow以及如何利用tensorflow来实现这些模型。 神经网络和大脑的神经元工作原理类似&#xff0c;但是比大脑的工作原理要简单的多。大脑中神经元的工作原理…

Ajax学习笔记第6天--COOKIE

放弃该放弃的是无奈&#xff0c;放弃不该放弃的是无能&#xff0c;不放弃该放弃的是无知&#xff0c;不放弃不该放弃的是执着&#xff01; 【1. cookie】 1.Cookie机制 而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕&#xff0c;客户端与…

python爬虫,如何在代理的IP被封后立刻换下一个IP继续任务?

前言 在实际的爬虫应用中&#xff0c;爬虫程序经常会通过代理服务器来进行网络访问&#xff0c;以避免访问过于频繁而受到网站服务器的限制。但是&#xff0c;代理服务器的IP地址也可能被目标网站限制&#xff0c;导致无法正常访问。这时候&#xff0c;我们需要在代理IP被封后…

聚观早报 |华为nova 11 SE登场;vivo Y100正式发布

【聚观365】10月31日消息 华为nova 11 SE登场 vivo Y100正式发布 PTC Arena落地中国 2023财年苹果印度业务营收 iQOO 12外观设计揭晓 华为nova 11 SE登场 半年前&#xff0c;华为发布了nova 11系列手机&#xff0c;以“敢拍&#xff0c;敢出色”为宣传口号&#xff0c;继…

Variations-of-SFANet-for-Crowd-Counting代码复现

前文对Variations-of-SFANet-for-Crowd-Counting做了一点基础梳理&#xff0c;并对开源框架的可视化代码进行了验证&#xff0c;链接如下&#xff1a; Variations-of-SFANet-for-Crowd-Counting记录-CSDN博客 Variations-of-SFANet-for-Crowd-Counting可视化代码-CSDN博客 这…

数字时代新趋势:TikTok算法与海外网红营销的融合策略

在当今数字化时代&#xff0c;社交媒体已经成为品牌推广和市场营销的重要渠道。TikTok作为全球范围内最受欢迎的短视频平台之一&#xff0c;以其独特的算法和用户参与度&#xff0c;正日益成为海外网红营销的热门选择。本文Nox聚星将和大家探讨TikTok算法和海外网红营销之间的融…

五种UI设计师的必备界面设计工具,干货来袭!

工具的重要性对设计师来说是不言而喻的。任何想法都需要通过工具来实现。要成为一名优秀的UI设计师&#xff0c;你需要掌握更多的技能来增强你的竞争力。同时&#xff0c;我们也给那些想成为UI设计师的朋友一些工具建议。接下来&#xff0c;让我们来看看那些UI设计师需要掌握的…

AUTOSAR CAN协议栈架构总览介绍

Classic AUTOSAR层级架构简介 如下图是Classic AUTOSAR层级架构图,每个层主要功能如下 微控制器抽象层:使上层软件和微处理器型号无关,包含MCU中内部外设的驱动以及MCU内存映射的外部设备的驱动ECU抽象层:使上层软件和ECU硬件设计无关,包含ECU板上外部设备的驱动以及内部…

已解决WARNING: You are using pip version 20.1.1:however,version 22.3.1 is available.

成功解决&#xff08;pip提示升级&#xff09;&#xff1a;已解决WARNING: You are using pip version 20.1.1&#xff1a;however&#xff0c;version 22.3.1 is available. You should consider upgrading via the ‘e: \python\python.exe -m pip install --upgrade pip’ c…

2023年【低压电工】作业考试题库及低压电工操作证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 低压电工作业考试题库参考答案及低压电工考试试题解析是安全生产模拟考试一点通题库老师及低压电工操作证已考过的学员汇总&#xff0c;相对有效帮助低压电工操作证考试学员顺利通过考试。 1、【单选题】()仪表由固定…

java数据机构.冒泡排序,选择排序 插入排序 递归算法,递归求阶乘,快速排序

排序算法 冒泡排序选择排序插入排序递归算法递归求1~100的和递归求阶乘 快速排序总结 冒泡排序 相邻两个元素比较,大的放右边,小的放左边 第一轮循环结束最大值已经找到,在数组最右边(归为算法) 第二轮在剩余的元素比较找到次大值,第二轮可以少循环一次 如果有n个数据,总共我们…

第18期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

微信小程序怎么制作?【小程序开发平台教学】

随着移动互联网的快速发展&#xff0c;微信小程序已经成为了人们日常生活中不可或缺的一部分。从购物、支付、出行到社交、娱乐、教育&#xff0c;小程序几乎涵盖了我们生活的方方面面。那么&#xff0c;对于有营销需求的企业商家来说&#xff0c;如何制作一个自己的微信小程序…