我的設計是純模塊,比較貴,但是方便安裝
小車: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'); } }
|