舵机信号线连接 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提供下载:
|