PCF8591學習(二)-AD轉換,演算法,串列埠列印

BretLi發表於2015-12-29
<pre name="code" class="csharp">/*
專案名稱:PCF8591AD和串列埠列印
專案內容:A/D轉換,把轉換的數字量
送給P0口控制LED的亮滅 ;
並把轉換的數字邏輯
運算,送給串列埠,列印到電腦上。
這樣就可以取樣電壓訊號了,並處理。
可以擴充套件做出電壓表,電流表等。
作者:YUAN
*/

#include <reg52.h>
#include <stdio.h>		//printf輸出標頭檔案
#include <intrins.h>	//_nop_()延時標頭檔案
typedef unsigned char uChar8;
typedef unsigned int uInt16;
sbit SDA = P1^0;
sbit SCL = P1^1;
#define PCF8591Add 0x90	//PCF8591的器件地址和寫操作
uChar8 gTemp;
float gfDataVal; 	//用在轉載計算的數值,併傳送給計算機

//延時函式
void DelayMS(uInt16 lValMS);
void Delay5us(void);
//IIC操作的幾個函式
void IICInit(void);		//IIC初始化
void IICStart(void);	//起始訊號
void IICStop(void);		//停止訊號
void IICAck(void);		//應答訊號
void IICReadAck(void);	//讀應答訊號
void IICWriteOneByte(uChar8 lByteVal);					//寫一個位元組
uChar8 IICReadOneByte(void);		//讀一個位元組
void PCF8591WriteRegulate(uChar8 lREGVal);	//Regulate控制器,這裡寫控制函式
uChar8  ReadDataPCF8591(void);
// 

//串列埠的幾個程式
void UartInit(void);		//串列埠初始化
void UartPrint(float iVal);	//Printd列印,列印函式
								
void main()
{
	IICInit();
	UartInit();
	while(1)
	{	 
		/*寫入控制字00,即模擬量輸出關閉,選擇通道0,
		不自動增加通道,模擬量輸入圍方式0*/
		 PCF8591WriteRegulate(0x00);
		 P0 = ReadDataPCF8591(); 
		 gTemp = P0; 	//用來中轉的儲存區
		 gfDataVal = (float)gTemp/255*5;   //強制轉換
		 DelayMS(1000);
		 UartPrint(gfDataVal);
	}
}

void DelayMS(uInt16 lValMS)	//延時函式
{
	uInt16 luiVal,lujVal;
	for(luiVal = 0; luiVal < lValMS; luiVal++)
		for(lujVal = 0; lujVal < 113; lujVal++);
}
void Delay5us(void)
{
	_nop_();_nop_();_nop_();
	_nop_();_nop_();_nop_();
}
//IIC匯流排空閒時均為高電平
void IICInit(void)		//IIC初始化
{
  	SCL = 0;
	SDA=1;
	Delay5us();
	SCL=1;
}
//SCL高電平期間SDA由高到低的變化為起始訊號
void IICStart(void)	//起始訊號
{
	SCL = 0;
	Delay5us();
	SDA = 1;
	Delay5us();
	SCL = 1;
	Delay5us();
	SDA = 0;
	Delay5us();
	//防止接下來SDA資料變化導致IIC匯流排誤判	
	SCL = 0;	 
}
//SCL高電平期間SDA由低到高的變化為終止訊號
void IICStop(void)		//停止訊號
{
	SCL = 0;
	Delay5us();
	SDA = 0;
	Delay5us();
	SCL = 1;
	Delay5us();
	SDA = 1;
	Delay5us();
	//防止接下來SDA資料變化導致IIC匯流排誤判	
	SCL = 0;
}
//一個脈衝期間,SDA為低電平為應答
void IICAck(void)		//應答訊號
{
	SCL = 0;
	Delay5us();
	SDA = 0;
	Delay5us();
	SCL = 1;
	Delay5us();
	SCL = 0; 		
}
/*cpu讀應答訊號,如果應答了則
繼續傳輸資料,否則在一定時間裡,
預設已經應答,繼續傳資料
*/
void IICReadAck(void)	//讀應答訊號
{
	uChar8 li = 0;
	SCL = 0;
	SDA = 1;  //確保讀出的值為0,因此先送1
	Delay5us();
	SCL = 1;
	Delay5us();
	//如果沒有應答或時間沒有超過預定時間則停在此處
	while((1 == SDA)&&(li<255))li++;
	SCL = 0;
	Delay5us();		
	SDA = 1;			
}
/*
	寫1個位元組,先寫高位。
*/
void IICWriteOneByte(uChar8 lByteVal)					//寫一個位元組
{
	uChar8 li,liVal;
	liVal = lByteVal;

	for(li=0;li<8;li++)	  
	{
		
		SCL = 0; 
		Delay5us();	
		SDA = (bit)(liVal&0x80);	//把資料準備好等待傳送
		Delay5us();	
		SCL = 1;
		Delay5us();
		liVal <<= 1;
	} 
	SCL = 0; 
	Delay5us();	
	SDA = 1;
}
/*
讀取一個位元組並把讀到的值返回
*/
uChar8 IICReadOneByte(void)
{
	uChar8 li,liVal;
	SCL = 0;
	SDA = 1;
	for(li=0;li<8;li++)
	{
		liVal <<= 1;
		SCL = 0;
		Delay5us();
		SCL = 1;
		Delay5us();
		liVal = (liVal|SDA);
	}
	SCL = 0; 
	return liVal;
}	
//Regulate控制器,這裡寫控制函式
void PCF8591WriteRegulate(uChar8 lREGVal)
{
	IICStart();
	IICWriteOneByte(PCF8591Add); 	//PCF8591的地址,寫控制
	IICReadAck();
	IICWriteOneByte(lREGVal);		//寫入控制字
	IICReadAck();
	IICStop();
}	
uChar8  ReadDataPCF8591(void)
{
	uChar8 liVal;
	IICStart();
	IICWriteOneByte(PCF8591Add|0x01); 	//PCF8591的地址,讀控制	
	liVal = IICReadOneByte();
	IICAck();
	IICStop();
	return liVal; 	
} 
//串列埠的程式
void UartInit(void)
{
	TMOD &= 0x0f;	 //只改變要改變的
	TMOD |= 0x20;	//設定定時器0為工作方式2
	TL1 = 0xfd;
	TH1 = 0xfd;		//設定波特率為9600bps
	TR1 = 1;		//允許T1開始計數

	SCON &= 0x5f;
	SCON |= 0x50;	//設定串列埠工作在方式1,允許接收資料 
}
//把讀出來的值列印到計算機上
void UartPrint(float iVal)
{
	TI=1;
	printf("測得電壓為:%f\n",iVal);
	while(!TI);
	TI=0;
}



相關文章