打印

调试四轴飞行器

[复制链接]
1391|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jxmzzr|  楼主 | 2014-6-4 10:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
调IIC好几天了,始终进展不大,用示波器测波形一直高,没有什么上升沿或下降沿出现。求朋友们指点一下,最好把程序留一下,十分感谢!
沙发
icecut| | 2014-6-4 11:19 | 只看该作者
用gpio去读写一下.没问题就继续换iic 硬件方式

使用特权

评论回复
板凳
mmuuss586| | 2014-6-4 11:33 | 只看该作者
ST的IIC调试起来比较麻烦;
先用硬件模拟看看;

使用特权

评论回复
地板
assans| | 2014-6-4 15:35 | 只看该作者
用的i2c1?和fsmc冲突了

使用特权

评论回复
5
拿起书本| | 2014-6-4 16:04 | 只看该作者
/*----------------------------------------------------
* 模块名:  I2C.c
* 功能描述:I2C接口驱动,软件模拟I2C接口时序
*----------------------------------------------------*/

#include "I2C.h"

/*----------------------------------------------------
* 函数原型:void I2C_delay(void)
* 功    能:I2C延时
* 输    入:无
* 输    出:无
* 备    注:
*----------------------------------------------------*/
void I2C_delay(void)
{        
   uint8_t i=5;
   while(i)
   {
     i--;
   }
}

/*----------------------------------------------------
* 函数原型:void I2C_NoAck(void)
* 功    能:产生NoAck信号
* 输    入:无
* 输    出:无
* 备    注:第9个周期SCL为高,SDA为高
*----------------------------------------------------*/
void I2C_NoAck(void)
{        
        SCL_L;
        I2C_delay();
        SDA_H;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}

/*----------------------------------------------------
* 函数原型:void I2C_Initial()
* 功    能:I2C初始化
* 输    入:无
* 输    出:无
* 备    注:配置SCL和SDA引脚
*----------------------------------------------------*/
void I2C_Initial()
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*----------------------------------------------------
* 函数原型:bool I2C_Start(void)
* 功    能:产生开始标志
* 输    入:无
* 输    出:bool:FALSE--总线忙,TRUE--启动成功
* 备    注:SCL为高,SDA下降沿
*----------------------------------------------------*/
bool I2C_Start(void)
{
        SDA_H;
        SCL_H;
        I2C_delay();
        if(!SDA_read)return FALSE;        //SDA线为低电平则总线忙,退出
        SDA_L;
        I2C_delay();
        if(SDA_read) return FALSE;        //SDA线为高电平则总线出错,退出
        SDA_L;
        I2C_delay();
        return TRUE;
}

/*----------------------------------------------------
* 函数原型:void I2C_Stop(void)
* 功    能:产生停止标志
* 输    入:无
* 输    出:无
* 备    注:SCL为高,SDA上升沿
*----------------------------------------------------*/
void I2C_Stop(void)
{
        SCL_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SDA_H;
        I2C_delay();
}

/*----------------------------------------------------
* 函数原型:void I2C_Ack(void)
* 功    能:产生ACK应答信号
* 输    入:无
* 输    出:无
* 备    注:第9个周期时,SCL为高,SDA为低
*----------------------------------------------------*/
void I2C_Ack(void)
{        
        SCL_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}

/*----------------------------------------------------
* 函数原型:void I2C_SendByte(uint8_t SendByte)
* 功    能:发送一个字节
* 输    入:SendByte:待发送的数
* 输    出:无
* 备    注:数据从高位到低位
*----------------------------------------------------*/
void I2C_SendByte(uint8_t SendByte)
{
    uint8_t i=8;
    while(i--)
    {
        SCL_L;
        I2C_delay();
      if(SendByte&0x80)
        SDA_H;  
      else
        SDA_L;   
        SendByte<<=1;
        I2C_delay();
                SCL_H;
        I2C_delay();
    }
    SCL_L;
}

/*----------------------------------------------------
* 函数原型:void I2C_SendAddress(uint8_t Address, uint8_t Direction)
* 功    能:发送器件地址与读写标志
* 输    入:Address:器件地址
*           Direction:方向 0--写,1--读
* 输    出:无
* 备    注:将7位器件地址与1位读写标志组合,然后发送
*----------------------------------------------------*/
void I2C_SendAddress(uint8_t Address, uint8_t Direction)
{               
        uint8_t send_data;
        send_data = Address << 1;
    send_data |= (Direction & 0x01);
    I2C_SendByte(send_data);      
}

/*----------------------------------------------------
* 函数原型:bool I2C_ChkAck(void)
* 功    能:检测有无收到Ack确认
* 输    入:无
* 输    出:bool:1--ACK, 0--NoAck
* 备    注:
*----------------------------------------------------*/
bool I2C_ChkAck(void)         
{
        SCL_L;
        I2C_delay();
        SDA_H;                        
        I2C_delay();
        SCL_H;
        I2C_delay();
        if(SDA_read)
        {
      SCL_L;
      return FALSE;
        }
        SCL_L;
        return TRUE;
}

