STC89C52單片機AD/DA介紹與代碼演示


目錄

AD/DA介紹

硬件電路模型

硬件電路圖

運算放大器

運放電路

AD原理

DA原理

AD/DA性能指標

XPT2046的使用介紹與配置

         XPT2046的時序

 代碼解釋


AD/DA介紹

AD(Analog to Digital):模擬-數字轉換,將模擬信號轉換為計算機可操作的數字信號

DA(Digital to Analog):數字-模擬轉換,將計算機輸出的數字信號轉換為模擬信號

AD/DA轉換打開了計算機與模擬信號的大門,極大的提高了計算機系統的應用范圍,也為模擬信號數字化處理提供了可能

硬件電路模型

AD轉換通常有多個輸入通道,用多路選擇開關連接至AD轉換器,以實現AD多路復用的目的,提高硬件利用率

AD/DA與單片機數據傳送可使用並口(一次性輸入8位,速度快、原理簡單),也可使用串口(一位一位的輸入,接線少、使用方便)

可將AD/DA模塊直接集成在單片機內,這樣直接寫入/讀出寄存器就可進行AD/DA轉換,單片機的IO口可直接復用為AD/DA的通道

硬件電路圖

典型的AD轉換器芯片是ADC0808/AD0809但是這塊板子為了更好的拓展性接的是XPT2046,好像是用來驅動電阻觸摸顯示屏的,但是在這里用來進行AD轉換也行。

同樣的DA轉換常用的是DAC0832這塊芯片,但是這里顯然也不是,但是結構圖很清楚的發現他是一個PWM型的DA轉換器

這里看不懂也沒有關系,我們后面說這么配置

運算放大器

運算放大器(簡稱“運放”)是具有很高放大倍數的放大電路單元。內部集成了差分放大器、電壓放大器、功率放大器三級放大電路,是一個性能完備、功能強大的通用放大電路單元,由於其應用十分廣泛,現已作為基本的電路元件出現在電路圖中

運算放大器可構成的電路有:電壓比較器、反相放大器、同相放大器、電壓跟隨器、加法器、積分器、微分器等

運算放大器電路的分析方法:虛短、虛斷(負反饋條件下)

運放電路

AD原理

DA原理

其實這個DA轉換和我們之前講到過的PWM是有幾分相似的:實事上只要我們加上低通濾波器和電壓跟隨器,來增強穩定與驅動。PWM也可以實現DA轉換

AD/DA性能指標

分辨率:指AD/DA數字量的精細程度,通常用位數表示。例如,對於5V電源系統來說,8位的AD可將5V等分為256份,即數字量變化最小一個單位時,模擬量變化5V/256=0.01953125V,所以,8位AD的電壓分辨率為0.01953125V,AD/DA的位數越高,分辨率就越高

轉換速度:表示AD/DA的最大采樣/建立頻率,通常用轉換頻率或者轉換時間來表示,對於采樣/輸出高速信號,應注意AD/DA的轉換速度

XPT2046的使用介紹與配置

在配置的時候主要對這些端口進行配置:

sbit XPY2046_CS=P3^5;//開始中斷
sbit XPY2046_DCLK=P3^6;//相當於時鍾
sbit XPY2046_DIN=P3^4;//輸入
sbit XPY2046_DOUT=P3^7;//輸出

Command位介紹:

A2,A1,A0根據上面的XPT2046的手冊來按需求是測XP,YP還是別的位連接的器件(在這里的結構圖中,AIN0連接的是AD1502即變阻器,AIN1連接的是NTC1熱敏電阻,AIN2連接的是GR1光敏電阻)

第七位S置1,表示開始。

第三位MODE置1,選擇8位為轉換分辨率。

第二位SER/DFR置1,表示單端輸入方式。

第一位PD1置0,用外部VCC提供的電壓。

第0位PD0置0,不開啟低功耗模式。

XPT2046的時序

 代碼解釋:

XPT2046代碼:

 #include <REGX52.H>
#include <INTRINS.H>

//引腳定義
sbit XPY2046_CS=P3^5;//開始中斷
sbit XPY2046_DCLK=P3^6;//相當於時鍾
sbit XPY2046_DIN=P3^4;//輸入
sbit XPY2046_DOUT=P3^7;//輸出

