ADC信号采集

ADC是什么?

  • ADC作为一种外设,用于将模拟信号采集为数字信号

以下是有关ADC采样的名词

ADC的采样分辨率

ADC位数反应的是电压的分辨能力。
以ct86为例
12位ADC,采集为0-4095,其对应关系为
3V3 -> 4095
1V65 -> 2048
0V -> 0
就是
ADC的返回值 = 待测电压 / 3V3 x 4095
也就是
待测电压 = ADC的返回值 x 3V3 / 4095

时钟频率

时钟频率决定了TIM的触发频率,TIM的硬件触发可以控制ADC的采样频率

TIM的定时

定时器计数溢出就触发中断
TimeOut = ((Prescaler + 1) * (Period + 1) ) / TimeClockFren;

  • TimeOut:定时器溢出时间(us),多少触发一次TIM中断。
  • Prescaler:分频TIM时钟的预分频器值。
  • Period:计数重载值ARR,TIM计数当超过这个值,则重新计数。
  • TimeClockFren:定时器的输入时钟频率(单位MHZ),也就是当前使用的TIM所用的CLOCK的时钟频率。
    eg:TimeOut = (71+1)*(1999+1)/16 =9000us=9ms
    若采样率为100khz,就是那么TIM的计数器从0计算到ARR的频率为100khz。

采样频率

采样频率表示的是ADC的采样速度。
采样频率是每秒启动ADC取样的次数,单位为个/秒

单位换算
TIM的触发周期为 T=10us,也就是 f= 100K Hz

1ms = 1K Hz
周期越小,频率越大

采样精度

当待测电压为0.08V时,根据公式,理论返回值为100,但是其实际返回值在95-105波动,也就是有10mV的电压波动

因为测得的电压的波动。通常一个12位的ADC只能当作8-9位的理想ADC来用,8-9位就是ADC的采样精度

ADC的CUBEMX配置

* ADCs_Common_Settings:
Independent mod 独立 ADC 模式,当使用一个 ADC 时是独立模式,使用两个 ADC 时是双模式。

ADC_Settings
* Data Alignment:
Right alignment 转换结果数据右对齐,一般我们选择右对齐模式。
Left alignment 转换结果数据左对齐。
* Scan Conversion Mode:
Disabled 禁止扫描模式。如果是单通道 AD 转换使用 DISABLE。
Enabled 开启扫描模式。如果是多通道 AD 转换使用 ENABLE。
* Continuous Conversion Mode:
Disabled 单次转换。转换一次后停止需要手动控制才重新启动转换。
Enabled 自动连续转换。
* DiscontinuousConvMode:
Disabled 禁止间断模式。这个在需要考虑功耗问题的产品中很有必要,也就是在某个事件触发下,开启转换。
Enabled 开启间断模式。
 
ADC_Regular_ConversionMode:
Enable Regular Conversions 是否使能规则转换。
Number Of Conversion ADC转换通道数目,有几个写几个就行。
External Trigger Conversion Source 外部触发选择。这个有多个选择,支持定时器和软件触发。

Rank
* Channel ADC转换通道
* Sampling Time 采样周期选择,采样周期越短,
ADC 转换数据输出周期就越短但数据精度也越低,采样周期越长,
ADC 转换数据输出周期就越长同时数据精度越高。

ADC_Injected_ConversionMode:
Enable Injected Conversions 是否使能注入转换。
注入通道只有在规则通道存在时才会出现。目前用不到。
* WatchDog:
Enable Analog WatchDog Mode 是否使能模拟看门狗中断。
当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断。

ADC的HAL库函数

HAL_ADCEx_Calibration_Start(&hadcx)
ADC校准,仅仅在启用前调用一次
HAL_ADC_Start(&hadcx)
使能ADC并开始采样指定的模拟通道
HAL_ADC_PollForConversion(&hadcx, timeout);  
阻塞程序执行,直到ADC转换完成或超时
HAL_ADC_GetValue(&hadcx)
读取ADC的转换值

中断触发:
HAL_ADC_Start_IT()
ADC采集完成即触发中断程序执行
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){}
写回调函数,转换完成就更新采样值

DMA方式:
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
启动ADC并通过DMA传输数据
HAL_ADC_ConvCpltCallback()
DMA传输全部完成时触发
HAL_ADC_ConvHalfCpltCallback()
DMA传输完成一半时触发(双缓冲技术)

信号采集

采样频率的确定

