PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行IIC总线接口。
首先蓝桥杯单片机开发板上的原理图部分
其中A0-A2为地址线,主要功能是当有多个PCF8591时,可将A0-A2按不同的最小项来区分不同PCF8591,比如第一个PCF8691的A0-A2=000,第二个A0-A2=001。
AIN0-AIN3是PCF8591的模拟输入端,参考电压为Vref两端的电压。
VDD和VSS为电源端。
AOUT是模拟输出端,AGND为模拟信号地。
SCL为IIC时钟线,SDA为IIC数据线。
本次主要将AIN1和AIN3接入的光敏电阻和滑动变阻器的A/D转换。
首先看蓝桥杯官方提供的IIC的读写程序,通过PCF8591数据手册的IIC时序也能编写。
#define DELAY_TIME 5
//
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//
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;
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;
}
值得注意时,使用时#define DELAY_TIME 5
要扩大一点,原因之前有讲。
然后就是IIC对硬件读程序,首先要发送起始信号,发送硬件地址加写指令等待,然后发送寄存器地址等待,然后发送停止信号,再发送硬件地址加读指令等待,然后接受数据等待,然后发送停止信号。
IIC对硬件写程序,首先要发送起始信号,发送硬件地址加写指令等待,然后发送寄存器地址等待,发送数据致寄存器等待,然后发送停止信号。
程序如下
void IIC_write(uchar hw_address,uchar reg_address,uchar data)
{
//hw_address为硬件地址,最低为表示读或者写 读1,写0
//reg_address为寄存器地址
//num为写入的数据
IIC_Start();
IIC_SendByte(hw_address&0xfe);
IIC_WaitAck();
IIC_SendByte(reg_address);
IIC_WaitAck();
IIC_SendByte(data);
IIC_WaitAck();
IIC_Stop();
}
uchar IIC_read(uchar hw_address,uchar reg_address)
{
//hw_address为硬件地址,最低为表示读或者写 读1,写0
//reg_address为寄存器地址
uchar num;
IIC_Start();
IIC_SendByte(hw_address&0xfe);
IIC_WaitAck();
IIC_SendByte(reg_address);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(hw_address|0x01);
IIC_WaitAck();
num=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return num;
}
然后打开PCF8591查看硬件地址
由于A0,A1,A2接地,所以0X90为写,0X91为读。
然后对模式进行选择,第二位表示模拟输出,因为时A/D不需要,所以置0,三四位表示选择AIN0-3对应通道的模式,这里选择00直接对应,六位表示自动增量,置零,七八位表示通道对应的AIN0-3,这与三四位联系起来要。
所以0X01对应AIN1对应光敏电阻。
0X03对应AIN3对应滑动变阻器。
最后写一个数码管显示光敏电阻和滑动变阻器的程序:文章来源:https://www.toymoban.com/news/detail-404570.html
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
#define uchar unsigned char
#define uint unsigned int
#define DELAY_TIME 40 //扩大8倍
#define PCF8591_address 0x90 //PCF 地址
#define Light_address 0x01 //光敏电阻 地址
#define Move_address 0x03 //滑动变阻器 地址
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_Stop(void);
void IIC_Start(void);
void IIC_Delay(unsigned char i);
unsigned char IIC_RecByte(void);
void IIC_SendByte(unsigned char byt);
uchar IIC_read(uchar hw_address,uchar reg_address);
void IIC_write(uchar hw_address,uchar reg_address,uchar num);
void init(void);
void SMG_output(void);
void Delay1ms(void);
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
uchar SMG[8]={10,10,10,10,10,10,10,10};
uchar move=0,light=0;
void main(void)
{
init();
while(1)
{//读取滑动变阻器
move=IIC_read(PCF8591_address,Move_address);
//读取光敏电阻
light=IIC_read(PCF8591_address,Light_address);
SMG[0]=move/100;SMG[1]=move%100/10;SMG[2]=move%10;
SMG[5]=light/100;SMG[6]=light%100/10;SMG[7]=light%10;
SMG_output();
}
}
void IIC_write(uchar hw_address,uchar reg_address,uchar num)
{
IIC_Start();
IIC_SendByte(hw_address&0xfe);
IIC_WaitAck();
IIC_SendByte(reg_address);
IIC_WaitAck();
IIC_SendByte(num);
IIC_WaitAck();
IIC_Stop();
}
uchar IIC_read(uchar hw_address,uchar reg_address)
{
uchar num;
IIC_Start();
IIC_SendByte(hw_address&0xfe);
IIC_WaitAck();
IIC_SendByte(reg_address);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(hw_address|0x01);
IIC_WaitAck();
num=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return num;
}
//
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//
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;
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;
}
void init(void)
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=(P2&0X1F)|0X80;
P0=0XFF;
P2=(P2&0X1F)|0XC0;
P0=0XFF;
P2=(P2&0X1F)|0XE0;
P0=0XFF;
}
void SMG_output(void)
{
uchar i;
for(i=0;i<8;i++)
{
P2=(P2&0X1F)|0XC0;
P0=(1 << i);
P2=(P2&0X1F)|0XE0;
P0=tab[SMG[i]];
Delay1ms();
}
P2=(P2&0X1F)|0XC0;
P0=0XFF;
P2=(P2&0X1F)|0XE0;
P0=0XFF;
}
void Delay1ms(void) //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
最后效果如下,前三位显示光敏电阻,后三位显示滑动变阻器。
不懂可以私信和评论文章来源地址https://www.toymoban.com/news/detail-404570.html
到了这里,关于蓝桥杯单片机(十一)PCF8591(A/D转换)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!