【蓝桥杯单片机进阶强化-01】PCF8591的基本原理与A/D转换应用
内容来自b站小蜜蜂老师 蓝桥杯练习进阶
一、题目展示
二、PCF8591基本介绍
2.1 PCF8591功能概述
PCF8591是具有IIC接口的8位A/D和D/A转换芯片,具有4路模拟输入、一路DAC输出和一个IIC总线接口。其主要的功能特性如下:
●单电源供电,典型值为5V。
●通过3个硬件地址引脚编址。
●8位逐次逼近式A/D转换。
●片上跟踪与保持电路,采样速率取决与IIC总线速度。
●4路模拟输入可编程为单端输入或查分输入。
●自动增量通道选择。
●带一个模拟输出的乘法DAC。
2.2 PCF8591内部AD/DA转换电路
2.3 访问规则
PCF8591为一个IIC挂载设备,所以在进行编程时就要符合IIC通信原理
同时也要满足器件本身的传输规则
PCF8591的设备地址包括固定部分和可编程部分。
可编程部分需要根据硬件引脚A0、A1和A2来设置。
设备地址的最后一位用于设置数据传输的方向,即读/写位。
由A0 A1 A2 的选择我们可以知道在进行IIC通信时可以同时
挂载8个PCF8591设备而设备的固定部位为1001是一致的所以
在进行不同设备选择时我们只需要改变A0 A1 A2 的值就可以
进行我们要想的设备工作。
2.4 板子上PCF8591原理图与控制寄存器
在我们使用的平台上面A0 A1 A2默认都是接的地 而且只挂载了一个设备所以
进行写操作时为1001 0000 ---》0x90
进行读操作时为1001 0001 ---》0x91
光敏传感器Rb1接到AIN1,通道1;控制寄存器应写入:0x01。
电位器Rb2接到AIN3,通道3;控制寄存器应写入:0x03。
AD转换流程
1--发送写设备地址,选择IIC总线上的PCF8591器件。
2--发送控制字节,选择模拟量输入模式和通道。
3--发送读设备地址,选择IIC总线上的PCF8591器件。
4--读取PCF8591中目标通道的数据。
三、代码展示
#include "reg52.h"
#include "iic.h"
/********************************************
Date:2022-1-15
Author:小殷同学
Learn From:B 站小蜜蜂老师
*********************************************/
sbit S4 = P3^3;
unsigned char Rd1 = 0; //光敏电阻AIN1
unsigned char Rd2 = 0; //可调电阻AIN3
unsigned char status = 0; //按键状态记录
//共阳数目管段码
//0-f 0xbf代表 -
unsigned char code SMG_Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf};
//---------------------------------简单延时函数-------------------------
void Delay(unsigned int t)
{
while(t--);
}
//-------------------------------74HC138初始化---------------------------
void Init_74HC138(unsigned char n)
{
switch(n)
{
case 4:P2 = P2| 0x1f; P2 = 0x80; break;
case 5:P2 = P2| 0x1f; P2 = 0xa0; break;
case 6:P2 = P2| 0x1f; P2 = 0xc0; break;
case 7:P2 = P2| 0x1f; P2 = 0xe0; break;
case 0:P2 = P2| 0X1f; P2 = 0x00; break; //所有锁存器都不选择
}
}
//----------------------------------系统初始化---------------------------
void InitSystem(void)
{
Init_74HC138(5);
P0 = 0x00; //关闭继电器与蜂鸣器
Init_74HC138(4);
P0 = 0xff; //关闭led
}
//---------------------------------数码管安位显示--------------------------
void SMG_DisplayBit(unsigned char pos ,unsigned char dat)
{
Init_74HC138(6);
P0 = 0x01 << pos ;//位选
Init_74HC138(7);
P0 = dat; //段码
}
//-------------------------------关闭所有数码管----------------------
void SMG_CLOSEALL(unsigned char dat)
{
Init_74HC138(6);
P0 = 0xff; //选中所有数码管
Init_74HC138(7);
P0 = dat; //关闭
}
//---------------------------------数码管AD显示----------------------
void SMG_Display_ADC(unsigned char channel,unsigned char dat)
{
SMG_DisplayBit(0,SMG_Duan[16]);
Delay(200);
SMG_DisplayBit(1,SMG_Duan[channel]);
Delay(200);
SMG_DisplayBit(2,SMG_Duan[16]);
Delay(200);
SMG_DisplayBit(3,0xff);
Delay(200);
SMG_DisplayBit(4,0xff);
Delay(200);
SMG_DisplayBit(5,SMG_Duan[dat/100]);
Delay(200);
SMG_DisplayBit(6,SMG_Duan[dat/10%10]);
Delay(200);
SMG_DisplayBit(7,SMG_Duan[dat%10]);
Delay(200);
SMG_CLOSEALL(0xff);
Delay(200);
}
//----------------------------读取光敏AD-----------------------------------
//PCF8591的设备的读操作地址为:0x91;而写操作地址则为:0x90
//光敏传感器接到AIN1,通道1;控制寄存器应写入:0x01。
//电位器Rb2接到AIN3,通道3;控制寄存器应写入:0x03。
void Read_Rd1_Data(void)
{
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0x90); //发送PCF8591设备地址 写操作
IIC_WaitAck(); //等待回应
IIC_SendByte(0x01); //发送AIN模拟通道号 AIN3
IIC_WaitAck(); //等待回应
IIC_Stop(); //IIC总线停止信号
SMG_Display_ADC(1,Rd1);
IIC_Start(); //起始信号
IIC_SendByte(0x91); //发送PCF8591设备地址 读操作
IIC_WaitAck(); //等待回应
Rd1 = IIC_RecByte(); //读取数据
IIC_SendAck(0); //发送应答信号
IIC_Stop(); //IIC总线停信号
SMG_Display_ADC(1,Rd1);
}
//-----------------------------读取滑动电阻AD-----------------------------
void Read_Rd2_Data(void)
{
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0x90); //发送PCF8591设备地址 写操作
IIC_WaitAck(); //等待回应
IIC_SendByte(0x03); //发送AIN模拟通道号 AIN3
IIC_WaitAck(); //等待回应
IIC_Stop(); //IIC总线停止信号
SMG_Display_ADC(3,Rd2);
IIC_Start();//起始信号
IIC_SendByte(0x91); //发送PCF8591设备地址 读操作
IIC_WaitAck(); //等待回应
Rd2 = IIC_RecByte(); //读取数据
IIC_SendAck(0); //发送应答信号
IIC_Stop(); //IIC总线停信号
SMG_Display_ADC(1,Rd2);
}
//----------------------------------按键切换控制----------------------------
void Key_Tackle(void)
{
if(S4 == 0)
{
Delay(20);
if(S4 == 0)
{
if(status == 0)
{
status = 1;
while(S4 == 0)
{
SMG_Display_ADC(1,Rd1);
}
}
else if(status == 1)
{
status = 0;
while(S4 == 0)
{
SMG_Display_ADC(1,Rd2);
}
}
}
}
}
void main(void)
{
InitSystem(); //初始化系统
Read_Rd1_Data(); //上电默认进行光敏数据采集
while(1)
{
Key_Tackle();
if(status == 0)
{
Read_Rd1_Data();
}
else
{
Read_Rd2_Data();
}
}
}
四、总结
通过该节PCF8591 AD转换的进阶练习 一方面将前面所学的知识进行了巩固 另一方面也对IIC通信的时序流程原理和PCF8591该芯片功能使用原理等等进行了熟悉 也掌握了如何基本该平台去驱动我们的硬件 实现我们想要的功能
路漫漫其修远兮 加油