求最简单的A/D转换程序
本人刚学单片机不久,自学《十天学会单片机和C语言》,现在学到A/D,D/A转换,这方面想了大半天都看不懂例程序,求最简单的A/D转换程序,要加说明 你还不如 贴上来让我们给你解释解释, 如果是用STC带AD的,最简单了,手册里就是有,我用STC12C5A系列,手册里提供了两种方法,中断及查询法。附手册:
http://www.stcmcu.com/datasheet/stc/STC-AD-PDF/STC12C5A60S2.pdf
jcrorxp 发表于 2012-12-2 16:35 static/image/common/back.gif
你还不如 贴上来让我们给你解释解释,
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit adwr=P3^6; //wr端口
sbit adrd=P3^7; //rd端口
uint i,j;
uchar s;
uchar k,m,n;
uchar code a[]={0x03,0x9f,0x25,0x0d,0x99,
0x49,0x41,0x1f,0x01,0x09};
void delay(uint x)
{
for(i=x;i>0;i--)
for(j=120;j>0;j--);
}
void xianshi(uchar k);//显示数码管
void main()
{
P2=0xff;
while(1)
{
adwr=1;
_nop_();
adwr=0;
_nop_();
m=P1;
adwr=1;
for(s=0;s<20;s++)
{
xianshi(n);
}
P1=0xff;
adrd=1;
_nop_();
adrd=0;
_nop_();
m=P1;
adrd=1;
n=m%10;
}
}
void xianshi(uchar k)
{
P2=0x00;
P0=a;
delay(1);
P2=0xff;
P0=0xff;
}
上面的程序是调节电位器可改变数码管的显示,但这程序不能,这程序是本人写的,仿照例题写的,出了一大堆问题,数码管只显示微弱光线的5字 李鸿鸿 发表于 2012-12-2 16:47 static/image/common/back.gif
#include
#include
#define uint unsigned int
调节电位器一点作用都没有 tian_cn 发表于 2012-12-2 16:38 static/image/common/back.gif
如果是用STC带AD的,最简单了,手册里就是有,我用STC12C5A系列,手册里提供了两种方法,中断及查询法。
附 ...
我用的是STC89C52单片机,PCF8591转换芯片的 楼主您要找的资料应该是这个 http://115.com/file/cl00dl9y# LZ
PCF8591 是IIC总线的AD
你的程序用的是ADC0804
PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I2C总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。 善用google,百度 william_rain 发表于 2012-12-2 20:18 static/image/common/back.gif
LZ
PCF8591 是IIC总线的AD
高手就是高手!换成PCF8591怎么用呢? Tliang 发表于 2012-12-2 21:31 static/image/common/back.gif
PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出 ...
那么这个程序怎么改呢? 李鸿鸿 发表于 2012-12-2 21:42 static/image/common/back.gif
那么这个程序怎么改呢?
你先看IIC协议,在看芯片数据手册就可以写出来了。//-----------------------函数声明,变量定义--------------------------------------------------------
#include <reg51.h>
#include <intrins.h>
sbit SDA=P2^1; // 将p1.0口模拟数据口
sbit SCL=P2^0; // 将p1.1口模拟时钟口
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
bit bdata SystemError; // 从机错误标志位
//-----------------------PCF8591专用变量定义--------------------------------------------------------
#define PCF8591_WRITE 0x90
#define PCF8591_READ0x91
#defineNUM4 // 接收和发送缓存区的深度
unsigned char idata receivebuf; // 数据接收缓冲区
//--------------------------------------------------------------------------------------------------
// 函数名称: iic_start()
// 函数功能: 启动I2C总线子程序
//--------------------------------------------------------------------------------------------------
void iic_start(void)
{EA=0; //时钟保持高,数据线从高到低一次跳变,I2C通信开始
SDA = 1;
SCL = 1;
delayNOP(); // 延时5us
SDA = 0;
delayNOP();
SCL = 0;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: iic_stop()
// 函数功能: 停止I2C总线数据传送子程序
//--------------------------------------------------------------------------------------------------
void iic_stop(void)
{
SDA = 0; //时钟保持高,数据线从低到高一次跳变,I2C通信停止
SCL = 1;
delayNOP();
SDA = 1;
delayNOP();
SCL = 0;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: slave_ACK
// 函数功能: 从机发送应答位子程序
//--------------------------------------------------------------------------------------------------
void slave_ACK(void)
{
SDA = 0;
SCL = 1;
delayNOP();
SDA = 1;
SCL = 0;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: slave_NOACK
// 函数功能: 从机发送非应答位子程序,迫使数据传输过程结束
//--------------------------------------------------------------------------------------------------
void slave_NOACK(void)
{
SDA = 1;
SCL = 1;
delayNOP();
SDA = 0;
SCL = 0;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: check_ACK
// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束
//--------------------------------------------------------------------------------------------------
void check_ACK(void)
{
SDA = 1; // 将p1.0设置成输入,必须先向端口写1
SCL = 1;
F0 = 0;
if(SDA == 1) // 若SDA=1表明非应答,置位非应答标志F0
F0 = 1;
SCL = 0;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: IICSendByte
// 入口参数: ch
// 函数功能: 发送一个字节
//--------------------------------------------------------------------------------------------------
void IICSendByte(unsigned char ch)
{
unsigned char idata n=8; // 向SDA上发送一位数据字节,共八位
while(n--)
{
if((ch&0x80) == 0x80) // 若要发送的数据最高位为1则发送位1
{
SDA = 1; // 传送位1
SCL = 1;
delayNOP();
SDA = 0;
SCL = 0;
}
else
{
SDA = 0; // 否则传送位0
SCL = 1;
delayNOP();
SCL = 0;
}
ch = ch<<1; // 数据左移一位
}
}
//--------------------------------------------------------------------------------------------------
// 函数名称: IICreceiveByte
// 返回接收的数据
// 函数功能: 接收一字节子程序
//--------------------------------------------------------------------------------------------------
unsigned char IICreceiveByte(void)
{
unsigned char idata n=8; // 从SDA线上读取一上数据字节,共八位
unsigned char tdata;
while(n--)
{
SDA = 1;
SCL = 1;
tdata = tdata<<1; // 左移一位,或_crol_(temp,1)
if(SDA == 1)
tdata = tdata|0x01; // 若接收到的位为1,则数据的最后一位置1
else
tdata = tdata&0xfe; // 否则数据的最后一位置0
SCL=0;
}
return(tdata);
}
//--------------------------------------------------------------------------------------------------
// 函数名称: DAC_PCF8591
// 入口参数: slave_add从机地址,n要发送的数据个数
// 函数功能: 发送n位数据子程序
//--------------------------------------------------------------------------------------------------
void DAC_PCF8591(unsigned char controlbyte,unsigned char wdata)
{
iic_start(); // 启动I2C
IICSendByte(PCF8591_WRITE); // 发送地址位
check_ACK(); // 检查应答位
if(F0 == 1)
{
SystemError = 1;
return; // 若非应答表明器件错误或已坏,置错误标志位SystemError
}
IICSendByte(controlbyte&0x77); //Control byte
check_ACK(); // 检查应答位
if(F0 == 1)
{
SystemError = 1;
return; // 若非应答表明器件错误或已坏,置错误标志位SystemError
}
IICSendByte(wdata); //data byte
check_ACK(); // 检查应答位
if(F0 == 1)
{
SystemError = 1;
return; // 若非应答表明器件错误或已坏,置错误标志位SystemError
}
iic_stop(); // 全部发完则停止
delayNOP();
delayNOP();
delayNOP();
delayNOP();
}
//--------------------------------------------------------------------------------------------------
// 函数名称: ADC_PCF8591
// 入口参数: controlbyte控制字
// 函数功能: 连续读入4路通道的A/D转换结果到receivebuf
//--------------------------------------------------------------------------------------------------
void ADC_PCF8591(unsigned char controlbyte)
{
unsigned char idata receive_da,i=0;
iic_start();
IICSendByte(PCF8591_WRITE); //控制字
check_ACK();
if(F0 == 1)
{
SystemError = 1;
return;
}
IICSendByte(controlbyte); //控制字
check_ACK();
if(F0 == 1)
{
SystemError = 1;
return;
}
iic_start(); //重新发送开始命令
IICSendByte(PCF8591_READ); //控制字
check_ACK();
if(F0 == 1)
{
SystemError = 1;
return;
}
while(i<4)
{
receive_da=IICreceiveByte();
receivebuf=receive_da;
slave_ACK(); // 收到一个字节后发送一个应答位
}
slave_NOACK(); // 收到最后一个字节后发送一个非应答位
iic_stop();
}
//--------------------------------------------------------------------------------------------------
// 函数名称: main
// 函数功能: 主程序
//--------------------------------------------------------------------------------------------------
void main(void)
{
DAC_PCF8591(0x40,0); //控制字为0100 0000,允许模拟量输出
while(1); //零值点输出测试
DAC_PCF8591(0x40,0xff); //控制字为0100 0000,允许模拟量输出
//满值点输入测试
ADC_PCF8591(0x40);
}
从网上下的。能不能用我不知道。一百度就出来了 如果楼主用STC的话可以看看这个:
http://www.doyoung.net/program/ADC/index.html
具体可以上STC的官网看看:
http://www.mcu-memory.com/
(千万不要在吃饭时看,这个官网的样子让人很无语) wsy2012 发表于 2012-12-2 22:23 static/image/common/back.gif
如果楼主用STC的话可以看看这个:
http://www.doyoung.net/program/ADC/index.html
具体可以上STC的官网看看 ...
"千万不要在吃饭时看,这个官网的样子让人很无语" ,顶楼上的这句话,哈!~ {:lol:}
Tliang 发表于 2012-12-2 21:45 static/image/common/back.gif
你先看IIC协议,在看芯片数据手册就可以写出来了。从网上下的。能不能用我不知道。一百度就出来了 ...
你这个代码让楼主刚学单片机的人,啃上一个月了,人家都被 你吓傻了!还IIC,人家说的是AD,DA,你说什么别的
mjh630 发表于 2012-12-3 11:30 static/image/common/back.gif
你这个代码让楼主刚学单片机的人,啃上一个月了,人家都被 你吓傻了!还IIC,人家说的是AD,DA,你说什么别的
...
拜托,你先看别人用的什么东西再发言OK。。
你牛逼你教会楼主不要IIC来控制这个芯片啊。 把你的例句和你的的程序一起发给我,我帮你看下,看能不能帮你的忙!QQ:290412297 jhjh630 发表于 2012-12-3 11:37 static/image/common/back.gif
把你的例句和你的的程序一起发给我,我帮你看下,看能不能帮你的忙!QQ:290412297 ...
教程上用的是ADC0804,我的开发板用的是PCF8591,程序编写方法都一样吧?我想原来的程序不用管了,芯片都不同。
PCF8591的例题是这样的:#ifndef __PCF8591_H__
#define __PCF8591_H__
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
//该ADC和DAC是串口输出,只要接两根线
sbit SCL=P3^6;//时钟脉冲
sbit SDA=P3^7;//双向输入输出数据端
#define SCL_SET SCL=1
#define SCL_CLR SCL=0
#define SDA_SET SDA=1
#define SDA_CLR SDA=0
#define AddWr 0x92 //写数据地址
#define AddRd 0x93 //读数据地址
#define adCon 0x40 //AD控制字节
//延时1US
void PDFDelay(uint cnt)
{
while(--cnt);
}
void start()
{
SDA_SET;
PDFDelay(1);
SCL_SET;
PDFDelay(5);
SDA_CLR;
}
void stop()
{
SDA_CLR;
PDFDelay(1);
SCL_SET;
PDFDelay(5);
SDA_SET;
}
void ack()
{
SDA_CLR;
SCL_SET;
PDFDelay(1);
SCL_CLR;
}
void noAck()
{
SDA_SET;
SCL_SET;
PDFDelay(1);
SCL_CLR;
}
void send(uchar Data)
{
uchar i=0;
uchar temp=0;
temp=Data;
for(i=0; i<8; i++)
{
SCL_CLR;
PDFDelay(1);
if(temp&0x80) SDA_SET;
else SDA_CLR;
PDFDelay(1);
SCL_SET;
PDFDelay(1);
temp<<=1;
}
SCL_CLR;
}
uchar recive()
{
uchar i=0;
uchar temp=0;
SDA_SET;//必须设置
for(i=0; i<8; i++)
{
SCL_CLR;//拉低允许数据改变
PDFDelay(1);
SCL_SET;//拉高保持数据,等待读走
PDFDelay(2);
if(SDA) temp|=0x01;
else temp&=0xfe;
if(i<7) temp<<=1;//最低位发送完成不能移位,否则出错
}
SCL_CLR;
return temp;
}
//ADC读函数。输入参数ch为通道数:0至3通道
uchar ADCGet(uchar ch)
{
uchar temp=0;
start();
send(AddWr);//确认芯片
ack();
send(adCon|ch);//确认通道
ack();
//读出数据,放进temp
start();
send(AddRd);
ack();
temp=recive();
noAck();
stop();
return temp;
}
//DAC设定参。输入参数value为设定的数字量
void DACSet(uchar value)
{
start();
send(AddWr);
ack();
send(0x40);//写入控制位,使能DAC输出
ack();
send(value);
ack();
stop();
}
//#include<reg52.h>
//#include"PCF8591.h"//自己封装的PCF8591芯片控制函数
void main()
{
while(1)
{
P1=ADCGet(2);//将2通道采样回来的值直接付给流水灯。二通道采样的是电位器的值,直接旋转电位器即可看到效果
}
} 本帖最后由 Tliang 于 2012-12-3 13:31 编辑
楼被占了。。 Tliang 发表于 2012-12-2 21:45 static/image/common/back.gif
你先看IIC协议,在看芯片数据手册就可以写出来了。从网上下的。能不能用我不知道。一百度就出来了 ...
控制SDA和SCL经过模数转换就能得到不同的地址?,再根据不同的地址让单片机做出不同的反应? 李鸿鸿 发表于 2012-12-3 12:31 static/image/common/back.gif
控制SDA和SCL经过模数转换就能得到不同的地址?,再根据不同的地址让单片机做出不同的反应? ...
通过单片机发地址信号给AD芯片,然后单片机发读命令,就可以把AD芯片里面的数据读出来!!! {:loveliness:}LZ是妹纸吧。。。 本帖最后由 Tliang 于 2012-12-3 13:32 编辑
地址开始的时候已经固定,由a0~a2确定,sda是iic总线的数据线,scl是iic总线的时钟线。通过IIC总线发送数据控制芯片转换,和读取转换的数据 先看显示程序都有问题,其他的不用考虑,你就让n=250,看它能显示不? 目测普中的开发板... Tliang 发表于 2012-12-3 12:55 static/image/common/back.gif
地址开始的时候已经固定,由a0~a2确定,sda是iic总线的数据线,scl是iic总线的时钟线。通过IIC总线发送数据 ...
a0~a3是什么? 楼主我建议你现在跳过这里,然后不看例程,使用PROTEUS软件自己画个流水灯。写程序,自己写完全不看书(因为看书理解了和自己写出来是两回事,抄书没用)。完成后。
再静态数码管显示。
然后动态数码管显示,然后点阵显示。然后在整LCD(简单的时序),595(SPI控制,主要学习时序),24CXX(IIC协议的EEPROM,例程特多)。这样过渡下来。再来整这个芯片。就会觉得小菜一碟了。 kcfoo1 发表于 2012-12-3 13:28 static/image/common/back.gif
先看显示程序都有问题,其他的不用考虑,你就让n=250,看它能显示不?
n=250?数组根本没有这么大?只是0到9 李鸿鸿 发表于 2012-12-3 13:39 static/image/common/back.gif
a0~a3是什么?
芯片的引脚。
下载个资料看看吧。。 Tliang 发表于 2012-12-3 13:43 static/image/common/back.gif
楼主我建议你现在跳过这里,然后不看例程,使用PROTEUS软件自己画个流水灯。写程序,自己写完全不看书(因 ...
这样啊?我想解决了AD转换我就可以做电压表了 李鸿鸿 发表于 2012-12-3 13:52 static/image/common/back.gif
这样啊?我想解决了AD转换我就可以做电压表了
这个芯片确实不适合新手学习。
做电压表?难道你没有万用表吗?用这个做也是鸡肋。0~5V可以测,超过了就得加工 Tliang 发表于 2012-12-3 14:14 static/image/common/back.gif
这个芯片确实不适合新手学习。
做电压表?难道你没有万用表吗?用这个做也是鸡肋。0~5V可以测,超过了就 ...
这样啊!我先绕过这,先学会其它的先 李鸿鸿 发表于 2012-12-3 14:16 static/image/common/back.gif
这样啊!我先绕过这,先学会其它的先
正确的选择,我看你数码管显示都还没掌握呀。。 我又回来了,经过几天的学习!我终于看懂了 郭老师的《十天学会单片机》里有讲I2C滴 IIC确实够看一阵子 百度一下就ok了 xyz543 发表于 2012-12-2 17:30 static/image/common/back.gif
楼主您要找的资料应该是这个 http://115.com/file/cl00dl9y#
{:smile:}
页:
[1]