九层妖塔 起于垒土

在这里插入图片描述




改编自国信长天蓝桥杯官方蓝皮书例程,按照自己的习惯进行了补充和修改


基础知识

【蓝桥杯】—{模块}—{PCF8591_8位A/D and D/A转换器Part_1}

【蓝桥杯】—{模块}—{PCF8591_8位A/D and D/A转换器Part_2}


一、原理图

PCF8591原理图:
在这里插入图片描述
Notes:
 ●PCF8591有4路A/D转换 模拟输入,分别为AIN0AIN1AIN2AIN31路D/A模拟输出OUT
 ●第一路A/D转换 模拟输入AIN0通道0 外部输入

在这里插入图片描述
 ●第二路A/D转换 模拟输入AIN1通道1 光敏电阻 RD1
在这里插入图片描述
 ●第三路A/D转换 模拟输入AIN2通道2 四路运算放大器LM324的输出引脚

在这里插入图片描述
 ●第四路A/D转换 模拟输入AIN3通道3 电位器Rb2
在这里插入图片描述



二、通过IIC对PCF8591的写操作与读操作

写操作

Created with Raphaël 2.3.0 总线启动 发送 地址字节 (写数据) 发送 控制字节 发送 数据字节 总线停止

在这里插入图片描述

Notes:
 ●PCF8591和AT24C02共用IIC总线。
 ●主机进行总线操作时,发送的第一个字节为地址字节 选择接收数据的从机,和数据传输方向(写操作时最后一位为0,写入)。主机等待从机发出应答。
 ●写操作时,主机发送的第二个字节为控制字节 ,写入从机的控制寄存器,设置从机的各种功能。主机等待从机发出应答。
 ●写操作时,主机发送的第三个字节为数据字节 ,写入从机的DAC数据寄存器,8位数据,数模转换的数字量电压。主机等待从机发出应答。
 ●地址字节和控制字节必须有,数据字节可以没有。

读操作

Created with Raphaël 2.3.0 总线启动 发送 地址字节 (读数据) 接收 数据字节 总线停止

在这里插入图片描述

Notes:
 ●主机进行总线操作时,发送的第一个字节为地址字节 规定接受数据的从机,和数据传输方向(读操作时最后一位为1,读取)。
 ●读操作时,主机发送完第一个字节地址字节规定了数据传输方向为读取后进入接受模式。一次只能传输一个字节,由于PCF8591只有8位数据,只需要传输一次。主机接收到一个字节后,发送非应答信号,告诉从机我不要了,别发送了



三、基本模板

1、头文件

 在原有头文件的基础上增加以下内容:

#define AIN0_extern 0X40   //通道0外部输入  模拟输出使能—四路单端输入
#define AIN1_RD1    0X41   //光敏电阻 RD1   模拟输出使能—四路单端输入
#define AIN3_Rb2    0X43   //通道3电位器Rb2 模拟输出使能—四路单端输入

extern uchar uc_PCF8591_ADC_Rb2;    ////电位器 Rb2
extern uchar uc_PCF8591_ADC_RD1;    //光敏电阻 RD1
extern uchar uc_PCF8591_ADC_extern;//外部输入

extern void PCF8591_DAC(float dat);     //DAC输出 
extern uchar PCF8591_ADC(uchar Control_Byte);  //通过IIC总线读取ADC结果 

2、数模转换函数PCF8591_DAC()

//------------------------------------------DAC输出---------------//
void PCF8591_DAC(float dat)
{
  IIC_Start();        //总线启动
	
  IIC_SendByte(0X90); //地址字节 写数据
  IIC_WaitAck();      //等待应答
	
  IIC_SendByte(0X43); //控制字节 模拟输出使能
  IIC_WaitAck();      //等待应答
	
  IIC_SendByte(dat/5.0*255);  //数据字节 数模转换的数据
  IIC_WaitAck();      //等待应答
	
  IIC_Stop();         //总线停止
}

Notes:
 ●数模转换进行数字量到模拟量的转换,数字量来自主机通过IIC总线写入从机,从机PCF8591进行转换后从OUT引脚输出模拟量。数据传输方向为单向,只从主机写入从机,只需要进行一个完整的写操作


3、模数转换函数PCF8591_ADC()

//------------------------------------------通过IIC总线读取ADC结果---------------//
uchar PCF8591_ADC(uchar Control_Byte)   
{
    uchar temp;
	
    IIC_Start();        //总线启动
	
	IIC_SendByte(0X90); //地址字节 写数据
    IIC_WaitAck();      //等待应答
	
	IIC_SendByte(Control_Byte); //控制字节
    IIC_WaitAck();      //等待应答
	
	IIC_Stop();         //总线停止

	
    IIC_Start();           //总线启动
	
	IIC_SendByte(0X91);    //地址字节 读数据
    IIC_WaitAck();         //等待应答
	
	temp = IIC_RecByte();  //从I2C总线上接收数据
	IIC_SendAck(1);        //发送非应答
	IIC_Stop();            //总线停止
	  
	return temp;
}

