搜索
bottom↓
回复: 6

我用AVR的TWI 读取MU6050,6个数据全显示为-023,哪位大神看.....

[复制链接]

出0入0汤圆

发表于 2013-8-2 16:47:10 | 显示全部楼层 |阅读模式
//系统时钟8M
#include <iom128v.h>
#include <string.h>
#include <stdio.h>
#include"1602.h"
#include "twi_master.h"
#include"mpu_6050.h"


#define uchar unsigned char
#define uint  unsigned int

uchar dis[4];          //存储要显示的(并且已经转化为字符串的)数据的ASCII码
uchar receive_data;
uchar send_data;
uchar bMastRead;                                                   //读写控制标志位
uchar cSendSlaveAddress;                                //从机地址+写信号   
uchar reg_read_adress;                                        //要读寄存器的地址
uchar reg_address;                                                //要写入寄存器的地址
uchar bSign1ms;
char i,j;
/********************************************/
//定时器0溢出中断服务例程
// Timer 0 overflow interrupt service routine
/********************************************/
//interrupt [TIM0_COMP] void timer0_comp_isr(void)
#pragma interrupt_handler time0_interrupt:iv_TIM0_OVF
void time0_interrupt(void)
{         
        TCNT0=216;                  //计数器赋初值定时为5MS
        bSign1ms = 1;
}                       

/********************************************/
//*******定时器0初始化
/********************************************/       
void time0_init(void)
{
        ASSR=0x00;                 //一般不用配置
        TCCR0=0x07;                 //普通模式,正常端口输出,1024分频
        TCNT0=216;                  //计数器赋初值定时为5MS
        TIFR=0X01;                 //清除中断标志
       
        TIMSK=0X01;                 //使能定时器溢出中断
        SREG|=0x80;                 //使能全局中断
}
/********************************************/
//*****I2C总线初始化
/********************************************/
void twi_init(void)
         {
          TWSR=0x11;   //0X00不分频  0x01 4,0x10 16,0x11 64分频
          TWBR=0x40;   // 大约为970HZ  (对应于8M晶振)
          TWAR=0x00;   //不作为从机,可不管                  
         // TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE);//TWCR=0x05;
         }

/********************************************/
//*****发送一个字节数据
/********************************************/
void twi_send(uchar REG_Address,uchar REG_data) //向MPU6050的REG_Address寄存器写入REG_data
{
bMastRead=0;
reg_address=REG_Address;
send_data=REG_data;
StartTwiMaster();
}
/********************************************/
//*****接收一个字节数据
/********************************************/
unsigned char twi_receive(uchar REG_Address )  //从MPU6050的REG_Adress寄存器读取数据
{
bMastRead=1;
reg_read_adress=REG_Address;
StartTwiMaster();
return receive_data;
}
/********************************************/
//*****MPU_6050初始化
/********************************************/
void mpu6050_init(void)
         {
        //  cSendSlaveAddress=SlaveAddress;  
        twi_send(PWR_MGMT_1, 0x80);
        delay_nms(10);
        twi_send(PWR_MGMT_1, 0x01);
        twi_send(PWR_MGMT_1, 0x00);          //解除休眠状态  关闭温度传感器

        twi_send(SMPLRT_DIV, 0x07);   //陀螺仪采样率,典型值:0x07(125Hz)
        twi_send(CONFIG, 0x06);                  //低通滤波频率,典型值:0x06(5Hz)
        twi_send(GYRO_CONFIG, 0x18);  //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
        twi_send(ACCEL_CONFIG, 0x01); //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)          
         }
//**************************************
//合成数据
//**************************************
int GetData(uchar REG_Address)
{
        char H,L;
        H=twi_receive(REG_Address);                        //一个数据有两个8位寄存器存储,且地址相邻
        L=twi_receive(REG_Address+1);
        return (H<<8)+L;   //合成数据
}
//****************************************
//将数据转字符串存在指针*s指向的数组里
//****************************************
void lcd_printf(uchar *s,int temp_data)          //将temp_data转化为对应  符号,百,十,个位数的ASCII码,
{                                                                                  //并存入指针*s指向首地址的数组  ,,将来lcd调用显示
        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;        
}
//**************************************
//在1602上显示10位数据
//**************************************
void Display10BitData(int value,uchar x,uchar y)
{
        value%=100;                                        //(相当于右移6位)转换为10位数据
        lcd_printf(dis, value);                //转换数据显示
        LCD_dis_string(x,y,dis,4);        //启始列,行,显示数组,显示长度
}
/***************** 2 Wire bus interrupt service routine *****************
模式标志位:(TWAR = 0x01,bMastRead = 1)->主机接收模式;
                        (TWAR = 0x00,bMastRead = 0)->主机发送模式;
        主机发送模式:
                写发送地址cSendSlaveAddress,包括广播地址和从机地址,bFinishSendData;
        主机接收模式:
                写接收地址cReceiveSlaveAddress,bFinishReceiveData;
*************************************************************************/
#pragma interrupt_handler twi_isr:34
void twi_isr(void)
{
        unsigned char cStatusCode=0;        //定义TWI状态,用于读取状态寄存器与预定的状态比较
        cStatusCode = TWSR & 0xF8;        //屏蔽分频因子?
/***********************接收模式*******************/        
if(bMastRead==1)                   
   {
         switch(cStatusCode)
                 {
                   case MT_START_08:                         //start已经发送,接下来发送SLA+W
                    PORTA|=(1<<0);
                       TWDR =cSendSlaveAddress;       //要写器件的地址+写信号
                         LoadSLA_W();               
                         break;
                 case MT_RESTART_10:           //重复START已发送
                PORTA|=(1<<1);                 
                         TWDR = cSendSlaveAddress+1 ;    //SLA+R
                        LoadSLA_R();                           //发送SLA+R
                        break;               
                 
                 case MT_SLAW_ACK_18:                         //SLA+W 已发送;接收到 ACK
                    PORTA|=(1<<2);
                        TWDR=reg_read_adress; //写入要读寄存器的地址
                        //TWDR= 0x3B;                        
                        SendData();                                         
                        break;
                case MT_SLAW_NACK_20:                        //SLA+W 已发送接收到   NACK
                        SendStop();                                        //TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)发送停止信号并使能中断
                        break;

                       
                case MT_DATA_ACK_28:                        //数据(要读寄存器首地址)已经发送,接收到ACK
                    PORTA|=(1<<3);
                    reStartTwiMaster();                          //发送RESTART信号       
                        break;               
       
                case MR_SLAR_ACK_40:                        //SLA+R 已发送接收到ACK
                    PORTA|=(1<<4);
                        receive_data=TWDR;                        //读出cSendSlaveAddress地址中的数据                                 
                        SendAck();
                        //SendStop();                                        //发送应答信号
                        break;               
                case MR_SLAR_NACK_48:                        //SLA+R 已发送接收到NACK
                        SendStop();
                        break;       
  
                case MR_DATA_ACK_50:                        //数据已经收到,应答
                    PORTA|=(1<<5);                                        
                        SendStop();         
                        break;               
                case MR_DATA_NACK_58:                         
                    PORTA|=(1<<6);               
                        SendStop();
                        break;         
                         
            }
   }
/***********************发送模式*******************/        
  else
   {
        switch(cStatusCode)
                {
                case MT_START_08:                     //start已经发送,将来发送SLA+W
                        //  PORTA|=(1<<0);
                   // TWDR =0XD0;             //要写器件的地址+写信号
                        TWDR =cSendSlaveAddress;      //要写器件的地址+写信号
                         LoadSLA_W();//主机发送,,,TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)发送地址,开中断
                        break;
                       
                 case MT_RESTART_10:             //重复START已发送,将来发送SLA+W或者SLA+R
                        //  PORTA|=(1<<1);
                      TWDR =0XD0;//cSendSlaveAddress;         //要写器件的地址+写信号
                         LoadSLA_W();//主机发送,,,TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)发送地址,开中断
                        break;
                 
            case MT_SLAW_ACK_18:                        //SLA+W 已发送;接收到 ACK
                         //  PORTA|=(1<<2);
                        //TWDR=0X19;                           
                        TWDR=reg_address;                //写入要写寄存器的地址
                        SendData();                                        //发送数据(地址),,,清零中断标志,TWI使能,TWI中断使能
                        break;
            case MT_SLAW_NACK_20:                        //SLA+W 已发送接收到   NACK                         
                        SendStop();                                        //TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)发送停止信号并使能中断
                        break;
                       
            case MT_DATA_ACK_28:                        // (要读寄存器地址)已经发送,接收到ACK               
                    if(i==0)                                        //i==0时为发送数据,i!=1时发送STOP;
                        {
                     ///PORTA|=(1<<3);           
                        //TWDR =0x07;      
                        TWDR = send_data;     //将要写的数据写进寄存器
                        i+=1;
                        LoadSLA_W();                    //写入数据
                        break;               
                        }
                        else
                        {
                        i=0;
                          //  PORTA|=(1<<4);
                         SendStop();       
                         break;
                        }
            case MT_DATA_NACK_30:                        //数据已经发送,接收到NACK            
                        //SendStop();                                 
                        break;               
                         
                case MT_SLAW_DATA_LOST:
                     PORTA|=1<<7;
                        SendStop();       
            }
   }                       
}       
//*************************************************************************
//                        主程序
//*************************************************************************/
void main(void)
{         
  uchar a;

    cSendSlaveAddress=SlaveAddress;
        DDRA=0XFF;
        DDRE=0XFF;
        PORTA=0X00;
        twi_init();     //TWI相关初始化,波特率
        delay_nms(10);                              
        LCD_init();                   
        //time0_init();                                 
        SREG|=0x80;               
        mpu6050_init();
         bMastRead=1;
         StartTwiMaster();

    while(1)
           {
            Display10BitData(GetData(ACCEL_ZOUT_H),2,0);        //显示X轴加速度
       // delay_nms(100);
           Display10BitData(GetData(ACCEL_XOUT_H),2,1);        //显示X轴加速度
       }

       
        /*
while (1)
   {

                //Display10BitData(128,2,0);        //显示X轴加速度
               
                Display10BitData(GetData(ACCEL_XOUT_H),2,0);        //显示X轴加速度                               
                Display10BitData(GetData(ACCEL_YOUT_H),7,0);        //显示Y轴加速度
                Display10BitData(GetData(ACCEL_ZOUT_H),12,0);        //显示Z轴加速度

                Display10BitData(GetData(GYRO_XOUT_H),2,1);        //显示X轴角速度
                Display10BitData(GetData(GYRO_YOUT_H),7,1);        //显示Y轴角速度
                Display10BitData(GetData(GYRO_ZOUT_H),12,1);        //显示Z轴角速度

  }                                 */                         
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2013-8-2 16:47:57 | 显示全部楼层
//#ifndef twi_master
//#define twi_master


/*************TWI相关宏定义*************************/
//主机发送模式:状态寄存器TWSR状态码定义
#define MT_START_08                                 0x08        //A START condition has been transmitted
#define MT_RESTART_10                                 0x10        //A repeated START condition has been transmitted
#define MT_SLAW_ACK_18                                 0x18        //SLA+W has been transmitted;ACK has been received
#define MT_SLAW_NACK_20                         0x20        //SLA+W has been transmitted;NOT ACK has been received
#define MT_DATA_ACK_28                                 0x28        //Data byte has been transmitted;ACK has been received
#define MT_DATA_NACK_30                         0x30        //Data byte has been transmitted;NOT ACK has been received
#define MT_SLAW_DATA_LOST                 0x38        //Arbitration lost in SLA+W or data bytes

//主机接收模式:状态寄存器TWSR状态码定义
//#define MR_SLAR_LOST_NACK 0x38
#define MR_SLAR_ACK_40                                 0x40
#define MR_SLAR_NACK_48                         0x48
#define MR_DATA_ACK_50                                 0x50
#define MR_DATA_NACK_58                         0x58

//控制寄存器TWCR位定义
#define TWINT         7                //TWI Interrupt Flag
#define TWEA         6                //TWI Enable Acknowledge Bit
#define TWSTA   5                //TWI START Condition Bit
#define TWSTO   4                //TWI STOP Condition Bit
#define TWWC         3                //TWI Write Collision Flag
#define TWEN         2                //TWI Enable Bit
#define TWIE         0                //TWI Interrupt Enable


//TWI控制函数
#define StartTwiMaster()        TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE) //发送start信号
#define reStartTwiMaster()        TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE) //发送start信号
#define LoadSLA_W()                        TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)                 //发送 地址+写
#define SendData()                        TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)                    //发送数据

#define ReStart()                        TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE) //发送start信号
#define SendStop()                        TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)           //发送stop信号

#define LoadSLA_R()                        TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWIE)           //发送 地址+读
#define Send_r_add()                TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWIE)                   //发送 要读寄存器的地址

#define SendAck()                        TWCR=(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)  //发送 ACK
#define SendNack()                        TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)                           //发送 NACK

//#endif

出0入0汤圆

 楼主| 发表于 2013-8-2 16:48:46 | 显示全部楼层

/*************MPU6050相关寄存器地址宏定义*********************/


#define        SMPLRT_DIV                0x19        //陀螺仪采样率,典型值:0x07(125Hz) **采样率 = 陀螺仪的输出率/(1+SMPLRT_DIV)  
                                                                //数字低通滤波器未使能时8kHz反之1kHz
#define        CONFIG                        0x1A        //低通滤波频率,典型值:0x06(5Hz)
#define        GYRO_CONFIG                0x1B        //陀螺仪自检及测量范围,典型值:0x18(不自检,2000度/s范围)
#define        ACCEL_CONFIG        0x1C        //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,+-2g范围,5Hz)

#define        ACCEL_XOUT_H        0x3B        //存储最近X,Y,Z轴加速度传感器测量值
#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为读取

出0入0汤圆

 楼主| 发表于 2013-8-2 16:52:32 | 显示全部楼层
//编译环境 ICCAVR 7.16A
//系统时钟 8MHZ,设置熔丝位为外部高频石英晶体振荡,启动时间4.1ms
//***********************************************************************
//                        包含文件
//***********************************************************************

#include <string.h>
#include <stdio.h>
//#include <delay.h>
#include <iom128v.h>

#define uchar unsigned char
#define uint  unsigned int

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

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

#define Data_IO                PORTC                //液晶数据口
#define Data_DDR        DDRC                 //数据口方向寄存器

//*************************************************************************
//                        IO端口初始化子程序
//*************************************************************************
void LCDio_init(void)
{

        Data_IO = 0xFF;                                        //电平设置
        Data_DDR = 0xFF;                                    //方向输出
        PORTF = 0xFF;                       //电平设置
        DDRF = 0xFF;                        //方向输出
    PORTC=0xFF;
        DDRC=0xFF;

}
/********************************************
延时1MS
7.3278M:i<1051 实际999.5us   
8M:i<1180  999.417us  i<1051  890.583us
1M:i<140   999.167us
********************************************/
void delay_1ms(void)            
  {
   unsigned int i;
   for (i=0;i<1180;i++);
  }
  
void delay_nms(unsigned int n)       //N ms精确延时nms
  {
   unsigned int i=0;
   for (i=0;i<n;i++)
   delay_1ms();
  }

//***********************************************************************
//        显示屏命令写入函数
//***********************************************************************


void LCD_write_com(unsigned char com)
{       
        RS_CLR;
        //RW_CLR;
        Data_IO = com;
        EN_SET;
        delay_nms(5);
        EN_CLR;
}
//***********************************************************************
//        显示屏数据写入函数
//***********************************************************************

void LCD_write_data(unsigned char data)
{
        RS_SET;
        //RW_CLR;
        Data_IO = data;
        EN_SET;       
        delay_nms(5);
        EN_CLR;
}
//***********************************************************************
//        显示屏清空显示
//***********************************************************************

void LCD_clear(void)
{
        LCD_write_com(0x01);
        delay_nms(5);
}
//***********************************************************************
//        显示单字符
//***********************************************************************

void LCD_dis_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);  
}
//***********************************************************************
//        显示字符串
//***********************************************************************

