七弦桐 发表于 2013-5-10 15:53:47

使用6050发现的奇怪现象

MPU6050的SDA线接在板子上时1602不能显示数据,把SDA拔下来时就能正常显示了,不是IO冲突的原因,是什么问题呢?(主控MSP430F149)
不应该是硬件的问题 换了个传感器还是这个问题 大家看下代码吧:
main.c#include <msp430f149.h>
#include <intrinsics.h>
#include "MPU6050.h"
#include "LCD1602.h"
#include "I2C.h"

#define CPU_F ((double)8000000)
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))

/*--------------------------------------------------------
功能:   系统时钟初始化
输入参数: 无                                 
输出参数: 无            
--------------------------------------------------------*/
static void ClockInit(void)
{
        int i;
    BCSCTL2 |= SELM1+SELS;                      //MCLK时钟源为XT2CLK,SMCLK时钟源为XT2CLK
        do{
    IFG1&=~OFIFG;                           //清除震荡标志
    for(i=0;i<100;i++)
       _NOP();                              //延时等待
        }
        while((IFG1&OFIFG)!=0);                 //如果标志为1 ,则继续循环等待
        IFG1&=~OFIFG;
}

/*--------------------------------------------------------
功能:   I/O初始化
输入参数: 无                                 
输出参数: 无            
--------------------------------------------------------*/
static void GPIOInit(void)
{
        P2SEL = 0x00;                             //设置IO口为普通I/O模式
        //P1SEL = 0x00;                     //设置IO口为普通I/O模式
        //P1DIR = 0x00;                                                //P1作为输入                                        
}

/*--------------------------------------------------------
功能:   定时器A初始化
输入参数: 无                                 
输出参数: 无            
--------------------------------------------------------*/
static void TimerAInit(void)
{
        TACTL |= TASSEL_2+TACLR;                               
        TACCTL0 |= CCIE;
        TACTL |= ID_3+MC0;
        TACCR0 = 1000;                                                //定时1ms       
}

/*--------------------------------------------------------
功能:   主函数
输入参数: 无                                 
输出参数: 无            
--------------------------------------------------------*/
void main(void)
{
        WDTCTL = WDTPW + WDTHOLD;

        /*各模块初始化*/
        ClockInit();
        GPIOInit();
        TimerAInit();
        LCDPort_init();
        LCD_init();
       
        LCD_clear();
        InitMPU6050();
        delay_ms(10);
       
        //_EINT();                                                        //开总中断
       
        while(1)
        {               
                  LCD_write_str(1,1,"Welcome");
                //delay_ms(3);
                //Display10BitData(GetData(ACCEL_XOUT_H),2,1);        //显示X轴加速度
                //Display10BitData(GetData(ACCEL_YOUT_H),7,0);        //显示Y轴加速度
                //Display10BitData(GetData(ACCEL_ZOUT_H),12,0);        //显示Z轴加速
        }
}

/*--------------------------------------------------------
功能:   定时器A中断服务程序         
--------------------------------------------------------*/
# pragma vector = TIMERA0_VECTOR               // 提供中断函数的入口地址
__interrupt void TimerA(void)
{       
                //P3OUT = ~P3OUT;                                        //控制灯闪烁
}1602.c:/*********************************************************
                  LCD1602驱动
*********************************************************/
#include <msp430x14x.h>

typedef unsigned int uint;
typedef unsigned char uchar;

#define CPU_F ((double)8000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))

#define P55 5
#define P56 6
#define P57 7

#define RS_CLR        P5OUT &= ~(1 << P55)      //RS置低
#define RS_SET        P5OUT |= (1 << P55)         //RS置高

#define RW_CLR        P5OUT &= ~(1 << P56)      //RW置低
#define RW_SET        P5OUT |= (1 << P56)         //RW置高

#define EN_CLR        P5OUT &= ~(1 << P57)      //E置低
#define EN_SET        P5OUT |= (1 << P57)         //E置高

