网站首页 > 技术文章 正文
这次我们改成连续转换模式并且给它添加DMA
DMA
直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
数据可以不在CPU的干预下通过DMA快速移动,节省CPU的资源。
STM32F10xxx系列的DMA框图如图所示,不过DMA2是大容量和互联型产品才有。
在X86架构中,DMA运作时会占用系统总线周期的一部分时间,但是在STM32控制器的Cortex-M3架构中,DMA占用另外的总线,不会和cpu的系统总线发生冲突。
ADC转换后的规则组的数据都放在规则数据寄存器(ADC_DR)中,注入组的数据放在注入数据寄存器(ADC_JDRx)中。为了防止不同通道转换的数据互相覆盖,就要在转换完成后把数据取走(之前的非DMA方式)或者直接把数据传输到内存中(这次的DMA方式)。
在手册的ADC部分可以看到
扫描模式的ADC当设置了DMA位后,在每次EOC后DMA控制器会把规则组通道的转换数据传输到SRAM中。
程序编写
以两个通道的ADC为例,每次转换的过程应该是
通道1转换得到数据->通过DMA写入->通道2转换得到数据->通过DMA写入
这样循环往复,所以获得数据是两个通道采样结果交替的。
我们预先定义一个数组
uint32_t ADC_buffer[bufferlen];
来存放采样结果,然后在程序中先打开ADC和DMA
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_buffer,bufferlen); //使用DMA传输
这里的第二个参数传入的是存放数据的地址,DMA便会不断的把数据放到这里,第三个参数则是这个区域的大小。
接下来在while循环里面实现数据的读取,我们只需交替的从ADC_buffer中读取通道1和通道2的数据即可。数据转换为电压的方式和之前相同。
for(uint8_t i=0;i<bufferlen;){
printf("Channel 1=%1.4f\r\n",ADC_buffer[i++]*3.3f/4096);
printf("Channel 2=%1.4f\r\n",ADC_buffer[i++]*3.3f/4096);
}
(这里是把printf重定向为了串口打印)
我将缓冲区的长度设为10,可以看到每轮发来的数据有10个,分别是5个channel1和5个channel2,他们交替出现,一个连接GND一个连接VCC
DMA已经把数据写满了的话就会从头开始写(最开始我们选了circular嘛),那我就有一个好奇了,如果我的bufferlen不是通道数的整数倍,会不会出现错位。
比如我把bufferlen设置为9
虽然我仍然是channel1接的GND,channel2接的VCC,但是很明显数据已经乱了
因为不再是第2*i个位置存放channel1,第2*i+1个位置存放channel2
所以bufferlen应当为通道数的整数倍。
printf的重定向
为了方便的使用串口打印,可以直接把printf重定向为串口发送字符串
首先在keil中启用微库,就是Use MicroLIB
然后在keil工程中进行引用
#include "stdio.h"
并添加重定向代码。
/* USER CODE BEGIN PFP */
/* re-code printf */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 0 */
猜你喜欢
- 2025-08-06 手把手教STM8S系列单片机工程创建和下载
- 2025-08-06 杰x分享(92):51单片机基础(十四)
- 2025-05-23 STM32学习笔记-CubeMX使用
- 2025-05-23 嵌入式开发丨51、STM32、Linux点灯的区别
- 2025-05-23 【基础】STM32F103C8T6制作舵机测试仪详细图文教程
- 2025-05-23 利用Proteus仿真STM32实现DHT11温湿度检测
- 2025-05-23 《GD32开发实战指南》第13章 DAC
- 2025-05-23 51-FORTH(1): 8051计算机诞生记
- 2025-05-23 _attribute__((weak))关键字如何使用?
- 2025-05-23 终极调试利器,各种Link通吃
- 08-06中等生如何学好初二数学函数篇
- 08-06C#构造函数
- 08-06初中数学:一次函数学习要点和方法
- 08-06仓颉编程语言基础-数据类型—结构类型
- 08-06C++实现委托机制
- 08-06初中VS高中三角函数:从"固定镜头"到"360°全景",数学视野升级
- 08-06一文讲透PLC中Static和Temp变量的区别
- 08-06类三剑客:一招修改所有对象!类方法与静态方法的核心区别!
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (70)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)