当前位置: 首页 > news >正文

从零开始之stm32之CAN通信

从小白的视角了解并实现简单的STM32F103的CAN通信,直接上手。

一、CAN协议简介

CAN总线上传输的信息称为报文,当总线空闲时任何连接的单元都可以开始发送新的报文,有5种类型的帧:数据帧、遥控帧、错误帧、过载帧、帧间隔。数据帧有两种格式:标准格式和扩展格式主要区别在于ID长度。

二、参数含义和设置

STM32CubeIDE关于CAN的参数设置

1、位时序参数说明和设置

Prescaler:预分频系数,定义CAN单位时钟周期=APB1外设时钟频率/分频系数,取值范围:1 ~ 1024,上述APB频率 = 36MHz。

用打电话的方式,表示设置参数:

步骤CAN总线对应参数作用
1. 你说:"今~天~晚~上~7~点~"TimeSeg1(匀速发送数据)放慢语速,确保对方听清每个字(信号稳定)
2. 停顿时间TimeSeg2(等待ACK)留时间让对方回应(同步采样点)
3. 对方可能在停顿内回应:  
- ✅ "好!"(ACK)正常接收,继续通信同步成功,无需调整
- ❌ 没回应(信号延迟)SyncJumpWidth 发挥作用! 
4. 你决定最多再等一等

SyncJumpWidth

等待xTq,x个单位时间

允许对方稍晚回应(时钟容错)
- 如果多等的时间内对方回应同步成功通信继续
- 如果多等的时间内仍无回应判定不同步,重传数据自动重传或报错

参数确定:

1、优先确定Prescaler:

计算 Prescaler = CAN_CLK / (波特率 × (1 + TimeSeg1 + TimeSeg2)),取最接近的整数值。

例如:36MHz目标1Mbps,假设 1+6+2=9Tq → Prescaler = 36MHz/(1MHz×9) = 4。

2、TimeSeg1/TimeSeg2分配:

短距离:TimeSeg1可小(如5~6Tq),TimeSeg2=1~2Tq。

长距离:TimeSeg1需大(如8~12Tq),TimeSeg2=2~4Tq。

规则:TimeSeg1 ≥ TimeSeg2 + SyncJumpWidth。

3、SyncJumpWidth选择:

高速CAN(≥500kbps):1Tq(严格同步)。

低速/工业CAN(≤250kbps):2Tq(增强容错)。

4、抗干扰优化:

增大TimeSeg1和SyncJumpWidth可提升稳定性,但会降低波特率。

若通信不稳定,逐步增加TimeSeg1(每次+1Tq)并测试。

2、基本参数说明和设置

参数说明:

基本参数含义
Time Triggered Communication Mode
(时间触发通信模式)
作用:为接收帧添加时间戳(用于时间同步协议)
ENABLE:硬件记录帧的接收时间戳(存储在CAN_RDTxR寄存器)
DISABLE:不记录时间戳(默认)
Automatic Bus-Off Management
(自动总线关闭管理)
作用:节点错误计数器超限后是否自动恢复
ENABLE:节点进入"Bus-Off"状态后,自动等待128次11位隐性位后恢复通信
DISABLE:需手动调用HAL_CAN_ResetError()恢复,适合需要人工干预的调试场景
Automatic Wake-up Mode
(自动唤醒模式)
作用:CAN从休眠模式唤醒的条件
ENABLE:检测到总线活动时自动唤醒(适合低功耗设备)
DISABLE:必须通过软件或硬件信号唤醒(如按键触发)
Automatic Retransmission
(自动重传)
作用:控制发送失败时是否自动重传
ENABLE:发送失败后自动重传(默认),确保数据可靠性,适合实时性要求高的场景(如汽车ECU)
DISABLE:仅发送一次,失败不重试。用于严格时序控制(如CAN FD协议中避免报文堆积)
Receive Fifo Locked Mode
(接收FIFO锁定模式)
接收FIFO满时的处理策略
ENABLE:FIFO满时丢弃新数据(避免覆盖旧数据)
DISABLE:新数据覆盖最旧数据(默认)
Transmit Fifo Priority
(发送FIFO优先级)
作用:发送邮箱的调度策略
ENABLE:按报文ID优先级发送(低ID优先)
DISABLE:按FIFO顺序发送(默认

3、高级参数设置和说明

测试模式说明

Test Mode
测试模式
CAN工作模式:
Normal:正常模式(向总线发送或从总线接收数据)
Loopback:环回模式(自发自收,无需硬件连接,用于本地回环测试)
Silent:静默模式(监听总线,不响应,),只监听不干扰,适合诊断
Loopback combined with Silent:静默环回模式(本地回环+总线监听),混合用途,调试复杂场景

4、开启中断

可以在System Core --> NVIC中设置中断优先等级

三、实际例程

1、CAN初始化

增加接收滤波器,可以用于筛选接收数据,硬件级过滤,可以

  1. 降低CPU负担(避免处理无关报文)

  2. 提高实时性(仅处理目标数据)

  3. 必须配置(否则无法接收数据)

  4. 灵活可控(支持掩码/列表两种过滤模式)

/*** @brief CAN Initialization Function* @param None* @retval None*/
static void MX_CAN_Init(void)
{/* USER CODE BEGIN CAN_Init 0 *//* USER CODE END CAN_Init 0 *//* USER CODE BEGIN CAN_Init 1 *//* USER CODE END CAN_Init 1 */hcan.Instance = CAN1;hcan.Init.Prescaler = 4;hcan.Init.Mode = CAN_MODE_LOOPBACK;hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;hcan.Init.TimeSeg1 = CAN_BS1_5TQ;hcan.Init.TimeSeg2 = CAN_BS2_3TQ;hcan.Init.TimeTriggeredMode = DISABLE;hcan.Init.AutoBusOff = DISABLE;hcan.Init.AutoWakeUp = ENABLE;hcan.Init.AutoRetransmission = DISABLE;hcan.Init.ReceiveFifoLocked = DISABLE;hcan.Init.TransmitFifoPriority = DISABLE;if (HAL_CAN_Init(&hcan) != HAL_OK){Error_Handler();}/* USER CODE BEGIN CAN_Init 2 *//* USER CODE BEGIN CAN_Init 2 */CAN_FilterTypeDef sFilterConfig;sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;sFilterConfig.FilterIdHigh = 0x0000; // 可以保持为0接收所有IDsFilterConfig.FilterIdLow = 0x0000;sFilterConfig.FilterMaskIdHigh = 0x0000;sFilterConfig.FilterMaskIdLow = 0x0000;sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;sFilterConfig.FilterBank = 0; // 添加过滤器组号sFilterConfig.SlaveStartFilterBank = 14;sFilterConfig.FilterActivation = ENABLE;HAL_StatusTypeDef state = HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);if (state != HAL_OK){Error_Handler();}state = HAL_CAN_Start(&hcan);if (state != HAL_OK){Error_Handler();}state = HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);if (state != HAL_OK){Error_Handler();}/* USER CODE END CAN_Init 2 *//* USER CODE END CAN_Init 2 */
}

关于接收滤波器说明与设置:

参数

说明

FilterMode
(过滤模式)
可选值:
CAN_FILTERMODE_IDMASK(掩码模式)
CAN_FILTERMODE_IDLIST(列表模式)
作用:
掩码模式:通过FilterId和FilterMask组合定义ID范围(类似通配符规则)
示例:FilterId=0x100, FilterMask=0xFF00 → 接收ID范围0x100~0x1FF
列表模式:精确匹配FilterId和FilterMask中指定的ID(最多2个32位ID或4个16位ID)
示例:FilterId=0x123, FilterMask=0x456 → 仅接收ID为0x123或0x456的帧
FilterScale
(过滤器尺度)
可选值:
CAN_FILTERSCALE_32BIT(32位宽过滤器)
CAN_FILTERSCALE_16BIT(16位宽过滤器)
作用:
32位模式:单个过滤器可处理1个完整扩展帧ID(29位)或2个标准帧ID(11位)。
16位模式:单个过滤器可处理2个标准帧ID(11位)或部分扩展帧ID(需组合使用)。
选择建议:
扩展帧或复杂过滤规则 → 32位模式。
仅标准帧且需更多过滤组 → 16位模式。
FilterIdHigh
FilterIdLow
(过滤器ID值)
作用:定义待匹配的基准ID值(具体解释取决于FilterMode和FilterScale)
32位模式下的存储规则
标准帧ID(11位):
FilterIdHigh = (StdId << 5);  // 左移5位对齐到寄存器位[15:5]
FilterIdLow = 0x0000;         // 低16位未使用
扩展帧ID(29位):
FilterIdHigh = (ExtId >> 13) & 0xFFFF;  // 高16位(bit28~bit13)
FilterIdLow = ((ExtId << 3) & 0xFFF8) | 0x04; // 低13位(bit12~bit0)+ IDE=1
FilterMaskIdHigh
FilterMaskIdLow
(过滤器掩码)
作用:
掩码模式:定义ID中哪些位必须匹配(1=必须匹配,0=不关心)。
示例:FilterId=0x100, FilterMask=0xFF00 → 匹配所有0x1XX的ID。
列表模式:作为第二个ID值(与FilterId组成精确匹配列表)。
特殊值:
全0x0000:接收所有ID(关闭过滤)。
全0xFFFF:精确匹配FilterId
FilterFIFOAssignment
(FIFO分配)
可选值:
CAN_RX_FIFO0 或 CAN_RX_FIFO1
作用:
指定匹配的报文存入哪个接收FIFO(STM32 CAN控制器有2个接收FIFO)。
推荐配置:
通常使用FIFO0,FIFO1可用于优先级更高的报文
FilterBank
(过滤器组编号)
取值范围:
单CAN设备:0~13(如STM32F103)
双CAN设备:0~27(如STM32F105)
作用:
选择具体的硬件过滤器组(STM32提供多个独立过滤器组,可并行工作)
SlaveStartFilterBank
(从CAN过滤器起始组)
作用:
在双CAN模式(如CAN1+CAN2)下,定义从CAN实例(CAN2)的起始过滤器组编号。
示例:SlaveStartFilterBank=14 → CAN1用组0~13,CAN2用组14~27。
单CAN模式:此参数无效,但需保留(通常设为14)
FilterActivation
(过滤器激活)
可选值:
ENABLE:立即激活过滤器。
DISABLE:配置但不启用(需后续手动激活)。
关键点:
必须至少有一个激活的过滤器,否则CAN控制器会丢弃所有报文!

2、添加中断回调函数

STM32 HAL库中CAN接收中断的回调函数,当CAN控制器的接收FIFO0(接收缓冲区0)中有新消息到达时,会自动触发此函数。

/* USER CODE BEGIN 4 */void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *CanHandle)
{/* Get RX message */if (HAL_CAN_GetRxMessage(CanHandle, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK){/* Reception Error */Error_Handler();}// 接收到的数据:RxData[8]// 接收到的ID值:RxHeader.StdId
}/* USER CODE END 4 */

3、发送数据

将CAN报文放入发送邮箱,由硬件自动发送到总线上

  • 非阻塞式发送:函数仅将数据存入CAN控制器的发送邮箱,实际发送由硬件完成,无需CPU持续等待。

    if (HAL_CAN_AddTxMessage(&hcan, &txHeader, TxData, &TxMailbox) != HAL_OK){Error_Handler();}

4、整个例程

可以通过调试查看接收的数据是否对应发送数据。

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */CAN_TxHeaderTypeDef txHeader ={.StdId = 0x123,.ExtId = 0x00,.IDE = CAN_ID_STD,.RTR = CAN_RTR_DATA,.DLC = 8,.TransmitGlobalTime = DISABLE};
CAN_RxHeaderTypeDef RxHeader;
uint8_t TxData[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; // 定义数据
uint8_t RxData[8];
uint32_t TxMailbox;/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_CAN_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if (HAL_CAN_AddTxMessage(&hcan, &txHeader, TxData, &TxMailbox) != HAL_OK){Error_Handler();}HAL_Delay(2000);HAL_GPIO_TogglePin(SYS_LED_GPIO_Port, SYS_LED_Pin);}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/*** @brief CAN Initialization Function* @param None* @retval None*/
static void MX_CAN_Init(void)
{/* USER CODE BEGIN CAN_Init 0 *//* USER CODE END CAN_Init 0 *//* USER CODE BEGIN CAN_Init 1 *//* USER CODE END CAN_Init 1 */hcan.Instance = CAN1;hcan.Init.Prescaler = 4;hcan.Init.Mode = CAN_MODE_LOOPBACK;hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;hcan.Init.TimeSeg1 = CAN_BS1_5TQ;hcan.Init.TimeSeg2 = CAN_BS2_3TQ;hcan.Init.TimeTriggeredMode = DISABLE;hcan.Init.AutoBusOff = DISABLE;hcan.Init.AutoWakeUp = ENABLE;hcan.Init.AutoRetransmission = DISABLE;hcan.Init.ReceiveFifoLocked = DISABLE;hcan.Init.TransmitFifoPriority = DISABLE;if (HAL_CAN_Init(&hcan) != HAL_OK){Error_Handler();}/* USER CODE BEGIN CAN_Init 2 *//* USER CODE BEGIN CAN_Init 2 */CAN_FilterTypeDef sFilterConfig;sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;sFilterConfig.FilterIdHigh = 0x0000; // 可以保持为0接收所有IDsFilterConfig.FilterIdLow = 0x0000;sFilterConfig.FilterMaskIdHigh = 0x0000;sFilterConfig.FilterMaskIdLow = 0x0000;sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;sFilterConfig.FilterBank = 0; // 添加过滤器组号sFilterConfig.SlaveStartFilterBank = 14;sFilterConfig.FilterActivation = ENABLE;HAL_StatusTypeDef state = HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);if (state != HAL_OK){Error_Handler();}state = HAL_CAN_Start(&hcan);if (state != HAL_OK){Error_Handler();}state = HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);if (state != HAL_OK){Error_Handler();}/* USER CODE END CAN_Init 2 *//* USER CODE END CAN_Init 2 */
}/*** @brief GPIO Initialization Function* @param None* @retval None*/
static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* USER CODE BEGIN MX_GPIO_Init_1 *//* USER CODE END MX_GPIO_Init_1 *//* GPIO Ports Clock Enable */__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOD_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(SYS_LED_GPIO_Port, SYS_LED_Pin, GPIO_PIN_SET);/*Configure GPIO pin : SYS_LED_Pin */GPIO_InitStruct.Pin = SYS_LED_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(SYS_LED_GPIO_Port, &GPIO_InitStruct);/* USER CODE BEGIN MX_GPIO_Init_2 *//* USER CODE END MX_GPIO_Init_2 */
}/* USER CODE BEGIN 4 */void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *CanHandle)
{/* Get RX message */if (HAL_CAN_GetRxMessage(CanHandle, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK){/* Reception Error */Error_Handler();}// 接收到的数据:RxData[8]// 接收到的ID值:RxHeader.StdId
}/* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

四、整个通信逻辑

CAN通信关键环节详解

1、发送端逻辑

步骤操作硬件/软件校验机制
组帧填充ID、数据、帧类型(标准/扩展)软件
CRC计算硬件自动计算15位CRC,附加到帧尾硬件CRC校验字段
发送仲裁竞争总线:低ID优先发送硬件

2. 总线传输

  • 广播特性:所有节点同时收到数据,但只有通过过滤的节点会处理。

  • 物理层校验

    • 差分信号(CAN_H/CAN_L)抗干扰

    • 显性电平(0)覆盖隐性电平(1)实现仲裁

3. 接收端逻辑

步骤操作硬件/软件校验机制
硬件过滤比较报文ID与过滤器规则硬件ID匹配
CRC校验硬件自动验证CRC,错误则丢弃硬件CRC校验
ACK响应接收节点发送ACK位(显性0)硬件ACK确认
数据存储通过校验的帧存入FIFO硬件
软件校验检查DLC、数据有效性等软件自定义校验(如和校验)

4. 硬件级校验

校验类型实现方式失败处理
CRC校验数据链路层硬件计算15位CRC自动丢弃错误帧
ACK响应数据链路层接收节点发送ACK位发送端重传
格式校验数据链路层检查帧格式(如EOF)触发错误帧

5、错误处理机制

错误类型检测方式处理动作
CRC错误硬件自动检测丢弃帧,错误计数器+1
ACK缺失发送节点未检测到ACK位自动重传(若AutoRetransmission=ENABLE)
总线离线错误计数器>255进入Bus-Off状态,需复位或等待恢复

6、应用场景建议

  • 汽车ECU:严格ID过滤 + CRC校验 + AutoRetransmission

  • 工业控制:自定义软件校验 + 长TimeSeg1抗干扰

  • 诊断工具:接收所有ID(FilterMask=0) + 软件解析

通过上述机制,CAN总线实现高可靠、实时的分布式通信。

http://www.dtcms.com/a/327225.html

相关文章:

  • 聚合搜索中的设计模式
  • 鲲鹏arm服务器安装neo4j社区版,实现图书库自然语言检索基础
  • leetcode49.字母异位词分组
  • NLP—词向量转换评论学习项目分析真实案例
  • 本地(macOS)和服务器时间不同步导致的 Bug排查及解决
  • linux 执行ls命令文件夹显示全白色
  • 微前端架构:原理、场景与实践案例
  • Rust 性能提升“最后一公里”:详解 Profiling 瓶颈定位与优化|得物技术
  • 计算机视觉(6)-自动驾驶感知方案对比
  • 使用 NetBird 创建安全的私有网络,简化远程连接!
  • Golang 语言中 Context 的使用方式
  • Rust学习笔记(二)|变量、函数与控制流
  • 【七指共振擒牛战法】副图+选股指标——多维度捕捉主升浪的量化交易利器
  • 智慧校园|智慧校园管理小程序|基于微信小程序的智慧校园管理系统设计与实现(源码+数据库+文档)
  • [Robotics_py] 定位滤波器 | 预测与更新 | 扩展卡尔曼滤波器(`EKF`)
  • Linux操作系统应用软件编程——标准IO
  • Java Stream ReduceOps
  • 负载均衡详解
  • 小程序排名优化:用户行为数据背后的提升密码
  • PostgreSQL 范围、空间唯一性约束
  • 「ECG信号处理——(23)基于ECG和PPG信号的血压预测」2025年8月12日
  • SQL 生成日期与产品的所有组合:CROSS JOIN(笛卡尔积)
  • Linux 系统运维、网络、SQL Server常用命令
  • 机器学习 [白板推导](九)[变分推断]
  • DRAM、SRAM、NAND Flash、NOR Flash、EEPROM、MRAM存储器你分得清吗?
  • 用pom文件从nexus3拉依赖,无法拉取的一个问题
  • 逻辑删除 vs 物理删除:MyBatis-Plus 实现指南与实践
  • 可泛化逻辑推理Python编程作为医疗AI发展方向研究
  • 关于数据库的restful api接口工具SqlRest的使用
  • 如何在 Ubuntu 24.04 LTS Linux 中安装 JSON Server