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

STM32之ADC详解

一、ADC概述       

        ADC(模拟量转数字量转换器),在 STM32 开发中,利用 ADC 端口的电压数据,转换为对应的具体数字量数据内容。可通过 ADC 方式获取常用数据内容有:

  • 光敏电阻、电池电量、油箱油量

        ADC 转换的数据,可用于执行器控制行为,如低电量警告、油箱油量不足警告(即【阈值警告】 【阈值处理】 ,通过设置阈值,数据达到或超出时触发相应警示或控制逻辑 ) 。

二、ADC 工作原理

1.ADC 的主要特征

2. ADC 内部架构框图

一、整体架构与核心组件

  1. 模拟输入部分
    • 外部输入通道ADCx_IN0 ~ ADCx_IN15 是 16 组外部模拟信号输入引脚,可连接光敏电阻、电压传感器等外设,采集外部模拟电压。
    • 内部传感器:集成温度传感器(需结合 V_REFINT 参考电压工作 ),用于检测芯片内部温度,方便实现温度补偿、过热保护等功能。
    • 模拟多路开关:最多支持 16 通道规则通道、4 通道注入通道切换,按需选通一路模拟信号送入转换器,实现多通道分时复用。
  2. 转换核心
    • 模拟至数字转换器:采用逐次逼近法,以 ADCCLK(来自 ADC 预分频器,需配置分频保证时钟稳定 )为基准时钟,将模拟电压与内部基准电压比较,逐位确定数字量,完成 0~3.3VVref+ = 3.3VVref- = 0V 时 )模拟信号到 12 位数字量(范围 0000 0000 0000 ~ 1111 1111 1111 )的转换。
    • 参考电压V_REF+V_REF- 是 ADC 转换基准,决定量程。3.3V 输入时,电压分辨率为 3.3V/4096 ≈ 0.0008V,即 1 个数字量对应约 0.8mV 电压变化。

二、通道与转换模式

  1. 规则通道
    • 通道特点:最多 16 通道,用于常规、连续的多通道采样,像循环采集电池电压、多路传感器数据。
    • 触发控制:通过 EXTSEL[2:0] 选择定时器触发源(如 TIM1_CH1TIM2_CH2 等 ),实现定时采样;也可由外部中断触发,灵活适配不同场景需求。
    • 数据存储:转换结果存入 规则通道数据寄存器(16 位),支持 DMA 请求,转换完成后直接通过 DMA 传输数据到内存,减轻 CPU 负担。
  2. 注入通道
    • 通道特点:最多 4 通道,优先级高于规则通道,用于紧急、需快速响应的采样(如安全阈值监测 )。
    • 触发控制:由 JEXTSEL[2:0] 选定时器触发源(如 TIM1_TRGOTIM4_CH3 等 ),或 JEXTRIG 控制位手动触发。
    • 数据存储:结果存入 注入通道数据寄存器(4×16 位),可独立处理,快速响应特殊需求。

三、中断与阈值监测(模拟看门狗)

  1. 中断机制
    • 转换结束中断:规则通道(EOC)、注入通道(JEOC)转换完成时,置标志位并可使能中断,触发 ADC中断 到 NVIC,通知 CPU 读取数据,实现实时处理。
    • 阈值中断:模拟看门狗比较转换结果与 阈值高限(12 位)阈值低限(12 位),超出范围置 AWD 标志位,使能中断(AWDIE)后触发中断,用于电压超限报警(如电池过压 / 欠压、传感器异常 )。
  2. 模拟看门狗:实时监控 ADC 转换结果,一旦超出设定阈值,立即触发中断或标志位,快速响应异常,保障系统安全。

四、工作流程总结

  1. 信号输入:外部 / 内部模拟信号经 ADCx_IN 或内部传感器进入,模拟多路开关选通通道。
  2. 触发转换:规则 / 注入通道通过定时器、外部中断等触发,启动 模拟至数字转换器 工作。
  3. 数据转换:逐次逼近法转换模拟电压为 12 位数字量,存入对应数据寄存器。
  4. 结果处理:可触发中断通知 CPU 读取,或通过 DMA 传输数据;模拟看门狗实时监测,超限触发报警,实现从模拟信号采集到数字信号处理、异常响应的完整流程,支撑 STM32 对模拟量的精准采集与智能控制 。

