蓝桥杯单片机(十二)PCF8591(D/A转换)

本文详细介绍了如何使用PCF8591进行8位A/D转换,并通过滑动变阻器实现模拟电压的实时调节,配合数码管展示了输出电压。文章还提供了相应的程序代码和实验效果分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接上一篇
蓝桥杯单片机(十一)PCF8591(A/D转换)
首先看蓝桥杯单片机开发板的原理图
在这里插入图片描述
AOUT是模拟输出端,AGND为模拟信号地。
模拟参考电压为Vref两端的电压。
由于Vref接到了VCC(5V),所以模拟输出就是以5V为参考电压。
由于PCF8591是8位数模转换,所以

模拟量=数字量×5/255

比如0000 00001就是5/255伏。
在这里插入图片描述
由于进行模拟输出,所以地址只需要将第二位置1,其余置零。写程序如下

void IIC_write(uchar hw_address,uchar reg_address,uchar data)
{
//hw_address为硬件地址,最低为表示读或者写 读1,写0
//reg_address为寄存器地址
//num为写入的数据
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);
	IIC_WaitAck();
	IIC_SendByte(data);
	IIC_WaitAck();	
	IIC_Stop();	
}	

//IIC_write(硬件地址,输出地址,数字量);

最后设计一个滑动变阻器控制PCF8591输出的实验,并用数码管显示输出电压。
代码如下

#include <STC15F2K60S2.H>
#include "intrins.h"

sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */
#define uchar unsigned char
#define uint unsigned int
#define DELAY_TIME 40
#define PCF8591_address 0x90
#define Light_address 0x01
#define Move_address 0x03
#define Output_address 0x40

bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_Stop(void);
void IIC_Start(void);
void IIC_Delay(unsigned char i);
unsigned char IIC_RecByte(void);
void IIC_SendByte(unsigned char byt);
uchar IIC_read(uchar hw_address,uchar reg_address);
void IIC_write(uchar hw_address,uchar reg_address,uchar num);

void init(void);
void SMG_output(void);
void Delay1ms(void);

uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};
uint move=0;
void main(void)
{
	init();
	while(1)
	{
		move=IIC_read(PCF8591_address,Move_address);//读取滑动变阻器
		IIC_write(PCF8591_address,Output_address,move);//输出
		move=1.9607*move;//move *(5 /255 *100) 将0-255转换到0-500,便于显示
		//显示电压
		SMG[0]=move/100+10;SMG[1]=move%100/10;SMG[2]=move%10;
		SMG_output();
	}
}

void IIC_write(uchar hw_address,uchar reg_address,uchar num)
{
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);
	IIC_WaitAck();
	IIC_SendByte(num);
	IIC_WaitAck();	
	IIC_Stop();	
}	

uchar IIC_read(uchar hw_address,uchar reg_address)
{
	uchar num;
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);	
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(hw_address|0x01);
	IIC_WaitAck();
	num=IIC_RecByte();
	IIC_WaitAck();
	IIC_Stop();	
	
	return num;
}

//
void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}

//
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//
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;
	
    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;    
}

void init(void)
{
	P2=(P2&0X1F)|0XA0;
	P0=0X00;
	P2=(P2&0X1F)|0X80;
	P0=0XFF;
	P2=(P2&0X1F)|0XC0;
	P0=0XFF;
	P2=(P2&0X1F)|0XE0;
	P0=0XFF;	
}

void SMG_output(void)
{
	uchar i;
	for(i=0;i<8;i++)
	{
	P2=(P2&0X1F)|0XC0;
	P0=(1 << i);
	P2=(P2&0X1F)|0XE0;
	P0=tab[SMG[i]];			
	Delay1ms();
	}
	P2=(P2&0X1F)|0XC0;
	P0=0XFF;
	P2=(P2&0X1F)|0XE0;
	P0=0XFF;		
}

void Delay1ms(void)		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
}

效果如下
与实际还是有些差距,可能是VCC电压的问题。

在这里插入图片描述
有不懂可以评论和私信。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月明Mo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值