陀螺仪+wifi从机
这篇博文是stc89c51作为wifi从机发送来使用
#include <reg51.H> #include <INTRINS.H> #include <stdio.h> //Keil library typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; //**************************************** // 定义51单片机端口 //**************************************** sbit SCL=P1^3; //IIC时钟引脚定义 sbit SDA=P1^4; //IIC数据引脚定义 sbit GA=P2^0; //定义灯的负极(换成鼓) sbit GB=P2^1; //sbit a=P2^2; //**************************************** //定义类型及变量 //**************************************** int dis_data; //变量 //*************************************** //定义AT指令 //**************************************** uchar code CMD_RST[]="AT+RST\r\n";//复位重启 uchar code CMD_MUX[]="AT+CIPMUX=1\r\n";//启动多连接 uchar code CMD_JAP[]="AT+CWJAP=\"主机\",\"0123456789\"\r\n";//链接WIFI uchar code CMD_TCP[]="AT+CIPSTART=2,\"TCP\",\"192.168.4.1\",8080\r\n";//TCP链接 uchar code CMD_SEND[]="AT+CIPSEND=2,1\r\n";//发送数据 int a; //发送数据的变量 //**************************************** // 定义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 #define ACCEL_XOUT_L 0x3C #define ACCEL_YOUT_H 0x3D #define ACCEL_YOUT_L 0x3E #define ACCEL_ZOUT_H 0x3F #define ACCEL_ZOUT_L 0x40 #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 #define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用) #define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读) #define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取 //**************************************** //函数声明 //**************************************** void delay(unsigned int k); //延时 //MPU6050操作函数 void InitMPU6050(); //初始化MPU6050 void Delay5us(); void I2C_Start(); void I2C_Stop(); void I2C_SendACK(bit ack); bit I2C_RecvACK(); void I2C_SendByte(uchar dat); uchar I2C_RecvByte(); void I2C_ReadPage(); void I2C_WritePage(); uchar Single_ReadI2C(uchar REG_Address); //读取I2C数据 void Single_WriteI2C(uchar REG_Address,uchar REG_data); //向I2C写入数据 //wifi函数声明 void init(); void serial_send(const char *str); void wifi(); void delay_ms(uint xms); void delay(unsigned int k) { unsigned int i,j; for(i=0;i<k;i++) { for(j=0;j<121;j++); } } void delay_ms(uint xms) { uint i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); } //************************************** //延时5微秒(STC90C52RC@12M) //不同的工作环境,需要调整此函数 //当改用1T的MCU时,请调整此延时函数 //************************************** void Delay5us() { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); } //************************************** //I2C起始信号 //************************************** void I2C_Start() { SDA = 1; //拉高数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 0; //产生下降沿 Delay5us(); //延时 SCL = 0; //拉低时钟线 } //************************************** //I2C停止信号 //************************************** void I2C_Stop() { SDA = 0; //拉低数据线 SCL = 1; //拉高时钟线 Delay5us(); //延时 SDA = 1; //产生上升沿 Delay5us(); //延时 } //************************************** //I2C发送应答信号 //入口参数:ack (0:ACK 1:NAK) //************************************** void I2C_SendACK(bit ack) { SDA = ack; //写应答信号 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } //************************************** //I2C接收应答信号 //************************************** bit I2C_RecvACK() { SCL = 1; //拉高时钟线 Delay5us(); //延时 CY = SDA; //读应答信号 SCL = 0; //拉低时钟线 Delay5us(); //延时 return CY; } //************************************** //向I2C总线发送一个字节数据 //************************************** void I2C_SendByte(uchar dat) { uchar i; for (i=0; i<8; i++) //8位计数器 { dat <<= 1; //移出数据的最高位 SDA = CY; //送数据口 SCL = 1; //拉高时钟线 Delay5us(); //延时 SCL = 0; //拉低时钟线 Delay5us(); //延时 } I2C_RecvACK(); } //************************************** //从I2C总线接收一个字节数据 //************************************** uchar I2C_RecvByte() { uchar i; uchar dat = 0; SDA = 1; //使能内部上拉,准备读取数据, for (i=0; i<8; i++) //8位计数器 { dat <<= 1; SCL = 1; //拉高时钟线 Delay5us(); //延时 dat |= SDA; //读数据 SCL = 0; //拉低时钟线 Delay5us(); //延时 } return dat; } //************************************** //向I2C设备写入一个字节数据 //************************************** void Single_WriteI2C(uchar REG_Address,uchar REG_data) { I2C_Start(); //起始信号 I2C_SendByte(SlaveAddress); //发送设备地址+写信号 I2C_SendByte(REG_Address); //内部寄存器地址, I2C_SendByte(REG_data); //内部寄存器数据, I2C_Stop(); //发送停止信号 } //************************************** //从I2C设备读取一个字节数据 //************************************** uchar Single_ReadI2C(uchar REG_Address) { uchar REG_data; I2C_Start(); //起始信号 I2C_SendByte(SlaveAddress); //发送设备地址+写信号 I2C_SendByte(REG_Address); //发送存储单元地址,从0开始 I2C_Start(); //起始信号 I2C_SendByte(SlaveAddress+1); //发送设备地址+读信号 REG_data=I2C_RecvByte(); //读出寄存器数据 I2C_SendACK(1); //接收应答信号 I2C_Stop(); //停止信号 return REG_data; } //************************************** //初始化MPU6050 //************************************** void InitMPU6050() { Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态 Single_WriteI2C(SMPLRT_DIV, 0x07); Single_WriteI2C(CONFIG, 0x06); Single_WriteI2C(GYRO_CONFIG, 0x18); Single_WriteI2C(ACCEL_CONFIG, 0x01); } int GetData(uchar REG_Address) { char H,L; H=Single_ReadI2C(REG_Address); L=Single_ReadI2C(REG_Address+1); return (H<<8)+L; //合成数据 } void work() { int ACCEL_Y,ACCEL_X,GYRO_Y,ACCEL_Z; ACCEL_X=GetData(ACCEL_XOUT_H)/128; ACCEL_Y=GetData(ACCEL_YOUT_H)/128; ACCEL_Z=GetData(ACCEL_ZOUT_H)/128; GYRO_Y=GetData(GYRO_YOUT_H)/64; if(ACCEL_Y<80&&ACCEL_Z>100&&GYRO_Y>60) //第一级垂直姿态鼓音 { a='3'; } if(ACCEL_Y<80&&ACCEL_Z<-200&&GYRO_Y>60) //第二级垂直姿态鼓音 { a='f'; } if(ACCEL_Y>110&&GYRO_Y>60) //斜侧音 { a='g'; } } void init() { TMOD=0x20; //方式2 TL1=0xfd; //赋初值 TH1=0xfd; TR1=1; SM0=0; //串口方式1 SM1=1; REN=1; //串口允许接收 EA=1;//开总中断 ES=1; //开串口中断 } //*********************************** //串口发送函数 //**************************** void serial_send(const char *str) { ES=0; while(*str) { SBUF=*str++; while(!TI); TI=0; } ES=1; } //*********************************** //单片机给wifi发AT指令的函数 //************************************ void wifi() { serial_send(CMD_MUX); delay_ms(1000); serial_send(CMD_TCP); delay_ms(3000); } //主程序 //********************************************************* void main() { delay(500); //上电延时 InitMPU6050(); //初始化MPU6050 delay(150); init(); wifi(); while(1) { work(); if(a=='3') { a=0; serial_send(CMD_SEND); delay_ms(100); ES=0; SBUF='3'; while(!TI); TI=0; ES=1; } if(a=='f') { a=0; serial_send(CMD_SEND); delay_ms(100); ES=0; SBUF='f'; while(!TI); TI=0; ES=1; } if(a=='g') { a=0; serial_send(CMD_SEND); delay_ms(100); ES=0; SBUF='g'; while(!TI); TI=0; ES=1; } } }