標(biāo)題:
單片機(jī)AD轉(zhuǎn)換 PCF8591數(shù)顯電壓表代碼Proteus仿真原理圖
[打印本頁(yè)]
作者:
小張小張1
時(shí)間:
2022-11-13 11:10
標(biāo)題:
單片機(jī)AD轉(zhuǎn)換 PCF8591數(shù)顯電壓表代碼Proteus仿真原理圖
以單片機(jī)為核心器件,組成一個(gè)簡(jiǎn)單數(shù)字電壓表。
(1)采用1路模擬量輸入,能夠測(cè)量0-10V(20v、30v、40v)之間的直流電壓值。
(2)電壓顯示可采用LCD1602顯示,能夠顯示兩位小數(shù)。
簡(jiǎn)易數(shù)字電壓表的制作,主要涉及數(shù)據(jù)(電壓)測(cè)量、A/D轉(zhuǎn)換及控制顯示方面的知識(shí)。
(1)A/D轉(zhuǎn)換采用PCF8591實(shí)現(xiàn)。
(2)電壓顯示采用LCD1602。
(3)單片機(jī)選用AT89C5.
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
仿真圖.png
(51.03 KB, 下載次數(shù): 35)
下載附件
2022-11-13 11:45 上傳
單片機(jī)源程序如下:
#include <reg52.h>
#include <intrins.h> //包含函數(shù)_nop_()定義的頭文件
#define u8 unsigned char
#define u16 unsigned int
#define AddWr 0x90 //PCF8591寫(xiě)地址
#define AddRd 0x91 //PCF8591讀地址
#define w_com P0
sbit RS=P2^2;
sbit RW=P2^3;
sbit E=P2^4;
sbit Sda=P1^2; //定義IIC總線(xiàn)引腳
sbit Scl=P1^1;
u8 datetab[10]; //存入電壓值
u8 ADtemp; //通道轉(zhuǎn)換后存入的數(shù)值
float V_1602;
u16 num=0;
unsigned long num_pow(u8 m,u8 n) //指數(shù)運(yùn)算
{
unsigned long result=1;
while(n--) result*=m;
return result;
}
void float2str(u8 str[],double floa,u8 len1,u8 len2) //浮點(diǎn)型轉(zhuǎn)字符型數(shù)組
{
u8 i=0,j=0;
u16 zhengshu=floa;
u16 xiaoshu=(floa-zhengshu)*num_pow(10,len2);
while(len1--)
{
str[len1]=zhengshu%10+0x30;
zhengshu=zhengshu /10;
i++;
}
str[i]='.';
while(len2--)
{
str[i+len2+1]=xiaoshu%10+0x30;
xiaoshu=xiaoshu/10;
j++;
}
str[i+j+1]='\0';
}
/*------------------------------------------------
啟動(dòng)IIC總線(xiàn)
------------------------------------------------*/
void Start(void)
{
Sda=1;
_nop_();
Scl=1;
_nop_();
Sda=0; //sda負(fù)跳變
_nop_();
Scl=0;
}
/*------------------------------------------------
停止IIC總線(xiàn)
------------------------------------------------*/
void Stop(void)
{
Sda=0;
_nop_();
Scl=1;
_nop_();
Sda=1; //sda正跳變
_nop_();
Scl=0;
}
/*------------------------------------------------
IIC總線(xiàn)應(yīng)答
------------------------------------------------*/
void Ack(void)
{
Sda=0; //scl高電平期間sda輸出低電平
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
}
/*------------------------------------------------
IIC總線(xiàn)非應(yīng)答
------------------------------------------------*/
void NoAck(void)
{
Sda=1; //scl高電平期間sda輸出高電平
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
}
/*------------------------------------------------
向PCF8591發(fā)送1字節(jié)數(shù)據(jù)(/地址/控制命令等)
------------------------------------------------*/
void Send(u8 Data)
{
u8 BitCounter=8; //定義發(fā)送位數(shù)為8
do
{
Scl=0;
_nop_();
if((Data&0x80)==0x80) //逐位判別1/0后送至SDA
Sda=1; //scl低電平期間數(shù)據(jù)送至sda線(xiàn)
else
Sda=0;
Scl=1; //scl變高輸出數(shù)據(jù)(寫(xiě)入pcf8591)
Data=Data<<1;
BitCounter--;
}while(BitCounter);
Scl=0;
}
/*------------------------------------------------
從PCF8591讀入1字節(jié)(例如A/D轉(zhuǎn)換結(jié)果)
------------------------------------------------*/
u8 Read(void)
{
u8 temp=0;
u8 BitCounter=8;
Sda=1; //拉高數(shù)據(jù)線(xiàn)
do
{
temp=temp<<1; //逐位移入temp
Scl=0;
_nop_();
Scl=1; //scl變高采樣sda線(xiàn)
_nop_();
if(Sda) //判別SDA線(xiàn)上為1/0
temp=temp|0x01;
else
temp=temp&0xfe;
BitCounter--;
}while(BitCounter);
return(temp); //返回值為讀入的字節(jié)
}
void DACconversion(u8 sla,u8 c, u8 Val) //8591輸出一個(gè)數(shù)據(jù)
{
Start();//啟動(dòng)總線(xiàn)
Send(sla);//發(fā)送器件地址
Ack();
Send(c);//發(fā)送控制字節(jié)
Ack();
Send(Val);//發(fā)送DAC的數(shù)值
Ack();
Stop();//結(jié)束總線(xiàn)
}
/*----------------------------------------------------------
啟動(dòng)PCF8591 Chl 通道A/D轉(zhuǎn)換并讀取轉(zhuǎn)換結(jié)果
--------------------------------------------------------------*/
u8 ReadADC(u8 Chl)
{
u8 Data;
Start(); //開(kāi)始信號(hào)
Send(AddWr); //發(fā)寫(xiě)地址(0x90)
Ack(); //等待 PCF8591應(yīng)答
Send(0x40|Chl); //寫(xiě)入控制字并啟動(dòng) Chl通道A/D轉(zhuǎn)換
Ack(); //等待 PCF8591應(yīng)答
Start(); //重發(fā)開(kāi)始信號(hào)
Send(AddRd); //寫(xiě)入讀地址
Ack();
Data=Read(); //讀取A/D轉(zhuǎn)換結(jié)果(注意是上次的)
NoAck(); //發(fā)非應(yīng)答信號(hào)
Stop(); //停止總線(xiàn)操作
return Data; //返回A/D轉(zhuǎn)換結(jié)果
}
void delay(u16 i)
{
while(i--);
}
void LCD_busy(void)
{
u8 temp;
do{
temp =0xff;
E = 0;
RS= 0;
RW = 1;
E =1;
temp = w_com;
}while(temp&0x80); // 如果 BF =1 則持續(xù)檢查
E = 0;
}
void write_command(u8 com)
{
LCD_busy();
E= 0;
RS =0;
RW =0;
w_com = com;
E =1;
delay(100);
E = 0;
}
void write_data(u8 com)
{
LCD_busy();
E=0;
RS= 1;
RW =0;
w_com = com;
E=1;
delay(100);
E =0;
}
void lcd_initial(void)
{
write_command(0x38); //8位數(shù)據(jù)接口,雙行顯示
delay(100);
write_command(0x0c); //開(kāi)顯示屏
delay(100);
write_command(0x01); //清屏
delay(100);
write_command(0x06); //光標(biāo)移動(dòng)
delay(100);
}
void string(u8 y,u8 x, u8 *s) //x表示行,y表示列
{
if (x==1)
{
write_command(0xc0|y); //因?yàn)镈DRAM尋址指令是 0x80開(kāi)頭。
}
else
write_command(0x80|y);
while(*s != '\0')
{
write_data(*s++);
}
}
void string_word(u8 y,u8 x,u8 num)
{
if (x==1)
{
write_command(0xc0|y); //因?yàn)镈DRAM尋址指令是 0x80開(kāi)頭。
}
else
write_command(0x80|y);
write_data(num);
}
void main()
{
lcd_initial();
while(1)
{
ADtemp=ReadADC(1); //讀取通道1 A/D轉(zhuǎn)換結(jié)果
V_1602=ADtemp*(10.0/256); //計(jì)算電壓值 10.0 20.0 30.0 40.0
float2str(datetab,V_1602,2,2); //顯示整數(shù)位與小數(shù)位的個(gè)數(shù)
string(5,0,datetab); //顯示的位置和內(nèi)容
string_word(10,0,'V'); //顯示單位
delay(10000);
}
}
復(fù)制代碼
Keil代碼與Proteus8.13版本的仿真下載(注意不能兼容其他版本 只能用8.13打開(kāi)):
程序+Proteus8.13仿真圖.7z
(74.12 KB, 下載次數(shù): 77)
2022-11-15 18:10 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1