【TINY4412】LINUX移植笔记:(26)设备树ADC驱动

【TINY4412】LINUX移植笔记:(26)设备树 ADC驱动

宿主机 : 虚拟机 Ubuntu 16.04 LTS / X64
目标板[底板]: Tiny4412SDK - 1506
目标板[核心板]: Tiny4412 - 1412
LINUX内核: 4.12.0
交叉编译器: arm-none-linux-gnueabi-gcc(gcc version 4.8.3 20140320)
日期: 2017-9-9 20:30:09
作者: SY

简介

开发板自带 4ADC

这里写图片描述
这里写图片描述
开发板将 ADC0 连接一个滑动变阻器。 ADC12 位,最大码值为:4095

移植

设备树

参考设备树文件:

adc: adc@126C0000 {
    compatible = "samsung,exynos-adc-v1";
    reg = <0x126C0000 0x100>;
    interrupt-parent = <&combiner>;
    interrupts = <10 3>;
    clocks = <&clock CLK_TSADC>;
    clock-names = "adc";
    #io-channel-cells = <1>;
    io-channel-ranges;
    samsung,syscon-phandle = <&pmu_system_controller>;
    status = "disabled";
};

写自己的设备树:

&adc {
    status = "okay";
};
Device Drivers  --->
    <*> Industrial I/O support  ---> 
        Analog to digital converters  --->     
            <*> Exynos ADC driver support

烧录

[    4.002206] exynos-adc 126c0000.adc: 126c0000.adc supply vdd not found, using dummy regulator

查看设备节点

[root@TINY4412:~]# ls /dev/iio\:device0 
/dev/iio:device0

APP

/*
 * adc driver for tiny4412
 *
 * Copyright (c) 2017
 * Author: SY <1530454315@qq.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version. 
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h> 
#include <signal.h>
#include <stdbool.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>


#define DEVICE_NAME             "/sys/bus/iio/devices/iio\:device0/"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

struct adc_dev {
        uint8_t chn;
        const char *dev;
};

const struct adc_dev adc_dev_table[] = {
        {0,     "in_voltage0_raw"},
        {1,     "in_voltage1_raw"},
        {2,     "in_voltage2_raw"},
        {3,     "in_voltage3_raw"},
};


#if 1
static void help(void)
{
        printf("Usage: ./adc <chn>\n");
}
#endif

int adc_chn;

bool esc = false;
static void sigint_handler(int dunno)
{
        switch (dunno) {
        case SIGINT:
                esc = true;
                printf("< Ctrl+C > Press.\n");
                break;
        default:
                break;
        }
}

const char* match_adc_dev(uint8_t chn)
{
        for (uint8_t i=0; i<ARRAY_SIZE(adc_dev_table); ++i) {
                if (chn == adc_dev_table[i].chn) {
                        return adc_dev_table[i].dev;
                }
        }

        return NULL;
}

static bool read_adc(char *dev, int32_t *code)
{
        int fd = open(dev, O_RDONLY);
        if (fd < 0) {
                perror("open error");
                return false;
        }

        char value[32];
        int ret = read(fd, value, sizeof(value));
        if (ret < 0) {
                perror("read error");
                return false;
        }
        int32_t adc = 0;
        sscanf(value, "%d", &adc);

        close(fd);

        *code = adc;
        return true;
}

static void* read_handler(void* data)
{
        printf("thread run.\n");
        char dev_name[64];
        strcpy(dev_name, DEVICE_NAME);
        const char *dev = match_adc_dev(adc_chn);

        if (!dev) {
                printf("it can't find device!\n");
                return NULL;
        }
        strcat(dev_name, dev);

        while (esc == false) {
                int32_t code = 0;
                if (read_adc(dev_name, &code) == false) {
                        printf("read_adc error!\n");
                        return NULL;
                }

                printf("[%d] %d\n", adc_chn, code);
                usleep(20*1000);
        }
        pthread_exit(NULL);

        return NULL;
}

int main(int argc, char **argv)
{
        if (argc != 2) {
                help();
                exit(0);
        }

        adc_chn = atoi(argv[1]);

        pthread_t thread_read;
        int ret = pthread_create(&thread_read, NULL, read_handler, NULL);
        if (ret) {
                perror("[thread_create]");
                return 1;
        }
        /* Register signal */
        signal(SIGINT, sigint_handler);

        pthread_join(thread_read, NULL);
        printf("done!\n");

        return 0;
}

使用 dev/iio:device0 读取数据有问题,因此使用 sysfs 读数据。

测试

[root@TINY4412:~]# ./tmp/adc 0
thread run.
[0] 0
[0] 0
[0] 0
[0] 5
[0] 20
[0] 38
[0] 81
[0] 135
[0] 181
[0] 225
[0] 263
[0] 284
[0] 311
[0] 347
[0] 362
[0] 396
[0] 433
[0] 453
[0] 484
[0] 513
[0] 531
[0] 543
[0] 567
[0] 606
[0] 621
[0] 640
[0] 662
[0] 696
[0] 724
[0] 748
[0] 798
[0] 820
[0] 845
[0] 875
[0] 893
[0] 925
[0] 946
[0] 997
[0] 1057
[0] 1097
[0] 1142
[0] 1232
[0] 1289
[0] 1368
[0] 1421
[0] 1478
[0] 1541
[0] 1601
[0] 1653
[0] 1724
[0] 1771
[0] 1800
[0] 1841
[0] 1875
[0] 1894
[0] 1942
[0] 1962
[0] 1986
[0] 2033
[0] 2062
[0] 2095
[0] 2120
[0] 2141
[0] 2162
[0] 2180
[0] 2213
[0] 2239
[0] 2273
[0] 2313
[0] 2342
[0] 2366
[0] 2391
[0] 2419
[0] 2448
[0] 2467
[0] 2496
[0] 2505
[0] 2554
[0] 2604
[0] 2623
[0] 2668
[0] 2723
[0] 2777
[0] 2836
[0] 2879
[0] 2951
[0] 3021
[0] 3046
[0] 3087
[0] 3113
[0] 3163
[0] 3211
[0] 3251
[0] 3296
[0] 3332
[0] 3377
[0] 3404
[0] 3457
[0] 3504
[0] 3561
[0] 3639
[0] 3691
[0] 3780
[0] 3854
[0] 3917
[0] 3968
[0] 4009
[0] 4064
[0] 4095
[0] 4095
[0] 4095
[0] 4095
^C< Ctrl+C > Press.
done!
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值