參考了之前實驗課上老師講的編碼器的程序,但我還是理解的不太清楚,也不確定我的連線是否正確,可以給我再講講嗎。我理解是利用定時器0去對脈沖進行計數,確定電機轉動的圈數,T1用來每1s檢測一次,然后利用液晶顯示速度。但把這部分加進我的程序中,好像沒有效果。
- //#include <reg52.h>
- #include <STC15.H>
- #include <intrins.h>
- #include <stdio.h>
- #include "DataForm_STC15.H"
- #include "LCD1602.h"
- #define uchar unsigned char
- #define uint unsigned int
- #define K 21/8
- sbit KEY1=P1^0;// 電機啟動
- sbit KEY2=P1^1;// 電機停止
- sbit KEY3=P1^2;// 電機加速
- sbit KEY4=P1^3; //減速
- bit KEY_flag=0; //按鍵標志位
- bit Timer1S_flag=0; // 定時器到1S標志位
- uint16 Timer1S_num=0; // 定時器溢出中斷計數,一千次為1S
- uint count = 0; //計時變量
- uint PWM = 0; //占空比控制變量
- uint EX0_counter=0,rad;//EX0_counter為脈沖數
- uchar8 LCD_BUFFER[16]={0}; // 液晶顯示緩沖區
- sbit MOTOR_A1=P1^4; //l293D芯片引腳定義
- sbit MOTOR_A2=P1^5;
- sbit MOTOR_B1=P1^6;
- sbit MOTOR_B2=P1^7;
- sbit ENA=P3^0;
- sbit ENB=P3^1;
- void delay1ms() //@11.0592MHz延時函數
- {
- unsigned char i, j;
- _nop_();
- _nop_();
- _nop_();
- i = 11;
- j = 190;
- do
- {
- while (--j);
- } while (--i);
- }
- void delayms(uint t) //1ms延時函數
- {
- uint x,y;
- for(x=t;x>0;x--)
- for(y=120;y>0;y--);
- }
- void Motor_Forward()//電機正轉
- {
- MOTOR_A1=1;
- MOTOR_A2=0;
- ENA=1;
- MOTOR_B1=1;
- MOTOR_B2=0;
- ENB=1;
- }
-
- void Motor_Stop()//電機停止
- {
- MOTOR_A1=0;
- MOTOR_A2=0;
- ENA=1;
- MOTOR_B1=0;
- MOTOR_B2=0;
- ENB=1;
- }
- void Start()
- {
- LCD_Init();
- LCD_Display_String(4,0,"Treadmill");
- }
- void Speed_Up()
- {
- LCD_Init();
- LCD_Display_String(4,0,"speed up");
- }
- void Speed_Down()
- {
- LCD_Init();
- LCD_Display_String(4,0,"speed down");
- }
- void KEY_Scan() // 按鍵驅動函數
- {
- if(KEY1==0) // 判斷是否按下 下同
- {
- delay1ms(); //消抖
- if(KEY1==0)
- {
- KEY_flag=~KEY_flag; //加速減速標志位取反
- Motor_Forward();
- PWM=30; //初始PWM=30,電機速度大約為22
-
- }
- while(KEY1==0); //檢測按鍵是否松開
- }
- if(KEY2==0) // 判斷是否按下 下同
- {
- delay1ms(); //消抖
- if(KEY2==0)
- {
- KEY_flag=0; //加速減速標志位清零
- Motor_Stop();
- PWM=0; //PWM清零
-
- }
- while(KEY2==0); //檢測按鍵是否松開
- }
- if(KEY3==0) // 判斷是否按下 下同
- {
- delay1ms(); //消抖
- if(KEY3==0)
- {
- if(KEY_flag==1) //判斷標志位只有在電機啟動的時候才能加速
- {
- if(PWM<250)
- {
- Speed_Up();
- PWM=PWM+30; //每次PWM+10 直到250
- }
- delayms(10); //給一個延時,讓電機反應快一些可減少此延時時間
- }
- }
- while(KEY3==0); //檢測按鍵是否松開
- }
- if(KEY4==0) // 判斷是否按下 下同
- {
- delay1ms(); //消抖
- if(KEY4==0)
- {
- if(KEY_flag==1) //判斷標志位只有在電機啟動的時候才能減速
- {
- if(PWM>0)
- {
- Speed_Down();
- PWM=PWM-30;
- }
- delayms(10);
- }
- }
- while(KEY4==0); //檢測按鍵是否松開
- }
- }
- void Timer0()
- {
- TMOD = 0x02; //定時器0,工作模式2,8位定時模式
- TH0=210; //寫入預置初值(取值1-255,數越大PWM頻率越高)
- TL0=210; //寫入預置值 (取值1-255,數越大PWM頻率越高)
- TR0=1; //啟動定時器
- ET0=1; //允許定時器0中斷
- EA=1; //允許總中斷
- }
- //定時器0中斷模擬PWM
- void serviceTimer0() interrupt 1
- {
- count++; //每次定時器溢出加1
- if(count==250) //PWM周期 100個單位
- {
- count=0; //使t=0,開始新的PWM周期
- Motor_Forward();
- }
-
- if(PWM==count) //按照當前占空比切換輸出為低電平
- {
- Motor_Stop();
- }
- }
- void Init_EINT0( ) // T0外部中斷初始化
- {
- IT0=1; // 外部信號下降沿觸發
- EX0=1; // 開T0外部中斷
- EA=1; // 開總中斷
- }
- void EINT0( ) interrupt 0 // T0外部中斷子程序
- {
- EX0_counter++; // 每中斷一次計數加1
- }
- void Init_Timer1( ) // 定時器T1初始化
- {
- AUXR |= 0x40; // 定時器時鐘為1T模式
- TMOD &= 0x0F; // 設置定時器模式,16位自動重裝
- TL1 = 0xCD; // 定時常數
- TH1 = 0xD4; // 定時常數
- TF1 = 0; // 清溢出標志位
- ET1=1; // 開T1溢出中斷
- EA=1; // 開總中斷
- }
- void Enable_Timer1( ) //開定時器
- {
- TR1=1;
- }
- void Disable_Timer1( ) //關定時器
- {
- TR1=0;
- }
- void Timer1( ) interrupt 3 // T1中斷子程序
- {
- Timer1S_num++; // 定時器溢出中斷計數,每中斷一次計數加1
- TF1 = 0; // 清溢出標志位
- if(Timer1S_num>=1000) // 中斷計數一千次為1S,到1S計數清零,1S標志位置1,即每1S檢測一次
- {
- Timer1S_num=0;
- Timer1S_flag=1;
- }
- }
- void Speed_Display() //計算速度
- {
- rad=EX0_counter*K;
- sprintf(LCD_BUFFER,"v=%.2f",rad);
- LCD_Display_String(2,1,LCD_BUFFER);
- }
- void main()
- {
- Start();//初始化顯示跑步機
- Timer0();//定時器0初始化
- Init_Timer1( );//定時器1初始化
- Enable_Timer1( );
- Init_EINT0( ); //電機編碼器中斷初始化
- EX0_counter=0; //電機旋轉圈數初始化
- Timer1S_num=0; //計時次數初始化
- Motor_Forward();//啟動電機
- // PWM=30; //PWM初始值
-
- while(1)
- {
- KEY_Scan();
- if(Timer1S_flag==1) // 如果時間到1S
- {
- Speed_Display(); // 液晶顯示
- EX0_counter=0; // 外部中斷計數清零
- Timer1S_flag=0; // 1S計數清零
- }
-
- }
- }
復制代碼
|