欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
單片機AD轉換 PCF8591數顯電壓表代碼Proteus仿真原理圖
[打印本頁]
作者:
小張小張1
時間:
2022-11-13 11:10
標題:
單片機AD轉換 PCF8591數顯電壓表代碼Proteus仿真原理圖
以單片機為核心器件,組成一個簡單數字電壓表。
(1)采用1路模擬量輸入,能夠測量0-10V(20v、30v、40v)之間的直流電壓值。
(2)電壓顯示可采用LCD1602顯示,能夠顯示兩位小數。
簡易數字電壓表的制作,主要涉及數據(電壓)測量、A/D轉換及控制顯示方面的知識。
(1)A/D轉換采用PCF8591實現。
(2)電壓顯示采用LCD1602。
(3)單片機選用AT89C5.
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
仿真圖.png
(51.03 KB, 下載次數: 35)
下載附件
2022-11-13 11:45 上傳
單片機源程序如下:
#include <reg52.h>
#include <intrins.h> //包含函數_nop_()定義的頭文件
#define u8 unsigned char
#define u16 unsigned int
#define AddWr 0x90 //PCF8591寫地址
#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總線引腳
sbit Scl=P1^1;
u8 datetab[10]; //存入電壓值
u8 ADtemp; //通道轉換后存入的數值
float V_1602;
u16 num=0;
unsigned long num_pow(u8 m,u8 n) //指數運算
{
unsigned long result=1;
while(n--) result*=m;
return result;
}
void float2str(u8 str[],double floa,u8 len1,u8 len2) //浮點型轉字符型數組
{
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';
}
/*------------------------------------------------
啟動IIC總線
------------------------------------------------*/
void Start(void)
{
Sda=1;
_nop_();
Scl=1;
_nop_();
Sda=0; //sda負跳變
_nop_();
Scl=0;
}
/*------------------------------------------------
停止IIC總線
------------------------------------------------*/
void Stop(void)
{
Sda=0;
_nop_();
Scl=1;
_nop_();
Sda=1; //sda正跳變
_nop_();
Scl=0;
}
/*------------------------------------------------
IIC總線應答
------------------------------------------------*/
void Ack(void)
{
Sda=0; //scl高電平期間sda輸出低電平
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
}
/*------------------------------------------------
IIC總線非應答
------------------------------------------------*/
void NoAck(void)
{
Sda=1; //scl高電平期間sda輸出高電平
_nop_();
Scl=1;
_nop_();
Scl=0;
_nop_();
}
/*------------------------------------------------
向PCF8591發送1字節數據(/地址/控制命令等)
------------------------------------------------*/
void Send(u8 Data)
{
u8 BitCounter=8; //定義發送位數為8
do
{
Scl=0;
_nop_();
if((Data&0x80)==0x80) //逐位判別1/0后送至SDA
Sda=1; //scl低電平期間數據送至sda線
else
Sda=0;
Scl=1; //scl變高輸出數據(寫入pcf8591)
Data=Data<<1;
BitCounter--;
}while(BitCounter);
Scl=0;
}
/*------------------------------------------------
從PCF8591讀入1字節(例如A/D轉換結果)
------------------------------------------------*/
u8 Read(void)
{
u8 temp=0;
u8 BitCounter=8;
Sda=1; //拉高數據線
do
{
temp=temp<<1; //逐位移入temp
Scl=0;
_nop_();
Scl=1; //scl變高采樣sda線
_nop_();
if(Sda) //判別SDA線上為1/0
temp=temp|0x01;
else
temp=temp&0xfe;
BitCounter--;
}while(BitCounter);
return(temp); //返回值為讀入的字節
}
void DACconversion(u8 sla,u8 c, u8 Val) //8591輸出一個數據
{
Start();//啟動總線
Send(sla);//發送器件地址
Ack();
Send(c);//發送控制字節
Ack();
Send(Val);//發送DAC的數值
Ack();
Stop();//結束總線
}
/*----------------------------------------------------------
啟動PCF8591 Chl 通道A/D轉換并讀取轉換結果
--------------------------------------------------------------*/
u8 ReadADC(u8 Chl)
{
u8 Data;
Start(); //開始信號
Send(AddWr); //發寫地址(0x90)
Ack(); //等待 PCF8591應答
Send(0x40|Chl); //寫入控制字并啟動 Chl通道A/D轉換
Ack(); //等待 PCF8591應答
Start(); //重發開始信號
Send(AddRd); //寫入讀地址
Ack();
Data=Read(); //讀取A/D轉換結果(注意是上次的)
NoAck(); //發非應答信號
Stop(); //停止總線操作
return Data; //返回A/D轉換結果
}
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 則持續檢查
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位數據接口,雙行顯示
delay(100);
write_command(0x0c); //開顯示屏
delay(100);
write_command(0x01); //清屏
delay(100);
write_command(0x06); //光標移動
delay(100);
}
void string(u8 y,u8 x, u8 *s) //x表示行,y表示列
{
if (x==1)
{
write_command(0xc0|y); //因為DDRAM尋址指令是 0x80開頭。
}
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); //因為DDRAM尋址指令是 0x80開頭。
}
else
write_command(0x80|y);
write_data(num);
}
void main()
{
lcd_initial();
while(1)
{
ADtemp=ReadADC(1); //讀取通道1 A/D轉換結果
V_1602=ADtemp*(10.0/256); //計算電壓值 10.0 20.0 30.0 40.0
float2str(datetab,V_1602,2,2); //顯示整數位與小數位的個數
string(5,0,datetab); //顯示的位置和內容
string_word(10,0,'V'); //顯示單位
delay(10000);
}
}
復制代碼
Keil代碼與Proteus8.13版本的仿真下載(注意不能兼容其他版本 只能用8.13打開):
程序+Proteus8.13仿真圖.7z
(74.12 KB, 下載次數: 77)
2022-11-15 18:10 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1