PCF8591芯片的AD/DA转换(适用于蓝桥杯单片机)

目录

1、PCF8591的引脚介绍

 2、用IIC发送或接收字节

             发送的第一个字节

        发送的第二个字节

  发送第三个字节  

  3.发送和接收的字节转换

 4.全部代码

IIC部分

接收电压数据

发送电压数据


1、PCF8591的引脚介绍

        0d5838137d8c4669898c2b50e410a02a.png

            在和单片机实际应用中它的接线图如下

9b494be48b334d6485c09498ad9d3dc1.png3b689a8fdeaf4930a742a0464a05a30c.png

297b783c4d1443febe4c4de713784746.png2f89680f717d4d569c65cbd12b71cf98.png

        PCF8591有四个模拟信号输入端(模转数),一个输出端(数转模),因为我们一般使用芯片的内部时钟,所以EXT和OSC接地,而VSS和VCC手册里写是用来上电复位的,只需要照着原理图接就行。

 2、用IIC发送或接收字节

             发送的第一个字节

             只要用到IIC通信首先要发送的就是芯片的地址

        c6cfc35cd811497cbc9827b4ec300715.png

       高四位为PCF8591的专用地址,只要用这个芯片高四位就必须是1001,低四位中A0、A1、A2表示要选择那个PCF8591,比如前面的原理图A0、A1、A2全部接地所以它的地址是000,最后低位R/W表示下一步写入还是读出数据,0是写1是读 ,下一步还要写数据所以这一位置0,总结起来这一个字节就是0x90

     IIC_Start();//开始
     IIC_SendByte(0x90);
     IIC_WaitAck();//应答如果接收到的话这个函数会返回1

       

              发送的第二个字节

        这个字节用来控制芯片的功能

                 16c5edb38611412987d9c6910df5cb79.png

      第一位和第二位 :AD转换的输入通道选择位  00 >>AIN0,  01>>AIN1,  10>>AIN2,  11>>AIN3

      第三位 :自动递增标志位,激活时给1,在每次A/D转换后,读取的通道会自动跳到下一位。

      第四位:无效位

      第五、六位:选择差分输入还是单端输入(如果对精度没有太大要求时选择单端输入置00)

     第七位: 使能模拟输出,使能时置1 ,表示切换为DA(数字转模拟模式)

     第八位:无效位

    1.AD模式 :比赛时建议一个一个通道使用,所以不启动递增位,发送字节为0x01(0000 001)接收通道1的电压值,这个时候所以要发送的控制字节已经发送完了,接下来是接收部分。

  IIC_SendByte(0x01);
  IIC_WaitAck();//应答标志位

    2.DA模式:因为PCF8591只有一个DA输出口,只要给第七位置1,发送字节0x40 (0000 0100)

       

    IIC_SendByte(0x04);
     IIC_WaitAck();

    发送第三个字节  

       1. AD模式: 首先和发送字节时一样要发送对应地址,接收地址为0x90,而接收地址为0x91,然后接收代码

        IIC_Start();
        IIC_SendByte(0x91);
        IIC_WaitAck();
        Date=IIC_RecByte();//要接收的值
        IIC_SendAck(1);//如果接收到的话发送
        IIC_Stop();//结束

        2.DA模式: 发送最后一个控制输出值的代码。 

        IIC_WaitAck();				
		IIC_SendByte(DATA); //要发送的值
		IIC_WaitAck();				
	    IIC_Stop();	

  3.发送和接收的字节转换

       因为PCF8591检测的电压是以8位二进制发送给单片机的,所以单片机得到的值是0~255,把它转换为0~5V的电压公式如下

                        检测到的电压  =   单片机上电电压(5V)gif.latex?%5Ctimesgif.latex?%5Cfrac%7B%7D%7B%7D  (测量到的值gif.latex?%5Cdiv255)gif.latex?%5Cfrac%7B%7D%7B%7Dgif.latex?%5Cfrac%7B%7D%7B%7D

     发送时把电压数据转换为二进制对应值,与上面就是将0~5V转换为0~255,把公式换一下即可。

                       发送要输出电压  =   255  gif.latex?%5Ctimesgif.latex?%5Cfrac%7B%7D%7B%7D (测量到的电压gif.latex?%5Cdiv 单片机上电电压(5V))gif.latex?%5Cfrac%7B%7D%7B%7D

 4.全部代码

IIC部分(官方的IIC代码SDA和 SCL可能是反的


#include <REGX52.H>
#include "intrins.h"
#define DELAY_TIME 5
sbit SDA = P2^1;
sbit SCL = P2^0;
   //IIC延时
void IIC_Delay(unsigned char i)
{
   
  

  while(i--);        

   
}

//开始发送
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//IIC结束发送
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//接收应答
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	  SDA=1;
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//发送一个字节
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//接收一个字节
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}

接收电压数据

 float PCF8951_Read(unsigned char date)
    {
         float Date;
        IIC_Start();//开始
        IIC_SendByte(0x90);//发送地址PCF8591的地址,表示要对其发送数据
        IIC_WaitAck();    //芯片接收到要返回一个应答位
        IIC_SendByte(date);//发送要执行的命令
        IIC_WaitAck();
        
        IIC_Start();
        IIC_SendByte(0x91);//发送地址PCF8591的地址,表示要接收它的数据
        IIC_WaitAck();
        Date=IIC_RecByte();//接收一个字节
        IIC_SendAck(1);//接收完成之后要发送一个1
        IIC_Stop();
        
        return (Date/255)*5;//电平转换
       
    }

发送电压数据

void PCF8951_Out(float DATE)
    {
        
        IIC_Start();
        IIC_SendByte(0x90);
        IIC_WaitAck();
        IIC_SendByte(0x04);
        IIC_WaitAck();
        IIC_WaitAck(255*(DATE/5));//发送要输出的电压
        IIC_WaitAck();
        IIC_Stop();
       
    }

物联沃分享整理
物联沃-IOTWORD物联网 » PCF8591芯片的AD/DA转换(适用于蓝桥杯单片机)

发表评论