Notes:
 ●模数转换进行模拟量转换为数字量。模拟量来自AIN0AIN1AIN2AIN3四个引脚。从机PCF8591进行转换后,通过IIC总线传输给主机。
 ●主机需要先写入数据给从机,配置从机的寄存器,设置相关功能。此时为写操作
 ●从机PCF8591进行转换后,主机还需要从IIC总线接收转换完的数据。此时为读操作


4、显示信息的处理

//-----------------------------------------数码管处理函数---------------//
void SEG_Proc(void)     //数码管处理函数
{
	if(ui_SEG_flag) return;   //刷新频率
	ui_SEG_flag = 1;

	……
	
	if(uc_Key_Value == 10)  
	{
	  PCF8591_DAC(2.0); 
	  
	  uc_PCF8591_ADC_extern = PCF8591_ADC(AIN0_extern);
	  if(uc_PCF8591_ADC_extern != 0x80)
      sprintf(puc_SEG_Buf,"%02u  %05.2f",(uint)uc_Key_Value,(float)uc_PCF8591_ADC_extern/256.0*5);
	}
	
	SEG_Tran(puc_SEG_Buf,puc_SEG_Code);   //数码管段码转换
}

四、备用拓展模板

1、多通道连续读取

 1、缓冲数组:

uchar idata puc_ADC_Buf[4] = {0,0,0,0};

 2、初始化部分

void main(void)
{
	
	ALL_Init();
    Timer1Init();
	UartInit();
	
	uc_ADC_Value_AIN0 = PCF8591_ADC(0x40); //初始值 0x80
	uc_ADC_Value_AIN1 = PCF8591_ADC(0x41); // 0
	uc_ADC_Value_AIN2 = PCF8591_ADC(0x42); // 1
	uc_ADC_Value_AIN3 = PCF8591_ADC(0x43); // 2
	
	//puc_ADC_Buf[0] = uc_ADC_Value_AIN0;  
	puc_ADC_Buf[0] = uc_ADC_Value_AIN1;
	puc_ADC_Buf[1] = uc_ADC_Value_AIN2;
	puc_ADC_Buf[2] = uc_ADC_Value_AIN3;
	
	uc_ADC_Value_AIN0 = PCF8591_ADC(0x40); //3
	uc_ADC_Value_AIN1 = PCF8591_ADC(0x41); //0
	uc_ADC_Value_AIN2 = PCF8591_ADC(0x42); //1
	uc_ADC_Value_AIN3 = PCF8591_ADC(0x43); //2
	
	puc_ADC_Buf[3] = uc_ADC_Value_AIN0; 
	puc_ADC_Buf[0] = uc_ADC_Value_AIN1;
	puc_ADC_Buf[1] = uc_ADC_Value_AIN2;
	puc_ADC_Buf[2] = uc_ADC_Value_AIN3;
	
	
	ES = 1;
	ET1 = 1;
	EA = 1;
    …………
	
	while(1)
	{
     ………… 
    }

 3、ADC处理函数

void ADC_Proc(void)
{
	if(uc_ADC_flag) return;
	uc_ADC_flag = 1;
	

	
	uc_ADC_Value_AIN0 = PCF8591_ADC(0x40); //3
	uc_ADC_Value_AIN1 = PCF8591_ADC(0x41); //0
	uc_ADC_Value_AIN2 = PCF8591_ADC(0x42); //1
	uc_ADC_Value_AIN3 = PCF8591_ADC(0x43); //2
	
	puc_ADC_Buf[3] = uc_ADC_Value_AIN0; 
	puc_ADC_Buf[0] = uc_ADC_Value_AIN1;
	puc_ADC_Buf[1] = uc_ADC_Value_AIN2;
	puc_ADC_Buf[2] = uc_ADC_Value_AIN3;
	
	sprintf(puc_Uart_Send_String,"通道0AIN0:%05.2f -- ",(float)puc_ADC_Buf[0]/255.0*5.0);
	Uart_Send_String(puc_Uart_Send_String);
	sprintf(puc_Uart_Send_String,"通道1AIN1:%05.2f -- ",(float)puc_ADC_Buf[1]/255.0*5.0);
	Uart_Send_String(puc_Uart_Send_String);
	sprintf(puc_Uart_Send_String,"通道2AIN2:%05.2f -- ",(float)puc_ADC_Buf[2]/255.0*5.0);
	Uart_Send_String(puc_Uart_Send_String);
	sprintf(puc_Uart_Send_String,"通道3AIN3:%05.2f\r\n",(float)puc_ADC_Buf[3]/255.0*5.0);
	Uart_Send_String(puc_Uart_Send_String);

}

  
  
  
  
彩 蛋

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