#define DataPort      P4OUT               //P4口为数据口

/*--------------------------------------------------------
功能:   显示屏IO初始化函数
输入参数: 无                                 
输出参数: 无            
--------------------------------------------------------*/
extern void LCDPort_init(void)
{
       
        P4SEL = 0x00;
    P4DIR = 0xFF;
    P5SEL = 0x00;
    P5DIR|= BIT5 + BIT6 + BIT7;   //控制口设置为输出模式
}

/*--------------------------------------------------------
功能:   显示屏命令写入函数
输入参数: com        要写入的命令                              
输出参数: 无            
--------------------------------------------------------*/
static void LCD_write_com(unsigned char com)
{       
        RS_CLR;
        RW_CLR;
        EN_SET;
        DataPort = com;               //命令写入端口
        delay_ms(5);
        EN_CLR;
}

/*--------------------------------------------------------
功能:   显示屏数据写入函数
输入参数: data        要写入的数据                                 
输出参数: 无            
--------------------------------------------------------*/
static void LCD_write_data(unsigned char data)
{
        RS_SET;
        RW_CLR;
        EN_SET;
        DataPort = data;                //数据写入端口
        delay_ms(5);
        EN_CLR;
}

/*--------------------------------------------------------
功能:   显示屏清空
输入参数: 无                                 
输出参数: 无            
--------------------------------------------------------*/
extern void LCD_clear(void)
{
        LCD_write_com(0x01);            //清屏幕显示
        delay_ms(5);
}

/*--------------------------------------------------------
功能:   显示屏字符串写入函数
输入参数: x        横坐标
                   y        纵坐标(0 1)
                   *s   指向字符串的指针
输出参数: 无            
--------------------------------------------------------*/
extern void LCD_write_str(unsigned char x,unsigned char y,unsigned char *s)
{
       
    if (y == 0)
    {
            LCD_write_com(0x80 + x);      //第一行显示
    }
    else
    {
            LCD_write_com(0xC0 + x);      //第二行显示
    }
   
    while (*s)
    {
            LCD_write_data( *s);
            s ++;
    }
}

/*--------------------------------------------------------
功能:   显示屏单字符写入函数
输入参数: x        横坐标
                   y    纵坐标(0 1)
                   data 字符
输出参数: 无            
--------------------------------------------------------*/
extern void LCD_write_char(unsigned char x,unsigned char y,unsigned char data)
{
       
    if (y == 0)
    {
            LCD_write_com(0x80 + x);      //第一行显示
    }
    else
    {
            LCD_write_com(0xC0 + x);      //第二行显示
    }
   
    LCD_write_data( data);
}

/*--------------------------------------------------------
功能:   显示屏初始化函数
输入参数: 无                                 
输出参数: 无            
--------------------------------------------------------*/
extern void LCD_init(void)
{
    LCD_write_com(0x38);                //显示模式设置
    delay_ms(5);
    LCD_write_com(0x08);                //显示关闭
    delay_ms(5);
    LCD_write_com(0x01);                //显示清屏
    delay_ms(5);
    LCD_write_com(0x06);                //显示光标移动设置
    delay_ms(5);
    LCD_write_com(0x0C);                //显示开及光标设置
    delay_ms(5);
}

//****************************************
//LCD1602显示字符串
//****************************************
void DisplayListChar(uchar X,uchar Y,uchar *DData,uchar L)
{
        uchar ListLength=0;
        Y&=0x1;               
        X&=0xF;               
        while(L--)            
        {                     
                LCD_write_char(X,Y,DData);
                ListLength++;
                X++;                        
        }   
}MPU6050.c:/*********************************************************
                  MPU6050驱动
*********************************************************/
#include "MPU6050.h"
#include "LCD1602.h"
#include "I2C.h"

uchar dis;                                                        //显示数字(-511至512)的字符数组
int        dis_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;   //合成数据
}

