CAN总线协议编程实例

1. can.h

#ifndef __CAN_H
#define __CAN_H#include "./SYSTEM/sys/sys.h"/******************************************************************************************/
/* CAN 引脚 定义 */#define CAN_RX_GPIO_PORT                GPIOA
#define CAN_RX_GPIO_PIN                 GPIO_PIN_11
#define CAN_RX_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PA口时钟使能 */#define CAN_TX_GPIO_PORT                GPIOA
#define CAN_TX_GPIO_PIN                 GPIO_PIN_12
#define CAN_TX_GPIO_CLK_ENABLE()        do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PA口时钟使能 *//******************************************************************************************//* CAN接收RX0中断使能 */
#define CAN_RX0_INT_ENABLE      0               /* 0,不使能; 1,使能; *//* 函数声明 */
uint8_t can_receive_msg(uint32_t id, uint8_t *buf);             /* CAN接收数据, 查询 */
uint8_t can_send_msg(uint32_t id, uint8_t *msg, uint8_t len);   /* CAN发送数据 */
uint8_t can_init(uint32_t tsjw,uint32_t tbs2,uint32_t tbs1,uint16_t brp,uint32_t mode); /* CAN初始化 */#endif

2. can.c

#include "./BSP/CAN/can.h"
#include "./BSP/LED/led.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"CAN_HandleTypeDef   g_canx_handler;     /* CANx句柄 */
CAN_TxHeaderTypeDef g_canx_txheader;    /* 发送参数句柄 */
CAN_RxHeaderTypeDef g_canx_rxheader;    /* 接收参数句柄 *//*** @brief       CAN初始化* @param       tsjw    : 重新同步跳跃时间单元.范围: 1~3;* @param       tbs2    : 时间段2的时间单元.范围: 1~8;* @param       tbs1    : 时间段1的时间单元.范围: 1~16;* @param       brp     : 波特率分频器.范围: 1~1024;*   @note      以上4个参数, 在函数内部会减1, 所以, 任何一个参数都不能等于0*              CAN挂在APB1上面, 其输入时钟频率为 Fpclk1 = PCLK1 = 36Mhz*              tq     = brp * tpclk1;*              波特率 = Fpclk1 / ((tbs1 + tbs2 + 1) * brp);*              我们设置 can_init(1, 8, 9, 4, 1), 则CAN波特率为:*              36M / ((8 + 9 + 1) * 4) = 500Kbps** @param       mode    : CAN_MODE_NORMAL,  普通模式;CAN_MODE_LOOPBACK,回环模式;* @retval      0,  初始化成功; 其他, 初始化失败;*/
uint8_t can_init(uint32_t tsjw, uint32_t tbs2, uint32_t tbs1, uint16_t brp, uint32_t mode)
{g_canx_handler.Instance = CAN1;g_canx_handler.Init.Prescaler = brp;                /* 分频系数*/g_canx_handler.Init.Mode = mode;                    /* 模式设置 */g_canx_handler.Init.SyncJumpWidth = tsjw;           /* 重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1TQ~CAN_SJW_4TQ */g_canx_handler.Init.TimeSeg1 = tbs1;                /* tbs1范围CAN_BS1_1TQ~CAN_BS1_16TQ */g_canx_handler.Init.TimeSeg2 = tbs2;                /* tbs2范围CAN_BS2_1TQ~CAN_BS2_8TQ */g_canx_handler.Init.TimeTriggeredMode = DISABLE;    /* 非时间触发通信模式 */g_canx_handler.Init.AutoBusOff = DISABLE;           /* 软件自动离线管理 */g_canx_handler.Init.AutoWakeUp = DISABLE;           /* 睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位) */g_canx_handler.Init.AutoRetransmission = ENABLE;    /* 禁止报文自动传送 */g_canx_handler.Init.ReceiveFifoLocked = DISABLE;    /* 报文不锁定,新的覆盖旧的 */g_canx_handler.Init.TransmitFifoPriority = DISABLE; /* 优先级由报文标识符决定 */if (HAL_CAN_Init(&g_canx_handler) != HAL_OK){return 1;}#if CAN_RX0_INT_ENABLE/* 使用中断接收 */__HAL_CAN_ENABLE_IT(&g_canx_handler, CAN_IT_RX_FIFO0_MSG_PENDING); /* FIFO0消息挂号中断允许 */HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);                          /* 使能CAN中断 */HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 1, 0);                  /* 抢占优先级1,子优先级0 */
#endifCAN_FilterTypeDef sFilterConfig;/*配置CAN过滤器*/sFilterConfig.FilterBank = 0;                             /* 过滤器0 */sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;sFilterConfig.FilterIdHigh = 0x0000;                      /* 32位ID */sFilterConfig.FilterIdLow = 0x0000;sFilterConfig.FilterMaskIdHigh = 0x0000;                  /* 32位MASK */sFilterConfig.FilterMaskIdLow = 0x0000;sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;    /* 过滤器0关联到FIFO0 */sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;       /* 激活滤波器0 */sFilterConfig.SlaveStartFilterBank = 14;                  //F103ZET6只有14组过滤器组//初始化时设置为掩码模式且收到的数据全部接收,在后面的接收中通过软件筛选报文/* 过滤器配置 */if (HAL_CAN_ConfigFilter(&g_canx_handler, &sFilterConfig) != HAL_OK){return 2;}/* 启动CAN外围设备 */if (HAL_CAN_Start(&g_canx_handler) != HAL_OK){return 3;}return 0;
}/*** @brief       CAN底层驱动,引脚配置,时钟配置,中断配置此函数会被HAL_CAN_Init()调用* @param       hcan:CAN句柄* @retval      无*/
void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan)
{if (CAN1 == hcan->Instance){CAN_RX_GPIO_CLK_ENABLE();       /* CAN_RX脚时钟使能 */CAN_TX_GPIO_CLK_ENABLE();       /* CAN_TX脚时钟使能 */__HAL_RCC_CAN1_CLK_ENABLE();    /* 使能CAN1时钟 */GPIO_InitTypeDef gpio_initure;gpio_initure.Pin = CAN_TX_GPIO_PIN;gpio_initure.Mode = GPIO_MODE_AF_PP;gpio_initure.Pull = GPIO_PULLUP;gpio_initure.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(CAN_TX_GPIO_PORT, &gpio_initure); /* CAN_TX脚 模式设置 */gpio_initure.Pin = CAN_RX_GPIO_PIN;gpio_initure.Mode = GPIO_MODE_AF_INPUT;HAL_GPIO_Init(CAN_RX_GPIO_PORT, &gpio_initure); /* CAN_RX脚 必须设置成输入模式 */}
}#if CAN_RX0_INT_ENABLE /* 使能RX0中断 *//*** @brief       CAN RX0 中断服务函数*   @note      处理CAN FIFO0的接收中断* @param       无* @retval      无*/
void USB_LP_CAN1_RX0_IRQHandler(void)
{uint8_t rxbuf[8];uint32_t id;can_receive_msg(id, rxbuf);printf("id:%d\r\n", g_canx_rxheader.StdId);printf("ide:%d\r\n", g_canx_rxheader.IDE);printf("rtr:%d\r\n", g_canx_rxheader.RTR);printf("len:%d\r\n", g_canx_rxheader.DLC);printf("rxbuf[0]:%d\r\n", rxbuf[0]);printf("rxbuf[1]:%d\r\n", rxbuf[1]);printf("rxbuf[2]:%d\r\n", rxbuf[2]);printf("rxbuf[3]:%d\r\n", rxbuf[3]);printf("rxbuf[4]:%d\r\n", rxbuf[4]);printf("rxbuf[5]:%d\r\n", rxbuf[5]);printf("rxbuf[6]:%d\r\n", rxbuf[6]);printf("rxbuf[7]:%d\r\n", rxbuf[7]);
}#endif/*** @brief       CAN 发送一组数据*   @note      发送格式固定为: 标准ID, 数据帧* @param       id      : 标准ID(11位)* @retval      发送状态 0, 成功; 1, 失败;*/
uint8_t can_send_msg(uint32_t id, uint8_t *msg, uint8_t len)
{uint32_t TxMailbox = CAN_TX_MAILBOX0;g_canx_txheader.StdId = id;         /* 标准标识符 */g_canx_txheader.ExtId = id;         /* 扩展标识符(29位) */g_canx_txheader.IDE = CAN_ID_STD;   /* 使用标准帧 */g_canx_txheader.RTR = CAN_RTR_DATA; /* 数据帧 */g_canx_txheader.DLC = len;if (HAL_CAN_AddTxMessage(&g_canx_handler, &g_canx_txheader, msg, &TxMailbox) != HAL_OK) /* 发送消息 */{return 1;}while (HAL_CAN_GetTxMailboxesFreeLevel(&g_canx_handler) != 3); /* 等待发送完成,所有邮箱为空 */return 0;
}/*** @brief       CAN 接收数据查询*   @note      接收数据格式固定为: 标准ID, 数据帧* @param       id      : 要查询的 标准ID(11位)* @param       buf     : 数据缓存区* @retval      接收结果*   @arg       0   , 无数据被接收到;*   @arg       其他, 接收的数据长度*/
uint8_t can_receive_msg(uint32_t id, uint8_t *buf)
{if (HAL_CAN_GetRxFifoFillLevel(&g_canx_handler, CAN_RX_FIFO0) == 0)     /* 没有接收到数据 */{return 0;}if (HAL_CAN_GetRxMessage(&g_canx_handler, CAN_RX_FIFO0, &g_canx_rxheader, buf) != HAL_OK)  /* 读取数据 */{return 0;}if (g_canx_rxheader.StdId!= id || g_canx_rxheader.IDE != CAN_ID_STD || g_canx_rxheader.RTR != CAN_RTR_DATA)       /* 接收到的ID不对 / 不是标准帧 / 不是数据帧 */{return 0;    }return g_canx_rxheader.DLC;//返回的是接收数据个数}//我们对于过滤器的配置是不过滤任何报文 ID,也就是说可以接收全部
//报文。但是我们可以编写接收函数时,使用软件的方式过滤报文 ID,通过形参来跟接收到的报
//文 ID 进行匹配。

2.1 注意点

关于can_init函数参数的设置,

 * @param       tsjw     : 重新同步跳跃时间单元.范围: 1~3;
 * @param       tbs2    : 时间段2的时间单元.范围: 1~8;
 * @param       tbs1    : 时间段1的时间单元.范围: 1~16;
 * @param       brp     : 波特率分频器.范围: 1~1024;
 *   @note      以上4个参数, 在函数内部会减1, 所以, 任何一个参数都不能等于0, 参数减1后的值是TS2[2:0]/TS1[3:0]/BRP[3:0]寄存器的值,由下图该寄存器参与波特率计算时还要+1,故init函数的参数直接填你要设置的TS2/TS1/BPR实际长度即可(如下面的计算)。                              
 *              CAN挂在APB1上面, 其输入时钟频率为 Fpclk1 = PCLK1 = 36Mhz
 *              tq     = brp * tpclk1;
 *              波特率 = Fpclk1 / ((tbs1 + tbs2 + 1) * brp);
 *              我们设置 can_init(1, 8, 9, 4, 1), 则CAN波特率为:
 *              36M / ((8 + 9 + 1) * 4) = 500Kbps

3. main.c

//本程序是用CAN总线协议发送一组数据到另一个开发板或自己接收自己发送的数据
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/CAN/can.h"int main(void)
{uint8_t key;uint8_t i = 0, t = 0;uint8_t cnt = 0;uint8_t canbuf[8];uint8_t rxlen = 0;uint8_t res;uint8_t mode = 1; /* CAN工作模式: 0,普通模式; 1,环回模式 */HAL_Init();                                                            /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9);                                    /* 设置时钟, 72Mhz */delay_init(72);                                                        /* 延时初始化 */usart_init(115200);                                                    /* 串口初始化为115200 */usmart_dev.init(72);                                                   /* 初始化USMART */led_init();                                                            /* 初始化LED */lcd_init();                                                            /* 初始化LCD */key_init();                                                            /* 初始化按键 */can_init(CAN_SJW_1TQ, CAN_BS2_8TQ, CAN_BS1_9TQ, 4, CAN_MODE_LOOPBACK); /* CAN初始化, 环回模式, 波特率500Kbps */lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);lcd_show_string(30, 70, 200, 16, 16, "CAN TEST", RED);lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);lcd_show_string(30, 110, 200, 16, 16, "LoopBack Mode", RED);lcd_show_string(30, 130, 200, 16, 16, "KEY0:Send KEK_UP:Mode", RED); /* 显示提示信息 */lcd_show_string(30, 150, 200, 16, 16, "Count:", RED);        /* 显示当前计数值 */lcd_show_string(30, 170, 200, 16, 16, "Send Data:", RED);    /* 提示发送的数据 */lcd_show_string(30, 230, 200, 16, 16, "Receive Data:", RED); /* 提示接收到的数据 */while (1){key = key_scan(0);if (key == KEY0_PRES) /* KEY0按下,发送一次数据 */{for (i = 0; i < 8; i++){canbuf[i] = cnt + i; /* 填充发送缓冲区 */if (i < 4){lcd_show_xnum(30 + i * 32, 190, canbuf[i], 3, 16, 0X80, BLUE); /* 显示数据 */}else{lcd_show_xnum(30 + (i - 4) * 32, 210, canbuf[i], 3, 16, 0X80, BLUE); /* 显示数据 */}}res = can_send_msg(0X12, canbuf, 8); /* ID = 0X12, 发送8个字节 */if (res){lcd_show_string(30 + 80, 170, 200, 16, 16, "Failed", BLUE); /* 提示发送失败 */}else{lcd_show_string(30 + 80, 170, 200, 16, 16, "OK    ", BLUE); /* 提示发送成功 */}}else if (key == WKUP_PRES) /* WK_UP按下,改变CAN的工作模式 */{mode = !mode;if (mode == 0) /* 普通模式,需要2个开发板 */{can_init(CAN_SJW_1TQ, CAN_BS2_8TQ, CAN_BS1_9TQ, 4, CAN_MODE_NORMAL);    /* CAN普通模式初始化, 普通模式, 波特率500Kbps */lcd_show_string(30, 110, 200, 16, 16, "Nnormal Mode ", RED);}else /* 回环模式,一个开发板就可以测试了. */{can_init(CAN_SJW_1TQ, CAN_BS2_8TQ, CAN_BS1_9TQ, 4, CAN_MODE_LOOPBACK);  /* CAN普通模式初始化, 回环模式, 波特率500Kbps */lcd_show_string(30, 110, 200, 16, 16, "LoopBack Mode", RED);}}rxlen = can_receive_msg(0X12, canbuf); /* CAN ID = 0X12, 接收数据查询 */if (rxlen) /* 接收到有数据 */{lcd_fill(30, 270, 130, 310, WHITE); /* 清除之前的显示 */for (i = 0; i < rxlen; i++){if (i < 4){lcd_show_xnum(30 + i * 32, 250, canbuf[i], 3, 16, 0X80, BLUE); /* 显示数据 */}else{lcd_show_xnum(30 + (i - 4) * 32, 270, canbuf[i], 3, 16, 0X80, BLUE); /* 显示数据 */}}}t++;delay_ms(10);if (t == 20){LED0_TOGGLE(); /* 提示系统正在运行 */t = 0;cnt++;lcd_show_xnum(30 + 48, 150, cnt, 3, 16, 0X80, BLUE); /* 显示数据 */}}
}

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

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

