GD32F470_光敏电阻光照传感器模块移植手册

2.3 光敏电阻光照传感器
光敏电阻是用硫化隔或硒化隔等半导体材料制成的特殊电阻器,其工作原理是基于内光电效应。随着光照强度的升高,电阻值迅速降低,由于光照产生的载流子都参与导电,在外加电场的作用下作漂移运动,电子奔向电源的正极,空穴奔向电源的负极,从而使光敏电阻器的阻值迅速下降。其在无光照时,几乎呈高阻状态,暗时电阻很大。光敏电阻模块一般用来检测周围环境的光线的亮度,触发单片机或继电器模块等。

2.3.1 模块来源
采购链接:光敏电阻传感器模块 光感应 智能车配件
资料下载链接:
https://pan.baidu.com/s/1VMFN1fVo5jxB80IYTsY67A
资料提取码:y8jw
2.3.2 规格参数
工作电压:3.3-5V
工作电流:1MA
模块尺寸:31.1475 x 14.097mm
输出方式: DO接口为数字量输出 AO接口为模拟量输出
读取方式:ADC
管脚数量:4 Pin(2.54mm间距排针)
2.3.3 移植过程
我们的目标是在梁山派GD32F470上能够判断当前光照强度的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
2.3.3.1 查看资料
这个模块采用的光敏电阻的型号是5516,对应下图,可以知道在光亮时的阻值在8到20KΩ左右,在光暗时的阻值在1MΩ左右。
图2.2.3.1-1 光敏电阻型号表
其对应的原理图见图2.2.3.1-2,其中U2.1为LM393,R3为光敏电阻。AO输出为R2和R3分压后直接输出电压,所以为模拟量;DO为经过LM393进行电压比较后,输出高低电平,所以为数字量。具体原理是,393的3号引脚电压与2号引脚进行电压比较。当3号引脚电压比2号引脚电压高时,1号引脚输出高电平;当3号引脚电压比2号引脚电压低时,1号引脚输出低电平;可以通过调整R4控制2号引脚的电压。
图2.2.3.1-2 光敏电阻光照传感器原理图

因此DO引脚可以配置为GPIO的输入模式,AO引脚需要配置为ADC模拟输入模式。
2.3.3.2 引脚选择
想要使用ADC,需要确定使用的引脚是否有ADC外设功能。可以通过数据手册
在这里插入图片描述

在数据手册的第28页结尾,是关于GD32F450Zx系列芯片引脚的功能定义示意图。

当前只有AO引脚需要使用到ADC接口,所以DO引脚可以使用开发板上其他的GPIO。这里选择使用PC1的附加ADC功能。使用ADC0的第11道输入通道。
在这里插入图片描述

光照传感器立创·梁山派
VCC3V3
GNDGND
DOPA1
AOPC1

在这里插入图片描述
2.3.3.3 移植至工程
移植步骤中的导入.c和.h文件与上一节相同,只是将.c和.h文件更改为bsp_illume.c与bsp_illume.h。见2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件bsp_illume.c中,编写如下代码。

/********************************************************************************
  * 文 件 名: bsp_illume.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月06日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/

#include "bsp_illume.h"
#include "systick.h"


 //DMA缓冲区
uint16_t gt_adc_val[ SAMPLES ][ CHANNEL_NUM ]; 



/******************************************************************
 * 函 数 名 称:Illume_GPIO_Init
 * 函 数 说 明:初始化光敏电阻光照传感器引脚功能
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void Illume_GPIO_Init(void)
{
    /* DMA初始化功能结构体定义 */
    dma_single_data_parameter_struct dma_single_data_parameter;
        
        /* 使能引脚时钟 */
    rcu_periph_clock_enable(RCU_ILLUME_GPIO_AO);                
    rcu_periph_clock_enable(RCU_ILLUME_GPIO_DO);                
        
        /* 使能ADC时钟 */
    rcu_periph_clock_enable(RCU_ILLUME_ADC);                
  
        /* 使能DMA时钟 */
        rcu_periph_clock_enable(RCU_ILLUME_DMA);
 
        /*        配置ADC时钟        */ 
    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);        
        
   /*        配置PA1(DO)为输入模式        */
    gpio_mode_set(PORT_ILLUME_DO, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_ILLUME_DO); 
        /*        配置PC1(AO)为浮空模拟输入模式        */
    gpio_mode_set(PORT_ILLUME_AO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_ILLUME_AO);  
 
        /*        配置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
 * 备       注:返回值最低0  最高4095
******************************************************************/
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_illume_Percentage_value
 * 函 数 说 明:读取光敏电阻值,并且返回百分比 
 * 函 数 形 参:无
 * 函 数 返 回:返回百分比
 * 作       者:LC
 * 备       注:最亮100  最暗0
