【蓝桥杯单片机省赛】PCF8591

问题

PCF8591在省赛题中很常考:

比如第四届蓝桥杯单片机设计与开发项目省赛:
在这里插入图片描述

比如第五届蓝桥杯单片机设计与开发项目省赛:
在这里插入图片描述
PCF8591是具有IIC接口的8位A/D和D/A转换芯片,具有4路模拟输入、一路DAC输出和一个IIC总线接口。

在这里插入图片描述
在此笔者对IIC总线协议不做详述,重点放在如何处理收到的数据

解决思路

本篇重点:交叉相乘
(是的,小学已经学过了)
在这里插入图片描述
在读出数据后也可以进行类似的处理,因为读出的数据时unsigned char(0-256)类型,但是要转换成电压(0-500),就应该用交叉相乘法进行转换

以下是电位器的值
定义:

float dat_rb2;

(读出数据后)数据处理:

dat_rb2 = dat_rb2*500/255;
unsigned int dat_rb2_show;
dat_rb2_show = (unsigned int)dat_rb2;

D/A同理:

void Write_dac(float U_dat)
{
	int  U_dat_2;
	U_dat_2 = U_dat *100*255/500;	
	IIC_Start();
	IIC_SendByte(0X90);
	IIC_WaitAck();
	IIC_SendByte(0X40);  
	IIC_WaitAck();
	IIC_SendByte(U_dat_2);
	IIC_WaitAck();	
	IIC_Stop();	
}

完整代码参考

实验现象:D/A输出4.5V电压(实测4.3V左右),检测电位器的电压

iic.h和iic.c请参考蓝桥杯官方的资料包

main.c:

#include "reg52.h"
#include "iic.h"



 
unsigned int dat_rd1;
float dat_rb2;

 
unsigned char code NixieTube_dat[18]=
		{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
		 0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};

void IIC_SendAck(bit ackbit);
void _573_select(unsigned char channal);


void Delay(unsigned int t)
{
	while(t--);
}
 
void NixieTube_Bit(unsigned char pos, unsigned char value)
{
	P0 = 0x00;
	_573_select(7);
	P0 = value;
	_573_select(0);
	P0 = 0x00;
	_573_select(6);
	P0 = 0x01<<pos;
}
void _573_select(unsigned char channal)
{
	switch (channal)
	{
		case 0 :P2 = (P2 & 0x1f) | 0x00;break;
		case 4 :P2 = (P2 & 0x1f) | 0x80;break;
		case 5 :P2 = (P2 & 0x1f) | 0xa0;break;
		case 6 :P2 = (P2 & 0x1f) | 0xc0;break;
		case 7 :P2 = (P2 & 0x1f) | 0xe0;break;
	}
}	

void NixieTube_Show()
{

  unsigned int dat_rb2_show;
	dat_rb2_show = (unsigned int)dat_rb2;

	NixieTube_Bit(0, NixieTube_dat[dat_rb2_show/100]);
	Delay(100);
	NixieTube_Bit(1, NixieTube_dat[dat_rb2_show%100/10]);
	Delay(100);
	NixieTube_Bit(2, NixieTube_dat[dat_rb2_show%10]);
	Delay(100);
			
	NixieTube_Bit(2, 0xFF);		
}
void NixieTube_Show_Delay(unsigned int t)
{
	while(t--)
	{
		NixieTube_Show();
	}
}

 

void Read_RB2()
{
	IIC_Start();								
	IIC_SendByte(0x90); 					
	IIC_WaitAck();  							
	IIC_SendByte(0x03); 				
	IIC_WaitAck();  						
	IIC_Stop(); 								
	
	IIC_Start();								
	IIC_SendByte(0x91); 				
	IIC_WaitAck(); 							
	dat_rb2 = IIC_RecByte(); 			
	IIC_SendAck(1);	
	IIC_Stop(); 
	
	dat_rb2 = dat_rb2*500/255;
	
}
//--------------DAC-------------------------//
/*输入的电压值可以是2.5V这种浮点型*/
void Write_dac(float U_dat)
{
	int  U_dat_2;
	U_dat_2 = U_dat *100*255/500;
	//EA = 0;							  //如果开了中断应该视情况关闭中断
	IIC_Start();
	IIC_SendByte(0X90);
	IIC_WaitAck();
	IIC_SendByte(0X40);  
	IIC_WaitAck();
	IIC_SendByte(U_dat_2);
	IIC_WaitAck();	
	IIC_Stop();
	//EA = 1;
}
 
void Init_SYS()
{
	_573_select(5);
	P0 = 0x00;
	_573_select(0);
	_573_select(4);
	P0 = 0xff;
	_573_select(0);
}
void main()
{	
	Init_SYS();	
	while(1)
	{				
		Write_dac(4.5);		
		NixieTube_Show_Delay(1000);
		Read_RB2();
	}
}

参考资料:
交叉相乘 https://www.shuxuele.com/algebra/cross-multiply.html
蓝桥杯官网 https://dasai.lanqiao.cn/

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值