函数定义
查找设备函数
该函数通过指定的名称查找设备。应用程序根据设备名称获取设备句柄,进而可以操作设备。
rt_device_t rt_device_find ( const char * name )
函数参数和返回值含义如下:
参数:
- name 设备的名称
- 返回 成功则返回已注册的设备句柄, 失败则返回 RT_NULL , 宏定义 RT_NULL 相当于 NULL
使能ADC通道
在读取 ADC 设备数据前需要先使能设备,通过如下函数使能设备:
rt_err_t rt_adc_enable( rt_adc_device_t dev,
rt_uint32_t channel
);
2
3
- 参数:
- dev ADC设备句柄
- channel ADC通道
- 返回:RT_EOK 成功,RT_ENOSYS 失败,设备操作方法为空,其他 失败
读取ADC通道采样值
读取 ADC 通道采样值可通过如下函数完成:
rt_uint32_t rt_adc_read(rt_adc_device_t dev,
rt_uint32_t channel
);
2
3
- 参数:
- dev ADC设备句柄
- channel ADC通道
- 返回:读取的数值。
关闭ADC通道
关闭 ADC 通道可通过如下函数完成:
rt_err_t rt_adc_disable( rt_adc_device_t dev,
rt_uint32_t channel
);
2
3
- 参数:
- dev ADC设备句柄
- channel ADC通道
- 返回:RT_EOK 成功,RT_ENOSYS 失败,设备操作方法为空,其他 失败
GPIO模拟配置
设置指定引脚为模拟模式。
rt_err_t HAL_PIN_Set_Analog( rt_base_t pin,
rt_uint8_t enable
);
2
3
- 参数:
- pin 引脚编号
- enable 启用/禁用模拟模式:1: 启用模拟模式,0: 禁用模拟模式(恢复为数字模式)
- 返回:RT_EOK 成功,其他 失败。
控制设备
该函数将在设备上执行各种控制功能。
rt_err_t rt_device_control ( rt_device_t dev,
int cmd,
void * arg
)
2
3
4
- 参数:
- dev 设备句柄
- cmd 命令控制字,这个参数通常与设备驱动程序相关。
- arg 控制命令相关的参数
- 返回:RT_EOK 成功,其他 失败。
ADC 接口说明
黄山派使用的是 LC-OPEN-SF32LB52-MOD 模组,详细信息参考立创·开源SF32LB52模组管脚复用。
黄山派的ADC CH1-7分布,对应软件配置的 Channel0-6,电压输入范围是 0-3.3V ,最后一路CH8(Channel 7),内部通过分压电阻已经连接到VBAT引脚,外部不可以用电阻分压,输入范围是 0-4.7V,建议用于电池电压测量。
图形化配置
接下来我们需要去配置工程,使能ADC定义,因为我们复制的是 hello_world 例程只有最简单的打印功能,很多组件都没有使能,即使在 main.c 里包含了组件的头文件,也无法调用相应函数,这时就需要我们去配置图形化工程。
接下来我在 powershell 里面进行一个操作,也可以在 VScode 终端进行操作。
在终端执行 scons --board=sf32lb52-lchspi-ulp --menuconfig 后,如下图所示:
进入图形化界面,使用⇧和⇩方向键在不同菜单项间移动,按Enter键进入子菜单,进 On-chip Peripheral RTOS Drivers->Enable ADC 选择 GPADC1,Space 选中菜单项,如下图所示:
我们接下来可以去选择 Enable GPADC1 ,通过⇧和⇩方向键来选择,选中之后按下 Y 键代表使能,按下 N 键则失能。按D保存,如下图所示:
接下来按 Enter 确定,后会出现提示是否保存到这个文件,如下图所示:
接下再按 Enter 确定,即保存成功,保存完成后我们按一下 键盘Q 键退出图形化界面,如下图所示:
提示再保存 选择 Y 即可。
接下来我们去验证一下 proj.conf 是否设置成功,路径(我的路径为例:Desktop\SF-text\rtt\project\proj.conf),可以看到里面有了一个 CONFIG_BSP_USING_ADC1=y ,这个就是我们刚刚设置的。如下图所示:
注:
- 可以尝试把我们刚刚配置的给失能看看这个文件是否还有 CONFIG_BSP_USING_ADC1=y 这个配置。
- 官方说是工程所在路径下rtconfig.h 会有变化,这里我没有看到变化。
程序编写
#include "rtthread.h"
#include "bf0_hal.h"
#include "drv_io.h"
#include "stdio.h"
#include "string.h"
#include <board.h>
#define ADC_DEV_NAME "bat1" /* ADC name */
#define BAT_CHANNEL 7 // BAT检测引脚ADC通道号
#define ADC_CHANNEL 6 // PA_34引脚ADC通道号
static rt_device_t s_adc_dev;
static rt_adc_cmd_read_arg_t read_arg;
/*
- Function : adc_example()
- Description : ADC采样函数
- Input : 无
- Return : 无
- Other : 读取两个不同通道的AD值
*/
void adc_example(void)
{
rt_err_t r;
/* 查找并初始化 ADC 设备 */
s_adc_dev = rt_device_find(ADC_DEV_NAME);
read_arg.channel = BAT_CHANNEL;
r = rt_adc_enable((rt_adc_device_t)s_adc_dev, read_arg.channel);
if (r != RT_EOK)
{
rt_kprintf("ADC enable failed\n");
return;
}
/* 配置并读取电池检测通道 */
rt_uint32_t value = rt_adc_read((rt_adc_device_t)s_adc_dev, BAT_CHANNEL);
if (value == RT_ERROR)
{
rt_kprintf("ADC read failed\n");
return;
}
rt_kprintf("VBAT read value: %d\n", value); // 打印PA_34读取的值
rt_adc_disable((rt_adc_device_t)s_adc_dev, read_arg.channel); // 禁用ADC通道
HAL_PIN_Set_Analog(PAD_PA28, 1); // 设置PA28为模拟输入模式
read_arg.channel = ADC_CHANNEL; // 设置ADC通道
r = rt_adc_enable((rt_adc_device_t)s_adc_dev, read_arg.channel); // 使能ADC通道
if (r != RT_EOK)
{
rt_kprintf("ADC enable failed\n");
return;
}
value = rt_device_control((rt_device_t)s_adc_dev, RT_ADC_CMD_READ, &read_arg.channel);
if (value == RT_ERROR)
{
rt_kprintf("ADC read failed\n");
return;
}
rt_kprintf("ADC read value: %d\n", read_arg.value); // 打印ADC读取的值
rt_kprintf("ADC example end\n");
}
/**
* @brief Main program
* @param None
* @retval 0 if success, otherwise failure number
*/
int main(void)
{
while (1)
{
adc_example();
rt_thread_mdelay(1000); // 延时1000ms
}
return 0;
}
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
注:接电池时需要 注意正负极,注意正负极,注意正负极。重要的事情说三遍
未接电池log,如下图所示:
未接电池log,按下KEY1,如下图所示:
接入电池后读取的电压log,实际供电3.2V ,如下图所示:
按下KEY1按键后log,如下图所示:
异常诊断
1、程序运行死机,log如下所示:
Start adc demo!
Assertion failed at function:rt_adc_enable, line number:144 ,(dev)
Previous ISR enable 0
2
3
原因:BSP_USING_ADC1没有定义,导致rt_hw_adc_register函数没有注册"bat1",rt_device_find该设备时Assert死机 确保rtconfig.h文件中包含了下面3个宏:
#define BSP_USING_ADC 1
#define BSP_USING_ADC1 1
#define RT_USING_ADC 1
2
3
2、ADC采样的电压值不对
- 检查ADC硬件是否连接正确,ADC采样的通道为固定IO口,不能任意指定,具体CH0-7为哪个IO,参照芯片手册。
- ADC输入电压范围为0V - 参考电压(黄山派默认为3v3),不能超出输入范围。
3、ADC精确度不够
- ADC校准参数是否获取和使用
- 分压电阻的精度是否达到要求
- ADC参考电压是否稳定和是否有过大纹波(具体参考ADC电压参考芯片手册)