相关文章

R2RNet: Low-light Image Enhancement viaReal-low to Real-normal Network

本研究针对在弱光条件下拍摄的图像可能严重降低图像质量的问题进行了探索。解决一系列低光图像的退化可以有效提高图像的视觉质量和高级视觉任务的性能。在本研究中&#xff0c;我们提出了一种新颖的基于Retinex的真实低光到真实正常光网络&#xff08;R2RNet&#xff09;&…

Vue自定义指令插槽作用域插槽具名插槽

Vue自定义指令&插槽&作用域插槽&具名插槽 一、学习目标 1.自定义指令 基本语法&#xff08;全局、局部注册&#xff09;指令的值v-loading的指令封装 2.插槽 默认插槽具名插槽作用域插槽 3.综合案例&#xff1a;商品列表 MyTag组件封装MyTable组件封装 4.路…

小红书笔记投流全攻略,打造爆款内容

在小红书平台上&#xff0c;信息流投放和搜索广告是两种主要的广告形式。信息流投放主要通过用户刷作品时展示你的笔记&#xff0c;而搜索广告则是用户搜索相关关键词时展示出的内容。今天就和大家分享下小红书笔记投流全攻略&#xff0c;打造爆款内容&#xff01; 一、什么样你…

探秘ipa文件签名工具在线签名工具:工作原理和代码表示原理