//**************************************
//在1602上显示10位数据
//**************************************
void Display10BitData(int value,uchar x,uchar y)
{
        value/=64;                                                        //转换为10位数据
        lcd_printf(dis, value);                        //转换数据显示
        LCD_write_str(x,y,dis);
        //DisplayListChar(x,y,dis,4);        //启始列,行,显示数组,显示长度
}

/*--------------------------------------------------------------------
功能:整数转字符串(便于在1602上显示)
--------------------------------------------------------------------*/
void lcd_printf(uchar *s,int temp_data)
{
        if(temp_data<0)
        {
                temp_data=-temp_data;
                *s='-';
        }
        else *s=' ';
        *++s =temp_data/100+0x30;
        temp_data=temp_data%100;   //取余运算
        *++s =temp_data/10+0x30;
        temp_data=temp_data%10;      //取余运算
        *++s =temp_data+0x30;        
}

I2C.c:/*********************************************************
                  I2C驱动
*********************************************************/
#include"msp430x14x.h"
#include "MPU6050.h"
//#define      SDA   P2.1
//#define      SCL   P2.0

#define   SDA_1      P2OUT |= BIT1 //SDA = 1
#define   SDA_0      P2OUT &= ~BIT1 //SDA = 0
#define   SCL_1      P2OUT |= BIT0 //SCL = 1
#define   SCL_0      P2OUT &= ~BIT0 //SCL = 0
#define   DIR_IN       P2DIR &= ~BIT1 //I/O 口为输入
#define   DIR_OUT      P2DIR |= BIT1 //SDA 输出数据
#define   SDA_IN       ((P2IN >> 1) & 0x01)
#define   TIME      5            //I2C 时序延时时间

unsigned int uiSendDataBuffer;
unsigned int uiReceiveDataBuffer;

/****************************************
*FUNCTION NAME: I2CDelay();
*CREATE DATE:2006.09.07
*CREATED BY:DreamHW
*FUNCTION:I2C 总线必要的延时程序
Y DATE:
*INPUT:n->延时时间数 相当于指令周期数
*OUTPUT:nop
*RETURN:nop
****************************************/
void I2CDelay(unsigned int n)
{
    unsigned int i;
    for(i = 0;i < n;i++)
    {
         ;
    }
}

/****************************************
*FUNCTION NAME: I2CStart();
*CREATE DATE:2006.09.07
*CREATED BY:DreamHW
*FUNCTION:I2C 总线启动时序
*MODIFY DATE:
*INPUT:nop
*OUTPUT:nop
*RETURN:nop
****************************************/
void I2CStart(void)
{
    DIR_OUT;
    SDA_1;
    I2CDelay(TIME);
    SCL_1;
    I2CDelay(TIME);
    SDA_0;
    I2CDelay(TIME);
    SCL_0;
}

/****************************************
*FUNCTION NAME: I2CStop();
*CREATE DATE:2006.09.07
*CREATED BY:DreamHW
*FUNCTION:I2C 总线停止时序
*MODIFY DATE:
*INPUT:nop
*OUTPUT:nop
RETURN:nop
****************************************/
void I2CStop(void)
{
    DIR_OUT;
    SDA_0;
    I2CDelay(TIME);
    SCL_1;
    I2CDelay(TIME);
    SDA_1;
}

/****************************************
*FUNCTION NAME: I2CReceiveACK();
CREATE DATE:    2006.09.08
*CREATED BY:DreamHW
*FUNCTION:等待接受 ACK 信号,完成一次操作
*MODIFY DATE:
*INPUT:nop
*OUTPUT:nop
*RETURN:nop
****************************************/
void I2CReceiveACK(void)
{
    SCL_1;
    I2CDelay(TIME);//
    DIR_IN;
    while(SDA_IN);
    DIR_OUT;
    SCL_0;
    I2CDelay(TIME);
}

