|
霍爾測速元件清單
1) 9*15萬用板
2) STC89C52單片機
3) 40腳IC座
4) 1602液晶
5) 16p母座
6) 16p排針
7) 10k電阻*3
8) 1k電阻
9) 3v直流電機
10) 3*1萬用板
11) 磁鐵*2
12) 201電位器
13) 3144霍爾傳感器
14) 103排阻
15) 100uf電解電容
16) 10uf電解電容
17) 30pf瓷片電容*2
18) 12M晶振
19) 自鎖開關
20) DC電源插口
21) 導線若干
22) 焊錫若干
23) USB電源線或電池盒
單片機程序源碼:
- #include<reg52.h> //包含頭文件
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int //宏定義
- /*************STC89單片機EEPROM參數定義和聲明********/
- #define RdCommand 0x01 //定義ISP的操作命令
- #define PrgCommand 0x02
- #define EraseCommand 0x03
- #define Error 1
- #define Ok 0
- #define WaitTime 0x01 //定義CPU的等待時間
- sfr ISP_DATA=0xe2;//寄存器申明
- sfr ISP_ADDRH=0xe3;
- sfr ISP_ADDRL=0xe4;
- sfr ISP_CMD=0xe5;
- sfr ISP_TRIG=0xe6;
- sfr ISP_CONTR=0xe7;
- char a_a;
- /********************************************/
- unsigned long temp=0;//報警上限轉速參數定義
- uchar h_w,h_q,h_b,h_s,h_g;//報警上限轉速的參數(萬、千、百、十、個位)
- /**************************************************/
- sbit COUNT_IN=P3^2;//霍爾傳感器信號輸入
- /****************************************************/
- //定義1602液晶相關管腳
- sbit rs=P2^7;
- sbit en=P2^6;
- sbit rw=P2^5;
- uchar menu;//液晶設置界面菜單
- /****************************************************/
- sbit key1=P1^1;//報警轉速參數設置按鍵
- sbit key2=P1^2;//加
- sbit key3=P1^3;//減
- sbit alarm=P1^0;//蜂鳴器報警
- /**************************************************/
- uint count,m,n; //定義計算速度變量
- unsigned long RPM=0; //定義速度變量
- unsigned long TT=0; //定義時間變量
- unsigned long sum=0; //計算平均值的總數
- unsigned char T_num=0; //平均值取值的次數
- unsigned long num=0; //單次轉速
- unsigned int TT1=0; //定義定時器中斷次數變量
- bit flag; //定義位變量,值只能是0或者1
- uchar p,sec;
- /********************************************************/
- //液晶初始化顯示定義
- uchar code tab1[]={"R:"}; //一行顯示的固定字符
- uchar code tab2[]={"r/min"}; //轉速顯示的固定字符
- uchar code tab3[]={"H:"}; //轉速顯示的固定字符
- /**************延時子函數定義************/
- void delay(uint x) //延時函數,大約延時1ms,不精確
- {
- uint i,j; //定義延時函數變量
- for(i=0;i<x;i++) //for循環延時
- for(j=0;j<110;j++);
- }
- void alarming()//蜂鳴器報警子函數
- {
- alarm=0;
- delay(50);
- alarm=1;
- delay(50);
- }
- /******************************STC89單片機 EERPROM函數******************/
- /*************打開 ISP,IAP 功能********************/
- void ISP_IAP_enable(void)
- {
- EA=0; //關中斷
- ISP_CONTR=ISP_CONTR&0x18; // 0001,1000
- ISP_CONTR=ISP_CONTR|WaitTime; //寫入硬件延時
- ISP_CONTR=ISP_CONTR|0x80; //ISPEN=1
- }
- /********************關閉 ISP,IAP 功能 ************/
- void ISP_IAP_disable(void)
- {
- ISP_CONTR=ISP_CONTR&0x7f; //ISPEN = 0
- ISP_TRIG=0x00;
- EA=1; //開中斷
- }
- /************公用的觸發代碼**********************/
- void ISPgoon(void)
- {
- ISP_IAP_enable();//打開 ISP,IAP 功能
- ISP_TRIG=0x46; //觸發ISP_IAP命令字節1
- ISP_TRIG=0xb9; //觸發ISP_IAP命令字節2
- _nop_();
- }
- /****************字節讀 *************************/
- unsigned char byte_read(unsigned int byte_addr)
- {
- EA=0;
- ISP_ADDRH=(unsigned char)(byte_addr>>8);//地址賦值
- ISP_ADDRL=(unsigned char)(byte_addr&0x00ff);
- ISP_CMD=ISP_CMD&0xf8;//清除低3位
- ISP_CMD=ISP_CMD|RdCommand;//寫入讀命令
- ISPgoon();//觸發執行
- ISP_IAP_disable();//關閉ISP,IAP功能
- EA=1;
- return(ISP_DATA);//返回讀到的數據
- }
- /*****************扇區擦除 ************************/
- void SectorErase(unsigned int sector_addr)
- {
- unsigned int iSectorAddr;
- iSectorAddr=(sector_addr&0xfe00); //取扇區地址
- ISP_ADDRH=(unsigned char)(iSectorAddr>>8);
- ISP_ADDRL=0x00;
- ISP_CMD=ISP_CMD&0xf8;//清空低3位
- ISP_CMD=ISP_CMD|EraseCommand; //擦除命令3
- ISPgoon();//觸發執行
- ISP_IAP_disable();//關閉ISP,IAP功能
- }
- /************************字節寫 *************************/
- void byte_write(unsigned int byte_addr, unsigned char original_data)
- {
- EA=0;
- ISP_ADDRH=(unsigned char)(byte_addr>>8);//取地址
- ISP_ADDRL=(unsigned char)(byte_addr & 0x00ff);
- ISP_CMD=ISP_CMD&0xf8;//清低3位
- ISP_CMD=ISP_CMD | PrgCommand;//寫命令2
- ISP_DATA=original_data;//寫入數據準備
- ISPgoon();//觸發執行
- ISP_IAP_disable();//關閉IAP功能
- EA =1;
- }
- /********************內部eeprom寫函數**************/
- void write_eeprom()
- {
- SectorErase(0x2000);//先把扇區清空
- delay(1);
- SectorErase(0x2c00);//先把扇區清空
- delay(1);
- SectorErase(0x2d00);//先把扇區清空
- delay(1);
- /**************寫入參數******************/
- byte_write(0x2d00,h_w);//存萬位
- delay(1);
- byte_write(0x2d01,h_q);//存千位
- delay(1);
- byte_write(0x2d02,h_b);//存百位
- delay(1);
- byte_write(0x2d03,h_s);//存十位
- delay(1);
- byte_write(0x2d04,h_g);//存個位
- delay(1);
-
- byte_write(0x2060,0x01);
- }
- /******************把數據從單片機內部eeprom中讀出來*****************/
- void read_eeprom()
- {
- h_w=byte_read(0x2d00);//萬位讀回來
- delay(1);
- h_q=byte_read(0x2d01);//千位讀回來
- delay(1);
- h_b=byte_read(0x2d02);//百位讀回來
- delay(1);
- h_s=byte_read(0x2d03);//十位讀回來
- delay(1);
- h_g=byte_read(0x2d04);//個位讀回來
- delay(1);
- a_a=byte_read(0x2060);
- }
- /**************開機自檢eeprom初始化*****************/
- void init_eeprom()
- {
- a_a=byte_read(0x2060);
- if(a_a!=1) //新的單片機初始單片機內問eeprom
- {
- a_a=1;
- write_eeprom();//保存數據
- delay(1);
- }
- }
- /********液晶寫入指令函數與寫入數據函數,以后可調用**************/
- void write_1602com(uchar com)//****液晶寫入指令函數****
- {
- rs=0;//數據/指令選擇置為指令
- P0=com;//送入數據
- delay(1);
- en=1;//拉高使能端,為制造有效的下降沿做準備
- delay(1);
- en=0;//en由高變低,產生下降沿,液晶執行命令
- }
- void write_1602dat(uchar dat)//***液晶寫入數據函數****
- {
- rs=1;//數據/指令選擇置為數據
- P0=dat;//送入數據
- delay(1);
- en=1; //en置高電平,為制造下降沿做準備
- delay(1);
- en=0; //en由高變低,產生下降沿,液晶執行命令
- }
- void lcd_init()//***液晶初始化函數****
- {
- uchar a;
- rw=0;
- write_1602com(0x38);//設置液晶工作模式,意思:16*2行顯示,5*7點陣,8位數據
- write_1602com(0x0c);//開顯示不顯示光標
- write_1602com(0x06);//整屏不移動,光標自動右移
- write_1602com(0x01);//清顯示
- write_1602com(0x80);//顯示固定符號從第一行第1個位置之后開始顯示
- for(a=0;a<2;a++)
- {
- write_1602dat(tab1[a]);//向液晶屏寫固定符號部分
- }
- write_1602com(0x80+8);//顯示固定符號寫入位置,從第2個位置后開始顯示
- for(a=0;a<5;a++)
- {
- write_1602dat(tab2[a]);//寫顯示固定符號
- }
- write_1602com(0x80+0x40);//顯示固定符號寫入位置,從第2個位置后開始顯示
- for(a=0;a<2;a++)
- {
- write_1602dat(tab3[a]);//寫顯示固定符號
- }
- }
- void display() //顯示函數
- {
- if(RPM<=99999) //范圍內時
- {
- uchar gw,sw,bw,qw,ww;//定義拆字變量
- ww=RPM/10000; //轉速/10000得到萬位
- qw=RPM%10000/1000; //轉速/10000的余數/1000得到千位
- bw=RPM%1000/100;//取得百位
- sw=RPM%100/10;//取得十位數字
- gw=RPM%10;//取得個位數字
- write_1602com(0x80+2); //選中第二行第二位
- if(ww==0) //萬位為0時
- {
- write_1602dat(' '); //顯示空格
- }
- else //萬位不為0時
- {
- write_1602dat(0x30+ww); //顯示萬位的數據 +0x30是因為在液晶的字庫中,0的地址是0x30,1的地址是0x31,以此類推
- }
- if((ww+qw)==0) //萬位和千位都為0時
- {
- write_1602dat(' '); //千位顯示空格
- }
- else //萬位和千位不都為0時
- {
- write_1602dat(0x30+qw); //顯示千位數據
- }
- if((ww+qw+bw)==0) //萬位、千位和百位都是0時
- {
- write_1602dat(' '); //顯示空格
- }
- else //萬位、千位和百位不都為0時
- {
- write_1602dat(0x30+bw); //顯示百位數據
- }
- if((ww+qw+bw+sw)==0) //萬位、千位、百位和十位都為0時
- {
- write_1602dat(' '); //顯示空格
- }
- else //萬位、千位、百位和十位不都為0時
- {
- write_1602dat(0x30+sw); //顯示十位數據
- }
- write_1602dat(0x30+gw); //顯示個位數據 數字+0x30得到該數字的LCD1602顯示碼
- }
- else //超過范圍時顯示-----
- {
- write_1602com(0x80+2); //選中第二行第二列
- write_1602dat('-'); //顯示‘-’
- write_1602dat('-'); //顯示‘-’
- write_1602dat('-'); //顯示‘-’
- write_1602dat('-'); //顯示‘-’
- write_1602dat('-'); //顯示‘-’
- }
- }
- /*********************報警轉速參數轉換函數************************/
- void conversion(unsigned long temp1)//數據轉換出 個,十,百,千,萬
- {
- h_w=temp1/10000;
- h_q=temp1%10000/1000;
- h_b=temp1%1000/100;
- h_s=temp1%100/10;
- h_g=temp1%10;
- }
- void key_shezhi()
- {
- if(key1==0)
- {
- delay(10);//延時消抖
- if(key1==0)
- {
- menu++;//切換液晶顯示界面菜單
- if(menu>1)
- {
- menu=0;
- lcd_init();
- delay(5);
- }
- }
- while(!key1);
- }
- if(menu==0)
- {
- if(temp<RPM)//實際轉速大于設置的上限,產生報警
- {
- alarming();//報警
- }
- else
- {
- alarm=1;
- }
- display();//返回初始化顯示,顯示當前的實時轉速
- write_1602com(0x80+0x40+2);//刷新顯示設置的報警參數
- write_1602dat(0x30+temp/10000);
- write_1602dat(0x30+temp%10000/1000);
- write_1602dat(0x30+temp%1000/100);
- write_1602dat(0x30+temp%100/10);
- write_1602dat(0x30+temp%10);
- temp=h_w*10000+h_q*1000+h_b*100+h_s*10+h_g;
- }
- if(menu==1)
- {
- if(key2==0)
- {
- delay(10);
- if(key2==0)
- {
- temp++;//參數加
- if(temp>29999)//最大值29999
- {
- temp=29999;
- }
- conversion(temp);//萬、千、百、十、個位轉換
- write_eeprom();//參數保存到EEPROM
- }
- }
- if(key3==0)//通過減按鍵
- {
- delay(10);
- if(key3==0)
- {
- if(temp>0)
- {
- temp--;//參數減
- }
- conversion(temp);//萬、千、百、十、個位轉換
- write_eeprom();//參數保存到EEPROM
- }
- }
- //conversion(temp);//萬、千、百、十、個位轉換
- //write_eeprom();//參數保存到EEPROM
- delay(30);//延時
- write_1602com(0x80+0x40+2);//在液晶上刷新參數顯示
- write_1602dat(0x30+temp/10000);
- write_1602dat(0x30+temp%10000/1000);
- write_1602dat(0x30+temp%1000/100);
- write_1602dat(0x30+temp%100/10);
- write_1602dat(0x30+temp%10);
- /*************************************************/
- write_1602com(0x80+0x40+6);//將光標移動到上限參數的個位
- write_1602com(0x0e);
- }
- }
- void init() //系統初始化設置
- {
- IT0=1; //INT0負跳變觸發
- TMOD=0x11;//定時器工作于方式1
- TH0=0;
- TL0=0;
- EA=1; //CPU開中斷總允許
- ET0=1;
- EX0=1;//開外部INTO中斷
- TR0=0;//啟動定時
- TH1=0x3c;
- TL1=0xb0;
- ET1=1;
- TR1=1;
- }
- /*****************主函數*************************************/
- void main()
- {
- init(); //調用初始化函數
- lcd_init();//液晶初始化
- delay(5);
- init_eeprom();//初始化eeprom
- delay(10);
- read_eeprom();//讀取eeprom數據
- delay(10);
- while(1) //進入while循環
- {
- key_shezhi();
- }
- }
- void EXINT0() interrupt 0 //外部中斷函數,霍爾元件有信號,會進入此中斷
- {
- if(TR0==0) //霍爾有信號輸入時,定時器沒有打開就打開定時器,準備計時
- {
- TH0=0;
- TL0=0; //定時器清零
- TT=0; //計時變量清零
- TT1=0; //定時器中斷次數清零
- TR0=1; //打開定時器,開始計時
- p=0;
- sec=0;
- }
- else //第二次檢測到信號時
- {
- p=0;
- sec=0;
- TR0=0; //關閉定時器
- TT=TT1*65536+TH0*256+TL0; //計算兩次信號的時間差。中斷次數*65536+TH0*256+TL0,得到時間差
- TH0=0;
- TL0=0; //計算完成后,將定時器清零
- num=60000000/TT; //根據時間計算1min中的速度。一分鐘是60秒,一秒是1000毫秒,1毫秒是1000us,所以是60*1000*1000/時間,TT的單位是單片機的最快速度1微秒
- TT1=0; //計算完速度后,TT1清零
- if(num>1000) //轉速超過1000時,取50次的平均值
- {
- sum=num+sum; //將數據加一起
- T_num++; //次數加
- if(T_num>=50) //加到50次
- {
- T_num=0; //次數清零
- RPM=sum/50; //總數除以50得到平均值
- sum=0; //計算完后總數清零
- }
- }
- else //轉速小于1000時
- {
- sum=0; //總數清零
- RPM=num; //數據直接賦值給轉速
- num=0; //數據清零
- T_num=0; //次數清零
- }
- }
- }
- void timeT0() interrupt 1 //兩次信號中間,定時器有中斷
- {
- TT1++; //說明達到一次65536,將TT1加1,計算時,將TT1乘以65536就是這個的時間了
- TH0=0;
- TL0=0; //定時器清零
- }
- void timeT1() interrupt 3 //兩次信號中間,定時器有中斷
- {
- TH1=0x3c;
- TL1=0xb0; //定時器清零
- p++;
- if(p>=20)
- {
- p=0;
- sec++;
- if(sec>=5)
- {
- sec=0;
- RPM=0;
- TR0=0;
- }
- }
- }
復制代碼
|
-
-
元件清單.doc
2019-1-19 11:28 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
27.5 KB, 下載次數: 9, 下載積分: 黑幣 -5
|