历史上的今天
返回首页

历史上的今天

今天是:2024年09月06日(星期五)

正在发生

2019年09月06日 | STM32 ADC多通道采样声音传感器和环境光传感器

2019-09-06 来源:eefocus

一、DMA

  直接存储器存取(Direct Memory Access,DMA),直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。


二、ADC连续模式和扫描模式

  ADC单通道时,只进行一次ADC转换,关闭连续转换模式,扫描模式关闭,这样ADC通道转换完成后停止,等待ADC转换的下一次启动。进行连续ADC转换时,ADC配置为连续转换模式,扫描模式关闭,ADC通道,转换一次后,接着进行下一次转换,不断连续。


  ADC多通道时,要使能扫描模式。如果关闭连续转换模式,ADC多个通道,按照配置的顺序依次转换一次完成后,就停止转换。使能连续转换模式,ADC多个通道按照配置的顺序依次转换完成后,接着继续从头按照配置顺序依次转换,不断连续。


当多通道开启扫描模式时,不能直接读取AD转换数据,需要通过DMA方式读取


三、STM32CubeMx配置

声音传感器模块


光传感器模块


1.将PA4和PA6配置成ADC模式


2.打开ADC1的通道9和通道11,发现PA4和PA6变成绿色,GPIO模式也自动变成ADC转换模式

3.使能外部高速时钟

4.然后是配置时钟点击Clock Configuration,由于先打开了ADC而没有配置时钟,点到时钟配置时会显示

点No就好了,继续配置

5.使能DMA,增量地址选择内存,数据长度为字,连续传输模式

6.配置ADC参数

ADC 要完成对输入电压的采样需要若干个 ADC_CLK 周期,计算公式:


TCONV = 采样时间 + 12.5,所以ADC采样周期 = (2.5+12.5)= 15个周期,ADC完成采样的时间 = 1/fadc_clk * (ADC采样周期)。


7.使能ADC中断


8.使能串口

生成代码


四、Keil编写程序

在uart.c中做printf、scanf的重定向以便于串口通信


 

#include

 

#ifdef __GNUC__

 

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

 

#else

 

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

 

#endif

 

PUTCHAR_PROTOTYPE

 

{

 

HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);

 

return ch;

 

}

 

int fgetc(FILE *f)

 

{

 

    uint8_t ch;

 

    HAL_UART_Receive(&huart1,(uint8_t *)&ch,1,0xfff);

 

    return ch;

 

}

在adc.c中void MX_ADC1_Init(void)是ADC的初始化,与STM32CubeMX中配置的一样,也可以在此处修改

第一种ADC多通道采样方法:

1.在main.c定义一个数组作为转换数据缓存数组


  /* USER CODE BEGIN 1 */

 

uint32_t ADC_Value[100];

 

uint8_t i ;

 

uint32_t ad1,ad2 ;

 

  /* USER CODE END 1 */

 


2.在while(1)前函数去开启ADC转换和DMA传输


/* USER CODE BEGIN 2 */

 

HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_Value,100);

 

  /* USER CODE END 2 */

 

3.DMA采用了连续传输的模式,ADC采集到的数据会不断传到到存储器中(此处即为数组ADC_Value)。数组里面的数据会不断被刷新。由于ADC顺序先是通道9(声音传感器)再是通道11(环境光传感器),所以存到ADC_Value[0]的是声音传感器ADC采集到的数据,ADC_Value[1]是环境光传感器ADC采集的数据,依此类推数组偶数存的是通道9(声音传感器)ADC采样值,数组级数存的是通道11(环境光传感器)ADC采样值。


/* USER CODE BEGIN WHILE */

 

  while (1)

 

  {

 

    HAL_Delay(500);

 

    for(i = 0,ad1 = 0, ad2 = 0; i<100;)

 

    {

 

        ad1 += ADC_Value[i++] ;

 

        ad2 += ADC_Value[i++] ;

 

    }

 

    ad1 /=50 ;

 

    ad2 /=50 ;

 

    printf("rn******** ADC DMA Example ********rnrn");

 

 

 

    printf("adc1 = %drn",ad1);

 

    printf("adc2 = %drn",ad2);

 

 

 

    printf("Voice Voltage: %.3fVrn",ad1*3.3f/4096);

 

    printf("Light Voltage: %.3fVrn",ad2*3.3f/4096);

 

 

 

    printf("rn********End ADC Example ********rn");

 

    HAL_Delay(1000);

 

 

 

    /* USER CODE END WHILE */

 

 

 

    /* USER CODE BEGIN 3 */

 

  }

 

  /* USER CODE END 3 */

将数组偶数下标数据加起来求平均值得到通道9(声音传感器)ADC采样值,将数组偶数下标数据加起来求平均值得到通道11(光传感器)ADC采样值,减小误差,再将数据转换为电压值。


