用PCF8951,AT89C51,滑动电阻POT—HG,显示器LCD1602,和排阻RESPACK—8。
PCF89C51:
PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I²C总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。
PCF8591的功能包括多路模拟输入、内置跟踪保持、8-bit模数转换和8-bit数模转换。PCF8591的最大转化速率由I2C总线的最大速率决定。
LCD1602在前文有所描述,这里不再一一解释。
仿真图如下:
程序如下:
main.c
#include#include #include unsigned char cp,cp1,flash,ad0,ad1; unsigned int year = 2020; unsigned int v0,v1,v2,v3; void timer_isr(void) interrupt 1 { TH0 = (65535 - 2000) / 256; TL0 = (65535 - 2000) % 256; cp++;cp1++; if(cp1 >= 250) { goto_xy(1,0); display_string("v0:"); display_num(v0 / 100); display_string("."); display_num(v0 / 10 % 10); display_num(v0 % 10); goto_xy(1,8); display_string("v1:"); display_num(v1 / 100); display_string("."); display_num(v1 / 10 % 10); display_num(v1 % 10); } } void timer_init(void) { TMOD = 0x01; TH0 = (65535 - 2000) / 256; TL0 = (65535 - 2000) % 256; EA = 1; ET0 = 1; TR0 = 1; } void main(void) { timer_init(); lcd1602_init(); lcd1602_clear(); while(1) { if(cp >= 250) { cp = 0; ad0 = get_pcf8591_ADC(0);delay(30); ad0 = get_pcf8591_ADC(0);delay(30); v0 = ad0 * 1.96; ad1 = get_pcf8591_ADC(1);delay(30); ad1 = get_pcf8591_ADC(1);delay(30); v1 = ad1 * 1.96; } } }
LCD1602.c
#define uchar unsigned char
#define uint unsigned int
sbit RS = P2^4;//数据/命令
sbit RW = P2^5;//读/写
sbit E = P2^6;//使能
uchar i;
void delay(unsigned int x)
{
while(x--);
}
void write_command(uchar command)
{
RW = 0;
RS = 0;
P0 = command;
E = 1;
delay(100);
E = 0;
RW = 1;
}
void write_data(uchar date)
{
RW = 0;
RS = 1;
E = 1;
P0 = date;
delay(100);
E = 0;
RW = 1;
}
void lcd1602_init(void)
{
write_command(0x38);
write_command(0x0f);
write_command(0x0c);
write_command(0x06);
}
void lcd1602_clear(void)
{
write_command(0x01);
write_command(0x02);
}
void display_string(uchar *p)
{
while(*p)
{
write_data(*p);
p++;
}
}
void display_num(uchar x)
{
双数字
// write_data((x / 10) + 0x30);
// write_data((x % 10) + 0x30);
//单数字
write_data(x + 0x30);
}
void goto_xy(uchar x,uchar y)
{
if(x == 1)
write_command(0x80 + y);
if(x == 2)
write_command(0x80 + 0x40 + y);
}
PCF8951.c
#include "intrins.h"
#define somenop Delay5us()
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA_s = P3^7;
sbit SCL_s = P3^6;
void Delay5us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 12;
while (--i);
}
//总线启动条件
void IIC_Start(void)
{
SDA_s = 1;
SCL_s = 1;
somenop;
SDA_s = 0;
somenop;
SCL_s = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA_s = 0;
SCL_s = 1;
somenop;
SDA_s = 1;
}
//应答位控制
void IIC_Ack(bit ackbit)
{
if(ackbit)
{
SDA_s = 0;
}
else
{
SDA_s = 1;
}
somenop;
SCL_s = 1;
somenop;
SCL_s = 0;
SDA_s = 1;
somenop;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA_s = 1;
somenop;
SCL_s = 1;
somenop;
if(SDA_s)
{
SCL_s = 0;
IIC_Stop();
return 0;
}
else
{
SCL_s = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA_s = 1;
}
else
{
SDA_s = 0;
}
somenop;
SCL_s = 1;
byt <<= 1;
somenop;
SCL_s = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL_s = 1;
somenop;
da <<= 1;
if(SDA_s)
da |= 0x01;
SCL_s = 0;
somenop;
}
return da;
}
int get_pcf8591_ADC(unsigned char x)
{
unsigned char adc;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(x);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
adc = IIC_RecByte();
IIC_WaitAck();
IIC_Ack(0);
IIC_Stop();
return(adc);
}
//void pcf8591_out(unsigned char x)
//{
// IIC_Start();
// IIC_SendByte(0x90);
// IIC_WaitAck();
// IIC_SendByte(0x40);
// IIC_WaitAck();
// IIC_SendByte(x);
// IIC_WaitAck();
//}
运行结果如下:



