【1TB嵌入式学习资料免费领取:https://link3.cc/sgzy】
2.40 灰度传感器
2.40.1 模块来源
2.40.2 规格参数
工作电压:3.3V-5V
工作电流:<20mA
输出格式:模拟信号输出
控制接口:ADC
管脚数量:3 Pin(2.54mm间距排针)
2.40.3 移植过程
我们的目标是在梁山派GD32F470上能够判断当前环境状况的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
2.40.3.1 查看资料
灰度传感器包括一个白色高亮发光二极管和一个光敏电阻,由于发光二极管照射到灰度不同的纸张上返回的光是不同的,光敏电阻接收到返回的光,根据光的强度不同,光敏电阻的阻值也不同,从而实现灰度值的测试。
2.40.3.2 引脚选择
2.40.3.3 移植至工程
移植步骤中的导入.c和.h文件与上一节相同,只是将.c和.h文件更改为bsp_grayscale.c与bsp_grayscale.h。见2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件bsp_grayscale.c中,编写如下代码。
/********************************************************************************
* 文 件 名: bsp_grayscale.c
* 版 本 号: 初版
* 修改作者: LC
* 修改日期: 2023年6月2日
* 功能介绍:
******************************************************************************
* 注意事项:
*********************************************************************************/
#include "bsp_grayscale.h"
#include "systick.h"
//DMA缓冲区
uint16_t gt_adc_val[ SAMPLES ][ CHANNEL_NUM ];
/******************************************************************
* 函 数 名 称:ADC_DMA_Init
* 函 数 说 明:初始化ADC+DMA功能
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void ADC_DMA_Init(void)
{
/* DMA初始化功能结构体定义 */
dma_single_data_parameter_struct dma_single_data_parameter;
/* 使能引脚时钟 */
rcu_periph_clock_enable(RCU_GRAYSCALE_OUT);
/* 使能ADC时钟 */
rcu_periph_clock_enable(RCU_GRAYSCALE_ADC);
/* 使能DMA时钟 */
rcu_periph_clock_enable(RCU_GRAYSCALE_DMA);
/* 配置ADC时钟 */
adc_clock_config(ADC_ADCCK_PCLK2_DIV4);
/* 配置AO为浮空模拟输入模式 */
gpio_mode_set(PORT_GRAYSCALE_OUT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_GRAYSCALE_OUT); // PC1 : ADC012_IN11
/* 配置ADC为独立模式 */
adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
/* 使能连续转换模式 */
adc_special_function_config(PORT_ADC, ADC_CONTINUOUS_MODE, ENABLE);
/* 使能扫描模式 */
adc_special_function_config(PORT_ADC, ADC_SCAN_MODE, ENABLE);
/* 数据右对齐 */
adc_data_alignment_config(PORT_ADC, ADC_DATAALIGN_RIGHT);
/* ADC0设置为规则组 一共使用 CHANNEL_NUM 个通道 */
adc_channel_length_config(PORT_ADC, ADC_REGULAR_CHANNEL, CHANNEL_NUM);
/* ADC规则通道配置:ADC0的通道11的扫描顺序为0;采样时间:15个周期 */
/* DMA开启之后 gt_adc_val[x][0] = PC1的数据 */
adc_regular_channel_config(PORT_ADC, 0, CHANNEL_ADC, ADC_SAMPLETIME_15);//PC1
/* ADC0设置为12位分辨率 */
adc_resolution_config(PORT_ADC, ADC_RESOLUTION_12B);
/* ADC外部触发禁用, 即只能使用软件触发 */
adc_external_trigger_config(PORT_ADC, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
/* 使能规则组通道每转换完成一个就发送一次DMA请求 */
adc_dma_request_after_last_enable(PORT_ADC);
/* 使能DMA请求 */
adc_dma_mode_enable(PORT_ADC);
/* 使能DMA */
adc_enable(PORT_ADC);
/* 等待ADC稳定 */
delay_1ms(1);
/* 开启ADC自校准 */
adc_calibration_enable(PORT_ADC);
/* 清除 DMA通道0 之前配置 */
dma_deinit(PORT_DMA, CHANNEL_DMA);
/* DMA初始化配置 */
dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(PORT_ADC)); //设置DMA传输的外设地址为ADC0基地址
dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; //关闭外设地址自增
dma_single_data_parameter.memory0_addr = (uint32_t)(gt_adc_val); //设置DMA传输的内存地址为 gt_adc_val数组
dma_single_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; //开启内存地址自增(因为不止一个通道)
dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT; //传输的数据位 为 16位
dma_single_data_parameter.direction = DMA_PERIPH_TO_MEMORY; //DMA传输方向为 外设往内存
dma_single_data_parameter.number = SAMPLES * CHANNEL_NUM; //传输的数据长度为:每个通道采集30次 * 1个通道
dma_single_data_parameter.priority = DMA_PRIORITY_HIGH; //设置高优先级
dma_single_data_mode_init(PORT_DMA, CHANNEL_DMA, &dma_single_data_parameter);//将配置保存至DMA1的通道0
/* DMA通道外设选择 */
/* 数据手册的195页根据PERIEN[2:0]值确定第三个参数,例是100 则为DMA_SUBPERI4 例是010 则为DMA_SUBPERI2 */
/* 我们是ADC0功能,PERIEN[2:0]值为000,故为DMA_SUBPERI0 */
dma_channel_subperipheral_select(PORT_DMA, CHANNEL_DMA, DMA_SUBPERI0);
/* 使能DMA1通道0循环模式 */
dma_circulation_enable(PORT_DMA, CHANNEL_DMA);
/* 启动DMA1的通道0功能 */
dma_channel_enable(PORT_DMA, CHANNEL_DMA);
/* 开启软件触发ADC转换 */
adc_software_trigger_enable(PORT_ADC, ADC_REGULAR_CHANNEL);
}
/******************************************************************
* 函 数 名 称:Get_Adc_Dma_Value
* 函 数 说 明:对DMA保存的数据进行平均值计算后输出
* 函 数 形 参:CHx 第几个扫描的数据
* 函 数 返 回:对应扫描的ADC值
* 作 者:LC
* 备 注:无
******************************************************************/
unsigned int Get_Adc_Dma_Value(char CHx)
{
unsigned char i = 0;
unsigned int AdcValue = 0;
/* 因为采集 SAMPLES 次,故循环 SAMPLES 次 */
for(i=0; i< SAMPLES; i++)
{
/* 累加 */
AdcValue+=gt_adc_val[i][CHx];
}
/* 求平均值 */
AdcValue=AdcValue / SAMPLES;
return AdcValue;
}
/******************************************************************
* 函 数 名 称:Get_Grayscale_Percentage_value
* 函 数 说 明:读取灰度传感器的值,并且返回百分比
* 函 数 形 参:无
* 函 数 返 回:返回百分比
* 作 者:LC
* 备 注:无
******************************************************************/
unsigned int Get_Grayscale_Percentage_Value(void)
{
int adc_max = 4095;
int adc_new = 0;
int Percentage_value = 0;
adc_new = Get_Adc_Dma_Value(0);
Percentage_value = ((float)adc_new/adc_max) * 100;
return Percentage_value;
}
在文件bsp_grayscale.h中,编写如下代码。
#ifndef _BSP_GRAYSCALE_H_
#define _BSP_GRAYSCALE_H_
#include "gd32f4xx.h"
#define RCU_GRAYSCALE_OUT RCU_GPIOC
#define RCU_GRAYSCALE_ADC RCU_ADC0
#define RCU_GRAYSCALE_DMA RCU_DMA1
#define PORT_DMA DMA1
#define CHANNEL_DMA DMA_CH0
#define PORT_ADC ADC0
#define CHANNEL_ADC ADC_CHANNEL_11
#define PORT_GRAYSCALE_OUT GPIOC
#define GPIO_GRAYSCALE_OUT GPIO_PIN_1
//采样次数
#define SAMPLES 30
//采样通道数
#define CHANNEL_NUM 1
extern uint16_t gt_adc_val[ SAMPLES ][ CHANNEL_NUM ]; //DMA缓冲区
void ADC_DMA_Init(void);
unsigned int Get_Adc_Dma_Value(char CHx);
unsigned int Get_Grayscale_Percentage_Value(void);
#endif
2.40.4 移植验证
在自己工程中的main主函数中,编写如下。
/********************************************************************************
* 文 件 名: main.c
* 版 本 号: 初版
* 修改作者: LC
* 修改日期: 2022年6月2日
* 功能介绍:
******************************************************************************
* 开发板官网:www.lckfb.com
*********************************************************************************/
#include "gd32f4xx.h"
#include "systick.h"
#include "bsp_usart.h"
#include "bsp_grayscale.h"
#include "stdio.h"
int main(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); // 优先级分组
systick_config(); //滴答定时器初始化 1ms
ADC_DMA_Init();
usart_gpio_config(115200U);
printf("ADC+DMA demo start\r\n");
while(1)
{
printf("%d%%\r\n", Get_Grayscale_Percentage_Value() );
delay_1ms(1000);
}
}
移植现象:识别黑色时返回的值为24%左右,识别白色时返回的值为70%左右。
移植成功示例,见文件2.40.4-1 。