寫在前言
? 此為博主自學江科大51單片機(B站)的筆記,方便后續重溫知識
? 在后面的章節中,為了防止篇幅過長和易于查找,我把一個小節分成兩部分來發,上章節主要是關于本節課的硬件介紹、電路圖、原理圖等理論知識,主要是為下章節的代碼部分打基礎。
? 我的單片機是24年12月在tb普中買的,型號是STC89C52,在原視頻中引腳或接口不對應的我都會改正,保證在我的機子上能運行才發上來的,還有一些文字部分是我的理解,并非照搬,所以可能有理解不到位的現象。
? 如有誤或交流,敬請指點提問
如果上一節的運放、電路圖、結構圖看不懂沒關系,只需要看懂下面這個時序圖就可以寫代碼實現功能了
一、AD模數轉換
先導入之前寫好的Delay和LCD1602模塊,然后新建XPT2046點c和點h文件
接下來就是對照這個時序把數據讀出來
1.先定義引腳
#include <REGX52.H>sbit XPT2046_CS=P3^5;
sbit XPT2046_DCLK=P3^6;
sbit XPT2046_DIN=P3^4;
sbit XPT2046_DOUT=P3^7;
?2.定義函數
給個參數(控制字),用于選擇通道
并且定義一個變量ADAvalue,最后返回出來
?然后是根據上圖對每個引腳先后賦值
首先把DCLK置0(初始化),CS置0,DIN賦值參數控制字的最高位
然后再給DCLK置1(上升沿),DIN就把最高位發出去,然后置0(下降沿),查看手冊發現上下時間是ns級,所以不用延時
接下來就是同理依次把8個位發出去,用for循環實現
發出去之后就可以讀數據了
接下來就是到圖中這個位置,先給DCLK一個上升沿,一個下降沿,數據才會過來
進行一個判斷,如果Dout為1,就讓ADAValue把數據讀出來(因為是16位所以或上0x8000)
然后對該過程循環16位,用for循環實現,因為只有12位是有數值的,后面都是零填充的,所以我們要在最后返回ADAValue的時候向右移位(如果選擇8位讀就移8位,12位讀就移4位)
最后再把CS置高,結束這個時序,到這里就寫完這個函數了
//XPT2046.c#include <REGX52.H>sbit XPT2046_CS=P3^5;
sbit XPT2046_DCLK=P3^6;
sbit XPT2046_DIN=P3^4;
sbit XPT2046_DOUT=P3^7;unsigned int XPT2046_ReadAD(unsigned char Command)
{unsigned char i;unsigned int ADValue=0;XPT2046_DCLK=0;XPT2046_CS=0;for(i=0;i<8;i++){XPT2046_DIN=Command&(0x80>>i);XPT2046_DCLK=1;XPT2046_DCLK=0;}for(i=0;i<16;i++){XPT2046_DCLK=0;XPT2046_DCLK=1;if(XPT2046_DOUT){ADValue|=(0x8000>>i);}}XPT2046_CS=1;if(Command&0x08){return ADValue>>8;}else{return ADValue>>4;}
}
}
這里再講一下命令字怎么寫
S就是起始位,給1;A2A1A0是地址,選擇通道;MODE就是模式選擇位,=0是12位模式,=1是8位模式;SER/DFR也是選擇模式,=1是單端模式,=0是差分模式,我們在這用單端模式;PD0和PD1表示掉電和內部參考電壓配置的關系,若為11,處于供電狀態,若為00,處于低功率模式(當PD1為0時關閉內部參考電壓源,為1時打開,內部參考源作用即假設原本測量值是從0-5V,接到這就是2.5-5V)
在這里我們給1 A2 A1 A0 1 1 0 0,A2A1A0的選擇要看下圖
下圖只看前面部分,A2A1A0控制測哪的電壓
為了方便寫代碼,我們把上面這些值給宏定義,這里要根據開發板的原理圖對應上圖,以及前面教的命令字寫出來,因為是要外部調用,所以寫在.h文件里?
?我們定義不同的命令字,一個是8位,一個是12位,方便后面選擇
8位是0-255,12位是0-4096,更精細
#ifndef __XPT0246_H_
#define __XPT0246_H_#define XPT2046_XP_8 0X9C
#define XPT2046_YP_8 0XDC
#define XPT2046_VBAT_8 0XAC
#define XPT2046_AUX_8 0XEC#define XPT2046_XP_12 0X94
#define XPT2046_YP_12 0XD4
#define XPT2046_VBAT_12 0XA4
#define XPT2046_AUX_12 0XE4unsigned int XPT2046_ReadAD(unsigned char Command);#endif
因為AUX接到了一個接口上,所以這里我們不讀,只讀其他三個
//main.c#include <REGX52.H>
#include " Delay.h"
#include " LCD1602.h"
#include " XPT2046.h"unsigned int ADValue;void main()
{LCD_Init();LCD_ShowString(1,1,"ADJ NTC RG");while(1){ADValue=XPT2046_ReadAD(XPT2046_XP_8);LCD_ShowNum(2,1,ADValue,3);ADValue=XPT2046_ReadAD(XPT2046_YP_8);LCD_ShowNum(2,5,ADValue,3);ADValue=XPT2046_ReadAD(XPT2046_VBAT_8);LCD_ShowNum(2,9,ADValue,3);Delay(10);}
}
這里我需要把DS18B20拔掉才能顯示正常,暫時還未找到原因?
#include <REGX52.H>
#include " Delay.h"
#include " LCD1602.h"
#include " XPT2046.h"unsigned int ADValue;void main()
{LCD_Init();LCD_ShowString(1,1,"ADJ NTC RG");while(1){ADValue=XPT2046_ReadAD(XPT2046_XP_8);LCD_ShowNum(2,1,ADValue,3);ADValue=XPT2046_ReadAD(XPT2046_YP_8);LCD_ShowNum(2,6,ADValue,3);ADValue=XPT2046_ReadAD(XPT2046_VBAT_8);LCD_ShowNum(2,11,ADValue,3);Delay(10);}
}
?這樣就可以調節我們電路板上的電阻,然后會把阻值通過AD轉換后輸出在LCD上
GR是光敏電阻,NTC是熱敏電阻,AD1(ADJ)是可調電阻
二、 DA數模轉換
接下是PWM,因為跟之前寫過的直流電機調速原理是一樣的,所以我們復制過來創建一個新的工程
首先是更改接口
sbit DA=P2^1;
然后是更改命名,可以點這里一鍵替代
然后把關于按鍵的部分刪掉,在主函數里實現一個呼吸燈的效果
#include <REGX52.H>
#include " Delay.h"
#include " Key.h"
#include " Nixie.h"
#include " Timer0.h"sbit DA=P2^1;unsigned char Counter,Compare;
unsigned char i;void main()
{Timer0_Init();while(1){for(i=0;i<100;i++){Compare=i;Delay(10);}for(i=100;i>0;i--){Compare=i;Delay(10);}}
}
void Timer0_Routine() interrupt 1
{Key_Loop();TL0 = 0xA4; //設置定時初值TH0 = 0xFF; //設置定時初值Counter++;Counter%=100;if(Counter<Compare){DA=1;}else{DA=0;}
}
其他部分都不需要改,這樣就實現了呼吸燈的效果。