ADC
ADC简介
ADC是 Analog Digital Converter 的缩写,翻译过来为模数转换器,ADC可以将模拟值转换成数字值。模拟值是什么呢?比如我们日常生活中的温度,速度,湿度等等都是模拟值。所以如果我们想测量这些模拟值的值是多少,就需要使用 adc把模拟值转换成数字值。
ADC的分辨率
分辨率就是 ADC可以分辨量化的做小信号的能力,好比尺子上的最小刻度,有的尺子上的最小刻度是厘米,有的尺子上的最小刻度是毫米。所以分辨率越高,得到的结果精度就越准确。(得到的数字信号再用 DAC转换成模拟信号就越接近原来的模拟值)。ADC的分辨率按位数可分为8位,10位,12位等等,位数越搞,分辨率也越高。
计算公式:分辨率=量程/2的n次方,n位 ADC的位数。
ADC的参考电压
有了最小刻度,那量程又是什么呢?
这里我们需要在了解一个重要的术语叫做参考电压,参考电压是一个已知的电压。通过已知的电压找到未知电压,这个是参考电压的作用。所以参考电压就是上面我们提到的量程。
举个例子:3位分辨率,2V参考电压
ADC框架
ADC的操作
在应用程序中使用sys接口来读取ADC的值
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]){float adc_value = 0;int sacle = 0;FILE *fp = NULL;fp = fopen("/sys/bus/iio/devices/iio:device0/in_voltage0_raw", "r");fscanf(fp, "%d", &sacle);adc_value = (1.8/1024)*(float)sacle; //1.8V is the voltage of the ADC// 1024 is the resolution of the ADC// so the real adc_value = (Measurement value) * ((reference voltage)/(ADC resolution))printf("The ADC value is %f\n", adc_value);fclose(fp);return 0;
}
ADC的驱动
1.在设备树中添加ADC设备
&iio_adc0 {compatible = "myadc";io-channels = <&saradc 4>; //adc控制器,使用adc通道4status = "okay";
};
2.在驱动中获得ADC的测量值
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h> //platform_device_register
#include <linux/of.h> //of_match_ptr
#include <linux/of_device.h> //of_device_id
#include <linux/platform_driver.h> //platform_driver_register
#include <linux/mod_devicetable.h>
#include <linux/iio/consumer.h> //iio_channel_get
#include <linux/miscdevice.h> //misc_register
#include <linux/uaccess.h> //copy_to_user
#include <linux/fs.h> //file_operations#define CMD_READ_SACLE _IOR('A',1,int)
struct iio_channel adc_channel= NULL;int adc_open(struct inode *inode, struct file *file){return 0;
}ssize_t adc_read(struct file *file, char __user *user_buf, size_t size, loff_t *ppos){return 0;
}
long adc_ioctl(struct file *file, unsigned int cmd, unsigned long arg){int scale = 0;if(cmd == CMD_READ_SACLE){iio_read_channel_raw(adc_channel, &scale); // get sacle value(Measurement value) from adc channelif(copy_to_user((int *)arg, &scale, sizeof(scale)) != 0){return -EFAULT;}}return 0;
}
const struct file_operations adc_fops = {.owner = THIS_MODULE,.read = adc_read,.open = adc_open,.unlocked_ioctl = adc_ioctl,
};
struct miscdevice adc_miscdev = {.minor = MISC_DYNAMIC_MINOR,.name = "adc",.fops = &adc_fops,
};
int adc_probe(struct platform_device *pdev){printk(KERN_INFO "ADC driver probe\n");adc_channel = iio_channel_get(&(pdev->dev),NULL); //get adc channelif(!adc_channel){printk(KERN_INFO "ADC channel get failed\n");return -1;}misc_deregister(&adc_miscdev);return 0;
}
int adc_remove(struct platform_device *pdev){printk(KERN_INFO "ADC driver remove\n");return 0;
}
const struct of_device_id adc_of_match[] = {{ .compatible = "myadc" },{ },
};
struct platform_driver adc_driver = {.driver = {.name = "adc_driver",.owner = THIS_MODULE,.of_match_table = of_match_ptr(adc_of_match),}.probe = adc_probe,.remove = adc_remove,
};
static int __init adc_init(void){printk(KERN_INFO "ADC driver init\n");platform_register_drivers(&adc_driver);return 0;
}
static void __exit adc_exit(void){printk(KERN_INFO "ADC driver exit\n");platform_unregister_drivers(&adc_driver);misc_deregister(&adc_miscdev);
}
module_init(adc_init);
module_exit(adc_exit);
MODULE_LICENSE("GPL");