/*----------------------------------------------------
* 函数原型:bool I2C_ReadByte(uint8_t DevAddr,
             uint8_t RegAddr, uint8_t* pRcvData)
* 功    能:从指定器件读取指定寄存器中的值
* 输    入:DevAddr:器件地址
*           RegAddr:寄存器地址
*           pRcvData:接收数据地址指针
* 输    出:bool:TRUE--读取成功, FALSE--读取失败
* 备    注:
*----------------------------------------------------*/
bool I2C_ReadByte(uint8_t DevAddr, uint8_t RegAddr, uint8_t* pRcvData)
{               
        if(!I2C_Start())
                return FALSE; // 发送启动标志

    I2C_SendAddress(DevAddr, DIR_WRITE); // 发送器件地址与写标志

    if(!I2C_ChkAck())
                return FALSE; // 等待应答信号

        I2C_SendByte(RegAddr); // 发送寄存器地址
        
        if(!I2C_ChkAck())
                return FALSE; // 等待应答信号

        if(!I2C_Start())
                return FALSE; // 发送启动标志

        I2C_SendAddress(DevAddr, DIR_READ); // 发送器件地址与读标志
        
        if(!I2C_ChkAck())
                return FALSE; // 等待应答信号
        
        *pRcvData = I2C_ReceiveByte();
        
        I2C_NoAck(); // 发送NoAck信号
        
        I2C_Stop();            
        
        return TRUE;
}

/*----------------------------------------------------
* 函数原型:uint8_t I2C_ReceiveByte(void)
* 功    能:I2C接收一个字节
* 输    入:无
* 输    出:uint8_t:接收到的数据
* 备    注:数据从高位到地位依次接收
*----------------------------------------------------*/
uint8_t I2C_ReceiveByte(void)  
{
    uint8_t i=8;
    uint8_t ReceiveByte = 0;

    SDA_H;                                
    while(i--)
    {
      ReceiveByte <<= 1;      
      SCL_L;
      I2C_delay();
          SCL_H;
      I2C_delay();        
      if(SDA_read)
      {
        ReceiveByte |= 0x01;
      }
    }
    SCL_L;
    return ReceiveByte;
}

/*----------------------------------------------------
* 函数原型:bool I2C_ReadBuffer(uint8_t DevAddr, uint8_t RegAddr,
             uint8_t* pBuffer, uint8_t NumByteToRead)
* 功    能:连续读取指定器件中的数据
* 输    入:DevAddr:器件地址
*           RegAddr:寄存器地址
*           pBuffer:接收的数组
*           NumByteToRead:读取的字节数
* 输    出:bool:成功标志 TRUE--读取成功,FALSE--读取失败
* 备    注:
*----------------------------------------------------*/
bool I2C_ReadBuffer(uint8_t DevAddr, uint8_t RegAddr, uint8_t* pBuffer, uint8_t NumByteToRead)
{
          if(!I2C_Start())
                return FALSE;

    I2C_SendAddress(DevAddr, DIR_WRITE); // 发送器件地址和写标志

    if(!I2C_ChkAck())  // 等待确认应答
                return FALSE;

    I2C_SendByte(RegAddr); // 发送寄存器地址

        if(!I2C_ChkAck()) // 等待确认应答        
                return FALSE;

          if(!I2C_Start())
                return FALSE;

    I2C_SendAddress(DevAddr, DIR_READ); // 发送器件地址和写标志

        if(!I2C_ChkAck())  // 等待确认应答
                return FALSE;

        while(NumByteToRead--)
        {
             *pBuffer++ = I2C_ReceiveByte(); // 接收数据
                if(NumByteToRead > 0) // 最后一次发送NoAck
                {
                        I2C_Ack();  // 发送Ack确认应答
                }
        }

        I2C_NoAck(); // 发送NoAck信号
        I2C_Stop();
        
        return TRUE;   
}

/*----------------------------------------------------
* 函数原型:bool I2C_WriteByte(uint8_t DevAddr, uint8_t RegAddr, uint8_t data)
* 功    能:单字节写入
* 输    入:DevAddr:地址
*           RegAddr:寄存器地址
*           data:待写数据
* 输    出:bool:成功标志 TRUE--写入成功,FALSE--写入失败
* 备    注:
*----------------------------------------------------*/
bool I2C_WriteByte(uint8_t DevAddr, uint8_t RegAddr, uint8_t data)
{               
    if(!I2C_Start()) return FALSE; // 发送起始标志

    I2C_SendAddress(DevAddr, DIR_WRITE); // 发送器件地址和写标志

        if(!I2C_ChkAck())return FALSE; // 等待确认信号

        I2C_SendByte(RegAddr); // 发送寄存器地址

        if(!I2C_ChkAck()) return FALSE;        // 等待确认信号

        I2C_SendByte(data); // 发送数据

    if(!I2C_ChkAck()) return FALSE;         // 等待确认信号
         
    I2C_Stop();  // 发送停止标志
        return TRUE;
}

