问题
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/