#define XPT2046_VBAT	0xAC
#define XPT2046_AUX		0xEC
#define XPT2046_XP		0x9C	//或者0xBC
#define XPT2046_YP		0xDC

/**
  * @brief  ZPT2046讀取AD值
  * @param  Command 命令字,范圍:頭文件內定義的宏,結尾的數字表示轉換的位數
  * @retval AD轉換后的數字量,范圍:8位為0~255,12位為0~4095
  */
unsigned int XPT2046_ReadAD(unsigned char Command)
{
	unsigned char i;
	unsigned int Data=0;
	XPY2046_DCLK=0;
	XPY2046_CS=0;
	for(i=0;i<8;i++)//依次將8位發出
	{
		XPY2046_DIN=Command&(0x80>>i);
		XPY2046_DCLK=1;
		XPY2046_DCLK=0;
	}
	for(i=0;i<16;i++)
	//時序要讀16位,有效位只有前面的12位,因為之前MODE選擇的是讀8位,所以最后8位置0
	//時序要讀16位,有效位只有前面的12位,如果MODE選擇的是讀16位,那么最后4位置0,那么要將第36行改寫為Data>>4
	{
		XPY2046_DCLK=1;
		XPY2046_DCLK=0;
		if(XPY2046_DOUT){Data|=(0x8000>>i);}
	}
	XPY2046_CS=1;
	return Data>>8;//因為之前MODE選擇的是讀8位
}

主函數:

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "XPT2046.h"

unsigned int ADValue;

void main(void)
{
	LCD_Init();
	LCD_ShowString(1,1,"ADJ  NTC  GR");
	while(1)
	{
		ADValue=XPT2046_ReadAD(XPT2046_XP);		//讀取AIN0,可調電阻
		LCD_ShowNum(2,1,ADValue,3);				//顯示AIN0
		ADValue=XPT2046_ReadAD(XPT2046_YP);		//讀取AIN1,熱敏電阻
		LCD_ShowNum(2,6,ADValue,3);				//顯示AIN1
		ADValue=XPT2046_ReadAD(XPT2046_VBAT);	//讀取AIN2,光敏電阻
		LCD_ShowNum(2,11,ADValue,3);			//顯示AIN2
		Delay(100);
	}
}

LCD1602代碼:

#include <REGX52.H>

//引腳配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函數定義:
/**
  * @brief  LCD1602延時函數,12MHz調用可延時1ms
  * @param  無
  * @retval 無
  */
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602寫命令
  * @param  Command 要寫入的命令
  * @retval 無
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602寫數據
  * @param  Data 要寫入的數據
  * @retval 無
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602設置光標位置
  * @param  Line 行位置,范圍:1~2
  * @param  Column 列位置,范圍:1~16
  * @retval 無
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/**
  * @brief  LCD1602初始化函數
  * @param  無
  * @retval 無
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位數據接口,兩行顯示,5*7點陣
	LCD_WriteCommand(0x0c);//顯示開,光標關,閃爍關
	LCD_WriteCommand(0x06);//數據讀寫操作后,光標自動加一,畫面不動
	LCD_WriteCommand(0x01);//光標復位,清屏
}

/**
  * @brief  在LCD1602指定位置上顯示一個字符
  * @param  Line 行位置,范圍:1~2
  * @param  Column 列位置,范圍:1~16
  * @param  Char 要顯示的字符
  * @retval 無
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置開始顯示所給字符串
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  String 要顯示的字符串
  * @retval 無
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/**
  * @brief  在LCD1602指定位置開始顯示所給數字
  * @param  Line 起始行位置,范圍:1~2
  * @param  Column 起始列位置,范圍:1~16
  * @param  Number 要顯示的數字,范圍:0~65535
  * @param  Length 要顯示數字的長度,范圍:1~5
  * @retval 無
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

Delay函數

void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

DA轉換的代碼其實就是和之前電機控制調速是一樣的,利用的是PWM來模擬脈沖來實現。這里用與呼吸燈相同的代碼后位聲明時這樣,sbit DA=P2^1;替換之前的端口即可


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM