51單片機輕松入門—基于STC15W4K系列(C語言版)
李友全 編著 詳見:http://www.zg4o1577.cn/bbs/dpj-37954-1.html
第16章 頻率檢測 1 頻率檢測的用途與頻率定義 2 頻率檢測實例 1 頻率檢測的用途與頻率定義
0.png (293.61 KB, 下載次數: 136)
下載附件
2016-3-28 22:40 上傳
實際工程中有時需要使用單片機檢測脈沖信號頻率,比如家用恒溫型熱水器內部 的水流量傳感器輸出的是12V的矩形脈沖信號,工業運用中的液體流量計輸出的 往往也是5~24V的脈沖信號,我們要知道當前液體的瞬時流量就需要測量流量計 輸出的脈沖信號頻率,然后通過頻率換算公式得到當前流量值,脈沖信號可能存 在如下圖所示的2種波形,一個波形周期固定不變,另一個波形周期是變動的。
1.png (92.58 KB, 下載次數: 126)
下載附件
2016-3-28 22:40 上傳
頻率定義:物質在1秒鐘內完成周期性變化的次數叫做頻率,常用f表示,比如 正弦交流電,其頻率是50Hz,也就是它在一秒鐘內做了50次周期性變化。 假設上圖波形總時間為1秒,則上下2個波形頻率都是6Hz,對于實際的檢測儀表,只要測量出1秒鐘內的脈沖個數也就知道頻率了,對上面2個波形測量結果 也都會是一致的(6Hz)。 例16.1 程序功能:把P3.4 、P3.5在精確1秒鐘內輸入的脈沖個數值測量出來并 通過串口發送給計算機。 電路如下圖所示,由1號單片機輸出脈沖信號,2號單片機 P3.4 、P3.5用著頻率 檢測輸入口。
2.png (142.51 KB, 下載次數: 119)
下載附件
2016-3-28 22:40 上傳
說明:由于要求同時測量2路脈沖信號頻率,使用T0(P3.4)與T1(P3.5)作 為外部計數脈沖輸入口,T2作串口波特率發生器,1S定時器可以使用T3、 T4,也可使用PCA模塊定時,使用頻率為22.1184MHz的外部晶振(重點),串口 通信波特率9600,可精確測量外部信號的最高頻率的理論值為22.1184MHz/4 = 5.5926 MHz,實驗結果:輸入6.021MHz時測量結果仍然是精確的,下限測 量到幾Hz依然是準確的,只是不能顯示小數部分而已。 程序要點分析: (1)T0與T1是16位計數器,最大計數值為65535,我們需要測量1000000Hz以 上的頻率信號,因此需要將計數器擴展為24位,可定義一個unsigned char 變量作為軟件計數器, 當16位計數器溢出一次就讓軟件計數器加1,因此最 大測量范圍是65536*255=16711680,即16.7MHz。 (2)PCA定時器定時時間設置為5ms產生一次中斷,200次中斷即為1秒, 1秒 時間到達時讀取計數器T0與T1的值和軟件計數器的值。
由于1號單片機的輸出信號串聯了240Ω電阻,在信號頻率很高時接入萬用表會對 信號波形產生影響,因此需要直接測量1號單片機信號輸出引腳相連的測試點, 另外2號單片機晶振一定得選用外部晶振。實測結果如圖16-2所示(圖中只給一 個輸入通道輸入了頻率信號)。
3.png (295.9 KB, 下載次數: 122)
下載附件
2016-3-28 22:40 上傳
1—1號單片機脈沖信號輸出程序:
- /****************《51單片機輕松入門-基于STC15W4K系列》配套例程 *************
- ★★★★★★★★★★★★★★★★★★★★★★★★
- 《51單片機輕松入門-基于STC15W4K系列》 一書已經由北航出版社正式出版發行。
- 作者親手創作的與教材配套的51雙核實驗板(2個MCU)對程序下載、調試、仿真方便,不需要外部
- 仿真器與編程器,這種設計方式徹底解決了系統中多個最高優先級誰也不能讓誰的中斷競爭問題。
- QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。
- 驗證信息:STC15單片機
- 郵箱:xgliyouquan@126.com
- ★★★★★★★★★★★★★★★★★★★★★★★★*/
- // 晶振頻率使用22.1184M
- #include "STC15W4K.H"
- void CLOCK_Init()
- {
- //***************** 設置主時鐘輸出,不分頻 *****************
- CLK_DIV = 0xc0; // 主時鐘輸出頻率= Fosc /4,R/C時鐘頻率要求不大于12MHz。
- }
- void delay2ms(void)
- {
- unsigned char i,j,k;
- for(i=2;i>0;i--) //注意后面沒分號
- for(j=30;j>0;j--) //注意后面沒分號
- for(k=180;k>0;k--); //注意后面有分號
- }
- void main()
- {
- CLOCK_Init(); // 時鐘輸出初始化,需要輸出高頻信號時使用本行代碼。
- while(1);
- // while(1) // 單通道低頻輸出時使用
- // {
- // P54=!P54;
- // delay2ms();
- // }
- }
-
復制代碼
1—2號單片機秒計數方式檢測頻率程序:
- /****************《51單片機輕松入門-基于STC15W4K系列》配套例程 *************
- ★★★★★★★★★★★★★★★★★★★★★★★★
- 《51單片機輕松入門-基于STC15W4K系列》 一書已經由北航出版社正式出版發行。
- 作者親手創作的與教材配套的51雙核實驗板(2個MCU)對程序下載、調試、仿真方便,不需要外部
- 仿真器與編程器,這種設計方式徹底解決了系統中多個最高優先級誰也不能讓誰的中斷競爭問題。
- QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。
- 驗證信息:STC15單片機
- 郵箱:xgliyouquan@126.com
- ★★★★★★★★★★★★★★★★★★★★★★★★*/
- // 晶振頻率為22.1184MHz外部晶振,串口通信波特率9600
- #include "STC15F2K60S2.H"
- #include <stdio.h> // 為使用KEIL自帶的庫函數printf而加入
- bit flag; // 需要通過串口向電腦發送數據的標志
- sbit LED_1s=P0^0; // 調試指示燈
- sbit LED_T0_Over=P0^1; // 調試指示燈
- sbit LED_T1_Over=P0^2; // 調試指示燈
- unsigned char Read_TH0,Read_TL0; // 讀取的定時器T0的高低位計數值
- unsigned char Read_TH1,Read_TL1; // 讀取的定時器T1的高低位計數值
- unsigned char HT0,HT1; // 超過16位的計數值,最大256*65536=16.777 216 MHz
- unsigned char Read_HT0,Read_HT1; // 讀取的超過16位的計數值,
- unsigned char Count=200; // 中斷計數變量(1S計時用),200*5mS = 1S
- void Uart_Init(void) // 9600bps@22.1184MHz
- {
- SCON = 0x50; // 8位數據,可變波特率
- AUXR |= 0x04; // 定時器2時鐘為Fosc,即1T
- T2L = 0xC0; // 設定定時初值
- T2H = 0xFD; // 設定定時初值
- AUXR |= 0x01; // 串口1選擇定時器2為波特率發生器
- AUXR |= 0x10; // 啟動定時器2
- TI=1;
- }
- void JiShuQ_Init() // 計數器初始化,T0和T1共2路計數脈沖輸入
- {
- TMOD=0x55; // 設置T1、T0工作于計數方式,16位計數
- HT0=0;TH0=0;TL0=0;HT1=0;TH1=0;TL1=0; // 清空計數器
- TR0=1;TR1=1; //開啟計數器0 /計數器1
- ET0=1;ET1=1; // 開啟計數器0與1的中斷
- }
- void DingSQ_Iint_5mS() // PCA定時器初始化為5mS中斷
- {
- CMOD=0x80; // #10000000B 空閑模式下停止PCA計數器工作
- // 選擇PCA時鐘源為fOSC/12,禁止PCA計數器溢出時中斷
- CCON=0; // 清0 PCA計數器溢出中斷請求標志位CF
- // CR = 0, 不允許 PCA 計數器計數;清0 PCA 各模塊中斷請求標志位CCFn
- CL=0; // 清0 PCA 計數器
- CH=0;
- CCAP0L=0; // 給PCA模塊0的CCAP0L置初值
- CCAP0H=0x24; // 給PCA模塊0的CCAP0H 置初值
- CCAPM0=0x49; // 設置PCA模塊0為16位軟件定時器
- // ECCF0=1允許PCA模塊0中斷
- // 當[CH,CL]=[CCAP0H,CCAP0L]時,CCF0=1,產生中斷請求
- EA=1; // 開整個單片機所有中斷共享的總中斷控制位
- CR=1; // 啟動PCA計數器(CH,CL)計數
- }
- void PCA(void) interrupt 7 // PCA中斷服務程序,每5ms中斷一次
- {
- union
- { // 定義一個聯合,以進行16位加法
- unsigned int num;
- struct
- { // 在聯合中定義一個結構
- unsigned char Hi,Lo;
- }Result;
- }temp;
-
- temp.num=(unsigned int)(CCAP0H<<8)+CCAP0L+0x2400; //0X1200=0.500112S, 0X11FF=0.500003S,
- CCAP0L=temp.Result.Lo; // 取計算結果的低8位
- CCAP0H=temp.Result.Hi; // 取計算結果的高8位
- CCF0=0; // 清 PCA 模塊0 中斷標志
- Count--; // 修改中斷計數
- if(Count==0)
- {
- Count=200; // 恢復中斷計數初值 200*5mS = 1S
- LED_1s =!LED_1s; // 在P0.0輸出脈沖寬度為1秒鐘的方波(周期2S)
- TR0=0;TR1=0; // 關閉計數器0與1 ,防止讀數錯誤
- CR=0; // 關閉16位PCA計數器(CH,CL)
-
- Read_HT0=HT0;Read_TH0=TH0;Read_TL0=TL0; // 讀取計數值
- Read_HT1=HT1;Read_TH1=TH1;Read_TL1=TL1; // 讀取計數值
- HT0=0;TH0=0;TL0=0; // 清空計數器
- HT1=0;TH1=0;TL1=0;
- TR0=1;TR1=1; // 開啟計數器0與1 ,防止讀數錯誤
- CR=1; // 開啟16位PCA計數器(CH,CL)
- flag=1; // 需要主程序處理數據
- }
- }
- void Timer0(void) interrupt 1 // 定時器T0 中斷函數
- {
- HT0++; // 超過16位計數值變量一次變量加1
- LED_T0_Over=!LED_T0_Over;
- }
- void Timer1(void) interrupt 3 // 定時器T1 中斷函數
- {
- HT1++; // 超過16位計數值變量一次變量加1
- LED_T1_Over=!LED_T1_Over;
- }
- void SendBuf()
- {
- unsigned long tmp;
- tmp= Read_HT0*65536+Read_TH0*256+Read_TL0;
- printf("F1: %ldHz ",tmp);
- tmp= Read_HT1*65536+Read_TH1*256+Read_TL1;
- printf("F2: %ldHz\n",tmp);
- }
- void main()
- {
- Uart_Init(); // 串口初始化
- JiShuQ_Init(); // 計數器初始化
- DingSQ_Iint_5mS(); // PCA定時器5mS初始化
- while(1)
- {
- if (flag==1) // 需要通過串口向電腦發送數據的標志
- {
- SendBuf();
- flag=0;
- }
- }
- }
-
復制代碼
|