angrybulb 发表于 2012-8-4 14:44:41

PCF8591 AD的问题一个

本帖最后由 angrybulb 于 2012-8-4 20:13 编辑

小弟新来,刚学单片机,现在遇到个问题,我想实现PCF8591芯片的AD转换,先用通道4,然后再LCD上显示电压值,可是我烧进单片机后,无论怎样旋转电位器,显示的值都不会变,麻烦各位指点,O(∩_∩)O谢谢。

//----------------I2C.h--------#ifndef _I2C_H_
#define _I2C_H_
#define uchar unsigned char
#define uintunsigned int
//bit          bdata I2C_ERROR;

sbit SCL        = P2^0;          //数据线
sbit SDA        = P2^1;                   //时钟线

extern void I2C_Start();
extern void I2C_Stop();
extern void Slave_ACK();
extern void Slave_NOACK();
extern void I2C_SendByte(uchar wd);
extern uchar I2C_ReceiveByte();

#endif//-----------------delay.h---------------
#ifndef        _DEALY_H_
#define _DEALY_H_
#define uchar unsigned char
#define uintunsigned int
//#define Delay4us()        { _nop_();_nop_();_nop_();_nop_();}
externvoid delay(uint z);
extern         void delay4us();
#endif

//-----------------LCD1602.h------------#ifndef _LCD1602_H_
#define _LCD1602_H_
#define uchar unsigned char
#define uintunsigned int
sbitRS = P1^0;                //LCD复位端
sbitRW = P1^1;                //LCD读写位
sbitEN = P2^5;          //LCD使能端

extern bit LCD_Busy();
extern void LCD_Pos(uchar pos);
extern void LCD_Wcmd(uchar cmd);
extern void LCD_Wdat(uchar str);
extern void LCD_Init();
extern void Display_String(uchar Line_Addr, uchar s[]);
#endif//-----------------这是main.c-----------#include<reg51.h>
#include<intrins.h>
#include"delay.h"
#include"I2C.h"
#include"LCD1602.h"

//------------------------------------------
uchar FirstLine={" . V            "};
uchar TempData;
bit ADFlag;


//------------------------------------------
void Init_Timer1();
uchar ReadADC(uchar Chl);
void disp();
//------------------------------------------

void Init_Timer1()
{
TMOD |= 0x10;                             
TH1=0xff;                      
TL1=0x00;
EA=1;                     
ET1=1;                     
TR1=1;
}

uchar ReadADC(uchar Chl)
{
       uchar Data;
           I2C_Start();      //写入芯片地址
           I2C_SendByte(0x90);
           Slave_ACK();
           I2C_SendByte(0x40|Chl);//写入选择的通道,本程序只用单端输入,差分部分需要自行添加
                                  //Chl的值分别为0、1、2、3,分别代表1-4通道
           Slave_ACK();
           I2C_Start();
           I2C_SendByte(0x91);    //读入地址
           Slave_ACK();
           Data=I2C_ReceiveByte();    //读数据
           SCL=0;
           Slave_NOACK();
           I2C_Stop();
           return Data;   //返回值
}

void disp()
{
        FirstLine='0'+TempData;
        FirstLine='0'+TempData;

        Display_String(0x00,FirstLine);
}

void main()
{
       uchar ADtemp;                //定义中间变量
       LCD_Init();
         Init_Timer1();
       while(1)
       {
           if(ADFlag)      //定时采集输入模拟量
       {
                   ADFlag=0;

           /*        ADtemp=ReadADC(0);
                TempData=(ReadADC(0))/50;//处理0通道电压显示
                TempData=((ReadADC(0))%50)/10;
       
      ADtemp=ReadADC(1);
                TempData=(ReadADC(1))/50;//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
                TempData=((ReadADC(1))%50)/10;
               
      ADtemp=ReadADC(2);
                TempData=(ReadADC(2))/50;//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
                TempData=((ReadADC(2))%50)/10;           */
               
      ADtemp=ReadADC(3);
                TempData=(ReadADC(3))/50;//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
                TempData=((ReadADC(3))%50)/10;
               
      disp();       
                }
       }
}

void Timer1_isr() interrupt 3 using 1//定时器1执行数码管动态扫描
{

static uint j;
TH1=0xfb;                //重新赋值
TL1=0x00;
j++;
if(j==200)
    {j=0;ADFlag=1;} //定时置位AD采样标志位
}
//------------------------------------------
//--------------------这是I2C.c---------------------#include<reg51.h>
#include"delay.h"
#include"I2C.h"


void I2C_Start()
{
        SDA = 0;
        SCL = 1;
        delay4us();
        SDA = 0;
        delay4us();
        SCL = 0;       
}

void I2C_Stop()
{
        SDA = 0;
        SCL = 1;
        delay4us();
        SDA = 1;
        delay4us();
        SCL = 0;
}

