SAR使用参考

Version 1.0


1. 概述

SAR口一共四个,10bit 精度,获取到的值范围在0~0x3ff之间,参考电压为3.3V,即如果你读到的值是0x1D2,得到的电压就是0x1D2/0x3FF *3.3=1.5v左右。


1.1. kernel中添加sar的支持

  1. 确保arch/arm/boot/dts/mercury6.dtsi里面有打开sar的支持

  2. 配置GPIO for sar mode,根据硬件连接在padmux.dtsi添加对应的配置,如:

    soc {
        padmux {
            <PAD_SAR_GPIO2              PINMUX_FOR_SAR_MODE             MDRV_PUSE_SAR_GPIO0 >,
        };
    };
    
  3. make menuconfig,确认sar的驱动有编译到kernel

    Device Drivers ---> [*] SStar SoC platform drivers ---> <*> sar driver
    

2. 内核使用SAR


2.1. 初始化为SAR口

先申明一下extern void  ms_sar_hw_init (void )函数,再通过这个函数初始化SAR。

  • 目的

    初始化

  • 语法

    void  ms_sar_hw_init ();
    
  • 参数

    参数名称 描述
  • 返回值

    返回值 描述

2.2. 取SAR值

先申明一下extern int  ms_sar_get (int ch)函数,再通过这个函数读取sar口电平。

  • 目的

    获取SAR口电平

  • 语法

    int  ms_sar_get (int ch)
    
  • 参数

    参数名称 描述
    ch SAR 通道,值范围为0~3
  • 返回值

    返回值 描述
    int 当前SAR口的电平

2.3. 举例

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/semaphore.h>
#include <linux/init.h>
#include <linux/mutex.h> 
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/random.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/proc_fs.h>

static int chn = 0;

module_param(chn, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(chn, "sar chn num");

extern void ms_sar_hw_init(void);
extern int ms_sar_get(int ch);

static int __init sar_test_init(void)
{
    int value = 0;

    ms_sar_hw_init();

    value = ms_sar_get(chn);

    printk("chn=%d, value=%d\n", chn, value);

    return 0;
}

static void __exit sar_test_exit(void)
{
    printk("sar_test driver exit success\n");
}

module_init(sar_test_init);
module_exit(sar_test_exit);

MODULE_DESCRIPTION("SAR_TEST driver");
MODULE_AUTHOR("SigmaStar");
MODULE_LICENSE("GPL");

3. 用户空间使用SAR

用户空间访问sar,通过IOCTL 的方式,首先open /dev/sar,通过IOCTL初始化SAR和读取电平。


3.1. IOCTL 初始化SAR

#define MS_SAR_INIT   _IO(SARADC_IOC_MAGIC, 0)
sar_fd= open("/dev/sar", /*O_RDONLY*/O_RDWR);
ioctl(sar_fd, MS_SAR_INIT, 0);

3.2. IOCTL 读取SAR值

#define SARADC_IOC_MAGIC               'a'
#define MS_SAR_SET_CHANNEL_READ_VALUE  _IO(SARADC_IOC_MAGIC, 1)

typedef struct 
{
    int channel_value;  ////0~3
    int adc_value;  ///读取到的值
}ADC_CONFIG_READ_ADC;

stCfg.channel_value=0;  ///SAR0
ioctl(sar_fd, MS_SAR_SET_CHANNEL_READ_VALUE, &stCfg);
printf("0: read stCfg.adc_value=:%x\n", stCfg.adc_value);

3.3. 举例

#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#define SARADC_IOC_MAGIC 'a'
#define MDRV_SARADC_SET_CHANNEL_MODE_READ_ADC _IO(SARADC_IOC_MAGIC, 1)
#define MS_SAR_INIT                         _IO(SARADC_IOC_MAGIC, 0)

#define SAR_MAX_CHN_NUM         4
#define SAR_DEV_NAME            "/dev/sar"

/// mdrv_sar_io.h
typedef struct
{
    int channel_value;
    int adc_value;
} ADC_CONFIG_READ_ADC;

int main(int argc, char **argv)
{
    ADC_CONFIG_READ_ADC stCfg;
    int sar_fd = -1;
    int chn = 0;
    int ret = 0;

    if (argc < 2)
    {
        printf("%s %d, such as: %s 1\n", __func__, __LINE__, argv[0]);
        return -1;
    }

    chn = atoi(argv[1]);
    if (chn < 0 || chn > SAR_MAX_CHN_NUM)
    {
        printf("%s %d, chn range is %d~%d\n", __func__, __LINE__, 0, SAR_MAX_CHN_NUM);
        return -1;
    }

    sar_fd = open(SAR_DEV_NAME, O_RDWR);
    if (sar_fd < 0)
    {
        perror("open error");
        return -1;
    }

    if (0 > ioctl(sar_fd, MS_SAR_INIT))
    {
        perror("ioctl MS_SAR_INIT error");
        close(sar_fd);
        return -1;
    }

    memset(&stCfg, 0, sizeof(ADC_CONFIG_READ_ADC));

    stCfg.channel_value = chn;
    if (0 > ioctl(sar_fd,MDRV_SARADC_SET_CHANNEL_MODE_READ_ADC, &stCfg))
    {
        perror("ioctl MDRV_SARADC_SET_CHANNEL_MODE_READ_ADC error");
        close(sar_fd);
        return -1;
    }

    printf("get success, chn=%d, value=%d\n", stCfg.channel_value, stCfg.adc_value);
    close(sar_fd);

    return 0;
}