随着iOS应用程序的兴起&#xff0c;ipa文件的安全性变得越来越重要。为了确保应用程序来源的可信度和完整性&#xff0c;开发者需要对其应用进行签名&#xff0c;并使用正确的证书来验证其身份。在这篇文章中&#xff0c;我们将探索一个名为在线签名工具的ipa文件签名工具&…

【JavaWeb笔记】单选框,结合Servlet

各个部分的作用 jsp部分 form action"..."&#xff1a;表单标签&#xff0c;供用户提交数据。内部的submit点击之后相当于是点action的URL input type"radio"&#xff1a;输入类型为单选框。把name设置为一样的&#xff0c;这样效果上就是单选&#xff…

SiC SBD/超结MOS在工业电源上的应用-REASUNOS瑞森半导体

一、前言 工业电源是指用于工业及相关领域中的电子设备与设施的电源系统&#xff0c;其重要性体现在为各类工业设备提供稳定的电力保障&#xff0c;维护设备正常运行&#xff0c;故需具有稳定可靠、高效节能、安全耐用等特点。 常见的工业电源类型包括&#xff1a;交流电源、…

数据库 02-03 补充的SQL的集合运算,字符串计算,更名计算

集合运算&#xff1a; 01.union&#xff0c;并运算 union运算自动去重&#xff0c;是包括两个集合的全部部分。 如果不要去重&#xff0c;union all 02.交运算&#xff0c;intersect intersect运算是去重&#xff0c;只保留两个集合的相同部分。 intersect all 保留重复…

《opencv实用探索·十六》opencv直方图计算calcHist函数解析

直方图理解&#xff1a; &#xff08;对于8位灰度图像亮度/灰度为(0-255)&#xff0c;12位灰度图像亮度/灰度为(0-4095)&#xff09; 以8位图像为例&#xff0c;亮度分为0到255共256个数值&#xff0c;数值越大&#xff0c;代表的亮度越高。其中0代表纯黑色的最暗区域&#xff…

【Docker二】docker网络模式、网络通信、数据管理、资源控制

目录 一、docker网络模式&#xff1a; 1、概述 2、docker网络实现原理&#xff1a; 3、docker的网络模式&#xff1a; 3.1、bridge模式&#xff1a; 3.2、host模式&#xff1a; 3.3、container模式&#xff1a; 3.4、none模式&#xff1a; 3.5、自定义网络模式&#x…

青光眼术后险致盲,辗转多院幸于成都爱尔眼科重获光明

“我在一家医院诊断为青光眼&#xff0c;然后就做了青光眼手术。结果没有成功&#xff0c;后面产生了脉络膜脱离&#xff0c;从4月到10月底一直没有恢复&#xff0c;我去找医生结果那家医院的医生让我等……等着恢复……”张先生是一位青光眼术后患者&#xff0c;一场手术给他带…

TailwindCSS 配置可视化检查器

问题 TailwindCSS 框架为我们提供了大量默认的类和属性&#xff0c;而且开发者也能够自定义类和配置。 对于初学者来说&#xff0c;这些配置其实是比较复杂的&#xff0c;这也是tailwindcss最大的入手成本&#xff0c;开发者的记忆负担和心智负担也都比较大。 有没有办法能够…

谷歌Gemini被骂了?让子弹飞一会儿;如何构建高效RAG系统;Pika是腐朽王朝的颠覆者;AGI将重塑组织架构;对话月之暗面杨植麟 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f440; 淘宝 X D.Design 堆友 | 淘宝年终好价节 AIGC 创作大赛 https://d.design/competition/taobao-promotion 淘宝携手堆友联合打造了「淘…

python用turtle画樱花飘落,python代码画樱花代码

这篇文章主要介绍了python用turtle画樱花飘落&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 1、python画樱花树代码为&#xff1a; import turtle as T import random import…

基于ssm保险业务管理系统设计与实现论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本保险业务管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

银行数字化转型导师坚鹏:兴业生活APP运营之道

基于招商银行案例研究的兴业生活APP运营之道培训圆满结束 ——线上引流平台流量经营与变现 兴业银行股份有限公司&#xff08;简称“兴业银行”&#xff09;成立于1988年8月&#xff0c;2022年总资产9.27万亿元&#xff0c;是经国务院、中国人民银行批准成立的首批股份制商业银…