五、举例讲解

一、场景与需求

  • 常规任务:每隔 100ms 采集 3 路信号
    • 电池电压(ADC1_IN0,规则通道)
    • 车外温度(ADC1_IN1,规则通道,接温度传感器)
    • 光照强度(ADC1_IN2,规则通道,接光敏电阻)
  • 紧急任务:实时监测电池电压,一旦超出 2.8V~3.6V 范围,立即触发报警
    • 复用电池电压信号到 ADC1_IN8(注入通道,优先级更高)

二、工作流程拆解(多转换触发逻辑)

1. 硬件连接与通道准备
  • 外部信号接入
    • 电池电压、温度传感器、光敏电阻的模拟信号,分别接到 ADC1_IN0/IN1/IN2(规则通道);
    • 电池电压同时接到 ADC1_IN8(注入通道,用于紧急阈值监测)。
  • 多路开关配置
    • 规则通道:使能 IN0/IN1/IN2,共 3 路,用于循环采样;
    • 注入通道:使能 IN8,共 1 路,用于紧急监测。
2. 触发转换的两种方式

(1) 规则通道触发(常规采集)

 
  • 触发源:定时器触发(如 TIM3_TRGO,配置为 100ms 触发一次)。
  • 流程
    ① 定时器每 100ms 产生一个触发信号 → 触发规则通道转换;
    ② 模拟多路开关按顺序选通 IN0IN1IN2
    ③ ADC 依次对 3 路信号进行转换(逐次逼近法),结果存入规则数据寄存器
 

(2) 注入通道触发(紧急监测)

 
  • 触发源:软件触发 + 模拟看门狗(双重保障)。
  • 流程
    ① 初始触发:系统启动时,手动触发一次注入通道转换(读取初始电池电压);
    ② 持续监测:ADC 转换后,模拟看门狗自动比较结果与阈值(2.8V~3.6V):
    • 若在范围内:不触发中断,等待下一次规则通道触发时,顺带重新触发注入转换(或定时触发);
    • 若超出范围:立即置 AWD 标志位 → 触发注入中断 → CPU 跳转到中断函数处理(如点亮故障灯、记录日志)。
3. 数据处理与响应
  • 规则通道数据
    转换完成后,通过 DMA 自动将 3 路结果搬运到内存数组 → 程序读取数组,计算电池电量、温度值、光照强度,更新仪表盘显示。

  • 注入通道数据
    若触发中断(电压超限):
    ① 中断函数中读取注入数据寄存器 → 获取实时电池电压;
    ② 执行紧急逻辑(如:点亮红色故障灯、发送 CAN 报警帧、限制非关键用电设备)。

4. 多转换并行的关键逻辑
  • 优先级:注入通道优先级 > 规则通道。若规则通道转换中触发注入中断,ADC 会暂停规则转换,优先处理注入通道,保障紧急任务响应。
  • 资源复用:同一模拟信号(如电池电压)可接入多个通道(规则 + 注入),实现 “常规轮询 + 紧急监测” 的差异化需求。

3. ADC 数据转换规则

ADC 转换核心信息:

  • 转换方法:ADC 转换器采用逐次逼近法进行数据转换
  • 采样精度:12 位,数值范围 0000 0000 0000 ~ 1111 1111 1111(对应十进制 0 ~ 4095 )
  • 参考电压Vref+ = 3.3VVref- = 0V
  • 电压分辨率3.3V / 4096 ≈ 0.0008V(即 1 个 ADC 数值对应约 0.8mV 电压 )
  • 示例场景:假设 ADC 读取到电压为 1.83V ,可基于上述参数换算数字量

三、ADC 编程实现和相关寄存器

1.  ADC 时钟问题

  • 分析依据:根据原理图进行分析
  • 引脚与通道对应:当前引脚为 PF8 引脚,其对应的 ADC 通道是 ADC3_IN6
  • 时钟归属:ADC3 所在的时钟为 APB2 总线时钟,即 ADC3 的时钟由 APB2 总线提供 ,在 STM32 中,不同的外设会挂载在不同的总线(如 APB1、APB2 等 )上,其时钟由对应总线时钟源分频等配置后提供,这里明确了 ADC3 依赖 APB2 总线时钟来进行工作时序的驱动 。

2. ADC_CR1 寄存器

3. ADC_CR2 寄存器

        当前寄存器主要控制,ADC 采用数据通道,通信触发规则,数据对齐方式,校验和 ADC开启。

ADC_CR2寄存器的配置内容:

  • SWSTART(位 22):置 1,用于开始规则通道的转换
  • EXTTRIG(位 20):置 1,使能规则通道的外部触发转换模式
  • EXTSEL(位 19 - 17):设为 111,选择启动规则通道组转换的外部事件
  • ALIGN(位 11):置 0,配置数据右对齐
  • RSTCAL(位 3):置 1,执行复位校准操作
  • CAL(位 2):置 1,进行 A/D 校准
  • CONT(位 1):置 1,使能连续转换模式
  • ADON(位 0):置 1,开启 A/D 转换器 ,各配置项共同定义了 ADC 的转换启动、触发、校准、数据对齐及运行模式等关键参数 。

4. ADC_SMPR 寄存器

5. ADC_SQR 寄存器

在 ADC 规则通道配置中,需两个寄存器配合实现:

  • ADC_SQR1:用于配置规则通道开启的数量(即决定要转换的规则通道总数 )。
  • ADC_SQR3:用于配置 SQ1(规则通道序列中的第 1 个转换通道 )寄存器位对应的具体通道,此处为 ADC3_IN6(指定第 1 个转换的规则通道是 ADC3 的 IN6 通道 ) 。

四、示例代码:

adc.c:

#include "adc.h"void LSEN_Init(void)
{// 1. RCC 时钟使能,需要提供 GPIOF 和 ADC3 RCC->APB2ENR |= (0x01 << 7) | (0x01 << 15);// 2. GPIOF --> PF8 模拟输入模式 ==> 0000GPIOF->CRH &= ~(0x0F);/*3. ADC 配置*//*3.1 ADC 预分配倍数配置因为当前 STM32F103ZET6 对应 72 MHz,ADCCLK 不得大于 14 MHz,预分频倍数最小可以选择 6*/RCC->CFGR &= ~(0x03 << 14);RCC->CFGR |= (0x02 << 14);/*3.2 配置 ADC 的工作通道选择工作通道为 ADC3_IN6,规则通道打开一个,配置 SQ1*/ADC3->SQR1 &= ~(0x0F << 20);ADC3->SQR3 &= ~(0x1F);ADC3->SQR3 |= 0x06;/*3.3 ADC 采用周期采样周期选择 239.5 + 12.5 最大 ADC 采样周期,可以获取到更大的数据精度。*/ADC3->SMPR2 |= (0x07 << 18);/*3.4. 配置 ADC CR 寄存器相关内容CR1- DUALMOD位 [19:16] : ADC 独立模式 ==> 0000- SCAN [位8] :  扫描模式关闭 ==> 0CR2- SWSTART [位22] : 开始转换规则通道 ==> 1- EXTTRIG [位20]:规则通道的外部触发转换模式 ==> 1- EXTSEL [位19:17]: 选择启动规则通道组转换的外部事件 ==> 111- ALIGN [位11]::数据对齐(Data alignment)  ==> 0 右对齐- CONT [位1]::连续转换(Continuous conversion) ==> 1*/ADC3->CR1 &= ~(0x0F << 16);ADC3->CR1 &= ~(0x01 << 8);ADC3->CR2 &= ~(0xFFFFFFFF);ADC3->CR2 |= (0x01 << 22);  // SWSTART [位22] : 开始转换规则通道 ==> 1ADC3->CR2 |= (0x01 << 20);  // EXTTRIG [位20]:规则通道的外部触发转换模式 ==> 1ADC3->CR2 |= (0x07 << 17);  // EXTSEL [位19:17]: 选择启动规则通道组转换的外部事件 ==> 111ADC3->CR2 &= ~(0x01 << 11); // ALIGN [位11]::数据对齐(Data alignment)  ==> 0 右对齐ADC3->CR2 |= (0x01 << 1);/*3.5 ADC 复位 + 校准ADC 自校准 + 重启过程- RSTCAL [位3]::复位校准(Reset calibration) ==> 1	- CAL [位2]::A/D校准(A/D Calibration) ==> 1- ADON [位0]::开/关A/D转换器(A/D converter ON/ OFF) ==> 1*/ADC3->CR2 &= ~(0x01); // 关闭 ADCDelay_ms(10);         // 延时 10 msADC3->CR2 |= 0x01;    // 打开 ADC/*开始复位校准,给予对应寄存器标志位 1,如果 ADC 复位校准结束对应寄存器位置硬件清除为 0*/ADC3->CR2 |= (0x01 << 3); // while 循环是等待当前复位校准结束 while ((ADC3->CR2 & (0x01 << 3)));Delay_ms(10); /*开始 A/D 校准,给予对应寄存器标志位 1,ADC A/D 校准之后对应寄存器位置硬件清除为 0*/ADC3->CR2 |= (0x01 << 2);// while 循环是等待当前 A/D 校准结束 while ((ADC3->CR2 & (0x01 << 2)));ADC3->CR2 |= 0x01;    // 打开 ADC
}u16 LSEN_GetValue(void)
{/*ADC->SR 状态寄存器 EOC [位1] 位置,如果数据未转换完成EOC 为 0 ,转换完成 EOC 为 1*/while (!(ADC3->SR & (0x01 << 1)));return ADC3->DR;}

