目录
先上结果图,DMA方式多路采集ADC数据并打印Count值和电压:
1、选择ADC1/ADC2的channel:
进入正文:打开CubeMX工程,选择好芯片时钟,然后开始配置ADC & DMA:
根据具体需要,这里举例选择ADC1的IN6 - IN9
2、配置ADC Setting参数:
在parameter settings中,主要配置ADC多路采集参数:
- Mode 模式:独立采集
- Scan Conversion Mode 扫描模式 :ENABLE
- Continuous Conversion Mode 连续转换模式:ENABLE
3、配置多路通道采集及顺序
配置有多少路ADC,这里是IN6-IN9,共4路
根据RANK1-4 配置采集顺序:其余保持默认
4、配置DMA
在ADC Configuration 参数选择DMA Settings, 点击Add,然后选择所用的ADC:
然后,针对ADC1对应的DMAChannel 1,
- 配置下DMA模式为Circular,既循环更新数据,否则默认的Normal模式触发后只执行 一次,
- 配置自增地址为Memory方式,并选择word或half word,这里选择word,是因为我程序里定义uint32_t 的数组来存储多路ADC数据的,占用四个字节既选择word
- 生成代码前要检查下时钟配置是否正常:
ADC Prescaler 这里为6,时钟为12M,最大不能超出14M
5、生成代码,修改代码:
- Generate code后,在定义一个全局数组给到DMA来存储ADC多路数据,
例如:
uint32_t ADC1_Value_DMA[4];
- 在使用之前,需要start DMA传输,这里在main() 初始化ADC之后就开始,加入代码:
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC1_Value_DMA, 4);
这里的最后一次参数4是代表有4路
- 还需要把DMA的中断注释掉,否则会一直进中断,因为我用了FreeRTOS,如果不注释会导致FreeRTOS运行异常,感觉这里DMA中断其实没有啥用,因为数据已经配置好了会实时更新到memory里,但CubeMx默认给Enable
6、使用DMA传输的ADC数据:
这样Debug运行起来,DMA就会不断的往ADC1_Value_DMA[]数组中更新RANK1-RANK4,既ADC1 IN6-IN9的采样数据,
可以增加log 代码 ,Debug打印出来,或live watch里查看:
float Channel_6 = (float)(ADC1_Value_DMA[0]&0xFFF)*3.3/4096;
float Channel_7 = (float)(ADC1_Value_DMA[1]&0xFFF)*3.3/4096;
float Channel_8 = (float)(ADC1_Value_DMA[2]&0xFFF)*3.3/4096;
float Channel_9 = (float)(ADC1_Value_DMA[3]&0xFFF)*3.3/4096;
printf("Star measure ADC1 channel 6-9\r\n");
printf("ADC1 Channel_6 Count: %d, voltage: %f \r\n",ADC1_Value_DMA[0],Channel_6);
printf("ADC1 Channel_7 Count: %d, voltage: %f \r\n",ADC1_Value_DMA[1], Channel_7);
printf("ADC1 Channel_8 Count: %d, voltage: %f \r\n",ADC1_Value_DMA[2], Channel_8);
printf("ADC1 Channel_9 Count: %d, voltage: %f \r\n",ADC1_Value_DMA[3], Channel_9);
附ADC初始化函数作为参考:
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 4;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_7;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = ADC_REGULAR_RANK_3;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = ADC_REGULAR_RANK_4;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
博主热门文章推荐:
一篇读懂系列:
LoRa Mesh系列:
网络安全系列:
- ATECC508A芯片开发笔记(一):初识加密芯片
- SHA/HMAC/AES-CBC/CTR 算法执行效率及RAM消耗 测试结果
- 常见加密/签名/哈希算法性能比较 (多平台 AES/DES, DH, ECDSA, RSA等)
- AES加解密效率测试(纯软件AES128/256)–以嵌入式Cortex-M0与M3 平台为例
嵌入式开发系列:
- 嵌入式学习中较好的练手项目和课题整理(附代码资料、学习视频和嵌入式学习规划)
- IAR调试使用技巧汇总:数据断点、CallStack、设置堆栈、查看栈使用和栈深度、Memory、Set Next Statement等
- Linux内核编译配置(Menuconfig)、制作文件系统 详细步骤
- Android底层调用C代码(JNI实现)
- 树莓派到手第一步:上电启动、安装中文字体、虚拟键盘、开启SSH等
- Android/Linux设备有线&无线 双网共存(同时上内、外网)
AI / 机器学习系列:
- AI: 机器学习必须懂的几个术语:Lable、Feature、Model…
- AI:卷积神经网络CNN 解决过拟合的方法 (Overcome Overfitting)
- AI: 什么是机器学习的数据清洗(Data Cleaning)
- AI: 机器学习的模型是如何训练的?(在试错中学习)
- 数据可视化:TensorboardX安装及使用(安装测试+实例演示)