接上一篇
蓝桥杯单片机(十一)PCF8591(A/D转换)
首先看蓝桥杯单片机开发板的原理图
AOUT是模拟输出端,AGND为模拟信号地。
模拟参考电压为Vref两端的电压。
由于Vref接到了VCC(5V),所以模拟输出就是以5V为参考电压。
由于PCF8591是8位数模转换,所以
模拟量=数字量×5/255
比如0000 00001就是5/255伏。
由于进行模拟输出,所以地址只需要将第二位置1,其余置零。写程序如下
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();
}
//IIC_write(硬件地址,输出地址,数字量);
最后设计一个滑动变阻器控制PCF8591输出的实验,并用数码管显示输出电压。
代码如下文章来源:https://www.toymoban.com/news/detail-408210.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
#define PCF8591_address 0x90
#define Light_address 0x01
#define Move_address 0x03
#define Output_address 0x40
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,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};
uint move=0;
void main(void)
{
init();
while(1)
{
move=IIC_read(PCF8591_address,Move_address);//读取滑动变阻器
IIC_write(PCF8591_address,Output_address,move);//输出
move=1.9607*move;//move *(5 /255 *100) 将0-255转换到0-500,便于显示
//显示电压
SMG[0]=move/100+10;SMG[1]=move%100/10;SMG[2]=move%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);
}
效果如下
与实际还是有些差距,可能是VCC电压的问题。
有不懂可以评论和私信。文章来源地址https://www.toymoban.com/news/detail-408210.html
到了这里,关于蓝桥杯单片机(十二)PCF8591(D/A转换)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!