/****************************************
*FUNCTION NAME: I2CSendByte();
*CREATE DATE: 2006.09.08
*CREATED BY:DreamHW
*FUNCTION:I2C 送一个字节的数据
*MODIFY DATE:
*INPUT:ucWRData
*OUTPUT:nop
*RETURN:nop
****************************************/
void I2CSendByte(unsigned char ucWRData)
{
    DIR_OUT;
    unsigned int i;
    for(i = 0;i < 8;i++)
    {
      SCL_0;
      I2CDelay(TIME);
      if((ucWRData >> 7) & 0x01) SDA_1;//最高位是否为 1,为则SDA= 1
      else SDA_0;                      //否则 SDA=0
      I2CDelay(TIME);
      SCL_1;
      I2CDelay(TIME);
      ucWRData <<= 1 ;//数据左移一位,进入下一轮送数
    }
    SCL_0;//
    SDA_1;//等待ack
    I2CDelay(TIME);
       
        I2CReceiveACK();       
}



/****************************************
*FUNCTION NAME: I2CReceiveByte();
*CREATE DATE:2006.09.08
*CREATED BY:DreamHW
*FUNCTION:接受一个字节的数据
*MODIFY DATE:
*INPUT:nop
*OUTPUT:ucRDData
*RETURN:ucRDData
****************************************/
unsigned char I2CReceiveByte(void)
{
    unsigned char i;
    unsigned char ucRDData = 0;//返回值
    unsigned char ucDataBit = 0;//每一个 clk 接受到的数据
    SCL_0;
    I2CDelay(TIME);
    SDA_1;
    DIR_IN;
    for(i = 0;i < 8;i++)
    {
      SCL_1;
      I2CDelay(TIME);
      ucDataBit = SDA_IN;
      I2CDelay(TIME);
                ucRDData = ((ucRDData << 1) | ucDataBit);//将数据依次存入 ucRDData
      SCL_0;
      I2CDelay(TIME);
    }
    return(ucRDData);
}

/****************************************
*FUNCTION NAME: I2CAcknowledge();
*CREATE DATE:    2006.09.08
*CREATED BY:DreamHW
*FUNCTION:接受数据后发送一个 ACK 信号
*MODIFY DATE:
*INPUT:nop
*OUTPUT:nop
*RETURN:nop
****************************************/
void I2CAcknowledge(void)
{
    SCL_0;
    DIR_OUT;
    SDA_0;
    I2CDelay(TIME);
    SCL_1;
    I2CDelay(TIME);
    SCL_0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------------------------
功能:   向I2C设备写入一个字节数据
输入参数:                                 
输出参数: 无            
--------------------------------------------------------*/
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
    I2CStart();                  //起始信号
    I2CSendByte(SlaveAddress);   //发送设备地址+写信号
    I2CSendByte(REG_Address);    //内部寄存器地址,
    I2CSendByte(REG_data);       //内部寄存器数据,
    I2CStop();                   //发送停止信号
}

/*--------------------------------------------------------
功能:   从I2C设备读取一个字节数据
输入参数:                                 
输出参数: 无            
--------------------------------------------------------*/
unsigned char Single_ReadI2C(uchar REG_Address)
{
        uchar REG_data;
        I2CStart();                   //起始信号
        I2CSendByte(SlaveAddress);    //发送设备地址+写信号
        I2CSendByte(REG_Address);   //发送存储单元地址,从0开始       
        I2CStart();                   //起始信号
        I2CSendByte(SlaveAddress+1);//发送设备地址+读信号
        REG_data=I2CReceiveByte();       //读出寄存器数据
        I2CAcknowledge();                //接收应答信号
        I2CStop();                  //停止信号
        return REG_data;
}

lijungei 发表于 2013-5-17 16:56:50

我的也是这样楼主 解决问题没有呀

七弦桐 发表于 2013-5-17 17:53:39

lijungei 发表于 2013-5-17 16:56 static/image/common/back.gif
我的也是这样楼主 解决问题没有呀

IIC等到握手信号没等到呗 然后程序就一直while在等待握手信号那句代码了
页: [1]
查看完整版本: 使用6050发现的奇怪现象