void Slave_ACK()
{
        SDA = 0;
        SCL = 1;
        delay4us();
        SCL = 0;
        SDA = 1;       
}

void Slave_NOACK()
{
        SDA = 1;
        SCL = 1;
        delay4us();
        SCL = 0;
        SDA = 0;
}

//----------------写一个字节 -------------------
void I2C_SendByte(uchar wd)
{
        uchar i,Temp;
        Temp = wd;
        for(i = 0;i < 8;i++)
        {
                Temp = Temp << 1;
                SCL = 0;
                delay4us();
                SDA = CY;
                delay4us();
                SCL = 1;
                delay4us();
        }       
        SCL = 0;
        delay4us();
        SDA = 1;
        delay4us();
}

//----------------读取一个字节------------------
uchar I2C_ReceiveByte()
{
        uchar i,k;
        SCL = 0;
        delay4us();
        SDA = 1;
        delay4us();
        for(i = 0;i < 8; i++)
        {
                SCL = 1;
                delay4us();
                k = ( k<<1 ) | SDA;
                SCL = 0;
                delay4us();
        }
        return k;
}
//----------------------------------------------//--------------这是LCD1602.c----------#include<reg51.h>
#include<delay.h>
#include<LCD1602.h>

//----------------------------------------------
//LCD初始化
//----------------------------------------------
void LCD_Init()
{
        LCD_Wcmd(0x38);           //8位数据长度 5X7像素字体
        delay(1);
        LCD_Wcmd(0x01);           //清屏
        delay(1);               
        LCD_Wcmd(0x06);           //字符进入模式:屏幕不动,字符后移
        delay(1);
        LCD_Wcmd(0x0c);           //显示开,关光标
        delay(1);               
}
//----------------------------------------------
//LCD忙检查
//----------------------------------------------
bit LCD_Busy()
{
        bit LCD_Status;
        RS = 0;
        RW = 1;
        EN = 1;
        delay(1);
        LCD_Status = P0;
        EN = 0;
        return LCD_Status;       
}
//----------------------------------------------
//LCD写命令
//----------------------------------------------
void LCD_Wcmd(uchar cmd)
{
        while((LCD_Busy() & 0x80) == 0x80);
        RS = 0;
        RW = 0;
        EN = 0;
        P0 = cmd;
        EN = 1;
        delay(1);
        EN = 0;       
}

//---------------------------------------------
//设置液晶显示位置
//---------------------------------------------
void LCD_Pos(uchar pos)
{
        LCD_Wcmd(pos | 0x80);
}
//----------------------------------------------
//LCD写入数据
//----------------------------------------------
void LCD_Wdat(uchar str)
{
        while((LCD_Busy() & 0x80) == 0x80);
        RS = 1;
        RW = 0;
        EN = 0;
        P0 = str;
        EN = 1;
        delay(1);
        EN = 0;
}
//--------------------------------------------------------
//在LCD指定的行上显示字符串
//---------------------------------------------------------
void Display_String(uchar Line_Addr, uchar s[])
{
        uchar k;
        LCD_Pos(Line_Addr);
        for(k = 0; k < 16; k++)
        {
                LCD_Wdat(s);
        }       
}
//----------------------------------------------//--------------------------这是delay.c---------------#include<reg51.h>
#include<intrins.h>
#include"delay.h"
void delay(uint z)
{
        uint x,y;
        for(x = z;x>0;x--)
                for(y = 110;y>0;y--);
}

void delay4us()
{
        _nop_();
        _nop_();
        _nop_();
        _nop_();
}

angrybulb 发表于 2012-8-4 15:34:45

{:sweat:}亲,第一次发帖给点面子啊

slzm40 发表于 2012-8-4 16:55:09

现象描述不清楚。。LCD上显示什么值, 全00?   最好首次写测试模块的测试,在程序里插入一个1S一闪的指示灯,万一程序跑死机了,还可以看出来是否是程序跑飞了。

Bungy 发表于 2012-8-4 18:11:15

读AD先0x90后0x91   再看下手册吧

angrybulb 发表于 2012-8-4 19:58:34

Bungy 发表于 2012-8-4 18:11 static/image/common/back.gif
读AD先0x90后0x91   再看下手册吧

哦,发现了,修改下试试看

angrybulb 发表于 2012-8-4 20:00:26

slzm40 发表于 2012-8-4 16:55 static/image/common/back.gif
现象描述不清楚。。LCD上显示什么值, 全00?   最好首次写测试模块的测试,在程序里插入一个1S一闪的指示 ...

嗯,我没说清楚,显示是5.0V;
测试模块的程序是写在main函数里面吗?

zengdz 发表于 2012-8-5 00:02:12

看下SDA和SCL有没有接反,查一下硬件、
页: [1]
查看完整版本: PCF8591 AD的问题一个