adc+dma
时间: 2025-05-18 19:18:08 浏览: 25
### 关于ADC与DMA的实现方法
#### 配置独立模式下的ADC初始化
在STM32微控制器中,可以通过`ADC_InitTypeDef`结构体来完成ADC模块的基础配置。以下是典型的初始化设置:
```c
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 设置ADC工作模式为独立模式[^1]
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 不使用外部触发转换
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 启用扫描模式
ADC_InitStructure.ADC_NbrOfChannel = 4; // 设置通道数量为4个
ADC_Init(ADC1, &ADC_InitStructure);
```
上述代码片段展示了如何通过软件配置使能多个ADC通道并启用扫描功能。
---
#### 利用DMA传输数据至内存缓冲区
为了提高效率,在实际应用中通常会结合DMA(Direct Memory Access)技术自动处理数据传输任务。下面是一个简单的例子展示如何利用DMA读取多路模拟信号并将它们存储到指定位置。
##### 定义全局变量和缓冲区
首先需要定义用于保存采样结果的数据缓冲区以及标志位指示操作状态:
```c
#define CHANNELS 3 // 宏定义表示使用的总共有几个输入端口[^3]
#define POINTS 256 // 每一路最多可以获取多少样本点数
uint16_t adc_buffer[POINTS][CHANNELS] = {0}; // 创建一个二维数组作为接收容器
volatile bool adc_finish = false; // 声明布尔型变量用来同步进程结束情况
```
这里创建了一个大小固定的二维整型数组 `adc_buffer` 来容纳来自三个不同传感器或者源设备上的数值记录;同时引入了另一个易失性的逻辑开关量 `adc_finish` ,它将在每次完整的周期完成后被更新一次从而通知其他部分程序继续执行下一步动作。
---
#### 开始转换过程并通过中断机制管理事件流
当一切准备就绪之后就可以启动真正的测量流程了。这一步骤涉及到调用库函数开启硬件资源,并且监听特定条件满足与否以便采取相应措施。
```c
LL_ADC_REG_StartConversionSWStart(ADC1); // 软件触发改寄存器开始新一轮序列化采集活动[^2]
LL_ADC_REG_SetFlagEndOfConversion(ADC1, LL_ADC_REG_FLAG_EOC_SEQUENCE_CONV);
if (LL_ADC_IsActiveFlag_EOCS(ADC1)) {
uint16_t raw_data = LL_ADC_REG_ReadConversionData12(ADC1); // 获取当前已完成项目的原始计数值
double voltage_value = ((double)raw_data / 4096) * 3.3; // 将其转化为对应的实际电压等级
LL_ADC_ClearFlag_EOCS(ADC1); // 清除EOC状态以防干扰后续判断逻辑
}
```
此段脚本说明了怎样手动查询每一个单独的结果项直至整个批次全部完毕为止。然而这种方法存在明显的缺点——即CPU会被迫处于繁忙等待的状态之中浪费大量宝贵时间片。因此更推荐采用基于异常响应式的策略来进行优化改进版本如下所示。
---
#### 结合DMA增强性能表现
最后介绍一种更为高效的方式就是让DMA接管所有的搬运事务而无需频繁打扰核心处理器参与其中的具体细节管理工作。这样不仅可以显著减轻负担而且还能有效提升吞吐率水平达到双赢的效果目标!
```c
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
if(hadc->Instance==ADC1){
adc_finish=true; // 当接收到回调消息时立即将标记设为真值告知外界已经成功收集到了所需资料集
}
}
HAL_StatusTypeDef status=HAL_OK;
status=HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&adc_buffer,sizeof(adc_buffer)/sizeof(uint16_t));
if(status!=HAL_OK){
Error_Handler(); // 如果发生错误则跳转进入专门设计好的错误处理子例程当中去尝试修复问题所在之处。
}
```
在这里我们注册了一个自定义类型的回调函数每当一组新的数据包准备好可供访问的时候就会立即激活这个特殊的服务例行公事进而改变共享对象属性值最终达成目的。
---
### 总结
综上所述,本文介绍了几种不同的途径可用于实现模数转换器的功能扩展及其配套支持服务的设计思路和技术要点等内容。希望对你有所帮助!
阅读全文
相关推荐


















