企业首页 资讯动态 客户案例 技术服务 免费二维码 GPS定位 物联平台
登录|注册
联系我们

客户案例
STM32单片机三角函数排水控制技术
2023-01-09 21:06:08

通过STM32单片机实时采集MPU6050二轴数数据,然后通过

三角函数计算出偏移角度,从而用单片机IO进行给水、排水控制。

以下代码由宇天网络科技编写

#include "stm32f10x.h"

#include "platform_config.h"

#include "stm32f10x_usart.h"

#include "misc.h"

#include "stdarg.h"

#include "math.h"



USART_InitTypeDef USART_InitStructure;



#define PI=3.1415926;

#define IIC_READ_SDA()   GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15);   /* 读SDA口线状态 */

#define GetKey()   GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);   /* 读SDA口线状态 */

#define GetKey2()   GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2);   /* 读SDA口线状态 */


#define SDA_1 GPIO_SetBits(GPIOB,GPIO_Pin_15);    /*字库IC接口定义:Rom_IN就是字库IC的SI*/

#define SDA_0 GPIO_ResetBits(GPIOB,GPIO_Pin_15); 


    

#define SCK_1 GPIO_SetBits(GPIOB,GPIO_Pin_13);   /*字库IC接口定义:Rom_SCK就是字库IC的SCK*/

#define SCK_0 GPIO_ResetBits(GPIOB,GPIO_Pin_13); 


typedef unsigned char  uchar;

typedef unsigned short ushort;

typedef unsigned int   uint;


// 定义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        TEMP_OUT_H                0x41

#define        TEMP_OUT_L                0x42

#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为读取

//****************************************

int CY=0;

//函数声明

//****************************************

void  delay(unsigned int k);                                                                                //延时                                                


//MPU6050操作函数

void  InitMPU6050();                                                                                                        //初始化MPU6050

void  Delay5us();

void  I2C_Start();

void  I2C_Stop();

void  I2C_SendACK(int ack);

int   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写入数据


/* Private function prototypes -----------------------------------------------*/

void RCC_Configuration(void);

void GPIO_Configuration(void);

void NVIC_Configuration(void);

void Delay_us(unsigned int time);


void Delay(__IO uint32_t nCount);

void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...);

char *itoa(int value, char *string, int radix);

void USART_Config(USART_TypeDef* USARTx);



GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStruct;

USART_ClockInitTypeDef USART_ClockInitStruct;




void USART_Config(USART_TypeDef* USARTx){

  USART_InitStructure.USART_BaudRate = 115200; //速率115200bps

  USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位

  USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位

  USART_InitStructure.USART_Parity = USART_Parity_No; //无校验位

  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;   //无硬件流控

  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式


  /* Configure USART1 */

  USART_Init(USARTx, &USART_InitStructure); //配置串口参数函数

 

  

  /* Enable USART1 Receive and Transmit interrupts */

  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                    //使能接收中断

  USART_ITConfig(USART1, USART_IT_TXE, ENABLE); //使能发送缓冲空中断

  //USART_ITConfig(USART1, USART_IT_TC, ENABLE); //使能发送完成中断


  /* Enable the USART1 */

  USART_Cmd(USART1, ENABLE);

}



//**************************************

//延时5微秒(STC90C52RC@12M)

//不同的工作环境,需要调整此函数

//当改用1T的MCU时,请调整此延时函数

//**************************************

void Delay5us()

{

    unsigned int i;

unsigned int j;                                

        for(i=0;i<1;i++)< span="">

        {                        

            for(j=0;j<5;j++);< span="">

        }    

}

//**************************************

//I2C起始信号

//**************************************

void I2C_Start()

{

    SDA_1;                    //拉高数据线

    SCK_1;                    //拉高时钟线

    Delay5us();                 //延时

    SDA_0;                    //产生下降沿

    Delay5us();                 //延时

    SCK_0;                    //拉低时钟线

}

//**************************************

//I2C停止信号

//**************************************

void I2C_Stop()

{

    SDA_0;                    //拉低数据线

    SCK_1;                    //拉高时钟线

    Delay5us();                 //延时

    SCK_1;                    //产生上升沿

    Delay5us();                 //延时

}

//**************************************

//I2C发送应答信号

//入口参数:ack (0:ACK 1:NAK)

//**************************************

void I2C_SendACK(int ack)

{

    if(ack==1){SDA_1;}else{SDA_0;}                  //写应答信号

    SCK_1;                    //拉高时钟线

    Delay5us();                 //延时

    SCK_0;                    //拉低时钟线

    Delay5us();                 //延时

}

//**************************************

//I2C接收应答信号

//**************************************

int I2C_RecvACK()

{

    SCK_1;                    //拉高时钟线

    Delay5us();                 //延时

    CY = IIC_READ_SDA();                   //读应答信号

    SCK_0;                    //拉低时钟线

    Delay5us();                 //延时

    return CY;

}

//**************************************

//向I2C总线发送一个字节数据

//**************************************

void I2C_SendByte(uchar dat)

{

    uchar i;

    for (i=0; i<8; i++)         //8位计数器

    {

        if(dat&0x80){SDA_1;}

else {SDA_0;}              //送数据口

        SCK_1;                //拉高时钟线

        Delay5us();             //延时

        SCK_0;                //拉低时钟线

        Delay5us();             //延时

dat=dat<<=1;< p="">

    }

    I2C_RecvACK();

}

//**************************************

//从I2C总线接收一个字节数据

//**************************************

uchar I2C_RecvByte()

