我的设计是纯模块,比较贵,但是方便安装
小车:L298N驱动模块,小车,STC89C52RC单片机,HC06蓝牙 12V电源
遥控器:STC12C5A60S2单片机,MPU6050重力传感器,HC 05蓝牙 5V电源
小车程序 #include<reg52.h> sbit ENA=P2^2; sbit IN1=P2^3; sbit IN2=P2^4; sbit ENB=P2^5; sbit IN3=P2^6; sbit IN4=P2^7; unsigned char u; void delay(unsigned int n) //延时子程序 { unsignedchar i,j,k; for(i=n;i>0;i--) for(j=100;j>0;j--) for(k=200;k>0;k--); } /********************中断初始化********************/ void interrupt_Init(void) { TH1|=0xFA; //波特率9600 晶振11.0592 TL1|=0xFA; IE|=0x91; //允许总中断,串口中断,使能 INT0 外部中断 TCON|=0x41; //启动定时器T1,INT0触发方式为脉冲负边沿触发 SCON|=0x50; //REN=1允许串行接受状态,串口工作模式1 TMOD|=0x20; //定时器工作方式2 PCON|=0x80; //波特率倍频 } /*************串口中断程序**************/ void ser_int(void) interrupt 4 using 1 { if(RI==1) { RI=0; u=SBUF; } } void go() { IN1=1; IN2=0; ENA=1; } void back() { IN1=0; IN2=1; ENA=1; } void stop() { IN1=0; IN2=0; ENA=0; ENB=0; } void left() { IN3=0; IN4=1; ENB=1; } void right() { IN3=1; IN4=0; ENB=1; } void main() { interrupt_Init(); while(1) { // 0001 // 0010 // 0100 // 1000 delay(1); u=u&0x0F; if(u==1)go(); if(u==2)back(); if(u==0)stop(); if(u==4)left(); if(u==8)right(); if(u==5){go();left();} if(u==9){go();right();} if(u==6){back();left();} if(u==0x0A){back();right();} u=0; } } 1.1 遥控器程序 #include "STC12C5A60S2.h" #include "intrins.h" #include "math.h" sbit SCL=P1^7; //IIC时钟引脚定义 sbit SDA=P1^6; //IIC数据引脚定义 #define u8 unsigned char #define u16 unsigned int //**************************************** // 定义MPU6050内部地址 //**************************************** #define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz) #define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz) #define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s) #define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz) #define ACCEL_XOUT_H 0x3B //MPU6050_BUF[0] #define ACCEL_XOUT_L 0x3C //MPU6050_BUF[1] #define ACCEL_YOUT_H 0x3D #define ACCEL_YOUT_L 0x3E #define ACCEL_ZOUT_H 0x3F #define ACCEL_ZOUT_L 0x40 #define TEMP_OUT_H 0x41 //MPU6050_BUF[6] #define TEMP_OUT_L 0x42 //MPU6050_BUF[7] #define GYRO_XOUT_H 0x43 #define GYRO_XOUT_L 0x44 #define GYRO_YOUT_H 0x45 #define GYRO_YOUT_L 0x46 #define GYRO_ZOUT_H 0x47 #define GYRO_ZOUT_L 0x48 //MPU6050_BUF[13] #define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用) #define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读) #define MPU6050_Addr 0xD0 //IIC写入时的地址字节数据,+1为读取 u8 MPU6050_BUF[14]; float angle_x,angle_y; //unsigned char AB,LR; static void Delay5us(void) { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } void I2C_Start(void) { SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA= 0; //产生下降沿 Delay5us(); //延时 SCL = 0; //拉低时钟线 } void I2C_Stop(void) { SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 1; //产生上升沿 Delay5us(); //延时 } void I2C_SendACK(bit ack) { SDA = ack; //写应答信号 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } bit I2C_RecvACK(void) { SCL = 1; //拉高时钟线 Delay5us(); //延时 CY = SDA; //读应答信号 SCL = 0; //拉低时钟线 Delay5us(); //延时 return CY; } void I2C_SendByte(u8 dat) { u8 i; for (i=0; i<8; i++) //8位计数器 { dat <<= 1; //移出数据的最高位 SDA = CY; //送数据口 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } I2C_RecvACK(); } u8 I2C_RecvByte(void) { u8 i, dat = 0; SDA = 1; //使能内部上拉,准备读取数据, for (i=0; i<8; i++) //8位计数器 { dat <<= 1; SCL = 1; //拉高时钟线 Delay5us(); //延时 dat |= SDA; //读数据 SCL = 0; //拉低时钟线 Delay5us(); //延时 } return dat; } void Single_Write_MPU6050(u8 REG_Address,u8REG_data) { I2C_Start(); //起始信号 I2C_SendByte(MPU6050_Addr); //发送设备地址+写信号 I2C_SendByte(REG_Address); //内部寄存器地址, I2C_SendByte(REG_data); //内部寄存器数据, I2C_Stop(); //发送停止信号 } u8 Single_Read_MPU6050(u8 REG_Address) { u8REG_data; I2C_Start(); //起始信号 I2C_SendByte(MPU6050_Addr); //发送设备地址+写信号 I2C_SendByte(REG_Address); //发送存储单元地址,从0开始 I2C_Start(); //起始信号 I2C_SendByte(MPU6050_Addr+1); //发送设备地址+读信号 REG_data= I2C_RecvByte(); //读出寄存器数据 I2C_SendACK(1); //接收应答信号 I2C_Stop(); //停止信号 returnREG_data; } void MPU6050_Init(void) { Single_Write_MPU6050(PWR_MGMT_1,0x00); //解除休眠状态 Single_Write_MPU6050(SMPLRT_DIV,0x07); Single_Write_MPU6050(CONFIG,0x06); Single_Write_MPU6050(GYRO_CONFIG,0x18); //2000,16.4 Single_Write_MPU6050(ACCEL_CONFIG,0x10); //8g ,4096 } void Get_MPU6050_Data(void) { u8i; intaccel_x,accel_y,accel_z; for(i=0;i<14;i++) { MPU6050_BUF= Single_Read_MPU6050(0x3B + i); } accel_x= MPU6050_BUF[0]; accel_x= (accel_x << 8) | MPU6050_BUF[1]; accel_y= MPU6050_BUF[2]; accel_y= (accel_y << 8) | MPU6050_BUF[3]; accel_z= MPU6050_BUF[4]; accel_z= (accel_z << 8) | MPU6050_BUF[5]; // //扩大1000倍 angle_x= atan2((float)accel_x,(float)accel_z) * (57.295779) ; angle_y= atan2((float)accel_y,(float)accel_z) * (57.295779) ; } //串口初始化 void UartInit(void) //9600bps@12.000MHz { PCON&= 0x7F; //波特率不倍速 SCON= 0x50; //8位数据,可变波特率 AUXR|= 0x04; //独立波特率发生器时钟为Fosc,即1T BRT= 0xD9; //设定独立波特率发生器重装值 AUXR|= 0x01; //串口1选择独立波特率发生器为波特率发生器 AUXR|= 0x10; //启动独立波特率发生器 } /********************发送一个字节********************/ void Sendchar(u8 ch) //单片机发送一字节数据 { SBUF=ch; while(!TI); //等待发送完成 TI=0; //清除标志位 } void Delay(u16 x) { u8i,j; for(i=x;i>0;i--) for(j=200;j>0;j--); } void cc(long int aa) { u8shiwan,wan,qian,bai,shi,ge; if(aa>0) { Sendchar('+'); } else { Sendchar('-'); aa= -aa; } shiwan= aa/100000; wan = aa%100000/10000; qian = aa%10000/1000; bai = aa%1000/100; shi = aa%100/10; ge = aa%10; Sendchar(shiwan+0x30); Sendchar(wan+0x30); Sendchar(qian+0x30); Sendchar('.'); Sendchar(bai+0x30); Sendchar(shi+0x30); Sendchar(ge+0x30); Sendchar(''); Sendchar(''); Sendchar(''); } void main(void) { UartInit(); MPU6050_Init(); while(1) { Get_MPU6050_Data(); // cc((longint)angle_x); // cc((longint)angle_y); // Sendchar(0x0D); // Sendchar(0x0A); if((angle_y>-20)&&(angle_y<20)&&(angle_x<-30))Sendchar('1'); if((angle_y<20)&&(angle_y>-20)&&(angle_x>25)) Sendchar('2'); // if(angle_y<20) // { // if(angle_y>-20) // { // if(angle_x>25) Sendchar('2'); // } // } if((angle_x<25)&&(angle_x>-30)&&(angle_y>25))Sendchar('8'); if((angle_x<25)&&(angle_x>-30)&&(angle_y<-25))Sendchar('4'); if((angle_y<-25)&&(angle_x<-30))Sendchar('5'); if((angle_y>25)&&(angle_x<-30))Sendchar('9'); if((angle_y<-25)&&(angle_x>25))Sendchar('6'); if((angle_y>25)&&(angle_x>25))Sendchar(':'); if((angle_y>-25)&&(angle_y<25)&&(angle_x<25)&&(angle_x>-30))Sendchar('0'); } }
|