二十一、 ADC光敏电阻实验
模块来源
采购链接:
光敏电阻传感器模块 光感应 智能车配件
资料下载链接:
https://pan.baidu.com/s/1VMFN1fVo5jxB80IYTsY67A
资料提取码:y8jw
规格参数
工作电压:3.3-5V
工作电流:1MA
模块尺寸:31.1475 x 14.097mm
输出方式: DO接口为数字量输出 AO接口为模拟量输出
读取方式:ADC
管脚数量:4 Pin(2.54mm间距排针)
1.配置流程
一般使用ADC功能,都需要有以下几个步骤。
- 配置时钟
- 配置引脚
- 配置ADC模式
- 配置数据对齐方式
- 配置分辨率
- 配置采集通道
- 配置触发方式
- 开启校准
- 使能ADC
1.1. 配置时钟
本案例使用ADC进行操作,需要开启ADC的时钟。 ADC的时钟来源有AHB(72MHz)、APB2(72MHz)和IRC28M(72MHz),我们需要选择一个时钟源,并将其分频到28MHz以下。
本案例使用的是APB2作为ADC时钟来源,其最大时钟频率为72MHz,我们需要将其分频到28MHz以下。而它分频的参数有2分频、4分频、6分频、8分频等等。选择4分频,最终的ADC时钟频率为:
4分频满足了我们的要求。
1.2. 配置引脚
GD32E230C8T6一共有10个外部ADC通道,我们将光敏电阻模块的AO引脚连接在PA1引脚上,查找数据手册的引脚定义可知,PA1的附加功能有ADC的通道1。
因为我们之前配置时钟的章节开启的是ADC的时钟,所以这里选择PA1的附加功能,ADC的通道1进行操作。要操作 GPIO 引脚,必不可少的就是对 GPIO 进行配置,包括开启时钟、配置模式、配置输出、设置功能等,还是这一系列的操作。
PA1引脚和ADC通道1的宏定义如下:
/* PA1 ADC_IN1 */
#define BSP_ADC_GPIO_RCU RCU_GPIOA
#define BSP_ADC_GPIO_PORT GPIOA
#define BSP_ADC_GPIO_PIN GPIO_PIN_1
/* PA1 ADC_IN1 */
#define BSP_ADC_RCU RCU_ADC
#define BSP_ADC ADC
#define BSP_ADC_CHANNEL ADC_CHANNEL_1
2
3
4
5
6
7
8
9
初始化GPIO引脚的配置如下:
//使能引脚时钟
rcu_periph_clock_enable(BSP_ADC_GPIO_RCU);
//使能ADC时钟
rcu_periph_clock_enable(BSP_ADC_RCU);
//配置ADC时钟
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV4);
//配置引脚为模拟浮空输入模式
gpio_mode_set(BSP_ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, BSP_ADC_GPIO_PIN);
2
3
4
5
6
7
8
以上代码需要注意的是使用ADC功能时,引脚必须设置为模拟浮空模式,如设置为上拉或下拉模式,则采集的电压是不准确的。
1.3. 配置ADC模式
ADC的模式有4种,分别是单次、连续、扫描和间断转换模式。
这里我们配置为扫描模式,这样就可以根据自己的需要,配置采集通道进行依次扫描采集对应引脚的模拟信号。也可以根据需要配置为连续模式和间断模式。
扫描模式配置如下:
//使能扫描模式
adc_special_function_config(ADC_SCAN_MODE, ENABLE);
//****** 设置为 ADC常规信道组,软件触发模式。
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
//****** 常规通道配置。通道1 采样周期为55.5
adc_regular_channel_config(0U, BSP_ADC_CHANNEL, ADC_SAMPLETIME_55POINT5);
2
3
4
5
6
7
8
1.4. 配置数据对齐方式
GD32E230C8T6微控制器的ADC支持各种数据对齐方式以适应不同的应用场景。常见的数据对齐方式包括左对齐和右对齐。在右对齐模式下,ADC的数据在转换结束后被右对齐到最低位,不足的位数在高位填充0。右对齐模式允许实现在没有精度的损失下更好的动态范围。
在左对齐模式下,ADC的数据被左对齐到最高位,不足的位数在低位填充0。左对齐模式可以提高分辨率,但会导致动态范围降低。
我们配置为右对齐方式,这样我们可以直接将转换完成的数据进行运算。
右对齐方式的配置如下:
//数据右对齐
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
2
1.5. 配置分辨率
GD32E230C8T6的分辨率可以配置为6、8、10、12 位。我们可以通过降低 ADC 的分辨率,获得较快的转换时间(tADC)。对于那些不需要高精度数据的应用,可以使用较低的分辨率来实现更快速地转换。
这里我们配置为12位分辨率。分辨率的配置如下:
//ADC设置为12位分辨率
adc_resolution_config(ADC_RESOLUTION_12B);
2
1.6. 配置采集通道
我们需要配置的是使用的通道和采集通道个数。这里我们使用的是常规通道组,并且只需要转换一个通道。后续需要采集多个通道时,只需要修改采集的通道即可。
采集通道的配置如下:
//ADC设置为规则组 一共使用 1 个通道
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
2
1.7. 配置触发方式
触发的方式有两种,分别是外部触发方式和软件触发方式。
其中外部触发输入的上升沿、下降沿可以触发规则组或注入组的转换。具体见GD32E23用户手册的第150页。需要注意的是可以实时修改外部触发选择,在修改期间不会出现触发事件。
软件触发方式是由软件触发启动,通常用在单次采样转换中。在软件触发模式下,ADC转换工作被触发后,由软件控制以固定的时间间隔进行转换,因此通常用于采集时间不太关键,但要求精度较高的应用。
这里选择的是软件触发方式,软件触发方式的配置如下:
//ADC外部触发禁用, 即只能使用软件触发
adc_external_trigger_config(ADC_REGULAR_CHANNEL,ENABLE);
//使能软件触发
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
2
3
4
1.8. 使能ADC
ADC配置好之后并不能开始工作,还需要去使能,就是相当于有一个开关可以打开关闭。需要注意的是要先使能了ADC之后,才能开始进行自校准。
//ADC使能
adc_enable();
delay_1ms(1U);
2
3
注意:使能后面延迟了1ms,等待adc使能完毕。
这个函数使能ADC。
1.9. 开启校准
ADC 带有一个前置校准功能。在校准期间,ADC 会计算一个出厂校准系数,这个系数是应用于 ADC 内部的,它直到 ADC 下次掉电才无效。在 A/D 转换前应执行校准操作。在校准期间,应用不能使用 ADC,它必须等到校准完成。通过软件设置 CLB=1 来对校准进行初始化,在校准期间CLB 位会一直保持 1,直到校准完成,该位由硬件清 0。可以直接使用库函数调用校准,完成操作。
开启校准的配置如下:
//开启ADC自校准
adc_calibration_enable();
2
最终的ADC全部配置参数如下:
/**********************************************************
* 函 数 名 称:ADC_Config
* 函 数 功 能:初始化ADC
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:
**********************************************************/
void ADC_Config(void)
{
//使能引脚时钟
rcu_periph_clock_enable(BSP_ADC_GPIO_RCU);
//使能ADC时钟
rcu_periph_clock_enable(BSP_ADC_RCU);
//配置ADC时钟
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV4);
//配置引脚为模拟浮空输入模式
gpio_mode_set(BSP_ADC_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, BSP_ADC_GPIO_PIN);
//使能扫描模式
adc_special_function_config(ADC_SCAN_MODE, ENABLE);
//****** 设置为 ADC常规信道组,软件触发模式。
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
//****** 常规通道配置。通道1 采样周期为55.5
adc_regular_channel_config(0U, BSP_ADC_CHANNEL, ADC_SAMPLETIME_55POINT5);
//数据右对齐
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
//ADC设置为12位分辨率
adc_resolution_config(ADC_RESOLUTION_12B);
//ADC设置为规则组 一共使用 1 个通道
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
//ADC常规通道组
adc_external_trigger_config(ADC_REGULAR_CHANNEL,ENABLE);
//使能软件触发
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
//ADC使能
adc_enable();
delay_1ms(1U);
//开启ADC自校准
adc_calibration_enable();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2. 采集转换
我们之前使用的是扫描模式并使用的是软件触发方式,因此当我们要采集信号时,需要配置好采集通道并开启软件转换。开启转换后,等待EOC标志位置1。其中EOC为转换完成标志位,我们可以通过判断其是否置1,确定是否转换完成。转换完成后将数据从16位寄存器中取出。
/**********************************************************
* 函 数 名 称:Get_ADC_Value
* 函 数 功 能:读取ADC值
* 传 入 参 数:ADC_CHANNEL_x=要采集的通道
* 函 数 返 回:测量到的值
* 作 者:LC
* 备 注:默认采样周期为13.5个ADC采样时间
**********************************************************/
unsigned int Get_ADC_Value(uint8_t ADC_CHANNEL_x)
{
unsigned int adc_value = 0;
//设置采集通道
adc_regular_channel_config(0, ADC_CHANNEL_x, ADC_SAMPLETIME_13POINT5);
//开始软件转换
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
//等待 ADC 采样完成
while ( adc_flag_get(ADC_FLAG_EOC) == RESET )
{
}
//读取采样值
adc_value = adc_regular_data_read();
//返回采样值
return adc_value;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
3. 实验现象
在main.c中调用unsigned int Get_ADC_Value(uint8_t ADC_CHANNEL_x);函数,采集PC1引脚的电压,并通过串口输出。
#include "gd32e23x.h"
#include "systick.h"
#include "bsp_usart.h"
#include <stdio.h>
#include "adc.h"
int main(void)
{
uint16_t value = 0;
systick_config();
usart_gpio_config(9600U);
ADC_Config();
printf("Start!\r\n");
while(1)
{
value = Get_ADC_Value(ADC_CHANNEL_1);
printf("value = %d\r\n", value );
printf("voltage = %f V\r\n", value / 4095.0 * 3.3 );
delay_1ms(500);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在灯光充足的情况下,ADC转换的值大约为990左右,转换为实际电压接近0.8V。
当用手遮住光敏电阻后,采集到的值大约在2750左右,转换为实际电压接近2.3V。
如果没有光敏电阻,则可以连接到3.3V或者GND进行测试。当接入3.3V时采集到的值接近4095;当接入GND时,采集到的值接近0。 完整代码下载:
通过网盘分享的文件:010ADC光敏电阻实验代码.zip
链接: https://pan.baidu.com/s/1yKY7xBAYj36SD6I8U57Dqw?pwd=lckf 提取码: lckf