ADC简介
单片机只能分析数字信号,帮你分析模拟信号。所以接受外界模拟量--->数字量(0或1)
分辨率:模拟信号能输出离散信号的个数。通常用2进制存储,所以通常用bit。输入5V,最小的电压变化值:5*1/2的12次方
转换误差:输出误差的最大值形式给出,即实际输出数字量和理论输出数字量的差别
转换速率:完成一次AD所需要的时间的倒数(每秒转换的次数)
采样:将连续变化的模拟量转化为离散的模拟量
编码:将量化后的结果按数字形式表示
(直接性转换)八个二进制位的数字信号存储在N位寄存器中,如10110001。顺序是从最高位像最低位逐个进行比较。比较时,第一次是最高位进入N位D/A转换器,传递给比较器。比较器的U0接收信号,与UX进行比较。若U0<UX,则保留该位的数字信号,否则清楚。重复上述操作
(间接性转换)主要依靠电子开关,积分器,比较器,控制逻辑组成。
XPT2046芯片介绍
因为单片机只能识别数字电路,因此需要模拟电路转化为数字电路的芯片.。
当CS脚为高电平时,BUSY为高阻态。
DIN脚串行数据输入端。单片机命令通过DIN写入
当CS为低电平时,开始工作。
DCLK:时钟信号输入,上升沿时写入数据(外部时钟信号输入)
VCC:电源脚。可选择5V或者3.3V
XP YP XN YN :分别是X+ Y+ X- Y-的数据输入端
Vbat:电磁监视输入端。可监视外部电磁/电压信号
AUX:辅助输入通道
Vref:参考电压输入管教(计算实际电压时用到,自身管脚有5V或者3.3V可选)
IOVDD:数字电源输入引脚
DOUT:数据输出引脚。输出信号给单片机
4个基本引脚:DIN,CS,DCLK,DOUT,其中,DIN和DOUT可以并联给单片机,即3线制SPI通信接口
最高位S:当S为1时,则新的字节到来,为0时,忽略引脚上的数据。因此,通常为1
A2,A1,A0:通道选择。如,为001,则由上上图可知,为XP,即X+。
可调整A2 A1 A0,用于测量Vbat和AUX和TEMP
MODE位:设置分辨率精度。为1时,则分辨率为8位,为0时,分辨率为12位。默认分辨率为12为,即默认为MDE为0
SER/DPR:设置芯片工作模式。(是单端输入还是差分输入),1是单端输入,0是差分输入(外部触摸屏的应用)。
PD1,PD0:功耗。均为0时,低功耗模式。默认掉电。均为1时,处于供电状态。默认设置为0.
芯片工作,需要:CS为低电平,DCLK有外部时钟输入.DIN将单片机的数据写入芯片内。对应上述分析的8个字节的效果,正好是8个周期。之后有个等待周期,等待周期过了之后,才进入BUSY和DOUT接收数据。因为分辨率只有12位,所以前12位有效,后4位无效。
注:此时为AD值,AD值需要计算转换为数字电路电压值。电压值=AD*Vrev*(2的12次方分之一)
Vref为固定的系统电源。
硬件设计:
A2-A4型:
注:AIN0,AIN1,AIN2,AIN3对应X+,Y+,AUX,VBAT,从单端模式输入配置图可查找。如AIN0为X+,为XP,为001或者011
A5-A7型:
计算公式:V=VAD*VCC/(2的12次方)
软件设计:
注:根据时序图编写程序
原始代码如下:
main部分代码:
#include "public.h" #include "smg.h" #include "xpt2046.h" void main() { u16 adc_value=0; float adc_vol;//ADC电压值 u8 adc_buf[3]; while(1) { adc_value=xpt2046_read_adc_value(0x94);//测量电位器 adc_vol=5.0*adc_value/4096;//将读取的AD值转换为电压 adc_value=adc_vol*10;//放大10倍,即保留小数点后一位 adc_buf[0]=gsmg_code[adc_value/10]|0x80; adc_buf[1]=gsmg_code[adc_value%10]; adc_buf[2]=0x3e;//显示单位V smg_display(adc_buf,6); } } xpt2046.c代码: #include "xpt2046.h" #include "intrins.h" //XPT2046写数据 void xpt2046_wirte_data(u8 dat) { u8 i; CLK = 0; _nop_(); for(i=0;i<8;i++)//循环8次,每次传输一位,共一个字节 { DIN = dat >> 7;//先传高位再传低位 dat <<= 1;//将低位移到高位 CLK = 0;//CLK由低到高产生一个上升沿,从而写入数据 _nop_(); CLK = 1; _nop_(); } } // XPT2046读数据 u16 xpt2046_read_data(void) { u8 i; u16 dat=0; CLK = 0; _nop_(); for(i=0;i<12;i++)//循环12次,每次读取一位,大于一个字节数,所以返回值类型是u16 { dat <<= 1; CLK = 1; _nop_(); CLK = 0; //CLK由高到低产生一个下降沿,从而读取数据 _nop_(); dat |= DOUT;//先读取高位,再读取低位。 } return dat; } //XPT2046读AD数据 u16 xpt2046_read_adc_value(u8 cmd) { u8 i; u16 adc_value=0; CLK = 0;//先拉低时钟 CS = 0;//使能XPT2046 xpt2046_wirte_data(cmd);//发送命令字 for(i=6; i>0; i--);//延时等待转换结果 CLK = 1; _nop_(); CLK = 0;//发送一个时钟,清除BUSY _nop_(); adc_value=xpt2046_read_data(); CS = 1;//关闭XPT2046 return adc_value; } xpt2046.h代码 #ifndef _xpt2046_H #define _xpt2046_H #include "public.h" //管脚定义 sbit DOUT = P3^7; //输出 sbit CLK = P3^6; //时钟 sbit DIN = P3^4; //输入 sbit CS = P3^5; //片选 //函数声明 u16 xpt2046_read_adc_value(u8 cmd); #endif