大家好,我是遠方,這一章我們來學習下STC8G1K12的比較器。
STC8G 系列單片機內部集成了一個比較器。比較器的正極 P3.7 端口或者 ADC 的模擬輸入通道。負極 P3.6 端口或者是內部 BandGap 經過 OP 後的 REFV 電壓。
比較器內部有可程序控制的兩級濾波:模擬濾波和數字濾波。
比較的結果軟件設置可以有P3.4或P4.1口輸出。
由上面的結構圖可以看出,PIS位選擇正極輸入。NIS位選擇負極輸入。經過濾波輸出。CMPRES位是比較器的比較結果。CMPOE位控制是否輸出比較結果。
我們開始配置寄存器。比較器的寄存器也是比較少的。只有二個寄存器。
CMPCR1 比較器控制寄存器 1 :
CMPEN位是比較器模塊使能位 0關閉比較功能 1使能比較功能 我們寫1,使能比較功能。
CMPIF位是比較器中斷標誌位。如果用中斷做。發生中斷,必須軟件清零。我們今天用查詢做,不管這位。
PIE位是比較器上升沿中斷使能位。我們寫0,禁止中斷。
NIE位是比較器下降沿中斷使能位。我們寫0,禁止中斷。
PIS位是比較器的正極選擇位 ,我們寫0,選擇外部端口 P3.7 為比較器正極輸入源。
NIS:比較器的負極選擇位 ,我們寫0,選擇內部 BandGap 的 REFV 1.344V。
CMPOE位是比較器結果輸出控制位 ,我們寫0,禁止輸出。
CMPRES:比較器的比較結果。我們到時候讀取這一位就能得到比較結果。
CMPCR1 = 0x80;
CMPCR2 比較器控制寄存器2 :
INVCMPO位是比較器結果輸出控制 ,前面我已經把輸出禁止了。這裡寫0寫1都無所謂。
DISFLT位是模擬濾波功能控制 ,我們寫0,使能 0.1us 模擬濾波功能 。
LCDTY[5:0]位是數字濾波功能控制 ,數字濾波功能即為數字信號去抖動功能。這個就跟按鍵消抖一個原理,濾出尖峰脈衝,這個根據實際輸入的信號設置。總共6位,0-63, 0 時表示關閉數字濾波功能。 我們這裡設置 10 個去抖時鐘後輸出 。
CMPCR2 = 0x0A;
比較器的相關配置已經講完了。我們開始寫代碼。今天我們實現的功能是用查詢模式。通過讀取比較器的比較結果CMPRES位。通過串口把結果發送到電腦端查看。我們依舊把串口那章的程序複製過來,在這個基礎上改,重複的工作我們就不做了。
全部工程代碼如下:
#include "STC8.H"
sbit LED = P1^1;
void Delay1ms(void)//@11.0592MHz 1mS
{
unsigned char i, j;
i = 15;
j = 90;
do
{
while (--j);
} while (--i);
}
void DelayNms(unsigned int Cnt)
{
while (Cnt > 0)
{
Cnt -- ;
Delay1ms();
}
}
/*----------------------------
發送串口數據
----------------------------*/
void uart1_SendData(unsigned char dat)
{
SBUF = dat;
while (TI == 0);
TI = 0;
}
/*----------------------------
發送字符串
----------------------------*/
void uart1_SendDataFrame(unsigned char *pDat)
{
while ((*pDat) != '\\0')
{
uart1_SendData(*pDat++);
}
}
void UartIsr() interrupt 4
{
unsigned char data l_RevDat = 0;
if (RI)
{
RI = 0; //清除RI位
l_RevDat = SBUF;
}
}
void cmp_Init(void) //比較器初始化
{
CMPCR2 = 0x0A;
CMPCR1 = 0x80;
}
void main(void)
{
unsigned int data ReadAdcVal = 0;
//使用內部時鐘 燒錄軟件會幫我們配置好 如不懂 參考前面第3章系統設置學習。
// 燒錄軟件設置11.0592MHz為系統時鐘。以後我們的學習都是這個時鐘頻率。
P_SW2 |= (1<<7);
CKSEL = 0x00; //選擇內部 IRC ( 默認 )
P_SW2 &= ~(1<<7);
//配置端口 對於控制我們系統板的LED,配置準雙向口和推輓輸出都可以。
//只要是做為輸出,我建議全部設置為推輓輸出。
/*
PnM1.x PnM0.x Pn.x 口工作模式
0 0 準雙向口
0 1 推輓輸出
1 0 高阻輸入
1 1 開漏輸出
*/
P1M1 &= ~(1<<1); P1M0 |= (1<<1); //設置為推輓輸出
P_SW2 |= (1<<7);
P1PU = 0x00;//禁止P1端口內部的 3.7K 上拉電阻
P1NCS = 0xFF; //禁止P1端口的施密特觸發功能。
P_SW2 &= ~(1<<7);
cmp_Init();//比較器初始化
/*串口1相關配置*/
P_SW1 &= ~(1 << 6);P_SW1 &= ~(1 << 7); //串口 1 功能腳選擇位
SCON = 0x50; //模式1 可變波特率8位數據方式
PCON &= 0x3F; //串口 1 的各個模式的波特率都不加倍 無幀錯檢測功能
AUXR |= (1 << 0); //選擇定時器 2 作為波特率發射器
AUXR &= ~(1 << 4);//定時器 2 停止計數,配置完再打開。
AUXR &= ~(1 << 3);//清0則用作定時器
AUXR &= ~(1 << 2);//12T 模式,即 CPU 時鐘 12 分頻( FOSC/12)
T2L = 0xE8; //12T 模式 9600
T2H = 0xFF;
IP |= (1<<4);//優先級控制
IPH |= (1<<4);
AUXR |= (1 << 4); //啟動定時器 2
ES = 1; //使能串口1中斷
EA = 1;//總中斷打開
LED = 1;//LED滅
while (1)
{
if (CMPCR1 & 0x01) uart1_SendDataFrame("CMP+的電平高於CMP-的電平");
else uart1_SendDataFrame("CMP+的電平低於CMP-的電平");
uart1_SendDataFrame("\\r\\n");
DelayNms(1000);
}
}
我們把程序編譯好,燒錄到板子裡面。連接好USB轉串口線,打開串口,波特率選擇9600。
用杜邦線把P3.7口接到GND。(GND < 1.344V) 返回結果 “CMP+的電平低於CMP-的電平”
用杜邦線把P3.7口接到VCC。(VCC > 1.344V)返回結果 “CMP+的電平高於CMP-的電平”
實踐證明我們的程序沒有問題,達到預期效果。
好了比較器這章就講到這裡。希望大家多多關注我的原創文章。謝謝。
閱讀更多 電子機械說 的文章