******************************************************************/
unsigned int Get_illume_Percentage_value(void)
{
    //GD32F470和GD32F450的ADC精度都是12位
    //2的12次方 = 4096
    //因为单片机是从0开始算,所以要4096-1=4095
    int adc_max = 4095;
    int adc_new = 0;
    int Percentage_value = 0;
    
    adc_new = Get_Adc_Dma_Value(0);
    //百分比 = ( 当前值 / 最大值 )* 100 
    Percentage_value = ( 1 - ( (float)adc_new / adc_max ) ) * 100;
    return Percentage_value;
}

/******************************************************************
 * 函 数 名 称:Get_DO_In
 * 函 数 说 明:读取DO引脚的电平状态
 * 函 数 形 参:无
 * 函 数 返 回:1=检测过亮   0=检测过暗
 * 作       者:LC
 * 备       注:无
******************************************************************/
char Get_DO_In(void)
{
    if( GET_DO_IN == 1 )
    {
        return 1;
    }
    return 0;
}

在文件bsp_encoder.h中,编写如下代码。

#ifndef _BSP_MQ2_H_
#define _BSP_MQ2_H_
 
#include "gd32f4xx.h"



#define RCU_ILLUME_GPIO_AO     RCU_GPIOC
#define RCU_ILLUME_GPIO_DO     RCU_GPIOA

#define RCU_ILLUME_ADC      RCU_ADC0
#define RCU_ILLUME_DMA      RCU_DMA1

#define PORT_DMA            DMA1
#define CHANNEL_DMA         DMA_CH0

#define PORT_ADC            ADC0
#define CHANNEL_ADC         ADC_CHANNEL_11

#define PORT_ILLUME_AO      GPIOC
#define GPIO_ILLUME_AO        GPIO_PIN_1

#define PORT_ILLUME_DO      GPIOA
#define GPIO_ILLUME_DO      GPIO_PIN_1

#define GET_DO_IN   gpio_input_bit_get(PORT_ILLUME_DO, GPIO_ILLUME_DO)

 //采样次数
#define SAMPLES         30
//采样通道数 
#define CHANNEL_NUM     1


extern uint16_t gt_adc_val[ SAMPLES ][ CHANNEL_NUM ];  //DMA缓冲区
 
void Illume_GPIO_Init(void);
unsigned int Get_Adc_Dma_Value(char CHx);
unsigned int Get_illume_Percentage_value(void);
char Get_DO_In(void);

#endif

2.3.4 移植验证
在自己工程中的main主函数中,编写如下。

/********************************************************************************
  * 文 件 名: main.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月06日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/


#include "gd32f4xx.h"
#include "systick.h"
#include "bsp_usart.h"
#include "bsp_illume.h"
#include "stdio.h"

int main(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 优先级分组
        systick_config();                //滴答定时器初始化 1ms

    usart_gpio_config(115200U);
    Illume_GPIO_Init();
    printf("ADC+DMA demo start\r\n");
    while(1)
    {
        printf("ADC-%d\r\n", Get_Adc_Dma_Value(0) );
        printf("illume-%d%%\r\n", Get_illume_Percentage_value() );
        delay_1ms(1000);
    }
}

移植现象:输出ADC值和换算后的光照度百分比。
在这里插入图片描述
移植成功示例,见文件2.3.4-1 。
文件2.3.4-1

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
gd32f470stm32f407是两款由不同公司生产的微控制器芯片。移植是指将原本为一种平台设计的软件或硬件系统成功转移到另一种平台上运行的过程。以下是关于将gd32f470stm32f407进行移植替换的一些要点: 1. 芯片架构:gd32f470stm32f407虽然都是基于ARM Cortex-M4内核,但芯片的架构可能存在一些差异。移植过程中,需要了解芯片的寄存器映射、外设配置等信息,并对原有的代码进行相应修改。 2. 外设接口:gd32f470stm32f407可能在外设接口上存在一些差异。例如,它们的GPIO接口可能存在差异,寄存器映射可能不同。移植过程中,需要对外设配置进行适当修改,确保移植后的代码可以正确地与外设进行通信。 3. 中断处理:gd32f470stm32f407的中断控制器可能有所不同。在移植过程中,需要针对不同的中断控制器进行相应的修改,以确保中断的正常触发和处理。 4. 系统时钟:gd32f470stm32f407的时钟配置可能存在差异。需要根据实际情况修改时钟配置,以确保移植后的系统可以正常工作。 5. 软件库和驱动程序:gd32f470stm32f407可能使用不同的软件库和驱动程序。在进行移植时,需要替换原有的软件库和驱动程序,确保其与gd32f470芯片的特性和功能兼容。 总结而言,移植gd32f470stm32f407需要对芯片的架构、外设接口、中断处理、系统时钟、软件库和驱动程序等进行适当的修改和替换。通过仔细分析和调整,可以成功将原本为stm32f407设计的软件或硬件系统移植gd32f470平台上运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值