驱动
驱动用的是IIC
#include <iic.h>
#include "intrins.h"
//这里需要在原有驱动的基础上复制7次
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
寄存器
这个是控制读或者写操作,在寄存器的最后一位是控制读还是写,1是读,0是写
前4位是固定的,当为1001时是选中PCF8591
这个选执行那个通道,一般就考两个,一个是光敏电阻,一个是滑动变阻器
光敏电阻:
滑动变阻器:
可以看出一个是通道1,一个是通道3
读函数代码
/**
* @Function adc_read
* @Description: adc转换
* @param void
* @return dat
*/
unsigned char adc_read(void)
{
unsigned char dat=0;
IIC_Start(); //启动
IIC_SendByte(0X90); //调用PCF8591,并且为写操作
IIC_WaitAck(); //等待
IIC_SendByte(0X03); //0X03是滑动变阻器,0X01是光敏电阻
IIC_WaitAck(); //等待
IIC_Start(); //再次启动
IIC_SendByte(0X91); //调用PCF8591,并且执行读操作
IIC_WaitAck(); //等待
dat=IIC_RecByte(); //把读出来的数据给dat
IIC_Stop(); //停止
return dat; //返回
}
main.c
1. 正常读值 范围:0~255 (8位)
unsigned char adc_dat;
adc_dat=adc_read();
/******数码管显示******/
dspbuf[0]=adc_dat/100;
dspbuf[1]=adc_dat%100/10;
dspbuf[2]=adc_dat%10;
2. 转换为过千
long adc_dat;
unsigned int v;
adc_dat=adc_read();
v=(unsigned int)(adc_dat*10000/255);
/******数码管显示******/
dspbuf[0]=v/10000;
dspbuf[1]=v%10000/1000;
dspbuf[2]=v%1000/100;
dspbuf[3]=v%100/10;
dspbuf[4]=v%10;
3. 转换为0~5V电压,保留两位小数
long adc_dat;
unsigned int v;
adc_dat=adc_read();
v=(unsigned int)(adc_dat*500/255);
/******数码管显示******/
dspbuf[0]=v/100+10;
dspbuf[1]=v%100/10;
dspbuf[2]=v%10;
如果读数据读的太快会导致数码管显示不佳,可以用定时器让其200ms读一次数据即可