/*----------------------------------------------------
* 函数原型:bool I2C_WriteBuffer(uint8_t DevAddr,
             uint8_t RegAddr, uint8_t* pBuffer,
                         uint8_t NumByteToWrite)
* 功    能:连续字节写入
* 输    入:DevAddr:器件地址
*           pBuffer:待写数据数组
*           RegAddr:寄存器地址
*           NumByteToWrite:写入字节数量
* 输    出:bool:成功标志 TRUE--写入成功,FALSE--写入失败
* 备    注:
*----------------------------------------------------*/
bool I2C_WriteBuffer(uint8_t DevAddr, uint8_t RegAddr, uint8_t* pBuffer, uint8_t NumByteToWrite)
{
          if(!I2C_Start()) return FALSE;

    I2C_SendAddress(DevAddr, DIR_WRITE); // 发送器件地址和写标志

    if(!I2C_ChkAck()) return FALSE; // 等待确认应答

    I2C_SendByte(RegAddr); // 发送寄存器地址

        if(!I2C_ChkAck()) return FALSE; // 等待确认应答

        while(NumByteToWrite > 0)
        {
             I2C_SendByte(*pBuffer); // 发送数据
                I2C_ChkAck(); // 等待确认应答
                pBuffer++;
                NumByteToWrite--;
        }
        I2C_Stop();         

        return TRUE;
}



使用特权

评论回复
评分
参与人数 1威望 +5 收起 理由
大秦正声 + 5 赞一个!
6
拿起书本| | 2014-6-4 16:05 | 只看该作者
#ifndef __I2C_H__
#define __I2C_H__
/*----------------------------------------------------
*   包含文件
*----------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_i2c.h"
#include <stdio.h>

/*----------------------------------------------------
*   宏定义
*----------------------------------------------------*/
#define SCL_H                GPIO_SetBits(GPIOB, GPIO_Pin_6)          // SCL高
#define SCL_L                GPIO_ResetBits(GPIOB, GPIO_Pin_6) // SCL低

#define SDA_H                GPIO_SetBits(GPIOB, GPIO_Pin_7)          // SDA高
#define SDA_L                GPIO_ResetBits(GPIOB, GPIO_Pin_7) // SDA低

#define SCL_read        GPIOB->IDR  & GPIO_Pin_6                  // 读取SCL
#define SDA_read        GPIOB->IDR  & GPIO_Pin_7                  // 读取SDA

#define DIR_WRITE         0                                                                  // 写
#define DIR_READ         1                                                                  // 读

/*----------------------------------------------------
*   全局函数
*----------------------------------------------------*/
void I2C_Initial(); // I2C初始化


bool I2C_ReadByte(uint8_t DevAddr, uint8_t RegAddr, uint8_t* pRcvData); /* 单字节读取 */


bool I2C_ReadBuffer(uint8_t DevAddr, uint8_t RegAddr, uint8_t* pBuffer, uint8_t NumByteToRead);        /* 连续字节读取        */


bool I2C_WriteByte(uint8_t DevAddr, uint8_t RegAddr, uint8_t Data);        /* 单字节写 */


bool I2C_WriteBuffer(uint8_t DevAddr, uint8_t RegAddr, uint8_t* pBuffer, uint8_t NumByteToWrite); /* 连续字节写 */

/*----------------------------------------------------
*   本地函数
*----------------------------------------------------*/
void I2C_delay(void); /* I2C延时 */

void I2C_Ack(void); /* 产生Ack回应 */

void I2C_NoAck(void); /* 产生NoAck回应 */         

bool I2C_Start(void); /* I2C启动 */

void I2C_Stop(void); /* I2C停止 */  

void I2C_SendByte(uint8_t SendByte); /* 传送字节 */         

void I2C_SendAddress(uint8_t Address, uint8_t Direction); /* 传送地址 */

uint8_t I2C_ReceiveByte(void); /* 接收字节 */        

bool I2C_ChkAck(void); /* 检测Ack回应 */

#endif


使用特权

评论回复
7
朝阳之光| | 2014-6-5 12:28 | 只看该作者
程序风格蛮好的

使用特权

评论回复
8
cos12a| | 2014-6-5 12:39 | 只看该作者
不错,很赞

使用特权

评论回复
9
大秦正声| | 2014-6-5 13:35 | 只看该作者
拿起书本 发表于 2014-6-4 16:05
#ifndef __I2C_H__
#define __I2C_H__
/*----------------------------------------------------

学习!

使用特权

评论回复
10
jxmzzr|  楼主 | 2014-6-5 17:07 | 只看该作者
谢谢楼上朋友提供的例程,和我的基本上一样,但是我连上了6050之后,用示波器测波形,sda  scl一直为高,没有高低变化,为什么呢?

使用特权

评论回复
11
unciauncia| | 2014-6-7 09:22 | 只看该作者
这大血程序啊

使用特权

评论回复
12
runningwzf| | 2014-6-7 22:57 | 只看该作者
我觉得模拟IO挺好的,毕竟大家应该都是用I2C存储一些配置数据而已,在上电的时候就已经读到RAM里面了,以后也不会操作几次。
数据量较大的话用FLASH,爽很多

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

460

主题

2188

帖子

12

粉丝