单片机——基于DA转换的呼吸灯

1、基础知识
1.1、 AD转换器的分辨率
12位的分辨率就是12位,或者说为满刻度的1/(2^12)。
1.2、 量化误差是ADC的有限位数对模拟量进行量化引起的误差。
1.3、AD转换器的类型
双积分型,逐次逼近型,并行比较型。
1.4、PCF8591
PCF8591是一款集成了4个12位模数转换器和1个8位数模转换器的8位通用模拟输入输出转换器。它可以通过I2C总线与其他设备通信,并可以将4个不同的模拟输入信号转换为数字信号输出。此外,它还提供了一个可编程增益放大器和可编程输出电压范围的电压输出。

PCF8591常用于模拟信号采集和处理应用,例如温度、压力、湿度等传感器的信号采集,以及控制系统中的模拟电路控制。它也可以用于音频处理、图像处理、运动控制和光学测量等领域。在嵌入式系统中,PCF8591是一个非常有用的工具,因为它可以实现模拟信号和数字信号的转换,并将不同的信号集成到一个芯片上,从而节省了系统空间和设计成本。

PCF8591采用的也是I2C通信协议。PCF8591的指令顺序是:主机先向其发送地址指令,然后是控制字指令,最后是数据指令。
在这里插入图片描述

它有ADC和DAC两种转化模式
ADC功能配置,先后发送0x90、0x40+channel(取值0、1、2、3,总共有四个通道)、0x91即可;
DAC功能配置,先后发送0x90、0x40、user_data(8bit)即可;
本次我们使用的是DAC。
2、程序部分
2.1、程序大体还是延时,I2C协议,发送数据,数码管锁存。在这里不再介绍了。分别参照我前面的博客。
链接1: 单片机控制一盏灯的亮与灭程序解释
链接2: 单片机——数码管动态显示
链接3: 单片机——IIC协议与24C02
2.2、新增部分——PCF8591的使用

 DAC(uchar dat)
{
    
    
start();
 send(0x90);
 ack();
 
 send(0x40);
 ack();

 send(dat);
 ack();

 stop();

}

基本原理
PCF8591的指令顺序是:主机先向其发送地址指令,然后是控制字指令,最后是数据指令。DAC功能配置,先后发送0x90、0x40、user_data(8bit)即可;所以这部分程序也比较好懂,就是开启,发送地址指令,应答,发送控制指令,应答,发送数据,应答。停止。
2.3、主函数

void main()
{
    
    
uchar num;
delay(5);
cmg();
   while(1)
   {
    
    
   DAC(num);
   num++;
   delay(30);
   }
}

该程序的具体流程为
在main函数中,首先调用了delay函数和cmg函数,分别用于延时和初始化I2C总线。

进入while循环后,首先调用了DAC函数,将num的值通过PCF8591芯片的DAC输出。DAC函数的作用是向PCF8591芯片的DAC输入端写入num的值,从而在PCF8591芯片的输出端产生相应的电压输出。

将num的值加1,以便下一次输出。

调用delay函数,延时30毫秒。便于显示。

重复执行步骤2到4,循环输出递增的数字。
3、完整代码

 #include<reg52.h>
 #include<intrins.h>
 #define uchar unsigned char
 #define uint unsigned int

 sbit duan=P2^6;
 sbit wei =P2^7;
 sbit RST =P2^4;
 sbit SCL=P2^1;
 sbit SDA=P2^0;

 void delay(uchar k)
{
    
    
  uchar i,j;
  for (i=0;i<k;i++)
  {
    
    
    for (j=0;j<113;j++)
    {
    
    
     ;
    }
  }
}


//iic部分
//start
void start()
{
    
    
SDA=1;
_nop_();
SCL=1;
_nop_(); 
SDA=0;
_nop_();
}

//Stop
void stop()
{
    
    
SDA=0;
_nop_();
SCL=1;
_nop_(); 
SDA=1;
_nop_();
}

//应答
void ack()
{
    
    
SDA=0;
_nop_();
SCL=1;
_nop_(); 
SCL=0;
_nop_();
}

//非应答
void noack()
{
    
    
SDA=1;
_nop_();
SCL=1;
_nop_(); 
SCL=0;
_nop_();
}

//发数据
void send(uchar dat)
{
    
      uchar i;
   for(i=0;i<8;i++)
   {
    
    
   SCL=0;
   _nop_();
   SDA=dat>>7;
   _nop_();
   SCL=1;
   _nop_();
  dat= dat<<1;
  }
  SCL=0;
}

//数码管锁存
void cmg()
{
    
    
duan=1;
P0=0x00;
duan=0;
wei=1;
P0=0x00;
wei=0;
RST=0;
}


//PCF先发地址,再发控制命令,最后发数据
 DAC(uchar dat)
{
    
    
start();
 send(0x90);
 ack();
 
 send(0x40);
 ack();

 send(dat);
 ack();

 stop();

}


void main()
{
    
    
uchar num;
delay(5);
cmg();
   while(1)
   {
    
    
   DAC(num);
   num++;//256溢出,8bit,2的八次方等于256
   delay(30);
   }
}

4、实验现象
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
就是一个动态的呼吸灯的效果。

猜你喜欢

转载自blog.csdn.net/m0_46155417/article/details/129538886