{

    uchar i;

    uchar dat = 0;

    SDA_1;                    //使能内部上拉,准备读取数据,

    for (i=0; i<8; i++)         //8位计数器

    {

        dat <<= 1;

        SCK_1;                //拉高时钟线

        Delay5us();             //延时

        dat |= IIC_READ_SDA();             //读数据               

        SCK_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)

{

        uchar H,L;

        H=Single_ReadI2C(REG_Address);

        L=Single_ReadI2C(REG_Address+1);


        return (H<<8)+L;   //合成数据

}

void RCC_Configuration(void)

{

  SystemInit();

}

void GPIO_Configuration(void)

{


  RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 |RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOC |RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO  , ENABLE);

 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_13|GPIO_Pin_15|GPIO_Pin_1;      //LED1

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;          //USART1 TX

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出

  GPIO_Init(GPIOA, &GPIO_InitStructure);     //A端口 


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;          //USART1 RX

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //复用开漏输入

  GPIO_Init(GPIOA, &GPIO_InitStructure);


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1| GPIO_Pin_2;      //LED1

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);


    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_2;      //LED1

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}


void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       //设置串口1中断

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;       //抢占优先级 0

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级为0

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能

  NVIC_Init(&NVIC_InitStructure);

}

int low=60;

int hgt=10;


short   a=0;

short b=0;

float c=0;

char buf[8];



int bt=1;

int bt2=1;

int ct=0;

bool led=1;

int main(void)

{

  RCC_Configuration();

  NVIC_Configuration();

  GPIO_Configuration();

  USART_Config(USART1); 

  InitMPU6050();


   GPIO_SetBits(GPIOA,GPIO_Pin_1);

  GPIO_SetBits(GPIOB,GPIO_Pin_1);

while(1)

{

    ct++;

        a=GetData(ACCEL_ZOUT_H);

b=GetData(ACCEL_XOUT_H); 

c=atan(abs(b)*1.0/abs(a));

c=c*180/3.14159;

sprintf(buf, "%.2f",c);


USART_OUT(USART1,buf);

USART_OUT(USART1,"\r\n"); 

if(ct==500)

{

if(led==1){GPIO_ResetBits(GPIOB,GPIO_Pin_6);}

else{GPIO_SetBits(GPIOB,GPIO_Pin_6);}

led=!led;

ct=0;

}

if(c

{

GPIO_ResetBits(GPIOB,GPIO_Pin_1);

}

if(c>low)

{

    GPIO_SetBits(GPIOB,GPIO_Pin_1);

}

bt=GetKey();

if(0==bt)

{

   Delay_us(40000);

   bt=GetKey();

   if(0==bt)

   {GPIO_ResetBits(GPIOA,GPIO_Pin_1);low=c;}

}

bt2=GetKey2();

if(0==bt2)

{

   Delay_us(40000);

   bt2=GetKey2();

   if(0==bt2)

   {GPIO_SetBits(GPIOA,GPIO_Pin_1);hgt=c;}

}

// Delay_us(50000);

}

}


void Delay_us(unsigned int time)

{

   unsigned int i=0;  

   while(time--)

   {

      i=100;  //自己定义

      while(i--) ;    

   }

}


/******************************************************

格式化串口输出函数

        "\r" 回车符    USART_OUT(USART1, "abcdefg\r")   

"\n" 换行符    USART_OUT(USART1, "abcdefg\r\n")

"%s" 字符串    USART_OUT(USART1, "字符串是:%s","abcdefg")

"%d" 十进制    USART_OUT(USART1, "a=%d",10)

**********************************************************/

void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...){ 

const char *s;

    int d;

    char buf[16];

    va_list ap;

    va_start(ap, Data);


while(*Data!=0){                           //判断是否到达字符串结束符

if(*Data==0x5c){   //'\'

switch (*++Data){

case 'r':           //回车符

USART_SendData(USARTx, 0x0d);    


Data++;

break;

case 'n':           //换行符

USART_SendData(USARTx, 0x0a);

Data++;

break;

default:

Data++;

    break;

}

 

}

else if(*Data=='%'){   //

switch (*++Data){

case 's':   //字符串

                s = va_arg(ap, const char *);

                for ( ; *s; s++) {

                    USART_SendData(USARTx,*s);

while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);

                }

Data++;

                break;

            case 'd':   //十进制

                d = va_arg(ap, int);

                itoa(d, buf, 10);

                for (s = buf; *s; s++) {

                    USART_SendData(USARTx,*s);

while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);

                }

Data++;

                break;

default:

Data++;

    break;

}  

}

else USART_SendData(USARTx, *Data++);

while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);

}

}


/******************************************************

整形数据转字符串函数

        char *itoa(int value, char *string, int radix)

radix=10 标示是10进制 非十进制,转换结果为0;  


    例:d=-379;

执行 itoa(d, buf, 10); 后

buf="-379"       

**********************************************************/

char *itoa(int value, char *string, int radix)

{

    int     i, d;

    int     flag = 0;

    char    *ptr = string;


    /* This implementation only works for decimal numbers. */

    if (radix != 10)

    {

        *ptr = 0;

        return string;

    }


    if (!value)

    {

        *ptr++ = 0x30;

        *ptr = 0;

        return string;

    }


    /* if this is a negative value insert the minus sign. */

    if (value < 0)

    {

        *ptr++ = '-';


        /* Make the value positive. */

        value *= -1;

    }


    for (i = 10000; i > 0; i /= 10)

    {

        d = value / i;


        if (d || flag)

        {

            *ptr++ = (char)(d + 0x30);

            value -= (d * i);

            flag = 1;

        }

    }


    /* Null terminate the string. */

    *ptr = 0;


    return string;


} /* NCL_Itoa */





评论/留言


桂公网安备 45110202000219号

桂ICP备2021005309号


CopyRight@贺州市宇天网络科技有限公司