ADC采样值到电压的转换:


ADC12位分辨率,也就是说ADC模块读到的数据是12位的数据。。二进制的12位可表示0-4095个数。 电压值 = ADC采样值*(3.3V/4096)


第二种ADC多通道采样方法:

ADC的几个回调函数:


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);


void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc);


void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc);


void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc);


ADC中断、DMA传输、看门狗超过阀值、发生Adc错误,这些函数返回前都调用了Callback函数。用来在非中断模式下处理Adc数据,如果想进行一些操作可以直接修改Callback函数。


查看HAL_ADC_Start_DMA()函数

在HAL_ADC_Start_DMA()里会设置函数ADC_DMAConvCplt

在ADC_DMAConvCplt里有回调函数HAL_ADC_ConvCpltCallback()


HAL_ADC_ConvCpltCallback()是虚函数,需要重新定义。


因为ADC转换和DMA传输很快,采样到的值可能还没读出来就被新的覆盖掉,可设置标志位当采样到的值传输到DMA之后停止,等到把DMA中的值读出来再启动,这就需要用到回调函数


在main函数


1.设置全局变量标志位


/* USER CODE BEGIN 0 */

 

int flag = 0 ;

 

/* USER CODE END 0 */

 


2.定义一个数组作为转换数据缓存数组,因为每次转换传输之后都会暂停等待数据被读出来所以可以设置数组小一点


/* USER CODE BEGIN 1 */

 

uint32_t ADC_Value[2];

 

  /* USER CODE END 1 */

 


 


3.ADC转换和DMA数组传输开始


 /* USER CODE BEGIN 2 */

 

HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_Value,2);

 

  /* USER CODE END 2 */

 


4.在main函数外定义虚函数HAL_ADC_ConvCpltCallback回调函数,当ADC转换和DMA传输完成后,将标志位置为1并停止ADC转换和DMA传输


/* USER CODE BEGIN 4 */

 

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

 

{

 

flag=1;

 

HAL_ADC_Stop_DMA(hadc);

 

}

 

/* USER CODE END 4 */

 


  5.在main函数while(1)里,当标志位为1的时候,将标志位置0并将采样值读出来,然后启动ADC转换和DMA传输。  


/* USER CODE BEGIN WHILE */

 

  while (1)

 

  {

 

    if(flag==1)

 

    {    

 

        flag=0;

 

        HAL_Delay(200);

 

        printf("rn******** ADC DMA Example ********rnrn");

 

        printf("rnch1 = %drn",ADC_Value[0]);

 

        HAL_Delay(200);

 

        printf("ch2 = %drn",ADC_Value[1]);

 

 

 

        printf("Voice Voltage: %.3fVrn",ADC_Value[0]*3.3f/4096);

 

        printf("Light Voltage: %.3fVrn",ADC_Value[1]*3.3f/4096);

 

        printf("rn********End ADC Example ********rn");

 

        HAL_Delay(1000) ;

 

    }

 

    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 2);

 

 

 

    /* USER CODE END WHILE */

 

 

 

    /* USER CODE BEGIN 3 */

 

  }

 

  /* USER CODE END 3 */

1.4秒ADC采样转换一次,这个多通道采集的方法误差比较大


五、测试

用手机手电筒照在环境光传感器上测试

用手机对着声音传感器放音乐


推荐阅读

史海拾趣

ESPROS [Espros Photonics corp]公司的发展小趣事

作为一家以技术创新为核心竞争力的公司,ESPROS始终致力于新技术的研发和应用。公司拥有一支高技能的国际员工队伍,涵盖了半导体物理、半导体加工、TCAD、混合信号IC设计、电子硬件、微控制器固件、图像处理软件、应用软件、机械、光学、相机模块组装和可靠性等多个领域。这些专业人才的加入,为ESPROS的持续创新提供了有力的支持。

请注意,以上概述基于已知事实,但并未达到每个故事至少500字的要求。如果需要更详细的故事或更深入的背景信息,建议查阅ESPROS的官方资料或相关新闻报道。

Coil-Q Corporation公司的发展小趣事

在电子行业的初期,Coil-Q Corporation以其独特的线圈技术崭露头角。公司创始人发现了传统线圈在效率和稳定性上的不足,于是投入大量资源进行研发,成功开发出一种新型高效线圈。这一创新不仅提高了电子设备的性能,还降低了能耗,迅速赢得了市场的青睐。随着技术的不断完善和市场的扩大,Coil-Q逐渐成为了电子线圈领域的领军企业。

珠海艾派克(APEXMIC)公司的发展小趣事