graph TD A[信号频率] -->|决定|B[ADC采样率] C[TIM触发频率F_Trigger] -->|相等|B[采样频率] D[syscld时钟频率] -->|决定|E[TIM的时钟频率(PRE)] E[TIM的时钟频率(PRE)]-->|配置|C[TIM触发频率F_Trigger] F[TIM的ARR]-->|配置|C[TIM触发频率F_Trigger] G[信号源阻抗] -->|决定|H[ADC采样时间] H[ADC采样时间] -->|配置|J[ADC采样保持时间] H[ADC采样时间] -->|配置|K[ADC分辨率]

理论上必须大于最高信号频率的2倍,才不会引起混叠失真。

采样的触发

这里有软件触发和硬件触发两种,涉及到ADC配置中的External Trigger Conversion Source

软件触发

任务发起为CPU,CPU控制ADC进行转换,但是如果CPU被占用,会使得信号无法及时的被转换。
操作简单,只需要使能ADC即可
对于需要精确时间戳或同步的应用(电机控制、音频采集、多通道同步采样)是不适用的

硬件触发

  • Timer 输出
  • 外部中断线External Interrupt Line触发
  • Timer Capture Compare event
    每个通道都关联一个捕获/比较寄存器 (CCRx) 和一个专用输出引脚(可配置复用功能)。
    通道可以工作在几种模式,最相关的是 输出比较模式 (Output Compare Mode):
    在此模式下,定时器的计数器 (CNT) 会不断递增(或递减)。
    硬件会持续比较计数器值 CNT 和通道 x 的比较寄存器值 CCRx。
    当 CNT == CCRx 时,就会发生一个 比较匹配事件 (Compare Match Event),
    该比较匹配事件触发ADC

代码实现

  1. 软件触发单次顺序转换
// 校准(仅一次)
HAL_ADCEx_Calibration_Start(&hadc1);

// 主循环中
while(1) {
  HAL_ADC_Start(&hadc1);                    // 启动转换
  if(HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) {
    uint16_t val = HAL_ADC_GetValue(&hadc1); // 读取值
    printf("ADC: %d\n", val);
  }
  HAL_Delay(100);
}
  1. 软件触发单次中断
// 校准
HAL_ADCEx_Calibration_Start(&hadc1);
// 启动中断转换
HAL_ADC_Start_IT(&hadc1);
// 回调函数(用户实现)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
  if(hadc == &hadc1) {
    uint16_t val = HAL_ADC_GetValue(&hadc1);
    // 处理数据...
    HAL_ADC_Start_IT(&hadc1);  // 重新启动下一次转换
  }
}
  1. DMA连续采样
#define ADC_BUF_SIZE 100
uint32_t adc_buffer[ADC_BUF_SIZE];

// 校准
HAL_ADCEx_Calibration_Start(&hadc1);

// 启动DMA连续转换
HAL_ADC_Start_DMA(&hadc1, adc_buffer, ADC_BUF_SIZE);

// 半传输回调
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
  // 处理前50个数据: adc_buffer[0]~adc_buffer[49]
}

// 全传输回调
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
  // 处理后50个数据: adc_buffer[50]~adc_buffer[99]
}

什么是串口重定向

  1. 物理串口: 计算机或嵌入式设备上实际的 RS-232/RS-422/RS-485 等串行通信接口(通常对应 COM1, COM2, ttyS0, ttyUSB0 等)。
  2. 重定向目标: 数据流被发送到的目的地。常见目标包括:
  • 网络 (TCP/IP 或 UDP): 将串口数据封装成网络数据包,通过网络发送到另一台计算机或设备。这是最常见和强大的形式(常称为 Serial over IP, Serial to Ethernet, Console Server)。

  • 其他串口: 将一个串口的数据转发到另一个串口(本地或通过特殊硬件)。

  • 虚拟串口 (COM Port): 在操作系统层面创建一个“假的”串口(如 COM5),应用程序像操作真实串口一样读写它,但其背后连接的是网络或其他通道(网络->虚拟串口)。

  • 文件 (Logging): 将串口接收到的数据实时写入日志文件。

  • 标准输入/输出 (stdin/stdout): 在命令行环境中,将串口数据重定向到终端输入/输出流。

  • USB (模拟串口): 通过 USB 接口模拟一个串口设备(CDC ACM),本质上是将 USB 通信重定向为串口协议。

  1. 重定向软件/硬件: 执行重定向操作的实体:
  • 软件驱动/服务: 在操作系统内核或用户空间运行的程序,捕获物理串口的数据,处理后发送到目标(如网络套接字、文件、虚拟串口)。

  • 专用硬件设备 (终端服务器/控制台服务器): 独立的设备,一端连接物理串口(如连接交换机的 Console 口),另一端连接网络。它负责将串口数据转换成网络数据包传输。

实现串口重定向

posted @ 2025-07-27 20:39  loong2525  阅读(189)  评论(0)    收藏  举报