adc.h:

#ifndef _ADC_H
#define _ADC_H#include "stm32f10x.h"#include "delay.h"/*** @brief 光敏电阻初始化函数*/
void LSEN_Init(void);u16 LSEN_GetValue(void);#endif

delay.c:

#include "delay.h"void Delay_us(u32 us)
{while (us--) {// 利用 __NOP() 操作占用 MCU 一次执行周期特征,调用 72 个 __NOP// 不建议使用 for 循环或者 while 循环,循环判断都需要占用一个 MCU 执行周期__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();}
}void Delay_ms(u32 ms)
{Delay_us(ms * 1000);
}

delay.h:

#ifndef _DELAY_H
#define _DELAY_H#include "stm32f10x.h"/*** @brief 延时微秒控制函数,延时单位是 us** @param us 延时微秒时间*/
void Delay_us(u32 us);/*** @brief 延时毫秒控制函数,延时单位是 ms** @param ms 延时毫秒时间*/
void Delay_ms(u32 ms);#endif

usart.c:

#include "usart1.h"USART1_Data usart1_val = {0};void USART1_Init(u32 brr)
{/*1. 时钟使能 GPIOA 和 USART1,两者都在 APB2 时钟控制USART1 对应位 14,GPIOA 对应位2*/RCC->APB2ENR |= (0x01 << 2) | (0x01 << 14);/*2. PA9 和 PA10 GPIO 配置PA9 是 MCU 的 TX 数据发送端,GPIO 工作模式选择【复用推挽输出模式】PA10 是 MCU 的 RX 数据发送端,GPIO 工作模式选择【浮空输入模式】*/GPIOA->CRH &= ~(0x00FF << 4);GPIOA->CRH |= 0x0B << 4;  // PA9 -->  TX【复用推挽输出模式】GPIOA->CRH |= 0x04 << 8;  // PA10 --> RX【浮空输入模式】/*3. USART1 串口配置3.1 8n1 配置,NRZ 数据格式配置,8个数据位,0 个校验位,1 个停止位3.2 USART1 对应 TE 和 RE 开启,打开 USART1 的发送数据和读取数据能力3.3 USART1 BRR 波特率配置*/// 3.1 8n1 配置,如果仅使用寄存器方式配置当前代码,可以省略一下过程// 当前代码是为了后续的 【标准库】和【Hal库】,也是代码逻辑的一部分USART1->CR1 &= ~(0x01 << 12); // 【8】USART1->CR1 控制寄存器对应 M (位12) 明确当前数据字长为 8 数据位USART1->CR1 &= ~(0x01 << 10); // 【n】USART1->CR1 控制寄存器对应 PCE (位10), 明确当前不使用校验位USART1->CR2 &= ~(0x03 << 12); // 【1】USART1->CR2 控制寄存器对应 STOP (位13,12), 限制当前数据停止位为 1// 3.2 USART1 对应 TE 和 RE 开启USART1->CR1 |= (0x03 << 2); // TE(位3) RE(位2) 进行赋值 1 开始操作// 3.3 USART1 BRR 波特率配置// 假设波特率是 115200 ==> USARTDIV 数据float usart_div = 72 * 1000 * 1000 / (16 * brr);// usart_div == 39.0625/*将 usart_div 进行拆解,分别对应整数部分和小数部分内容,提供给当前 USART1 中用于计算波特率对应寄存器位。*/int usart_div_Mantissa = (u32)usart_div;int usart_div_fraction = (u32)((usart_div - usart_div_Mantissa) * 16);// 两个数据进行组合 提供给 USART1 波特率寄存器的数据为 USART1->BRR |= (usart_div_Mantissa << 4) | usart_div_fraction;// 4. 启动 USART1 USART1->CR1 |= (0x01 << 13);
}void USART1_SendByte(u8 byte)
{/*利用 USART1_SR 寄存器,判断之前的数据内容是否发送完成,如果没有发送完成,本次发送操作进入【阻塞状态】如果 USART1_SR TC ==> 0 表示之前的数据发送未完成如果 USART1_SR TC ==> 1 表示之前的数据发送完毕TC Transmission Complete*/while (0 == (USART1->SR & (0x01 << 6)));/*将需要发送的数据存储到 USART1->DR 数据寄存器中,DR 会将数据直接提供给 TDR 寄存器,TDR 寄存器会将数据提供给移位寄存器,SR 寄存器 TC TC 寄存器位置 0发送完毕会将 SR 寄存器的中,TC 寄存器位置修改为 1*/USART1->DR = byte;
}void USART1_SendBuffer(u8 *buffer, u16 count) 
{while (count--){USART1_SendByte(*buffer);buffer++;}
}void USART1_SendString(const char * str) 
{while (*str){USART1_SendByte(*str);str++;}
}u8 USART1_ReceiveByte(void)
{u8 data = 0;/*判断在 USART1->SR 寄存器中,对应的 RXNE (Read data register not empty) 标志位如果没有数据可以收到,RXNE 为 0如果有数据可以读取,RXNE 为 1while 进行 RXNE 标志位判断,如果没有数据当前循环【阻塞后续代码】*/while (0 == (USART1->SR & (0x01 << 5)));data = (u8)USART1->DR; return data;
}/*
非重要知识点,仅实现 printf 函数功能重定向,可以实现
printf 打印操作数据 USART1 发送到 PC
*/
int fputc(int c, FILE *stream)
{USART1_SendByte(c);return c;
}void USART1_Interrupt_Enable(void)
{/*当前 USART1 的控制寄存器中,打开 IDLEIE 数据总线空闲中断使能打开 RXNEIE 数据总线空闲中断使能*/USART1->CR1 |= (0x01 << 4) | (0x01 << 5);/*设置当前 USART1 对应的中断优先级为 0001 在全局优先级设置为 2 的情况下  占先 0 次级 1*/NVIC_SetPriority(USART1_IRQn, 1); // 0001 占先 0 次级 1/*告知当前 MCU 使能对应的 USART1_IRQn 中断*/NVIC_EnableIRQ(USART1_IRQn);
}/*
完成 USART1 对应的 USART1_IRQn 对应的中断处理函数
当前中断处理函数是用于接收的数据内容进行处置操作,将接收的数据
存储到 USART1_Data 结构体中,对应的 u8 data[DATA_SIZE] 数组
*/
void USART1_IRQHandler(void)
{u32 val = 0;/*usart1_val.flag ==> 1 表示当前数据接收完毕,同时已经回显到PC 端 USART 工具*/if (usart1_val.flag){// 对当前数据空间进行擦除,memset(&usart1_val, 0, sizeof(USART1_Data));}/*如果当前触发的中断为 【RXNE 中断】,表示数据在通过串口传递到 MCU 中*/if (USART1->SR & (0x01 << 5)){usart1_val.data[usart1_val.count++] = USART1->DR;/*当前接收到的有效字节个数 == DATA_SIZE,当前数据缓冲区数组已满*/if (DATA_SIZE == usart1_val.count){USART1_SendBuffer(usart1_val.data, usart1_val.count);usart1_val.flag = 1;}}/*如果当前数据总线空闲 【IDLE 中断】,表示数据传递完毕*/if (USART1->SR & (0x01 << 4)){/*表示当前数据接收已完成*/usart1_val.flag = 1;/*需要完成对于当前 USART1->SR IDLE 数据总线空闲中断标志位进行清除操作。【官方要求】1. 读取 USART1->SR 寄存器2. 读取 USART1->DR 寄存器*/val = USART1->SR;val = USART1->DR;// 将数据回显到 PC 端 USART 调试工具USART1_SendBuffer(usart1_val.data, usart1_val.count);}
}

usart.h:

#ifndef _USART1_H
#define _USART1_H#include "stm32f10x.h"#include "stdio.h"
#include "stdlib.h"
#include "string.h"#define DATA_SIZE (256)typedef struct usart1_data
{u8 data[DATA_SIZE]; // 接受数据缓冲区u8 flag;            // 数据处理标志位u16 count;           // 读取到的有效字节个数
} USART1_Data;extern USART1_Data usart1_val;/*** @brief USART1 初始化函数,需要完成*     1. PA9 和 PA10 GPIO 配置*     2. USART1 配置** @param brr 用户提供的对应当前 USART1 的波特率*/
void USART1_Init(u32 brr);/*** @brief USART1 发送一个字节数据到其他设备** @param byte 发送的字节数据。*/
void USART1_SendByte(u8 byte);void USART1_SendBuffer(u8 *buffer, u16 count);void USART1_SendString(const char * str);/*** @brief USART1 接受外部输入的数据内容,当前函数是接收一个字节数据** @return 返回值是接收到的数据内容*/
u8 USART1_ReceiveByte(void);/*
后续代码中需要利用【中断】对代码内容进行优化1. 接收数据终止条件2. 提供外部可以持续使用数据内容3. 数据发送中断判断
*//*** @brief USART1 串口中断使能函数*/
void USART1_Interrupt_Enable(void);#endif

main.c:

#include "stm32f10x.h"//#include "led.h"
//#include "key.h"
#include "delay.h"
//#include "beep.h"
#include "usart1.h"
#include "adc.h"int main(void)
{//Led_Init();LSEN_Init();USART1_Init(115200);USART1_Interrupt_Enable();//Led1_Ctrl(1);while (1){u16 adc_data = LSEN_GetValue();printf("adc_data : %d\r\n", adc_data);printf("U_LSEN : %f\r\n", 3.3 / 4096 * adc_data);Delay_ms(500);}
}

https://github.com/0voice
http://www.dtcms.com/a/345026.html

相关文章:

  • [系统架构设计师]大数据架构设计理论与实践(十九)
  • ​维基框架 (Wiki Framework) 1.1.0 版本发布​ 提供多模型AI辅助开发
  • TNS(ORACLE)协议分析
  • [硬件电路-162]:PID参数受哪些因素影响?
  • 【Redis】缓存和分布式锁
  • MySQL - 视图,事务和索引
  • AAA 服务器与 RADIUS 协议笔记
  • C语言初学笔记【联合与枚举】
  • Unreal Engine USceneComponent
  • 如何实现二维CAD与3D建模工程图关联一体化出图 | 中望3D 2026新亮点
  • android sdk 虚拟机是否可以通过命令行打开?
  • 数字逻辑与数字系统设计之电梯控制器设计
  • 防爆连接器在防爆箱上的作用
  • shell脚本第二阶段-----选择结构
  • Unreal Engine IWYU Include What You Use
  • DLT645仪表通信,串口助手调试读写地址
  • 【C#】观察者模式 + UI 线程调度、委托讲解
  • vuex如何在js文件中使用
  • NVIDIA GB200 架构详解及与 B200/H200/H100 的区别
  • 【芯芯相印】芯片设计生产全流程核心技术术语与实践指南:从架构定义到量产交付的完整图谱
  • NLP学习之Transformer(2)
  • 数据预处理学习笔记
  • Thunderbird 将推出在德国托管的加密电子邮件服务
  • Android Jetpack | Hilt
  • 快速了解深度学习
  • 数学建模--Topsis(Python)
  • 学习python第12天
  • 第5.3节:awk数据类型
  • gcc 和 make 命令
  • 机试备考笔记 17/31