目录
正点原子的STM32F103ZET6开发板(精英版)
CUBEMX配置软件
KEIL5

右对齐就是正常的数据格式。左对齐除以16后得正常数据。(当输出非常大时考虑是否改了对齐方式,默认都是右对齐)
扫描模式,连续转换模式使能。(多通道下扫描模式自动使能)
采样周期 SamplingTime 越大越精确,越小则则会频繁触发DMA中断(在开启dma中断时,我试了在14M的adc时钟程序进不来while(因为频繁触发DMA中断)
看数据手册,知道三个adc中(adc1,adc2,adc3只有adc1和adc3能用DMA通道。

ADC的时钟不能超过14Mhz,
配置外设到内存(cubeMX自动配置好了),外设adc地址是不变的,而DMA把数据存到存储器的地址是增长的。
Circular循环模式连续搬运adc数据。
在配置DMA时,因为ad的精度是12位,最大也就是4096,而DMA转储adc是一个通道接着一个通道去存储的,所以转储的时候dma搬运半字(stm32 32位为一个字,半字16位 最大位4096*16)就可以了,节省dma资源提升速度。然后在程序里用一个缓存为uint16_t去接受就不会有问题。
__IO uint16_t adcbuf[100]={0};
开启DMA
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adcbuf,100);//
(不推荐的的一种配置,也不是不可以,接受数据缓存定义位32位)

正常情况下我们还是配置成半字长的

而我走的一个坑点就adcbuf这个DMA转移数据的缓存数组定义成立uint32_t,(在dma半字转移下)结果就翻船。。。
想着不应该啊,大类型接受小类型数据C是不会出问题的。
- int temp=0;
- for (int i=0 ;i < 100; ){
- temp=i;
- //adcreal[0]+= adcbuf[i++]*3.3/4096;
- //adcreal[1]+= adcbuf[i++]*3.3/4096;
- printf(" %d-Channel1:%d\r\n", temp,adcbuf[i++]);
- printf(" %d-Channel2:%d\r\n",temp ,adcbuf[i++]);
-
- }
依次取两个通道的数据(i为偶数是通道1,i为奇数则是通道二),看串口打印结果(两个通道,一个接3.3v一个接5v电压)

前50是3.3v电压采集,后50是接地采集结果,完全乱了。这种情况下把接受类型改成uint16_t就解决了。
定义接受缓存(定义成单字转移)
- __IO uint16_t adcbuf[100]={0};
- float adcreal[2]={0};
开启接受
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adcbuf,100);//
打印数据 (平均滤波)
- HAL_Delay(1000);
- adcreal[0]=0.0;
- adcreal[1]=0.0;
-
- for (int i=0 ;i < 100; ){
-
- adcreal[0]+= adcbuf[i++]*3.3/4096;
- adcreal[1]+= adcbuf[i++]*3.3/4096;
-
-
- }
-
- printf(" -Channel1:%1.3f\r\n",adcreal[0]/50);
- printf(" -Channel5:%1.3f\r\n",adcreal[1]/50);
- printf("\r\n");
结果

配置时单字dma转移,uint32_t类型定义缓存。
配置时半字dma转移,uint16_t类型定义接受缓存。