V853开发板开发进阶——GPADC
-
以下内容转自全志在线V853在线文档:https://v853.docs.aw-ol.com/soft/dev_gpadc/
GPADC
GPADC(General Purpose Analog to Digital Converter)是指高精度数模转换模块,拥有12bit分辨率,8位采集精度。模拟输入范围0~1.8V,最高采样率1MHz。
V853 GPADC驱动路径:
tina/lichee/linux-4.9/drivers/input/sensor/sunxi_gpadc.c tina/lichee/linux-4.9/drivers/input/sensor/sunxi_gpadc.h
GPADC硬件介绍
AVCC 为 1.8V 电源供电,通过一个电阻串联到GPADC的按键组。按键通过不同阻值的电阻相连接,按下不同的按键,GPADC0 口的电压不同,CPU 通过对这个电压的采样来决定具体是哪一个按键被按下。上图按键与电压的对应关系如下表所示:0.21V 0.41V 0.59V 0.75V 0.88V VOL+ VOL- MENU ENTER HOME 当按键按下时,会触发 GPADC 模块的中断,CPU 会采集 GPADC 的数据,采集到的数据转换成相应的键值之后通过 input 子系统上传到
/dev/input/event
节点,程序便可以从相应的节点获取数据。GPADC软件介绍
设备树配置
GPADC 的设备树配置分为两个部分:
第一部分包括基础的寄存器配置、设备驱动绑定配置和时钟中断配置。这一部分的配置位于
kernel/linux-4.9/arch/arm/boot/dts/sun8iw21p1.dtsi
文件内。这一部分通常不需要修改。gpadc:gpadc@2009000 { compatible = "allwinner,sunxi-gpadc"; // 用于驱动和设备的绑定 reg = <0x0 0x02009000 0x0 0x400>; // 设备使用的寄存器地址 interrupts = <GIC_SPI 57 IRQ_TYPE_NONE>; // 设备使用的中断 clocks = <&clk_gpadc>; // 设备使用的时钟 status = "disabled"; // 配置默认不启用GPADC };
第二部分包括采样相关的配置,键值,电压数据等等,在
device/config/chips/v853/configs/vision/board.dts
文件内&gpadc { channel_num = <1>; // 使用1通道 channel_select = <0x01>; // 选择 0x01 通道 channel_data_select = <0>; // 启用数据通道 channel_compare_select = <0x01>; // 启用通道比较功能 channel_cld_select = <0x01>; // 启用数据小于比较功能 channel_chd_select = <0>; // 启用数据大于比较功能 channel0_compare_lowdata = <1700000>; // 小于这个值触发中断 channel0_compare_higdata = <1200000>; // 大于这个值触发中断 channel1_compare_lowdata = <460000>; // 小于这个值触发中断 channel1_compare_higdata = <1200000>; // 大于这个值触发中断 key_cnt = <5>; // 按键数量 key0_vol = <210>; // 按键电压,单位mv key0_val = <115>; // 按下按键的键值 key1_vol = <410>; // 按键电压,单位mv key1_val = <114>; // 按下按键的键值 key2_vol = <590>; // 按键电压,单位mv key2_val = <139>; // 按下按键的键值 key3_vol = <750>; // 按键电压,单位mv key3_val = <28>; // 按下按键的键值 key4_vol = <880>; // 按键电压,单位mv key4_val = <102>; // 按下按键的键值 status = "okay"; // 启用GPADC };
内核驱动配置
make kernel_menuconfig
进入内核配置界面,找到Device Drivers
,进入。找到
Input device support
,进入。找到
Sensors
空格勾选并进入。空格选中
<*> SUNXI GPADC
,保存并退出配置页面。之后编译内核,打包烧录即可
测试 GPADC
make menuconfig
进入 openWrt 配置页面,找到getevent
软件包。Utilities ---> <*> getevent.................................... getevent for Android Toolbox
之后编译打包烧录到开发板上,运行
getevent
,可以看到sunxi-gpadc
此时按下按键,可以看到按键键值显示出来了
编写一个程序
测试完成设备正常使用后,可以尝试编写一个程序测试GPADC。
以下demo程序用来读取 GPADC 模块用于 KEY 的按键上报事件,其循环10次读取按键上报事件输入,并且显示出相应按键的值。
#include <stdio.h> #include <linux/input.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/time.h> #include <limits.h> #include <unistd.h> #include <signal.h> #define DEV_PATH "/dev/input/event3" //查看上节sunxi-gpadc的event号,是event3 static int gpadc_fd = 0; unsigned int test_gpadc(const char * event_file) { int code = 0, i; struct input_event data; gpadc_fd = open(DEV_PATH, O_RDONLY); if(gpadc_fd <= 0) { printf("open %s error!\n", DEV_PATH); return -1; } for(i = 0; i < 10; i++) //读10次 { read(gpadc_fd, &data, sizeof(data)); if(data.value == 1) { printf("key %d pressed\n", data.code); } else if(data.value == 0) { printf("key %d releaseed\n", data.code); } } close(gpadc_fd); return 0; } int main(int argc,const char *argv[]) { int rang_low = 0, rang_high = 0; return test_gpadc(DEV_PATH); }
编译后将demo
adb push
到开发板中,执行demo并按下对应按键,将会有响应的按键反馈输出: -
@bayche
那要测量某一个引脚电压值的话,得怎么用呀? -
@jr_online
sunxi_gpadc_read_data()static u32 sunxi_gpadc_read_data(void __iomem *reg_base, enum gp_channel_id id) { switch (id) { case GP_CH_0: return readl(reg_base + GP_CH0_DATA_REG) & GP_CH0_DATA_MASK; case GP_CH_1: return readl(reg_base + GP_CH1_DATA_REG) & GP_CH1_DATA_MASK; case GP_CH_2: return readl(reg_base + GP_CH2_DATA_REG) & GP_CH2_DATA_MASK; case GP_CH_3: return readl(reg_base + GP_CH3_DATA_REG) & GP_CH3_DATA_MASK; case GP_CH_4: return readl(reg_base + GP_CH4_DATA_REG) & GP_CH4_DATA_MASK; case GP_CH_5: return readl(reg_base + GP_CH5_DATA_REG) & GP_CH5_DATA_MASK; case GP_CH_6: return readl(reg_base + GP_CH6_DATA_REG) & GP_CH6_DATA_MASK; case GP_CH_7: return readl(reg_base + GP_CH7_DATA_REG) & GP_CH7_DATA_MASK; default: pr_err("%s, invalid channel id!", __func__); return -EINVAL; } }
-
@whycan 在 V853开发板开发进阶——GPADC 中说:
@jr_online
sunxi_gpadc_read_data()static u32 sunxi_gpadc_read_data(void __iomem *reg_base, enum gp_channel_id id) { switch (id) { case GP_CH_0: return readl(reg_base + GP_CH0_DATA_REG) & GP_CH0_DATA_MASK; case GP_CH_1: return readl(reg_base + GP_CH1_DATA_REG) & GP_CH1_DATA_MASK; case GP_CH_2: return readl(reg_base + GP_CH2_DATA_REG) & GP_CH2_DATA_MASK; case GP_CH_3: return readl(reg_base + GP_CH3_DATA_REG) & GP_CH3_DATA_MASK; case GP_CH_4: return readl(reg_base + GP_CH4_DATA_REG) & GP_CH4_DATA_MASK; case GP_CH_5: return readl(reg_base + GP_CH5_DATA_REG) & GP_CH5_DATA_MASK; case GP_CH_6: return readl(reg_base + GP_CH6_DATA_REG) & GP_CH6_DATA_MASK; case GP_CH_7: return readl(reg_base + GP_CH7_DATA_REG) & GP_CH7_DATA_MASK; default: pr_err("%s, invalid channel id!", __func__); return -EINVAL; } }
好滴,谢谢大佬
-
Copyright © 2023 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号