標(biāo)題:
分享一個(gè) PCF8591 AD轉(zhuǎn)換文件
[打印本頁]
作者:
miaomi_love
時(shí)間:
2018-6-18 13:08
標(biāo)題:
分享一個(gè) PCF8591 AD轉(zhuǎn)換文件
用12864顯示,AD芯片采用IIC通訊方式,需要用多路時(shí)要做小許修改。
#include<reg52.h>
#include<intrins.h>
//P0口為12864數(shù)據(jù)輸出口
#define uchar unsigned char
#define uint unsigned int
#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
sbit PM=P1^0;
sbit SCL=P1^1; //I2C時(shí)鐘引腳
sbit SDA=P1^2;//I2C數(shù)據(jù)輸入輸出引腳
uchar Recv_Buffer[4];//數(shù)據(jù)接收緩沖
uint Voltage[]={'0','0','0'};//數(shù)據(jù)分解為電壓x.xx
bit bdata IIC_ERROR; //I2C錯(cuò)誤標(biāo)志位
uchar LCD_Line_1[]={"1- . V 2- . V"};
uchar LCD_Line_2[]={"3- . V 4- . V"};
//延時(shí)
void delay(int ms)
{
uchar i;
while(ms--) for(i=0;i<250;i++) Delay4us();
}
//LCD忙檢測
bit LCD_Busy_Check()
{
bit Result;
LCD_RS=0;LCD_RW=1;
LCD_EN=1;Delay4us();Result=(bit)(P0&0x80);
LCD_EN=0;
return Result;
}
//寫指令
void LCD_Write_Command(uchar cmd)
{
while(LCD_Busy_Check());
LCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();
P0=cmd;Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
// 寫數(shù)據(jù)
void LCD_Write_Data(uchar dat)
{
while(LCD_Busy_Check());
LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=dat;Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
//初始化
void LCD_Initialise()
{
LCD_Write_Command(0x38);delay(5);
LCD_Write_Command(0x0c);delay(5);
LCD_Write_Command(0x06);delay(5);
LCD_Write_Command(0x01);delay(5);
}
//設(shè)置顯示位置
void LCD_Set_Position(uchar pos)
{
//LCD_Write_Command(pos|0x80);
LCD_Write_Command(pos);
}
//顯示一行
void LCD_Display_A_Line(uchar Line_Addr,uchar s[])
{
uchar i;
LCD_Set_Position(Line_Addr);
for(i=0;i<16;i++)LCD_Write_Data(s[i]);
}
// 將模數(shù)轉(zhuǎn)換后得到的值分解存入緩存
void Convert_To_Voltage(uchar val)
{
uchar Tmp; //最大值為255,對應(yīng)5V,255/5=51
Voltage[2]=val/51+'0';//整數(shù)部分
Tmp=val%51*10;// 第一位小數(shù)
Voltage[1]=Tmp/51+'0';
Tmp=Tmp%51*10;
Voltage[0]=Tmp/51+'0';
}
//啟動(dòng)I2C總線
void IIC_Start()
{
SDA=1;
SCL=1;
Delay4us();
SDA=0;
Delay4us();
SCL=0;
}
//停止I2C總線
void IIC_Stop()
{
SDA=0;
SCL=1;
Delay4us();
SDA=1;
Delay4us();
SCL=0;
}
// 從機(jī)發(fā)送應(yīng)答位
void Slave_ACK()
{
SDA=0;
SCL=1;
Delay4us();
SCL=0;
SDA=1;
}
// 從機(jī)發(fā)送非應(yīng)答位
void Slave_NOACK()
{
SDA=1;
SCL=1;
Delay4us();
SCL=0;
SDA=0;
}
//發(fā)送一字節(jié)
void IIC_SendByte(uchar wd)
{
uchar i;
for(i=0;i<8;i++) //循環(huán)移入8位
{
SDA=(bit)(wd&0x80);_nop_();_nop_();
SCL=1;Delay4us();SCL=0;wd<<=1;
}
Delay4us();
SDA=1; //釋放總線并準(zhǔn)備讀取應(yīng)答
SCL=1;
Delay4us();
IIC_ERROR=SDA;//IIC_ERROR=1表示無應(yīng)答
SCL=0;
Delay4us();
}
//接收一字節(jié)
uchar IIC_ReceiveByte()
{
uchar i,rd=0x00;
for(i=0;i<8;i++)
{
SCL=1;
rd<<=1;
rd|=SDA;
Delay4us();
SCL=0;
Delay4us();
}
SCL=0;
Delay4us();
return rd;
}
//連續(xù)讀入4路通道的A/D轉(zhuǎn)換結(jié)果并保存到Recv_Buffer
void ADC_PCF8591(uchar CtrlByte)
{
uchar i;
IIC_Start();
//PCF8591地址定義1001****,高四位固定1001
//第3,2,1位對應(yīng)A2,A1,A0第0位為讀寫標(biāo)志位,1為讀0為寫
//下面代碼中0x90,0x91分別為10010000,10010001
IIC_SendByte(0x90);// 發(fā)送寫地址
if(IIC_ERROR==1)return;
// IIC_SendByte(CtrlByte);//發(fā)送控制字節(jié)
//if(IIC_ERROR==1)return;
//屏蔽上面兩行會(huì)產(chǎn)生警告
IIC_Start();//重新發(fā)送開始命令
IIC_SendByte(0x91);// 發(fā)送讀地址
if(IIC_ERROR==1)return;
IIC_ReceiveByte();//空讀一次,調(diào)整讀順序
Slave_ACK(); //收到一字節(jié)后發(fā)送一個(gè)應(yīng)答位
/*------------------------------
個(gè)人認(rèn)為下面句子有問題,但是不知道怎么改,如果把
Recv_Buffer[i++]=IIC_ReceiveByte();中的++去掉,整個(gè)四組都是一個(gè)結(jié)果
但是加上好像有些重復(fù),并且13組相同,還是不很好啊
*/
for(i=0;i<4;i++)
{
Recv_Buffer[i++]=IIC_ReceiveByte();
Slave_ACK();//收到一個(gè)字節(jié)后發(fā)送一個(gè)應(yīng)答位
}
Slave_NOACK();
IIC_Stop();//收到一個(gè)字節(jié)后發(fā)送一個(gè)非應(yīng)答位
}
// 向 PCF8591發(fā)送1字節(jié)進(jìn)行AD轉(zhuǎn)換
void DAC_PCF8591(uchar CtrlByte,uchar dat)
{
IIC_Start();
Delay4us();//啟動(dòng)I2C
IIC_SendByte(0x90); //發(fā)送地址字節(jié)
if(IIC_ERROR==1)return;
IIC_SendByte(CtrlByte); //發(fā)送控制字節(jié)
if(IIC_ERROR==1)return;
IIC_SendByte(dat);//發(fā)送待轉(zhuǎn)換為模擬量的數(shù)值
if(IIC_ERROR==1)return;
IIC_Stop();
Delay4us();
Delay4us();
}
void timer0init()
{
PM=0;//傳感器的輸入信號(hào)
TMOD=0x11;//設(shè)置定時(shí)器0為工作方式1
TH0=(65536-40)/256;
TL0=(65536-40)%256;
ET0=1;//開定時(shí)器0中斷
TR0=1;//啟動(dòng)定時(shí)器0
EA=0; //開總中斷
}
//主程序
/*
PCF8591控制字節(jié)定義:0***0***,第3,7位固定為0
第6位取0時(shí)為模擬輸入,取1時(shí)為模擬輸出
第4,5位為00表示4路單端的模擬輸入
第二位為自動(dòng)遞增標(biāo)志,取1時(shí)自動(dòng)遞增
第0,1位取值為00,01,10,11分別表示通道0,1,2,3
調(diào)用ADC_PCF8591時(shí)參數(shù)為00000100,即0x04
調(diào)用DAC_PCF8591時(shí)參數(shù)為01000000,即0x40
*/
void main()
{
LCD_Initialise();
timer0init();
while(1)
{
ADC_PCF8591(0x04);
Convert_To_Voltage(Recv_Buffer[0]);
LCD_Line_1[2]=Voltage[2];
LCD_Line_1[4]=Voltage[1];
LCD_Line_1[5]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[1]);
LCD_Line_1[11]=Voltage[2];
LCD_Line_1[13]=Voltage[1];
LCD_Line_1[14]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[2]);
LCD_Line_2[2]=Voltage[2];
LCD_Line_2[4]=Voltage[1];
LCD_Line_2[5]=Voltage[0];
Convert_To_Voltage(Recv_Buffer[3]);
LCD_Line_2[11]=Voltage[2];
LCD_Line_2[13]=Voltage[1];
LCD_Line_2[14]=Voltage[0];
// 液晶兩行顯示四個(gè)通道的轉(zhuǎn)換結(jié)果
LCD_Display_A_Line(0x80, LCD_Line_1);
LCD_Display_A_Line(0x90, LCD_Line_2);
// 將0通道模擬轉(zhuǎn)換后的數(shù)值重新轉(zhuǎn)換為模擬量并從Aout輸出
//通過LED亮度表現(xiàn)出來
// DAC_PCF8591(0x40,Recv_Buffer[0]);
}
}
void timer0() interrupt 1
{
int N;
TH0=(65536-40)/256;
TL0=(65536-40)%256;
N++;
//if(N==7)
//PM=1;
if(N==8)
PM=0;
if(N>=250)
{
PM=1;
N=0;
}
}
復(fù)制代碼
pcf8591.zip
2018-6-18 13:05 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
2.4 KB, 下載次數(shù): 12, 下載積分: 黑幣 -5
主要文件,工程需自建
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1