蓝桥杯单片机PCF8591芯片ADC与DAC运行冲突解决

单片机型号:STC15F2K60S2

目录

文章附上工程下载地址:

在进行ADC与DAC测试时发现了如下冲突:

实验问题发现:

解决方案:


文章附上工程下载地址:

https://download.csdn.net/download/qq_64257614/87854725?spm=1001.2014.3001.5503

在进行ADC与DAC测试时发现了如下冲突:

ADC与DAC都运行,即使安排了不同的开启时间,但DAC输出电压有明显抖动。

实验问题发现:

如下代码写了PCF8591芯片在不同时间段开启 ADC与DAC

ADC采集电位器的模拟值,

DAC是将一个变量value(大小在0~100之间)做转化,

(0输出0V,100输出5V,一次函数关系作输出)

然后转化为电压输出.

按键S4 S5分别可对value进行加减操作

u8 nr1,nr2,nr3,nr4,nr5,nr6,nr7,nr8;

float read_ADC;                  //浮点ADC读取
u16 ADC_value;                   //ADC读取变量
u8 DAC_value;                    //DAC输出变量
u8 value;

u8 DAC_cnt;
u16 ADC_cnt;
bit DAC_flag;
bit ADC_flag;


bit key_flag = 0;
u8 key_value;
u8 key_cnt;

void main()
{

	inint();
	while(1)
	{
		if(key_flag==1)              //按键S4 S5改变value  大小
		{
			key_flag=0;
			key_value=key_scan_return();
			switch(key_value)         
			{
				case 4:value++;break;
				case 5:value--;break;
			}
		}
		if(ADC_flag==1)								//ADC采样
		{
			ADC_flag=0;
			read_ADC=ADC_pcf8591(0x03);
			ADC_value=(unsigned int)read_ADC*100;
		}
		if(DAC_flag==1)               //DAC输出
		{
			DAC_flag=0;
			DAC_value=value * 255 /100 ;
			dac_pcf8591(DAC_value);
		}
	}
}

void inint()
{
	cls_buzz_led();
	inint_smg();
	Timer0Init();
}



void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;					//定时器时钟12T模式
	TMOD &= 0x01;	
	TL0 = 0x18;		 
	TH0 = 0xFC;		  
	
	
	TF0 = 0;		 
	TR0 = 1;		   
	EA=1;
	ET0=1;
}

void Timer0_server() interrupt 1
{
	u8 i;
	if(++i==8) {i=0;
							nr1=value/100%10;nr2=value/10%10;
							nr3=value%10;nr4=17;nr5=17;
							nr6=17;nr7=17;nr8=17;
							smg_display(nr1,nr2,nr3,nr4,nr5,nr6,nr7,nr8);}
	if(++key_cnt==16)  {key_cnt=0;key_flag=1;}
	if(++DAC_cnt==166) {DAC_cnt=0;DAC_flag=1;}
	if(++ADC_cnt==450) {ADC_cnt=0;ADC_flag=1;}
}

从中我们发现,即使我们将DAC定位166ms一次转化输出

ADC为450ms一次转化输出,但下载后发现,

DAC的电压输出依旧收到了干扰:

 为证明确实是ADC与DAC相互作用的冲突,我注释掉了ADC采样的代码

 在此编译下载进了开发板,发现DAC输出变得正常了,十分稳定:

在此后的实验中发现,不论是将ADC采样延长,

还是设定标志位,让一个读取完了再开启另一个,都没有成效。

但有一点可以确定的是,ADC与DAC的使用,确实是需要在不同时间段进行的

解决方案:

 在CT107D单片机上,PCF8591三个硬件引脚地址均接地,两路模拟信号均为单端输入,则有:

光敏传感器接在AIN1即通道1,控制寄存器应该写入0x01

电位器Rb2接到AIN3即通道3,控制寄存器应该写入0x03

以上为ADC单独使能用的地址,

照常理来说,我们调用ADC函数时,只需将参数 channel 填为0x01 或 0x03即可:

但我在查阅网上资料后,发现在ADC采样同时,也能使能DAC的地址,

就比如我想读取电位器的0x03的ADC采样值,我把这个地址写成0x43

(即将channel改填为0x43)

这样就能既不影响ADC采样,DAC输出也变得稳定许多:

//ADC读取

unsigned char ADC_pcf8591(unsigned char channel)
{
	unsigned char ad_value,i;
	
	for(i=0;i<2;i++)
	{
			I2CStart();
			I2CSendByte(0X90);
			
			I2CWaitAck();
			I2CSendByte(channel);
			I2CWaitAck();
			
			I2CStart();
			I2CSendByte(0X91);
			I2CWaitAck();
			ad_value=I2CReceiveByte();
			I2CSendAck(1);    //官方驱动少这句
			I2CStop();
	}
	
	return ad_value;
}

 DAC输出函数地址就是固定的0x40:

void dac_pcf8591(unsigned char dat)   //DAC输出 dat - 输入进行数模转换的数据
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);  //DAC输出模式
	IIC_WaitAck();
	
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

如此改动之后,我们发现DAC输出变得稳定,在串口测试ADC等数据也十分正常:

 这样我们的问题就解决了,觉得有用就三连!

  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NULL指向我

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

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

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

打赏作者

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

抵扣说明:

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

余额充值