这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【转载】五路模拟量灰度传感器ADC+DMA--from毅

共1条 1/1 1 跳转至

【转载】五路模拟量灰度传感器ADC+DMA--from毅

工程师
2025-06-19 21:29:44     打赏

我使用的是五路模拟量灰度传感器,单片机是stm32f103c8t6.要注意灰度电源端最好接5v。其余A0、A1、A2、A3、A4我接的是单片机ADC1的PA0、PA1、PA2、PA3、PA5,(为什么不接PA4呢,那是由于PA4被占用了,那如何判断IO口是否被占用,我们可以不给灰度传感器供电,其他IO口都接上,然后与电脑通信,查看那个口有数据就说明他被占用了)还要注意,ADC1只能用DMA1进行搬运。

灰度传感器原理:每一组传感器均由一只发光二极管和一只灰度接收管组成;两个探 头安装在电路板同一面上,发光管发射的光会被检测面反射后由灰度 接收管进行回收。由于光线照射到不同颜色后一部分光被颜色吸收, 一部分则被反射出去,会得到不同颜色光反射强度的变化,灰度接收 管对被探测面颜色光反射的强弱不同进行采集回收,然后输出对应的 电压值信号(也叫做模拟信号);得到此种信号,我们就可配合单片 机编程控制,用于颜色识别、巡线智能小车机器人等领域。模拟量灰度传感器可对被探测面的多种任意颜色进行识别,在探测到 不同颜色时,输出不同的电压信号(俗称为一种状态值);输出的电 压值是随被探测面的颜色变化而变化的,所以也就可以识别出任意颜 色。使用时需要注意的是由于它的值是受到探头离地高度不同和被探 测面颜色变化而产生变化,所以在编程时需预先固定好传感器高度后 再对各种颜色进行取值,

然后将对应的值作为条件判断进行识别控制 (一般取一定范围的值,防止环境光干扰产生波动。

我们需要注意,我们要先安装好灰度传感器再去进行采取参数。安装高度一般是5~20mm,个人建议最后15mm左右。

我们可以通过RCC_ADCCLKConfig(RCC_PCLK2_Div6);//对应APB272MHZ6分频与ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5);来配置ADC采样时间。(ADC_RegularChannelConfig是规则组通道配置,第三个参数是配置序列位置,相当于是第几个传输出去)

要注意使用连续转换与连续扫描模式,这样可以不断进行采样(转换:就是指你需要将你采集的数据转换几次。扫描就是指你要接着转换下去吗。)

配置ADC:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

RCC_ADCCLKConfig(RCC_PCLK2_Div6);//对应APB272MHZ6分频

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_13Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_13Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_13Cycles5);

ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_13Cycles5);

ADC_InitTypeDef ADC_InitStructure;

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式,ADC1和ADC2各自转换各自的

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//选用触发源(这里使用内部软件触发)

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//选择连续转换模式

ADC_InitStructure.ADC_ScanConvMode = ENABLE;//选用扫描模式

ADC_InitStructure.ADC_NbrOfChannel = 5;//选择通道数目

ADC_Init(ADC1, &ADC_InitStructure);

这里由于ADC寻址空间是32位的但是数据寄存器是16位的,而我们需要将他转成32位但是址需要他的低16位,采用半字(16位)进行传输就可以。

 配置DMA:

DMA_InitTypeDef DMA_InitStructure;

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;//外设站点起始地址

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//地址是否自增,不用因为ADC地址一定

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;//存储器基地址

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//存储器数据宽度

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器地址是否自增

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//指定外设站点是源端还是目的地

DMA_InitStructure.DMA_BufferSize = 5;//传输几次

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//是否自动重装

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//是否用软件触发

DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//指定通道优先级

DMA_Init(DMA1_Channel1, &DMA_InitStructure);

DMA_Cmd(DMA1_Channel1, ENABLE);

ADC_DMACmd(ADC1, ENABLE);

ADC_Cmd(ADC1, ENABLE);

ADC_ResetCalibration(ADC1);//重置指定的ADC的校准寄存器

while (ADC_GetResetCalibrationStatus(ADC1) == SET);

ADC_StartCalibration(ADC1); //开始指定ADC的校准状态 

while (ADC_GetCalibrationStatus(ADC1) == SET);

ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发ADC转换

来源: 整理文章为传播相关技术,网络版权归原作者所有,如有侵权,请联系删除。




共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]