STC單片機(jī)有89、90、10、11、12、15這幾個(gè)大系列,每個(gè)系列都有自己的特點(diǎn)。89系列是老舊而傳統(tǒng)的單片機(jī),可以和AT89系列完全兼容,是12T單片機(jī)。90是基于89系列的改進(jìn)型產(chǎn)品系列。10和11系列是有著便宜價(jià)格的1T單片機(jī),有PWM、4態(tài)IO接口、EEPROM等功能,但都沒有ADC這個(gè)高級(jí)功能。12是增強(qiáng)型功能的1T單片機(jī),型號(hào)后面有“AD”的就有ADC功能的單片機(jī)。目前12系列是主流產(chǎn)品。15:15系列是STC公司最新推出的產(chǎn)品,最大的特別是內(nèi)部集成了高精度的R/C時(shí)鐘,可以完全不需要接外部晶振。
STC12C5A60S2單片機(jī)中包含中央處理器(CPU)、程序存儲(chǔ)器(Flash)、數(shù)據(jù)存儲(chǔ)器(SRAM)、定時(shí)/計(jì)數(shù)器、UART串口、串口2、I/O接口、高速A/D轉(zhuǎn)換、SPI接口、PCA、看門狗及片內(nèi)R/C振蕩器和外部晶體振蕩電路等模塊。STC12C5A60S2系列單片機(jī)幾乎包含了數(shù)據(jù)采集和控制中所需的所有單元模塊,可稱得上一個(gè)片上系統(tǒng)。
STC12C系列增強(qiáng)型單片機(jī)片上擴(kuò)展了基本51單片機(jī)的功能,如提供了PCA/PWM接口,定時(shí)器能工作在1T模式下(基本51單片機(jī)的時(shí)鐘是Fosc的12分頻,1T模式下1分頻)。
PCA可以用于脈寬測(cè)量,但是,protues暫不支持該系列單片機(jī)的仿真功能,反復(fù)燒寫也挺麻煩,所以還是先用基本51單片機(jī)實(shí)現(xiàn)該功能,在后面的博文里在實(shí)現(xiàn)PCA測(cè)量脈寬。
實(shí)現(xiàn)思路如下:
TMOD最高位GATEn置位后,Tn啟動(dòng)計(jì)數(shù)受INTn(Pin3.3)和TRn的共同影響:TRn為1,當(dāng)INTn引腳輸入為高電平時(shí),Tn才允許計(jì)數(shù)。利用這個(gè)功能可測(cè)量INTn上正脈沖的寬度。
1):1處 在上升沿之前,初始化TMOD,TRn=1;
2):2處 INTn引腳為高電平,開始計(jì)數(shù)測(cè)量脈寬;
3):3處 INTn引腳為低電平,測(cè)量結(jié)束停止計(jì)數(shù)TRn=0
再上仿真圖:
1)。信號(hào)發(fā)生器電平選5v方波。注信號(hào)發(fā)生器的反相端接地,否則正向端只輸出2.5v的方波(剩下的2.5v輸出反相方波,可以接到示波器上試試),INTn上永遠(yuǎn)收不到高電平,達(dá)不到預(yù)期效果。
2).T0定時(shí)器做計(jì)數(shù)器使用,收到一個(gè)負(fù)脈沖產(chǎn)生溢出,啟動(dòng)T1;
3).T0,T1全工作在方式2自動(dòng)裝載計(jì)數(shù)值模式。
然后,上代碼:
工作頻率12Mhz
#include
#include
sbit P1_0 = P3^3;
#define MakeByte(target, Hi,Lo) \
do{ \
target |= (((Hi)《《4)|(Lo)); \
}while(0); \
#define SetTH(n,val) \
do{ \
TH##n = val; \
}while(0); \
#define SetTL(n,val) \
do{ \
TL##n = val; \
}while(0); \
#define EnableET(n) \
do{ \
ET##n = 0x01; \
IE |= 0x80; \
}while(0); \
unsigned int click;
unsigned int oneMs;
unsigned char getPlusWidth;
int main()
{
unsigned int totalus=0,maxPlusWidth=0;
P3 = 0xFF;
getPlusWidth = 0;
MakeByte(TMOD,0x0A,0x06);
SetTH(0,0xff);
SetTL(0,0xff);
SetTH(1,0x38);
SetTL(1,0x38);
EnableET(0);
EnableET(1);
TR0 = 0x01;
while(1)
{
while(!getPlusWidth);
//等待INT1至低
while(INT1==0x01);
//等待INT1至高電平
while(INT1==0x00);
//等待INT1至低電平,脈寬結(jié)束
while(INT1==0x01);
TR1 = 0x00;
totalus = 1000*(oneMs+(click*0.2))+(TL1-TH1);
oneMs = 0;
}
return 0;
}
//T0引腳上接受到負(fù)跳變
void IsrT0() interrupt 1
{
TR1 = 0x00;
getPlusWidth = 1;
TR1 = 0x01;
}
void IsrT1() interrupt 3
{
//每次進(jìn)入中斷0.2ms
click++;
if(click == 5)
{
oneMs++;
click=0;
}
}
最后 上仿真結(jié)果:
500Hz的方波,脈寬981us
1kHz的方波,脈寬587us
2kHz方波,脈寬234us
一種很精確測(cè)量脈沖寬度的方法。
具體思想是:
用定時(shí)器的內(nèi)部資源(當(dāng)GATE = 1時(shí),計(jì)數(shù)器的停止和開始受TR和INT的電平共同控制),我們這里用定時(shí)器0 ,將外部脈沖接在INT0上,配置定時(shí)器0和外部中斷0。當(dāng)脈沖是高電平時(shí),計(jì)數(shù)器(TH0,TL0)計(jì)數(shù),當(dāng)計(jì)數(shù)器溢出時(shí),觸發(fā)定時(shí)器中斷。當(dāng)脈沖為下降沿時(shí),觸發(fā)外部中斷,此時(shí)停止計(jì)數(shù),所記下的時(shí)間也就是脈沖的寬度。
代碼如下:
#include 《reg51.h》
#include 《intrins.h》
#define uint unsigned int
#define uLint unsigned long int //長整型
uLint pulse_w = 0 ;//計(jì)算脈沖的時(shí)間,用長整型可以達(dá)到10的9次方us,如果用uint,最大只能達(dá)到65535us(還不到100ms)
sbit in = P3^2 ;
void Int0 (void) interrupt 0
{
pulse_w += TL0 ;
TL0 = 0 ;
}
void Time0(void) interrupt 1
{
pulse_w += 256 ;//計(jì)數(shù)寄存器溢出,直接加最大值
}
int main()
{
//初始化
TMOD = 0xA ; //定時(shí)器0,模式2,GATE0 = 1
TH0 = 0 ; //填初值
TL0 = 0 ;
TR0 = 0 ;
ET0 = 1 ;//開定時(shí)器0中斷
IT0 = 1 ;//外部中斷0下降沿觸發(fā)中斷
EX0 = 1 ;//開外部中斷0
EA = 1 ;//開總中斷
while(1)
{
if(in == 0)//見下面的解釋
TR0 = 1 ;
}
}
信號(hào)函數(shù):
signal void test(double cc)
{
port3 &= ~(0x1《《2) ;
swatch(1) ;
port3 |= (0x1《《2) ;
swatch(cc) ;
port3 &= ~(0x1《《2) ;
swatch(0.1) ;
_break_ = 1 ;
}
輸入波形(脈沖高電平1s)
查看變量的值(0xF4240 = 1000000)
注釋1:由于單片機(jī)復(fù)位后所有port都為高電平,所以如果不做一些措施的話,單片機(jī)一復(fù)位,計(jì)數(shù)器就會(huì)計(jì)數(shù),造成測(cè)量誤差。我的做法是:開始設(shè)TR0= 0,這樣port3.2就無法開啟計(jì)數(shù)器。當(dāng)外部脈沖低電平時(shí),我才讓TR0 = 1,這時(shí)port3.2才能開啟計(jì)數(shù)器,達(dá)到精準(zhǔn)計(jì)時(shí)的要求
注釋2:單片機(jī)的晶振為12M,所以時(shí)鐘周期為1us
評(píng)論