STM32CubeMX教程21 CAN - 双机通信
1、准备材料
STM32CubeMX软件(Version 6.10.0)
keil µVision5 IDE(MDK-Arm)
CH340G Windows系统驱动程序(CH341SER.EXE)
2、实验目标
使用STM32CubeMX软件配置两台STM32F407开发板的CAN1模块实现双机通信
3、实验流程
3.0、前提知识
3.0.1、CAN总体概述
STM32F407内部有两个CAN控制器,其中CAN1做为主CAN拥有所有的权限,而CAN2做为从CAN不能单独设置验证筛选器,每个CAN都有3个发送邮箱和两个接收FIFO,每个接收FIFO可以存储三条完整消息,具体的CAN框图如下图所示 (注释1)
CAN的总线网络结构有开环和闭环两种形式
闭环网络结构下,两根信号线H/L组成一个环路,在网络环路的两端连接120欧姆的电阻,这种网络是一种高速、短距离的CAN网络,通信速率最高1Mbit/s;
开环网络结构下,两根信号线H/L各自独立,在两根信号线上各自串联一个2.2千欧的电阻,这种网络是一种低速、远距离的CAN网络,通信速率最高125kbit/s;
如下图所示为开环/闭环的CAN总线网络结构 (注释2)
不管是开环还是闭环CAN网络结构都可以挂载多个节点,CAN网络上的每个节点由CAN控制器和CAN收发器组成,STM32F407内部集成的是CAN控制器,因此硬件设计时需要外部搭载CAN收发器才可以组成一个完整的CAN节点,如下图所示为笔者使用的开发板上搭载的CAN收发器芯片硬件原理图
这里CAN收发器芯片的TX/RX引脚并没有直接与单片机CAN1控制器的TX/RX引脚相连接,而是通过了一个跳线帽来进行调节,读者在做该实验的时候应该注意USB/CAN排针座应该利用跳线帽将CAN_TX/RX引脚与USB_D+/D-进行短接,具体硬件原理图如下图所示
3.0.2、CAN位时序和波特率
CAN通信是一种异步通信,异步通信的收发双方无时钟同步,因此需要确保收发双方发送/接收一帧数据的帧格式和波特率保持一致,这样才能保证收发双方正确的进行通信
CAN1/2挂载在APB1最高42MHz的时钟总线上,其一个时间片的长度由PCLK1频率和CAN分频参数决定,假设PCLK1频率为25MHz,CAN分频参数位5,则一个时间片的长度为5/25Mhz=0.0000002s=0.0002ms=0.2us=200ns
CAN网络上一个节点采集一个位数据的时序叫做位时序,位时序由同步段(SYNC_SEG)、位段 1(BS1)和位段2(BS2)三段组成,其中同步段固定为一个时间片,在该段总线上应该发生一次位信号的跳变;位段1定义了采样点的位置,其可以是1-16个时间片;位段2定义了发送点的位置,其可以是1-8个时间片;
除了上面几个可调节的参数外,CAN还有一个再同步跳转宽度(SJW)参数可以调节,其取值可以是1-4个时间片,通过调节该参数长短决定了CAN再同步时自动调节位段1和位段2长度缩短/加长的上限,此处笔者未深究该参数
通过调节时钟分频、位段1、位段2和再同步跳转宽度SJW四个参数,就可以确定CAN通信的波特率,如下图所示位位序数的结构图 (注释1)
3.0.3、CAN帧格式
CAN通信过程中共有数据帧、遥控帧、错误帧、过载帧和帧间空间五种不同用途的帧,其中数据帧和遥控帧又有标准格式的帧和扩展格式的帧两种,数据帧可以理解为CAN网络上的节点发送消息ID+要发送的数据,遥控帧可以理解为CAN网络上某个节点需要另外一个节点的数据,收到遥控帧的节点就发送对应的数据给请求数据的节点,这里不详细介绍每个帧的格式,想要知道具体帧格式的读者请阅读其他文章,如下图所示为CAN数据/遥控帧一帧的结构图 (注释1)
在HAL库中有一个CAN发送消息头结构体CAN_TxHeaderTypeDef,以下为结构体内主要定义参数
- IDE(帧格式):可选参数CAN_ID_STD(标准格式帧)和CAN_ID_EXT(扩展格式帧)
- StdId(标准格式帧ID):可选值范围0-0x7FF(11位)
- ExtId(扩展格式帧ID):可选值范围0-0x1FFF FFFF(29位,其中标准11位+扩展18位)
- RTR(帧类型):可选参数CAN_RTR_DATA(数据帧)和CAN_RTR_REMOTE(遥控帧)
- DLC(发送数据的长度):可选值范围0-8
- TransmitGlobalTime(传输时间戳使能):ENABLE/DISABLE
3.0.4、CAN验收筛选器
CAN网络上的所有节点没有地址的概念,因此当某个节点发送了特定ID的一条数据帧的时候,所有节点都会收到该帧消息,但是该帧应该只被需要接收该帧的节点接收,而其他不需要接收该数据帧的节点应该自动筛除掉该消息,减少资源浪费,那一个节点如何判断是否应该接收该帧呢?
配置CAN控制器的验收筛选器,STM32F407的CAN提供了28个可调整/可配置的标识符筛选器组,注意CAN1/2共用这个标识符筛选器组,而且CAN2不能够单独直接配置,需要使用CAN1来配置,这里的筛选功能为硬件筛选功能,无需软件筛选,可以节省软件筛选所需的CPU资源
筛选器可配置为掩码模式或标识符列表模式,在掩码模式下,标识符寄存器与掩码寄存器关联,用以指示标识符的哪些位“必须匹配”,哪些位“无关”
在HAL库中有一个CAN过滤器配置结构体CAN_FilterTypeDef用于配置筛选器,以下为结构体内主要定义参数
- FilterMode(筛选器模式):可选参数CAN_FILTERMODE_IDMASK(掩码模式)和CAN_FILTERMODE_IDLIST(标识符列表模式)
- FilterBank(筛选器组):指定将初始化的筛选器组,单CAN时参数范围0-13,双CAN时参数范围0-27
- FilterFIFOAssignment(分配给筛选器的FIFO):指定分配给过筛选器的FIFO0/1,可选参数CAN_FILTER_FIFO0(FIFO0)和CAN_FILTER_FIFO1(FIFO1)
- FilterScale(筛选器宽度):CAN_FILTERSCALE_16BIT(两个16位)和CAN_FILTERSCALE_32BIT(一个32位)
- FilterActivation(筛选器使能):CAN_FILTER_DISABLE(不使能)和CAN_FILTER_ENABLE(使能)
- FilterIdHigh(CAN_FxR1 的高16位):在32位的屏蔽位模式下,用于指定这些位的标准值
- FilterIdLow(CAN_FxR1 的低16位):在32位的屏蔽位模式下,用于指定这些位的标准值
- FilterMaskIdHigh(CAN_FxR2的高16位):在32位的屏蔽位模式下,用于指定需要关心哪些位
- FilterMaskIdLow(CAN_FxR2的低16位):在32位的屏蔽位模式下,用于指定需要关心哪些位
这一部分很重要,不配置筛选器则CAN不能正常接收数据,具体配置请阅读本实验3.2.3小节程序,这里笔者自认为讲的不是很到位,读者可以阅读“STM32 CAN 过滤器、滤波屏蔽器配置总结”文章
3.0.5、CAN工作模式
CAN1/2有工作模式和测试模式两种模式,工作模式中又包括初始化模式、正常模式和睡眠模式三种,测试模式中包括静默模式、环回模式和环回与静默组合模式三种,测试模式主要用于测试单个CAN是否工作正常,本实验主要实现双机通信,因此CAN工作在正常模式即可,由于内容太多这里不再详细介绍,具体内容可参考STM32F4xx 参考手册 RM009,如下图所示为测试模式下结构示意图 (注释1)
3.0.6、CAN发送和接收流程
CAN1/2均有3个邮箱可以发送数据,当用户发送数据时只需要利用CAN_TxHeaderTypeDef结构体生成要发送的帧(具体可阅读本实验3.0.3小节),然后使用HAL_CAN_AddTxMessage()函数将生成的帧添加到邮箱即可,如果此时有空闲邮箱那么邮箱就会被挂起,当该邮箱具有最高优先级的时候就会安排发送出去,发送出去的过程完全由硬件实现,用户只需按要求生成帧,然后放入空闲邮箱即可,如下图所示为发送邮箱状态流程图 (注释1)
CAN1/2均有两个接收FIFO,每个接收FIFO都有三级深度,通俗理解就是有三个邮箱,可以接收三条信息,当发送的信息通过某个CAN网络上的节点验收筛选器成为一条有效信息时,那么该消息就会被该节点的CAN接收FIFO接收,同时该FIFO的接收0会被挂起,如果持续收到消息,该FIFO的接收1/2也会被挂起,直到三个邮箱全部用完,如果开启了CAN RX接收中断,那么当FIFO接收0/1/2/被挂起时会进入对应的中断服务回调函数中,当使用HAL_CAN_GetRxMessage()函数读取掉接收FIFO0/1的某级深度的消息时,该级别邮箱将会被释放,方便接收下一条消息,如下图所示为接收FIFO状态流程图 (注释1)
值得提醒的是,在本实验中由于笔者使用了两个一摸一样的开发板,因此下面配置的一套程序可以直接烧录到两个开发板上就可以通信,但是如果读者使用了不一样的开发板,每个板子的配置流程和下述流程一模一样,但请注意调节时钟树和CAN的参数配置时将两个开发板的CAN通信波特率调节为一致,两个开发板的连接应该如下图所示连接 (注释4)
另外就是尽量使用CAN1作为通信CAN,因为在STM32F407的两个CAN中CAN1为主CAN,本实验使用CAN2可能在接收信息时存在问题(大概率笔者没有彻底了解到应该对CAN2如何正确配置),读者可以自行尝试
3.1、CubeMX相关配置
3.1.0、工程基本配置
打开STM32CubeMX软件,单击ACCESS TO MCU SELECTOR选择开发板MCU(选择你使用开发板的主控MCU型号),选中MCU型号后单击页面右上角Start Project开始工程,具体如下图所示
开始工程之后在配置主页面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具体如下图所示
详细工程建立内容读者可以阅读“STM32CubeMX教程1 工程建立”
3.1.1、时钟树配置
本实验时钟树建议按照下图所示将MCU时钟频率配置为100MHz,APB1时钟频率配置为25MHz,这样设置是为了能够得到一个整数的时间片,当然也可以和之前的实验类似,将所有总线频率均设置为最高频率
3.1.2、外设参数配置
本实验需要初始化开发板上KEY2用户按键做普通输入,具体配置步骤请阅读“STM32CubeMX教程3 GPIO输入 - 按键响应”
本实验需要需要初始化USART2作为输出信息渠道,具体配置步骤请阅读“STM32CubeMX教程9 USART/UART 异步通信”
单击Pinout & Configuration页面左边Connectivity/CAN1,在Mode中勾选Activated激活CAN1,在其下方的参数配置栏目中按照图示参数配置即可,位时序参数详解可以阅读本实验“3.0.2、CAN位时序和波特率”小节
3.1.3、外设中断配置
在Pinout & Configuration页面左边System Core/NVIC中勾选CAN1 TX interrupts和CAN1 RX0 interrupts发送接收两个中断,然后选择合适的中断优先级即可,具体如配置下图所示
3.2、生成代码
3.2.0、配置Project Manager页面
单击进入Project Manager页面,在左边Project分栏中修改工程名称、工程目录和工具链,然后在Code Generator中勾选“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最后单击页面右上角GENERATE CODE生成工程,具体如下图所示
详细Project Manager配置内容读者可以阅读“STM32CubeMX教程1 工程建立”实验3.4.3小节
3.2.1、外设初始化调用流程
在生成的工程代码中新增加了MX_CAN1_Init()函数,该函数对CAN1的参数进行了配置,并调用了CAN初始化函数HAL_CAN_Init()
在该CAN初始化函数HAL_CAN_Init()中调用了HAL_CAN_MspInit()函数对外设CAN1所需要的时钟使能,引脚复用和中断进行了配置
CAN1具体初始化调用流程如下图所示
3.2.2、外设中断调用流程
在STM32CubeMX中勾选CAN1的TX中断和RX0中断后,会在生成的工程代码stm32f4xx_it.c中新增CAN1_TX_IRQHandler()和CAN1_RX0_IRQHandler()中断服务函数
这两个中断服务函数均调用了HAL库的CAN中断统一处理函数HAL_CAN_IRQHandler(),在该函数中当CAN1邮箱0发送完成消息后会调用HAL_CAN_TxMailbox0CompleteCallback()函数,当CAN1FIFO0消息挂起时会调用HAL_CAN_RxFifo0MsgPendingCallback()函数,这两个函数均为虚函数,需要用户重新实现
CAN1接收/发送中断具体调用流程如下图所示
3.2.3、添加其他必要代码
在can.c中添加FIFO0的消息筛选器函数CAN_SetFilters(),然后添加CAN发送数据测试函数CAN1_Send_Test(),具体源代码如下所示 (注释3)
//设置筛选器,要在完成CAN初始化之后调用此函数
HAL_StatusTypeDef CAN_SetFilters(void)
{
CAN_FilterTypeDef canFilter; //筛选器结构体变量
// Configure the CAN Filter
canFilter.FilterBank = 0; //筛选器组编号
canFilter.FilterMode = CAN_FILTERMODE_IDMASK; //ID掩码模式
canFilter.FilterScale = CAN_FILTERSCALE_32BIT; //32位长度
//设置1:接收所有帧
// canFilter.FilterIdHigh = 0x0000; //CAN_FxR1 的高16位
// canFilter.FilterIdLow = 0x0000; //CAN_FxR1 的低16位
// canFilter.FilterMaskIdHigh = 0x0000; //CAN_FxR2的高16位。所有位任意
// canFilter.FilterMaskIdLow = 0x0000; //CAN_FxR2的低16位,所有位任意
//设置2:只接收stdID为奇数的帧
canFilter.FilterIdHigh = 0x0020; //CAN_FxR1 的高16位
canFilter.FilterIdLow = 0x0000; //CAN_FxR1 的低16位
canFilter.FilterMaskIdHigh = 0x0020; //CAN_FxR2的高16位
canFilter.FilterMaskIdLow = 0x0000; //CAN_FxR2的低16位
canFilter.FilterFIFOAssignment = CAN_RX_FIFO0; //应用于FIFO0
canFilter.FilterActivation = ENABLE; //使用筛选器
canFilter.SlaveStartFilterBank = 14; //从CAN控制器筛选器起始的Bank
HAL_StatusTypeDef result=HAL_CAN_ConfigFilter(&hcan1, &canFilter);
return result;
}
/*CAN发送数据测试函数*/
void CAN1_Send_Test(uint32_t msgid, uint8_t *data)
{
TxMessage.IDE = CAN_ID_STD; //设置ID类型
TxMessage.StdId = msgid; //设置ID号
TxMessage.RTR = CAN_RTR_DATA; //设置传送数据帧
TxMessage.DLC = 4; //设置数据长度
if(HAL_CAN_AddTxMessage(&hcan1, &TxMessage, data, &TxMailbox) != HAL_OK)
{
printf("CAN send test data fail!\r\n");
Error_Handler();
}
}
在can.c中重新实现CAN接收/发送中断处理函数,具体源代码如下所示
/*CAN接收FIFO0挂起中断处理函数*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t data[8];
HAL_StatusTypeDef status;
if(hcan == &hcan1)
{
status = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, data);
if (HAL_OK == status)
{
printf("--->Data Receieve!\r\n");
printf("RxMessage.StdId is %#x\r\n", RxMessage.StdId);
printf("data[0] is 0x%02x\r\n", data[0]);
printf("data[1] is 0x%02x\r\n", data[1]);
printf("data[2] is 0x%02x\r\n", data[2]);
printf("data[3] is 0x%02x\r\n", data[3]);
printf("<---\r\n");
}
}
}
/*CAN发送完成中断处理函数*/
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
{
printf("--->Into TxMailbox0CompleteCallback Function!\r\n");
printf("--->CAN send test data success!\r\n\r\n");
}
在main.c主函数中设置CAN接收筛选器,启动CAN,使能中断,然后再主循环中实现按键控制,每当按键KEY2按下时就调用CAN1_Send_Test()函数发送数据
具体源代码如下所示
/*主循环外程序*/
printf("----- CAN Test Board #1 -----\r\n");
//设置筛选器
if (CAN_SetFilters() == HAL_OK)
printf("ID Filter: Only Odd IDs\r\n");
//启动CAN1模块
if (HAL_CAN_Start(&hcan1) == HAL_OK)
printf("CAN is started\r\n");
//启用CAN发送/接收中断
if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_TX_MAILBOX_EMPTY) != HAL_OK)
{
printf("CAN_IT_RX_FIFO0_MSG_PENDING Enable Fail\r\n");
Error_Handler();
}
uint32_t msg_id=0;
uint8_t data[4] = {0x01, 0x02, 0x03, 0x04};
/*主循环内程序*/
/*按键KEY2按下*/
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(50);
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET)
{
for(uint16_t i =0;i<4;i++)
data[i]++;
CAN1_Send_Test(msg_id++,data);
while(!HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin));
}
}
最后将在can.c中定义的消息筛选器函数、发送数据测试函数在can.h中声明即可,具体源代码如下所示
/*can.h中函数声明*/
void CAN1_Send_Test(uint32_t msgid, uint8_t *data);
HAL_StatusTypeDef CAN_SetFilters(void);
4、常用函数
/*CAN开始通信*/
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)
/*CAN停止通信*/
HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan)
/*获取当前空闲邮箱数量*/
uint32_t HAL_CAN_GetTxMailboxesFreeLevel(const CAN_HandleTypeDef *hcan)
/*请求发送相应的邮箱内容*/
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, const CAN_TxHeaderTypeDef *pHeader,const uint8_t aData[], uint32_t *pTxMailbox)
/*获取FIFO中挂起的消息数*/
uint32_t HAL_CAN_GetRxFifoFillLevel(const CAN_HandleTypeDef *hcan, uint32_t RxFifo)
/*读取FIFI中挂起的消息信息并释放邮箱*/
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo,CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])
/*CAN发送完成中断处理函数*/
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
/*CAN接收中断处理函数*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
5、烧录验证
烧录程序,开发板1/2上电后均显示CAN初始化成功可以开始通信
当第一次按下开发板1的KEY2按键,此时串口输出进入CAN发送完成中断处理函数中并成功发送信息的提示,但是开发板2并没有接收消息(因为开发板1/2均设置了只接收stdID为奇数的帧)
当第二次按下开发板1的KEY2按键时,可以发现开发板2收到了消息,并将接收到的消息打印了出来,具体实验现象如下图所示(左边为开发板1,右边为开发板2)
6、注释详解
注释1:图片来源 STM32F4xx 中文参考手册 RM009
注释2:图片来源 通信——CAN总线基础介绍
注释3:在CAN发送测试函数末尾不要使用printf输出,如果非要使用请在使用前进行1ms延时,否则可能进不去发送完成函数HAL_CAN_TxMailbox0CompleteCallback中
注释4:图片来源 STM32CubeMX | 36 - 使用CAN总线进行双板通信(TJA1050)
参考资料
更多内容请浏览 STM32CubeMX+STM32F4系列教程文章汇总贴
STM32CubeMX教程21 CAN - 双机通信的更多相关文章
- [SQL基础教程] 2-1 SELECT语句基础
[SQL基础教程] 2-1 SELECT语句基础 列的查询 Syntax SELECT<列名>,..... FROM<表名>; SELECT col_1, col_2 FROM ...
- Linux can双机通信(2440+MCP2515 && 51+SJA1000)
2012-01-12 22:43:24 上图: 自收发成功完成后,那么双机通信就比较容易了.关键就是CAN波特率.ID标识.滤波设置正确即可双机通信了.
- 学习7__STM32--SPI外设之双机通信---
<target> # 整透stm32之spi双机通信(包括双机同为stm32,stm32& others) <概念> # 双机通信(全双工) 在主机的MOSI管脚输出1 ...
- iView 实战系列教程(21课时)_汇总贴
iView 实战系列教程(21课时)_汇总贴 课程地址; https://segmentfault.com/ls/1650000016424063 iView 实战系列教程(21课时)_1.iView ...
- [译]Vulkan教程(21)顶点input描述
[译]Vulkan教程(21)顶点input描述 Vertex input description 顶点input描述 Introduction 入门 In the next few chapters ...
- [转帖]Linux教程(21)-Linux条件循环语句
Linux教程(21)-Linux条件循环语句 2018-08-24 16:49:03 钱婷婷 阅读数 60更多 分类专栏: Linux教程与操作 Linux教程与使用 版权声明:本文为博主原创文 ...
- Directx11教程(21) 修正程序最小化异常bug
原文:Directx11教程(21) 修正程序最小化异常bug 很长时间竟然没有注意到,窗口最小化时候,程序会异常,今天调试水面程序时,随意间最小化了窗口,发现程序异常了.经过调试,原来程 ...
- arduino双机通信 (解决引脚不够用)
作用 实现将一个 arduino 中的多个 String 类型变量准确地传到另一个 arduino 中对应的多个 String 类型变量 中. 接线图 注意 TX 接另一个arduino的 RX !可 ...
- Proteus仿真—51单片机实现AC信号测频、显示、双机通信
文章目录 一.原理图部分 二.源码部分 单片机1 单片机2 在Proteus仿真软件里面使用STC89C52实现指定频率的AC信号的测频.显示.双机通信. 一.原理图部分 整体的电路图如示: DC-A ...
- WCF入门教程五[WCF的通信模式]
一.概述 WCF在通信过程中有三种模式:请求与答复.单向.双工通信.以下我们一一介绍. 二.请求与答复模式 描述: 客户端发送请求,然后一直等待服务端的响应(异步调用除外),期间处于假死状态,直到服务 ...
随机推荐
- 【开源项目推荐】Apache Superset——最优秀的开源数据可视化与数据探索平台
大家好,我是独孤风. 数据可视化是数据领域一个非常重要的应用.而结合了数据可视化和数据探索功能的BI(商业智能)工具,更是被各大公司青睐.但是,由于数据可视化工具的开发成本过高,长期以来一直是商业化的 ...
- S32Kxxx bootloader之CAN FD UDS bootloader
了解更多关于bootloader 的C语言实现,请加我Q扣: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 六年前, 汽车内ECU ...
- [Acwing 164. 可达性统计] 题解报告
事实上,这道题并不需要拓扑排序.(当然,拓扑排序还是更快) 题目分析 首先,题目中说了,这是一个有向无环图,所以,我们可以考虑 \(\texttt{DP}\) / 记搜 / 拓扑排序 来解决这道题. ...
- <Python全景系列-1> Hello World,1分钟配置好你的python环境
<从此开始:1分钟配置好你的python环境> 欢迎来到我们的系列博客<Python360全景>!在这个系列中,我们将带领你从Python的基础知识开始,一步步深入到高级话题, ...
- 探秘华为云盘古大模型:AI for industries的身体力行
摘要:大模型是新一轮AI发展的核心,其已在推进产业智能化升级中已表现出巨大潜力,并将在未来三年里形成风起云涌之势. 本文分享自华为云社区<探秘华为云盘古大模型:AI for industries ...
- 简化业务代码开发:看Lambda表达式如何将代码封装为数据
摘要:在云服务业务开发中,善于使用代码新特性,往往能让开发效率大大提升,这里简单介绍下lambad表达式及函数式接口特性. 1.Lambda 表达式 Lambda表达式也被称为箭头函数.匿名函数.闭包 ...
- Tarjan:这个算法大神
摘要:图的算法是进行静态分析的基础数据算法,如何提高图的分析效率,就需要对图的算法有进一步的认识. 1. 引言 在静态分析技术中, 我们常用会将代码转成抽象语法树(AST), 然后采用深度遍历(DFS ...
- Mac 安装 cnpm
npm set registry https://registry.npm.taobao.org npm set disturl https://npm.taobao.org/dist npm cac ...
- lab3 page tables
1.Speed up system calls (easy) 要求:有些操作系统(例如 Linux)通过在用户空间和内核之间的只读区域共享数据来加速某些系统调用.这样可以消除在执行这些系统调用时进行内 ...
- AIGC加速迭代,云栖大会视频云「媒体服务」专场与你共话云智深度融合
2023杭州·云栖大会 倒计时5天! 阿里云视频云 5大并行Session 11场话题演讲 深度演绎云智融合的全面进化 「媒体服务」Tech专场 重磅议题剧透来袭 01 「媒体服务」Tech • 新数 ...