|
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
1.png (118.68 KB, 下載次數(shù): 47)
下載附件
2022-3-26 04:04 上傳
51hei.png (22.49 KB, 下載次數(shù): 46)
下載附件
2022-3-26 06:35 上傳
2.png (92.22 KB, 下載次數(shù): 38)
下載附件
2022-3-26 04:21 上傳
單片機(jī)源程序如下:
- #include <intrins.h> //引用程序目錄的相對(duì)路徑中的頭文件
- #include <reg52.h> //引用編譯器的類庫(kù)路徑里面的頭文件
- #define LCD P2 //LCD2004數(shù)據(jù)接口
- sbit RS=P1^2; //設(shè)置RS引腳接口,RS=0,指令寄存器;RS=1,數(shù)據(jù)寄存器
- sbit RW=P1^1; //設(shè)置R/W引腳接口,R/W=0,寫(xiě);R/W=1,讀
- sbit E=P1^0; //設(shè)置E引腳接口,E允許信號(hào)
- unsigned char RPM_R[]="000"; //右電機(jī)轉(zhuǎn)速,H整型轉(zhuǎn)換為字符型,定義數(shù)組長(zhǎng)度。
- unsigned char RPM_L[]="000"; //左電機(jī)轉(zhuǎn)速,H整型轉(zhuǎn)換為字符型,定義數(shù)組長(zhǎng)度。
- unsigned char V_R[]="000"; //右電機(jī)時(shí)速,H整型轉(zhuǎn)換為字符型,定義數(shù)組長(zhǎng)度。
- unsigned char V_L[]="000"; //左電機(jī)時(shí)速,H整型轉(zhuǎn)換為字符型,定義數(shù)組長(zhǎng)度。
- unsigned int rpm_r=0; //初始化右電機(jī)轉(zhuǎn)速
- unsigned int rpm_l=0; //初始化左電機(jī)轉(zhuǎn)速
- unsigned int v_r=0; //初始化右電機(jī)時(shí)速
- unsigned int v_l=0; //初始化左電機(jī)時(shí)速
- unsigned int D=770; //直徑
- unsigned char cnt=0; //中斷次數(shù)倍數(shù),50ms為單位,若20倍,組成1秒
- unsigned char flag=0; //時(shí)鐘標(biāo)志位
- /******************************
- LCD忙檢測(cè)函數(shù)子程序
- ******************************/
- void CheckBusy(void)
- {
- unsigned int nTimeOut=0;
- RS=0;
- RW=1;
- E=0;
- E=1;
- while((LCD&0x80)&&(++nTimeOut !=0));
- E=0;
- RS=0;
- RW=1;
- }
-
- /******************************
- LCD發(fā)送命令或數(shù)據(jù)子程序
- ******************************/
- void SendCmdorData(unsigned char byCmdorData,bit DI)
- {
- CheckBusy();
- RS=DI; //為寄存器選擇腳,高電平時(shí)選擇數(shù)據(jù)寄存器、低電平時(shí)選擇指令寄存器
- RW=0; //為讀、寫(xiě)信號(hào)線,低電平時(shí)進(jìn)行寫(xiě)操作
- E=0; //E端為使能端,當(dāng)E端由高電平跳變?yōu)榈碗娖綍r(shí),液晶模塊執(zhí)行命令
- LCD=byCmdorData; //送數(shù)據(jù)
- _nop_(); //空操作,給硬件反應(yīng)時(shí)間
- _nop_(); //空操作,給硬件反應(yīng)時(shí)間
- E=1;
- _nop_(); //空操作,給硬件反應(yīng)時(shí)間
- _nop_(); //空操作,給硬件反應(yīng)時(shí)間
- E=0; //E引腳要有一個(gè)下降沿,才能把數(shù)據(jù)線上數(shù)據(jù),命令送入1602
- RW=1; //為讀、寫(xiě)信號(hào)線,高電平時(shí)進(jìn)行讀操作
- RS=0; //為寄存器選擇腳,低電平時(shí)選擇指令寄存器
- }
- /******************************
- 延時(shí)1毫秒
- ******************************/
- void Delay(unsigned int nDelay)
- {
- unsigned int i;
- for(;nDelay>0;nDelay--)
- {
- for(i=124;i>0;i--);
- }
- }
- /******************************
- LCD初始化子程序
- ******************************/
- void Init(void)
- {
- SendCmdorData(0x38,0); //寫(xiě)命令,設(shè)置16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口
- Delay(50); //50ms延時(shí),給硬件反應(yīng)時(shí)間
- SendCmdorData(0x01,0); //寫(xiě)命令,顯示清屏:1、數(shù)據(jù)指針清零 2、所有顯示清零
- Delay(50); //50ms延時(shí),給硬件反應(yīng)時(shí)間
- SendCmdorData(0x06,0); //寫(xiě)命令,當(dāng)讀或?qū)懸粋(gè)字符后地址指針加一,且光標(biāo)加一
- Delay(50); //50ms延時(shí),給硬件反應(yīng)時(shí)間
- SendCmdorData(0x0c,0); //寫(xiě)命令,開(kāi)顯示、不顯示光標(biāo)、光標(biāo)不顯示
- Delay(50); //50ms延時(shí),給硬件反應(yīng)時(shí)間
- }
- /******************************
- 地址轉(zhuǎn)換子程序
- x為行號(hào) y為列號(hào)
- ******************************/
- void SetAddress(unsigned char x,y)
- {
- unsigned char byAddress;
- switch(x)
- {
- case 1:byAddress=0x80+y;break; //第一行首地址
- case 2:byAddress=0xC0+y;break; //第二行首地址
- case 3:byAddress=0x94+y;break; //第三行首地址
- case 4:byAddress=0xD4+y;break; //第四行首地址
- default:break; //default就是如果沒(méi)有符合的case就執(zhí)行它,default并不是必須的.
- }
- SendCmdorData(byAddress,0); //執(zhí)行發(fā)送指令子程序
- }
- /******************************
- 發(fā)送字符串到LCD子程序
- ******************************/
- void PutString(unsigned char x,y,unsigned char *pData)
- {
- SetAddress(x,y); //執(zhí)行地址轉(zhuǎn)換子程序
- while(*pData !='\0') //表示顯示內(nèi)容不為空時(shí),執(zhí)行循環(huán)體的代碼段,
- {
- SendCmdorData(*pData++,1); //發(fā)送命令子程序,*就是聲明他的類型,是一個(gè)指向整型數(shù)據(jù)的指針
- }
- }
- /******************************
- 4位數(shù)的H整型轉(zhuǎn)換為字符型, 加48為轉(zhuǎn)ASCII。
- *就是聲明他的類型,是一個(gè)指向整型數(shù)據(jù)的指針
- ******************************/
- void Inttochar4(unsigned int a,unsigned char *chx)
- {
- chx[0]=a/1000+48; //高電平千位
- chx[1]=(a/100)%10+48; //高電平百位
- chx[2]=(a/10)%10+48; //高電平十位
- chx[3]=a%10+48; //高電平個(gè)位
- }
- /******************************
- 3位數(shù)的H整型轉(zhuǎn)換為字符型,加48為轉(zhuǎn)ASCII。
- *就是聲明他的類型,是一個(gè)指向整型數(shù)據(jù)的指針
- ******************************/
- void Inttochar3(unsigned int a,unsigned char *chx)
- {
- chx[0]=a/100+48; //百分?jǐn)?shù)百位
- chx[1]=(a/10)%10+48; //百分?jǐn)?shù)十位
- chx[2]=a%10+48; //百分?jǐn)?shù)個(gè)位
- }
- /******************************
- LCD數(shù)據(jù)顯示子程序
- ******************************/
- void Display(void)
- {
- Inttochar3(rpm_r,(unsigned char *)RPM_R); //右電機(jī)轉(zhuǎn)速,H整型轉(zhuǎn)換為字符型。*就是聲明他的類型,是一個(gè)指向整型數(shù)據(jù)的指針
- Inttochar3(rpm_l,(unsigned char *)RPM_L); //左電機(jī)轉(zhuǎn)速,H整型轉(zhuǎn)換為字符型。*就是聲明他的類型,是一個(gè)指向整型數(shù)據(jù)的指針
- Inttochar3(v_r,(unsigned char *)V_R); //右電機(jī)速度,H整型轉(zhuǎn)換為字符型。*就是聲明他的類型,是一個(gè)指向整型數(shù)據(jù)的指針
- Inttochar3(v_l,(unsigned char *)V_L); //左電機(jī)速度,H整型轉(zhuǎn)換為字符型。*就是聲明他的類型,是一個(gè)指向整型數(shù)據(jù)的指針
- PutString(1,4,"R:"); //字體,2字節(jié)
- PutString(1,7,RPM_R); //RPM_R為右電機(jī)轉(zhuǎn)速的ASCII數(shù)組,3字節(jié)
- PutString(1,11,"r/min"); //字體,5字節(jié)
- PutString(2,4,"L:"); //字體,2字節(jié)
- PutString(2,7,RPM_L); //RPM_L為左電機(jī)轉(zhuǎn)速的ASCII數(shù)組,3字節(jié)
- PutString(2,11,"r/min"); //字體,5字節(jié)
- PutString(3,4,"R:"); //字體,2字節(jié)
- PutString(3,7,V_R); //V_R為右電機(jī)速度的ASCII數(shù)組,3字節(jié)
- PutString(3,11,"km/h"); //字體,4字節(jié)
- PutString(4,4,"L:"); //字體,2字節(jié)
- PutString(4,7,V_L); //V_L為左電機(jī)速度的ASCII數(shù)組,3字節(jié)
- PutString(4,11,"km/h"); //字體,4字節(jié)
- }
- /******************************
- 單片機(jī)初始化
- ******************************/
- void Initial()
- {
- TMOD=0x55; //定時(shí)器T0、T1工作于計(jì)數(shù)器模式1;解釋:C/T=1時(shí)為計(jì)數(shù)功能:加1計(jì)數(shù)器對(duì)來(lái)自輸入引腳T0(P3.4)和T1(P3.5)的外信號(hào)脈沖進(jìn)行計(jì)數(shù);M1=0、M0=1,方式1:16位定時(shí)器/計(jì)數(shù)器
- RCAP2H=(65536-50000)/256; //定時(shí)/計(jì)數(shù)器2陷阱寄存器高字節(jié),50000次溢出一次產(chǎn)生中斷
- RCAP2L=(65536-50000)%256; //定時(shí)/計(jì)數(shù)器2陷阱寄存器低字節(jié),50ms中斷
- ET2=1; //打開(kāi)定時(shí)器中斷
- TR2=1; //打開(kāi)定時(shí)器開(kāi)關(guān)
- EA=1; //打開(kāi)總中斷
- TR0=1; //打開(kāi)定時(shí)器開(kāi)關(guān)
- TR1=1; //打開(kāi)定時(shí)器開(kāi)關(guān)
- }
- /******************************
- 主程序
- ******************************/
- void main()
- {
- Init(); //LCD初始化子程序
- Initial(); //單片機(jī)初始化
- while(1)
- {
- TH0=0; //定時(shí)器T0高八位的初值
- TL0=0; //定時(shí)器T0低八位的初值
- TH1=0; //定時(shí)器T1高八位的初值
- TL1=0; //定時(shí)器T1低八位的初值
- flag=0; //時(shí)鐘標(biāo)志位
- while(flag==0); // 時(shí)間未滿等待
- rpm_r=(TH0*256+TL0)*60/20; //計(jì)算轉(zhuǎn)速,乘以60秒,除以每周產(chǎn)生20個(gè)脈沖,單位為r/min
- v_r=D*3.14*(TH0*256+TL0)/20*3.6/1000; //v=2π*R*n,線速度為v,單位為m/s,轉(zhuǎn)速為n,單位為r/s,1m/s=3.6km/h
- rpm_l=(TH1*256+TL1)*60/20; //計(jì)算轉(zhuǎn)速,除以每周產(chǎn)生20個(gè)脈沖,單位為r/s
- v_l=D*3.14*(TH1*256+TL1)/20*3.6/1000; //v=2π*R*n,線速度為v,單位為m/s,轉(zhuǎn)速為n,單位為r/s,1m/s=3.6km/h
- Display();
- }
- }
- /******************************
- 中斷0(P3.2),C1接收個(gè)數(shù)累加
- ******************************/
- void time2() interrupt 5//定時(shí)器T2中斷服務(wù)程序
- {
- TF2=0; //定時(shí)器2溢出標(biāo)志位,注意!定時(shí)器2必須由軟件對(duì)溢出標(biāo)志位清零,硬件不能清零,這里與定時(shí)器0和定時(shí)器1不同。
- cnt++; //中斷次數(shù)倍數(shù),50ms為單位
- if(cnt==20) //中斷20次,每次50ms秒,累加1s。
- {
- flag=1; //時(shí)鐘標(biāo)志位
- cnt=0; //中斷次數(shù)倍數(shù)
- }
- }
復(fù)制代碼
Keil代碼下載:
OPG測(cè)速1.rar
(84.35 KB, 下載次數(shù): 21)
2022-3-26 04:22 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|