|
#include <STC12C5A60S2.H>
#include "intrins.h"
//typedef unsigned char BYTE;
//typedef unsigned int WORD;
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/*Define ADC operation const for ADC_CONTR*/
#define ADC_POWER 0x80 //ADC 電源控制位 10000000 0X80 /
#define ADC_FLAG 0x10 //ADC 完成標(biāo)志 00010000 0x10
#define ADC_START 0x08 //ADC 啟動(dòng)ADC開(kāi)關(guān) 00001000 0x08 /
#define ADC_SPEEDLL 0x00 //420 轉(zhuǎn)換速度 00000000 0x00 /
#define ADC_SPEEDL 0x20 //280 轉(zhuǎn)換速度 00100000 0x20
#define ADC_SPEEDH 0x40 //140 轉(zhuǎn)換速度 01000000 0x40
#define ADC_SPEEDHH 0x60 //70 轉(zhuǎn)換速度 01100000 0x60
//float temp; //定義temp為浮點(diǎn)型參數(shù)
/*----------------------------------------------------------------------------------------------
meidangzuidivoltage:表示AD最高電壓5V對(duì)應(yīng)10bit_AD轉(zhuǎn)換的最小電壓是多少 5/1024= 0.00488V 也就是AD在
//10bit下測(cè)量的最小電壓,
//那么在計(jì)算AD電壓值的時(shí)候?qū)⒐?“GetADCResult(ch)*5/1024”分兩步進(jìn)行 方便后面對(duì)數(shù)據(jù)分離顯示到
//1602上面 先計(jì)算ADC_jiancedaozuidivoltage=5*10000000/1024 先將這個(gè)數(shù)放大100萬(wàn)倍
//最后在算AD_jie_guo=(ADC_jiancedaozuidivoltage*GetADCResult(ch);
----------------------------------------------------------------------------------------------*/
ulong ADC_jiancedaozuidivoltage,AD_jie_guo,temp;
uint num,i,vlue;//ADC_mV,ADC_RESX,VCC_V=5.2;
sbit lcden = P2^7;
sbit rs = P2^6;
sbit rw = P2^5;
sbit LED = P3^0;
void Delay(uint n); //延時(shí)函數(shù)
uint GetADCResult(uchar ch); // ad轉(zhuǎn)換函數(shù)
void InitADC(); //ad初始化函數(shù)
//ulong count(uchar ch); //ad計(jì)算函數(shù)
uchar code table[20]= {" Shu Kong QuDong"};
uchar code table2[20]={" CQDZ Alan V1.01"};
float count(uchar ch);
/* 延時(shí)函數(shù)*/
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for (j=960;j>0;j--);
}
/******寫(xiě)命令****/
void lcd_write_com(uchar com)
{
rw=0;
rs=0; //寫(xiě)命令狀態(tài)
P0=com;
lcden=1;
delayms(5);
lcden=0;
}
/**寫(xiě)數(shù)據(jù) ***/
void write_date_(uchar date)
{
rw=0; //寫(xiě)數(shù)據(jù)
rs=1; //寫(xiě)數(shù)據(jù)狀態(tài)
P0=date;
delayms(5);
lcden=1; //使能
delayms(5);
lcden=0;
}
/*初始化顯示屏*/
void lcd_init(void)
{
lcden=0;
lcd_write_com(0x38); //設(shè)置8位格式,2行,5*7
lcd_write_com(0x0c); //整體顯示,關(guān)光標(biāo),不顯示
lcd_write_com(0x06); // 設(shè)定輸入方式,增量不移位
lcd_write_com(0x01);//清屏幕
delayms(5); //延?
}
/*-----------------------
函數(shù)名稱(chēng) 格式定義
函數(shù)的介紹 在某個(gè)屏幕位置上顯示一個(gè)字符,X(0-16),y(1-2)
X:表示字的格式 一共16個(gè) Y:表示行 一共2行
-------------------------*/
//格式定義
void lcd_disp_char(uchar y,uchar x, uint dat)
{
uint address;
if(y==1) //y為1 在第一行
address=0x80+0x10+4+x; //整屏左移動(dòng)以后 從新定義新的起始位置 但是要加上之前移動(dòng)后的地址
else
address=0xc0+0x10+x; //y為2 在第二行 X顯示字的位置 0XC0是 0x80+0x40的結(jié)果
lcd_write_com(address); //寫(xiě)入要寫(xiě)的位置
write_date_( dat); //寫(xiě)入你要寫(xiě)的數(shù)據(jù)
}
/*顯示函數(shù)2*********/
void disp()
{
temp=(ADC_jiancedaozuidivoltage*AD_jie_guo);
temp=(temp*6)/100; //擴(kuò)大電壓 我的量程是0-30V 分壓電阻是 10k 2k 電阻比的5 反推 當(dāng)測(cè)試電壓為5v
//的時(shí)候 最高電壓為25V 測(cè)量后調(diào)試
//0x30是顯示數(shù)字 0-9 30表示第一個(gè)數(shù)0 int是將count轉(zhuǎn)換為整數(shù)
lcd_disp_char(1,0, temp%10000000/1000000+0x30 ); //十位
lcd_disp_char(1,1, temp%1000000/100000+0x30); //個(gè)位
lcd_disp_char(1,2,'.' ); // 小數(shù)點(diǎn)
lcd_disp_char(1,3, temp%100000/10000+0x30 ); //個(gè)分位
lcd_disp_char(1,4, temp%10000/1000+0x30 ); //百分位
lcd_disp_char(1,5,'V' );
}
//count(0)
/*-----------------------------------
功能 開(kāi)機(jī)的時(shí)候顯示一下銘牌
for來(lái)完成 屏幕左移動(dòng)
----------------------------------*/
void init()
{
// lcd_write_com(0x80+0x10); //定義顯示的位置 起始地址
lcd_write_com(0x80); //定義顯示的位置 起始地址
for(num=0;num<20;num++)
{
write_date_(table[num]); //初始化屏幕的初始數(shù)字“0000”
delayms(5);
}
// lcd_write_com(0x80+0x40+0x10); //定義第二排,顯示的地址 0x80是顯示屏寄存器第一排起始地址
lcd_write_com(0xc0); //定義顯示的位置 起始地址
for(num=0;num<20;num++) //0x40是第二排起始地址
{
write_date_(table2[num]);
delayms(5);
}
for(num=0;num<20;num++) //整屏左移動(dòng) 這里的21就是指可以移動(dòng)多少格 可以是100可以是1000 相當(dāng)于是電子屏幕一樣
{
lcd_write_com(0x18); //0x18是整屏左移 指令
delayms(50);
}
}
void main()
{
lcd_init();
init();
InitADC(); //Init ADC sfr
ADC_jiancedaozuidivoltage=49700000/1024; //5V參考電壓,計(jì)算分度值的時(shí)候,數(shù)值過(guò)小會(huì)出現(xiàn)很大偏差
//所以放大1000萬(wàn)倍 這樣精度會(huì)高一些
while (1)
{
/*
if(temp > 3)
{
LED = 0;
// 調(diào)試的時(shí)候用的 通過(guò)判斷temp來(lái)判斷是否過(guò)壓 如果過(guò)壓就啟動(dòng)保護(hù)
}
if(temp < 3)
{
LED = 1;
}*/
AD_jie_guo = count(0); //經(jīng)過(guò)上面的計(jì)算求出來(lái)100次的平均值存放在AD_jie_guo里面
disp();
}
}
/*************************
* 功能 ADC轉(zhuǎn)換函數(shù)
* 帶結(jié)果返回 帶結(jié)果返回
**************************/
uint GetADCResult(uchar ch) //參數(shù)的定義“ch”初始化就是為0 所以這里的“ch”應(yīng)該是用來(lái)設(shè)置用哪個(gè)端口
{ //來(lái)設(shè)置AD的 這個(gè)“ADC_POWER|ADC_SPEEDLL|ch|ADC_START”;或出來(lái)的結(jié)果是
//10001000 后面三個(gè)0對(duì)應(yīng)的是 CHS2 CHS1 CHS0 查表格 剛好是P1.0口
//作為AD模擬輸入的。如果要改變端口就要給ch賦值 假如要P1.2 就需要賦值為ch=0x02;
ADC_CONTR = ADC_POWER|ADC_SPEEDLL|ch|ADC_START; //配置相關(guān)項(xiàng)目打開(kāi)
_nop_();
_nop_();
_nop_(); //4個(gè)機(jī)器時(shí)間的延時(shí) 以保障轉(zhuǎn)換完成
_nop_();
while(!(ADC_CONTR&ADC_FLAG)); //判斷是否轉(zhuǎn)換完成
ADC_CONTR &= ~ADC_FLAG; //關(guān)閉ADC
vlue = (ADC_RES*4+ADC_RESL); //返回結(jié)果10bit 也就是電壓值
Delay(2); //延時(shí)一下不然電壓的后2位變化的太快
return vlue;
}
/******************************
* 功能:計(jì)算1結(jié)果函數(shù) 將10bit的結(jié)果計(jì)算為對(duì)應(yīng)電壓值MV
* 函數(shù)類(lèi)型 float 型 浮點(diǎn)型
* 帶結(jié)果返回 帶結(jié)果返回
******************************/
/*
ulong count(uchar ch)
{
ADC_RESX=GetADCResult(ch);
ADC_mV=(VCC_V*(long)ADC_RESX*10000/1024+5)/10;//強(qiáng)制轉(zhuǎn)換長(zhǎng)整型運(yùn)算,得到結(jié)果mV(4舍5入)
return ADC_mV;
}*/
/******************************
* 功能:計(jì)算2結(jié)果函數(shù) 將10bit的結(jié)果計(jì)算為對(duì)應(yīng)電壓值MV
* 函數(shù)類(lèi)型 float 型 浮點(diǎn)型
* 帶結(jié)果返回 帶結(jié)果返回
******************************/
float count(uchar ch)
{
float AD_val; //定義處理后的數(shù)值A(chǔ)D_val為浮點(diǎn)數(shù)
uchar n;
for(n=0;n<100;n++)
AD_val+=GetADCResult(ch); //轉(zhuǎn)換100次求平均值(提高精度)
AD_val/=100; //意思是GetADCResult(ch)經(jīng)過(guò)了100次轉(zhuǎn)換后的值保存到了AD_val里面 然后在
//除以100 就是求平均值 這樣的精度高一點(diǎn)
// AD_val=(AD_val*5)/1024; //AD的參考電壓是單片機(jī)上的5v,所以乘5即為實(shí)際電壓值,應(yīng)為分段計(jì)算這個(gè)就
//暫時(shí)不用 如果測(cè)量0-5v就可以這樣計(jì)算
return AD_val;
// temp = (float)GetADCResult(ch)*5/1024; //5表示單片機(jī)的供電 這個(gè)公式在手冊(cè)上可以看到
//temp = (float) temp*5;
// return temp;
//這里的temp值就是最終的電壓值MV 轉(zhuǎn)換成V就在乘以1000
} //在顯示屏函Dispy數(shù)里面已經(jīng)做了倍率乘法
/*----------------------------
功能 ADC初始化函數(shù)
----------------------------*/
void InitADC() //adc初始化函數(shù)
{
P1M1=0x01; //設(shè)置P1.0高阻模式
P1M0=0x00; //設(shè)置P1.0高阻模式
P1ASF = 0x01; //開(kāi)放P1.0通道ADC功能 就是8個(gè)I/O口全部開(kāi)放
ADC_RES = 0; //清除之前的結(jié)果
ADC_RESL = 0;
ADC_CONTR = ADC_POWER | ADC_SPEEDLL; //打開(kāi)AD電壓 轉(zhuǎn)換速度540
Delay(2); //ADC 延時(shí)一下
}
/*----------------------------
Software delay function
----------------------------*/
void Delay(uint n)
{
uint x;
while (n--)
{
x = 5000;
while (x--);
}
}
|
|