舵機信號線連接 P3.5
電機連接 uln2003 A腳
ch- 停止舵機轉動
ch 開始舵機轉動
prev 停止風扇轉動
next 開始風扇轉動
- 風扇減速
+ 風扇加速
具體代碼見附件
一、元件清單 1、9G舵機 1個 2、直流電機 1個 3、電機支架 1組 4、51主板 1個 5、杜邦線 若干 6、螺絲、螺帽 若干 二、軟件 1、Keil4軟件 2、程序燒錄軟件 三、硬件安裝 1、舵機 2、直流電機 四、硬件接線 1.舵機接線說明
2.直流電機接線說明 一個腳接步進電機模塊的+,另一個腳接步進電機模塊的A 。
3.實物接線圖 3.1602直插即可。 五、實驗操作說明 用紅外遙控器對準紅外接收頭,操作即可。
單片機源程序如下: - /*******************************************************************************
- * 實驗名 : 1602顯示紅外線值實驗
- * 使用的IO : 電機用P1口,鍵盤使用P3.0、P3.1、P3.2、P3.3
- * 實驗效果 : LCD1602顯示出讀取到的紅外線的值
- * 注意 :
- *******************************************************************************/
- #include<reg51.h>
- #include"lcd.h"
- #include <stdio.h>
- //#include "delay.h"
- sfr T2CON = 0xC8; //timer2 control register
- sfr RCAP2L = 0xCA;
- sfr RCAP2H = 0xCB;
- sfr TL2 = 0xCC;
- sfr TH2 = 0xCD;
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- #define FOSC 12000000L //System frequency
- #define BAUD 9600 //UART baudrate
- /*Define UART parity mode*/
- #define NONE_PARITY 0 //None parity
- #define ODD_PARITY 1 //Odd parity
- #define EVEN_PARITY 2 //Even parity
- #define MARK_PARITY 3 //Mark parity
- #define SPACE_PARITY 4 //Space parity
- #define PARITYBIT NONE_PARITY //Testing even parity
- sbit bit9 = P2^2; //P2.2 show UART data bit9
- bit busy;
- sbit Sevro_moto_pwm = P3^5; //接舵機信號端輸入PWM信號調節速度
- sbit FanPin=P1^0;
- unsigned int pwm_val_left = 0;//變量定義
- unsigned char push_val_left =14;//舵機歸中,產生約,1.5MS 信號
- unsigned int timer=0; //延時基準變量
- unsigned int Servo_Ctr=0;
- unsigned int pwm_val_Fan=0;
- unsigned char Fan_speed=199;
- int flag=0;
- sbit IRIN=P3^2;
- unsigned char code CDIS1[13]={" Red Control "};
- unsigned char code CDIS2[13]={" IR-CODE:--H "};
- unsigned char code Test_OK[2]={"OK"};
- unsigned char IrValue[6];
- unsigned char Time;
- unsigned char IrOK=0;
- /*--------------------------------------------------------------
- 函數聲明
- --------------------------------------------------------------*/
- void InitUART(void);
- char putchar(char c);
- void IrInit();
- void DelayMs(unsigned int );
- void SendString(char *s);
- void SendData(BYTE dat);
- void pwm_Servomoto_angle(unsigned int angle,unsigned int Servo_time);
- void pwm_Servomoto(void);
- void test_servo(void);
- void Motor_Ctr(void);
- void Pwm_Motor(void);
- /*******************************************************************************
- * 函數名 : main
- * 函數功能 : 主函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void main()
- {
- unsigned char i;
- //串口初始化
-
- // printf("\r\n\n\r\n");
-
- TMOD=0X11;
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- TH0=0;
- TL0=0;
- TR1= 1;
- ET1= 1;
- ET0= 1;
- EA = 1;
- IrInit();
- LcdInit();
- InitUART();
- LcdWriteCom(0x80);
-
- for(i=0;i<13;i++)
- {
- LcdWriteData(CDIS1[i]);
- }
- LcdWriteCom(0x80+0x40);
- for(i=0;i<13;i++)
- {
- LcdWriteData(CDIS2[i]);
- }
- while(1)
- {
- test_servo();
- IrValue[4]=IrValue[2]>>4; //高位
- IrValue[5]=IrValue[2]&0x0f; //低位
- if(IrValue[4]>9)
- {
- LcdWriteCom(0xc0+0x09); //設置顯示位置
- LcdWriteData(0x37+IrValue[4]); //將數值轉換為該顯示的ASCII碼
- }
- else
- {
- LcdWriteCom(0xc0+0x09);
- LcdWriteData(IrValue[4]+0x30); //將數值轉換為該顯示的ASCII碼
- }
- if(IrValue[5]>9)
- {
- LcdWriteCom(0xc0+0x0a);
- LcdWriteData(IrValue[5]+0x37); //將數值轉換為該顯示的ASCII碼
- }
- else
- {
- LcdWriteCom(0xc0+0x0a);
- LcdWriteData(IrValue[5]+0x30); //將數值轉換為該顯示的ASCII碼
- }
- DelayMs(50);
- // printf("\r\n SZ-51 UART printftest OK if you see these words! c%c%", IrValue[2], IrValue[3]);
- if(IrOK==1) //如果處理好后進行紅外處理
- {
- // printf("\r\n SZ-51 UART printftest OK if you see these words!");
- SendString(Test_OK);
- if(IrValue[4]>9)
- {
- LcdWriteCom(0x80+0x0d); //設置顯示位置
- LcdWriteData(0x37+IrValue[4]); //將數值轉換為該顯示的ASCII碼
- }
- else
- {
- LcdWriteCom(0x80+0x0d);
- LcdWriteData(IrValue[4]+0x30); //將數值轉換為該顯示的ASCII碼
- }
- if(IrValue[5]>9)
- {
- LcdWriteCom(0x80+0x0e);
- LcdWriteData(IrValue[5]+0x37); //將數值轉換為該顯示的ASCII碼
- }
- else
- {
- LcdWriteCom(0x80+0x0e);
- LcdWriteData(IrValue[5]+0x30); //將數值轉換為該顯示的ASCII碼
- }
- switch(IrValue[2])
- {
- case 0x18:
- LcdWriteCom(0x80+0x0f);
- LcdWriteData(CDIS1[3]); //將數值轉換為該顯示的ASCII碼
- break;
- case 0x52:
- LcdWriteCom(0x80+0x0f);
- LcdWriteData(CDIS1[2]); //將數值轉換為該顯示的ASCII碼
- break;
- default:break;
- }
- IrOK=0;
- }
- else
- {
- // printf("\r\n SZ-51 UART printftest OK if you see these words!");
- }
- DelayMs(50);
- }
- }
- /*******************************************************************************
- * 函數名 : DelayMs()
- * 函數功能 : 延時
- * 輸入 : x
- * 輸出 : 無
- *******************************************************************************/
- void DelayMs(unsigned int x) //0.14ms誤差 0us
- {
- unsigned char i;
- while(x--)
- {
- for (i = 0; i<13; i++)
- {}
- }
- }
- /*******************************************************************************
- * 函數名 : IrInit()
- * 函數功能 : 初始化紅外線接收
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void IrInit()
- {
- IT0=1;//下降沿觸發
- EX0=1;//打開中斷0允許
- EA=1; //打開總中斷
- IRIN=1;//初始化端口
- }
- /*******************************************************************************
- * 函數名 : ReadIr()
- * 函數功能 : 讀取紅外數值的中斷函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void ReadIr() interrupt 0
- {
- unsigned char j,k;
- unsigned int err;
- Time=0;
- DelayMs(70);
- if(IRIN==0) //確認是否真的接收到正確的信號
- {
-
- err=1000; //1000*10us=10ms,超過說明接收到錯誤的信號
- /*當兩個條件都為真是循環,如果有一個條件為假的時候跳出循環,免得程序出錯的時
- 侯,程序死在這里*/
- while((IRIN==0)&&(err>0)) //等待前面9ms的低電平過去
- {
- DelayMs(1);
- err--;
- }
- if(IRIN==1) //如果正確等到9ms低電平
- {
- err=500;
- while((IRIN==1)&&(err>0)) //等待4.5ms的起始高電平過去
- {
- DelayMs(1);
- err--;
- }
- for(k=0;k<4;k++) //共有4組數據
- {
- for(j=0;j<8;j++) //接收一組數據
- {
- err=60;
- while((IRIN==0)&&(err>0))//等待信號前面的560us低電平過去
- // while (!IRIN)
- {
- DelayMs(1);
- err--;
- }
- err=500;
- while((IRIN==1)&&(err>0)) //計算高電平的時間長度。
- {
- DelayMs(1);//0.14ms
- Time++;
- err--;
- if(Time>30)
- {
- EX0=1;
- return;
- }
- }
- IrValue[k]>>=1; //k表示第幾組數據
- if(Time>=8) //如果高電平出現大于565us,那么是1
- {
- IrValue[k]|=0x80;
- }
- Time=0; //用完時間要重新賦值
- }
- }
- }
- if(IrValue[2]==~IrValue[3])
- {
-
- IrOK=1;
- DelayMs(5);
- return;
- }
- else
- {
- IrOK=0;
- }
- }
-
- }
- /*--------------------------------------------------------------
- 串口初始化
- --------------------------------------------------------------*/
- void InitUART(void)
- {
- #if (PARITYBIT == NONE_PARITY)
- SCON = 0x50; //8-bit variable UART
- #elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
- SCON = 0xda; //9-bit variable UART, parity bit initial to 1
- #elif (PARITYBIT == SPACE_PARITY)
- SCON = 0xd2; //9-bit variable UART, parity bit initial to 0
- #endif
- TL2 = RCAP2L = (65536-(FOSC/32/BAUD)); //Set auto-reload vaule
- TH2 = RCAP2H = (65536-(FOSC/32/BAUD)) >> 8;
- T2CON = 0x34; //Timer2 start run
- ES = 1; //Enable UART interrupt
- EA = 1;
- }
- /*--------------------------------------------------------------
- printf調用的底層發送一個字節函數
- --------------------------------------------------------------*/
- char putchar(char c)
- {
- SBUF = c;
- while(!TI);
- TI = 0;
- return c;
- }
- /*----------------------------
- UART interrupt service routine
- ----------------------------*/
- void Uart_Isr() interrupt 4 using 1
- {
- if (RI)
- {
- RI = 0; //Clear receive interrupt flag
- P0 = SBUF; //P0 show UART data
- bit9 = RB8; //P2.2 show parity bit
- }
- if (TI)
- {
- TI = 0; //Clear transmit interrupt flag
- busy = 0; //Clear transmit busy flag
- }
- }
- /*----------------------------
- Send a byte data to UART
- Input: dat (data to be sent)
- Output:None
- ----------------------------*/
- void SendData(BYTE dat)
- {
- while (busy); //Wait for the completion of the previous data is sent
- ACC = dat; //Calculate the even parity bit P (PSW.0)
- if (P) //Set the parity bit according to P
- {
- #if (PARITYBIT == ODD_PARITY)
- TB8 = 0; //Set parity bit to 0
- #elif (PARITYBIT == EVEN_PARITY)
- TB8 = 1; //Set parity bit to 1
- #endif
- }
- else
- {
- #if (PARITYBIT == ODD_PARITY)
- TB8 = 1; //Set parity bit to 1
- #elif (PARITYBIT == EVEN_PARITY)
- TB8 = 0; //Set parity bit to 0
- #endif
- }
- busy = 1;
- SBUF = ACC; //Send data to UART buffer
- }
- /*----------------------------
- Send a string to UART
- Input: s (address of string)
- Output:None
- ----------------------------*/
- void SendString(char *s)
- {
- while (*s) //Check the end of the string
- {
- SendData(*s++); //Send current char and increment string ptr
- }
- }
- /************************************************************************/
- /* PWM調制舵機電機轉速 */
- /************************************************************************/
- /* 舵機電機調速 */
- /*調節push_val_left的值改變舵機電機轉速,占空比 */
- void pwm_Servomoto(void)
- {
-
- if(pwm_val_left<=push_val_left)
- Sevro_moto_pwm=1;
- else
- Sevro_moto_pwm=0;
- if(pwm_val_left>=200)
- pwm_val_left=0;
-
- }
- void Pwm_Motor(void)
- {
- if(flag==1)
- {
- FanPin=0;
- }
- else
- {
- if(pwm_val_Fan<=Fan_speed)
- FanPin=1;
- else
- FanPin=0;
- if(pwm_val_Fan>=200)
- pwm_val_Fan=0;
- }
- }
- /***************************************************/
- ///*TIMER1中斷服務子函數產生PWM信號*/
- void time1()interrupt 3 using 2
- {
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- timer++; //定時器100US為準。在這個基礎上延時
- pwm_val_left++;
- pwm_val_Fan++;
- pwm_Servomoto();
- Pwm_Motor();
-
- }
- void pwm_Servomoto_angle(unsigned int angle,unsigned int Servo_time)
- {
- push_val_left=5+angle*20/180; //舵機向左轉90度
- timer=0;
- while(timer<=Servo_time); //延時400MS讓舵機轉到其位置 4000
- }
- void test_servo(void)
- {
- int pos;
- for(pos=0;pos<180;pos+=3)
- {
- Motor_Ctr();
- // pwm_Fan_speed();
- while(Servo_Ctr==0)
- {
- Motor_Ctr();
-
- }
-
- pwm_Servomoto_angle(pos,100) ;
- DelayMs(10);
- }
- for(pos = 180; pos>=0; pos-=3) // goes from 180 degrees to 0 degrees
- {
- Motor_Ctr();
- while(Servo_Ctr==0)
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
|