在Ascend昇腾硬件用npu加速paddleLite版本ocr(nnadapter)

在Ascend昇腾硬件用npu加速paddleLite版本ocr&#xff08;nnadapter&#xff09; 参考文档* nnadapter参考文档地址* 华为昇腾 NPU参考文档地址* PaddleLite的CAPI参考文档 一.确保cpu版本运行正常二.编译Ascend上npu加速库三.跑通npu加速版本Demo1.Demo下载地址2.参考手册网址…

Jupyter Notebook工具

Jupyter Notebook 是一个交互式的笔记本环境&#xff0c;允许用户以网页形式编写和分享代码、文本、图像以及其它多媒体内容。它支持超过 40 种编程语言&#xff0c;最常用的是 Python。 以下是 Jupyter Notebook 工具的一些特点和用法&#xff1a; 1. 特点&#xff1a; 交互式…

vscode eide arm-gcc 编译环境搭建调试

安装cube&#xff0c;vscode 1.安装vscode插件 C/C Extension Pack Chinese (Simplified) (简体中文) Language Pack Cortex-Debug Embedded IDE 工具链设置 2.软件工程生成 调试 3.生成工程&#xff0c;导入工程 4. 配置工程 编译完毕

【PTA刷题】 求子串(代码+详解)

【PTA刷题】 求子串(代码详解) 题目 请编写函数&#xff0c;求子串。 函数原型 char* StrMid(char *dst, const char *src, int idx, int len);说明&#xff1a;函数取源串 src 下标 idx 处开始的 len 个字符&#xff0c;保存到目的串 dst 中&#xff0c;函数值为 dst。若 len…

【W5500】关于使用外部网络变压器的原理图设计

直接上原理图 链接也放一个吧【链接】 按照这个画&#xff0c;我实验在立创EDA上打了一个实验过是可以用的~ 画出来的板子长这个样子【就不公开原理图和PCB了&#xff0c;这个板子还是很容易画的】~ 注意在立创上找对网口&#xff0c;要无变压器的网口&#xff0c;相比TB卖的那…