目录
1、PCF8591的引脚介绍
2、用IIC发送或接收字节
发送的第一个字节
发送的第二个字节
发送第三个字节
3.发送和接收的字节转换
4.全部代码
IIC部分
接收电压数据
发送电压数据
1、PCF8591的引脚介绍
在和单片机实际应用中它的接线图如下
PCF8591有四个模拟信号输入端(模转数),一个输出端(数转模),因为我们一般使用芯片的内部时钟,所以EXT和OSC接地,而VSS和VCC手册里写是用来上电复位的,只需要照着原理图接就行。
2、用IIC发送或接收字节
发送的第一个字节
只要用到IIC通信首先要发送的就是芯片的地址
高四位为PCF8591的专用地址,只要用这个芯片高四位就必须是1001,低四位中A0、A1、A2表示要选择那个PCF8591,比如前面的原理图A0、A1、A2全部接地所以它的地址是000,最后低位R/W表示下一步写入还是读出数据,0是写1是读 ,下一步还要写数据所以这一位置0,总结起来这一个字节就是0x90。
IIC_Start();//开始
IIC_SendByte(0x90);
IIC_WaitAck();//应答如果接收到的话这个函数会返回1
发送的第二个字节
这个字节用来控制芯片的功能
第一位和第二位 :AD转换的输入通道选择位 00 >>AIN0, 01>>AIN1, 10>>AIN2, 11>>AIN3
第三位 :自动递增标志位,激活时给1,在每次A/D转换后,读取的通道会自动跳到下一位。
第四位:无效位
第五、六位:选择差分输入还是单端输入(如果对精度没有太大要求时选择单端输入置00)
第七位: 使能模拟输出,使能时置1 ,表示切换为DA(数字转模拟模式)
第八位:无效位
1.AD模式 :比赛时建议一个一个通道使用,所以不启动递增位,发送字节为0x01(0000 001)接收通道1的电压值,这个时候所以要发送的控制字节已经发送完了,接下来是接收部分。
IIC_SendByte(0x01);
IIC_WaitAck();//应答标志位
2.DA模式:因为PCF8591只有一个DA输出口,只要给第七位置1,发送字节0x40 (0000 0100)。
IIC_SendByte(0x04);
IIC_WaitAck();
发送第三个字节
1. AD模式: 首先和发送字节时一样要发送对应地址,接收地址为0x90,而接收地址为0x91,然后接收代码。
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
Date=IIC_RecByte();//要接收的值
IIC_SendAck(1);//如果接收到的话发送
IIC_Stop();//结束
2.DA模式: 发送最后一个控制输出值的代码。
IIC_WaitAck();
IIC_SendByte(DATA); //要发送的值
IIC_WaitAck();
IIC_Stop();
3.发送和接收的字节转换
因为PCF8591检测的电压是以8位二进制发送给单片机的,所以单片机得到的值是0~255,把它转换为0~5V的电压公式如下
检测到的电压 = 单片机上电电压(5V) (测量到的值255)
发送时把电压数据转换为二进制对应值,与上面就是将0~5V转换为0~255,把公式换一下即可。
发送要输出电压 = 255 (测量到的电压 单片机上电电压(5V))文章来源:https://www.toymoban.com/news/detail-445952.html
4.全部代码
IIC部分(官方的IIC代码SDA和 SCL可能是反的)
#include <REGX52.H>
#include "intrins.h"
#define DELAY_TIME 5
sbit SDA = P2^1;
sbit SCL = P2^0;
//IIC延时
void IIC_Delay(unsigned char i)
{
while(i--);
}
//开始发送
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//IIC结束发送
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;
SDA=1;
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;
}
接收电压数据
float PCF8951_Read(unsigned char date)
{
float Date;
IIC_Start();//开始
IIC_SendByte(0x90);//发送地址PCF8591的地址,表示要对其发送数据
IIC_WaitAck(); //芯片接收到要返回一个应答位
IIC_SendByte(date);//发送要执行的命令
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);//发送地址PCF8591的地址,表示要接收它的数据
IIC_WaitAck();
Date=IIC_RecByte();//接收一个字节
IIC_SendAck(1);//接收完成之后要发送一个1
IIC_Stop();
return (Date/255)*5;//电平转换
}
发送电压数据
void PCF8951_Out(float DATE)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x04);
IIC_WaitAck();
IIC_WaitAck(255*(DATE/5));//发送要输出的电压
IIC_WaitAck();
IIC_Stop();
}
为什么接收数据的代码那么长,而发送数据的代码那么少呢?因为在接收电压数据的时候 IIC_SendByte(0x90) 是向芯片写数据,所以加IIC_SendByte(0x91) 让芯片给我发数据。然而我们给芯片发送数据时一直都是单方向的,所以代码看起来很少。文章来源地址https://www.toymoban.com/news/detail-445952.html
到了这里,关于PCF8591芯片的AD/DA转换(适用于蓝桥杯单片机)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!