单片机AD转换
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_DATAPINS P0
#define WRITEADDR 0x90 //写地址
#define READADDR 0x91 //读地址
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;
void Pcf8591SendByte(unsigned char channel);
unsigned char Pcf8591ReadByte();
void Pcf8591DaConversion(unsigned char value);
void I2C_Delay10us();
void I2C_Start();
void I2C_Stop();
uchar I2C_SendByte(uchar dat, uchar ack);
uchar I2C_ReadByte();
void Lcd1602_Delay1ms(uint c);
void LcdWriteCom(uchar com);
void LcdWriteData(uchar dat) ;
void LcdInit();
void I2C_Delay10us()
{
uchar a, b;
for(b=1; b>0; b--)
{
for(a=2; a>0; a--);
}
}
void I2C_Start()
{
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
I2C_SDA = 0;
I2C_Delay10us();//保持时间是>4us
I2C_SCL = 0;
I2C_Delay10us();
}
void I2C_Stop()
{
I2C_SDA = 0;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间大于4.7us
I2C_SDA = 1;
I2C_Delay10us();
}
uchar I2C_SendByte(uchar dat, uchar ack)
{
uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。
for(a=0; a<8; a++)//要发送8位,从最高位开始
{
I2C_SDA = dat >> 7; //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
dat = dat << 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();//建立时间>4.7us
I2C_SCL = 0;
I2C_Delay10us();//时间大于4us
}
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
{
b++;
if(b > 200) //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
{
I2C_SCL = 0;
I2C_Delay10us();
return 0;
}
}
I2C_SCL = 0;
I2C_Delay10us();
return 1;
}
uchar I2C_ReadByte()
{
uchar a = 0,dat = 0;
I2C_SDA = 1; //起始和发送一个字节之后I2C_SCL都是0
I2C_Delay10us();
for(a=0; a<8; a++)//接收8个字节
{
I2C_SCL = 1;
I2C_Delay10us();
dat <<= 1;
dat |= I2C_SDA;
I2C_Delay10us();
I2C_SCL = 0;
I2C_Delay10us();
}
return dat;
}
void Lcd1602_Delay1ms(uint c) //误差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择输入数据
LCD1602_RW = 0; //选择写入
LCD160
2_DATAPINS = dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
void main()
{
unsigned int adNum[5];
float value0;
LcdInit();
while(1)
{
//--显示电位器电压--//
Pcf8591SendByte(0); //发送电位器转换命令
//--由于8591在第一次读取的时候是读取到的上次转换的结果--//
//--所以我们先读一次,只是读到的数据不做处理--//
adNum[0]= Pcf8591ReadByte()*2;//将前一次转换结果读走
//--在读走上一次转换结果之后,才开始启动下一次转换,需要一点时间--//
//--为了不浪费单片机的资源,让单片机空着,我们直接发送给我们下次--//
//--要读取的命令,做一些数据处理和显示当做延时--//
LcdWriteCom(0x80+0x46); //发送显示坐标
LcdWriteData('0'+adNum[3]/1000); //发送显示数据
LcdWriteData('0'+adNum[3]%1000/100);
LcdWriteData('0'+adNum[3]%100/10);
LcdWriteData('0'+adNum[3]%10);
Pcf8591SendByte(1); //发送热敏转换命令
adNum[0]= Pcf8591ReadByte()*2;//读取电位器转换结果
//--读取走了,上一次转换结果就是电位器的转换结果之后,热敏的转换开始--//
//--我们继续做一些处理当延时。--//
//--我们8591每读取到一个1就表示5/256V,所以要知道电压值就乘以0.01953--//
value0=adNum[0]/2*0.01953; //转为电压值
adNum[0]=value0*100; //保留两位小数
LcdWriteCom(0x80);
LcdWriteData('0'+adNum[0]%1000/100);
LcdWriteData('.');
LcdWriteData('0'+adNum[0]%100/10);
LcdWriteData('0'+adNum[0]%10);
LcdWriteData('V');
Pcf8591SendByte(2); //发送光敏转换命令
adNum[1]=Pcf8591ReadByte()*2; //ADC1读取热敏
//--一下读取的方式跟上面一样处理--//
//--读光敏--//
LcdWriteCom(0x86);
LcdWriteData('0'+adNum[1]/1000);
LcdWriteData('0'+adNum[1]%1000/100);
LcdWriteData('0'+adNum[1]%100/10);
LcdWriteData('0'+adNum[1]%10);
Pcf8591SendByte(3); //发送外部输入电压转换命令
adNum[2]=Pcf8591ReadByte()*2; //ADC2读取光敏
//--读取外部输入电压--//
LcdWriteCom(0x80+0x40);
LcdWriteData('0');
LcdWriteData('0'+adNum[2]/1000);
LcdWriteData('0'+adNum[2]%1000/100);
LcdWriteData('0'+adNum[2]%100/10);
LcdWriteData('0'+adNum[2]%10);
adNum[3]=Pcf8591ReadByte()*2; //ADC3读取外部输入电压
//--DA输出--//
adNum[4]=adNum[0];
Pcf8591DaConversion(adNum[4]/2); //DAC 数模转换
}
}
//* 函数功能 : 写入一个控制命令
//* 输 入 : chan
nel(转换通道)
void Pcf8591SendByte(unsigned char channel)
{
I2C_Start();
I2C_SendByte(WRITEADDR, 1); //发送写器件地址
I2C_SendByte(0x40|channel, 0); //发送控制寄存器
I2C_Stop();
}
//* 函数功能 : 读取一个转换值
//* 输 出 : dat
unsigned char Pcf8591ReadByte()
{
unsigned char dat;
I2C_Start();
I2C_SendByte(READADDR, 1);//发送读器件地址
dat=I2C_ReadByte(); //读取数据
I2C_Stop(); //结束总线
return dat;
}
//* 函数功能 : PCF8591的输出端输出模拟量
//* 输 入 : value(转换的数值)
void Pcf8591DaConversion(unsigned char value)
{
I2C_Start();
I2C_SendByte(WRITEADDR, 1);//发送写器件地址
I2C_SendByte(0x40, 1); //开启DA写到控制寄存器
I2C_SendByte(value, 0); //发送转换数值
I2C_Stop();
}