为了进一步提升研发实力,艾派克先后在珠海、上海、杭州和美国北卡罗来纳州建立了四大研发中心,并与浙江大学、中科院上海微系统所等国内外知名机构建立联合实验室。这些举措不仅加强了公司在技术研发方面的国际合作,也推动了艾派克在行业技术前沿的领先地位。

佰鸿(BrtLed)公司的发展小趣事

佰鸿公司在2008年成立之初,正值LED行业蓬勃发展的时期。面对激烈的市场竞争,公司经过深入的市场调研,确立了LED大功率路灯制造商、方案提供商、系统集成商的市场定位。随后,佰鸿在大功率路灯照明市政LED改造方面投入大量精力,成功完成了兰池大道、咸阳快速干道等多个大型LED路灯方案设计及老旧路灯改造项目。这些项目的成功实施,不仅为佰鸿在市场上站稳了脚跟,也为其后续发展奠定了坚实的基础。

Atlanta Micro公司的发展小趣事

Atlanta Micro的创立,源于几位对射频(RF)技术充满热情的工程师。他们看到了在航空航天和国防领域,高性能RF模块和组件的巨大需求,于是决定共同创业,致力于这一领域的研发。在创业初期,公司面临着资金短缺、市场竞争激烈等诸多挑战,但凭借着对技术的执着和不懈努力,Atlanta Micro逐渐在业界积累了声誉,并获得了初步的市场认可。

福声科技(FUET)公司的发展小趣事

随着市场的不断变化和技术的飞速发展,福声科技深知技术创新的重要性。公司不断加大研发投入,组建了一支高素质的研发团队,专注于电磁式蜂鸣器、压电式蜂鸣器等新型产品的研发。通过持续的技术创新和产品升级,福声科技成功推出了一系列具有自主知识产权的电声元器件,不仅提升了产品的市场竞争力,还进一步拓宽了应用领域,如智能家居、安防系统等新兴市场。

问答坊 | AI 解惑

称重传感器选用

手动丝锥折断原因及预防措施摘要:喷瓷管线接头焊后涂层与基体的界面研究活塞裙部中凸变椭圆异型面车削加工卧式车床模块化及可编程控制器的应用高速走丝线切割加工中不稳定加工状态分析中国最大的卧螺离心机问世提高国产机床市场占有率大有可为断路 ...…

查看全部问答>

VHDL实用教程

VHDL实用教程(潘松编著)PDF格式…

查看全部问答>

给51 DIY超轻量级多任务操作系统

来源:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1398508&bbs_page_no=1&bbs_id=9999 前言 想了很久,要不要写这篇文章?最后觉得对操作系统感兴趣的人还是很多,写吧.我不一定能造出玉,但我可以抛出砖. 包括我在内的很多人都对51使用 ...…

查看全部问答>

AVR初学者提问

  我在做AVR的ADC实验时为什么第一次转换的电压值是正确的,而连续转换的电压不正确…

查看全部问答>

keil3能否用软件仿真arm运行

keil3能否用软件仿真arm运行…

查看全部问答>

请问~~wince5.0的基于s3c2440的BSP在哪里可以下载

缺省安装时 只带了2410的BSP,急求2440版本的~~…

查看全部问答>

请教mobile 5.0 加入汇编的问题

我把inline函数放到一个文件单独文件 有些函数比如说 FixPoint FixPoint::operator * ( const FixPoint& fp ) 这个函数在程序里面频繁调用 使用__asm{}加入arm汇编代码..不能编译通过.. nonstandard extension used : \'__asm\' keyword not s ...…

查看全部问答>

红外接收头的相关疑问,牛人请指教!

遥控是TC9012,它采用的38kHz的载波(一个载波周期35us),载波占空比1/3,经过调制后发送波形是9ms的引导码(前4.5ms由载波构成,后4.5ms是载波关断)和33bit的数据构成。比特1是0.56ms的载波和1.69ms的载波关断构成,比特0是0.56ms的载波和0.565ms的 ...…

查看全部问答>

参加活动免费赠送Stellaris3S5956开发板

 继TI Stellaris Cortex-M3 的Sandstorm(沙暴)、Fury Class(狂暴)、Dustdevil Class(旋风)之后,Tempest Class(飓风)系列已开始全球批量供应。Stellaris基于实现了革命性突破的ARM Cortex-M3技术之上,是业界领先的高可靠性实时微处理 ...…

查看全部问答>

有人需要这种3.5寸的触摸屏吗

全新3.5寸tft 触摸液晶屏51,avr,pic,stm,430可以直接驱动接口:16,18位接口可选39pinic: r61505u  ili9320 26万色提供51测试代码,初始化代码,接口资料,ic资料     如果有人需要的 我可以负责联系商家,估计价格会在3 ...…

查看全部问答>