void LCD_dis_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 ++;
    }
}
//显示指针*s指向首地址的数组里的数据,num为要数据的个数
void LCD_dis_string(uchar x,uchar y,uchar *s,uchar num)
{
        unsigned char length=0;
        x&=0x0f;
        y&=0x01;
        while(num--)
        {
                        LCD_dis_char(x,y,s[length]);
                        length++;
                        x++;
        }
}
//***********************************************************************
//        显示屏初始化函数
//***********************************************************************

void LCD_init(void)
{
         LCDio_init();
        //DDRA = 0xFF;                                        //I/O口方向设置
        //DDRA |= (1 << PA5) | (1 << PA6) | (1 << PA7);
        LCD_write_com(0x38);                                //显示模式设置
        delay_nms(5);
        LCD_write_com(0x08);                                //显示关闭
        delay_nms(5);
    LCD_write_com(0x01);                                //显示清屏
        delay_nms(5);
    LCD_write_com(0x06);                                //显示光标移动设置
        delay_nms(5);
        LCD_write_com(0x0C);                                //显示开及光标设置
    delay_nms(5);
        LCD_dis_char(0,0,'A');
        LCD_dis_char(0,1,'G');
       
}

出0入0汤圆

 楼主| 发表于 2013-8-2 16:58:31 | 显示全部楼层
补充说明一,下那些.H文件只是相关函数的声明,,twi中断函数里的PA端口是为了看一下程序跑了哪了,结果都正确,中断也表示读到了数据,就是显示不对,希望好心人帮忙看看,小弟弄了一周了

出0入0汤圆

发表于 2013-10-14 21:12:11 | 显示全部楼层
同求帮顶。。

出0入0汤圆

发表于 2017-2-16 10:42:10 | 显示全部楼层
你好,前辈,我也在弄ATmega16和MPU6050通讯。老是出故障,可以分享一下源码吗?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 01:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表