打印

求助香水STM32 模拟I2C的问题

[复制链接]
3650|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
taotaobobo|  楼主 | 2010-6-8 14:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
网上下了好几个代码,都大同小议,使用起来很不稳定,香水帮忙看下哪里的问题。

我用的I0有所变化,PC9-----WP
                         PC10----SDA
                         PC11----SCL

修改后程序如下:

#include <stm32f10x_lib.h>   

bool I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite);
bool I2C_FRAM_BufferRead(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead);
#define I2C1_SLAVE_ADDRESS7    0xA0
#define I2C_PageSize           256
#define SCL_H         GPIOC->BSRR = GPIO_Pin_11
#define SCL_L         GPIOC->BRR  = GPIO_Pin_11  
   
#define SDA_H         GPIOC->BSRR = GPIO_Pin_10
#define SDA_L         GPIOC->BRR  = GPIO_Pin_10
#define SCL_read      GPIOC->IDR  & GPIO_Pin_11
#define SDA_read      GPIOC->IDR  & GPIO_Pin_10

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
vu8 FRAM_ADDRESS;
/* Private function prototypes -----------------------------------------------*/
/**/
void I2C_delay(void)
{         
   u8 i=100; //这里可以优化速度        ,经测试最低到5还能写入
   while(i)  
   {  
     i--;  
   }  
}
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_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SDA_H;
        I2C_delay();
}
void I2C_Ack(void)
{         
        SCL_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}
void I2C_NoAck(void)
{         
        SCL_L;
        I2C_delay();
        SDA_H;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}
bool I2C_WaitAck(void)          //返回为:=1有ACK,=0无ACK
{
        SCL_L;
        I2C_delay();
        SDA_H;                        
        I2C_delay();
        SCL_H;
        I2C_delay();
        if(SDA_read)
        {
    SCL_L;
    return FALSE;
        }
        SCL_L;
        return TRUE;
}
void I2C_SendByte(u8 SendByte) //数据从高位到低位//
{
    u8 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;
}
u8 I2C_ReceiveByte(void)  //数据从高位到低位//
{  
    u8 i=8;
    u8 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 WriteFM24C04(u16 WriteAddr, u16 NumByteToWrite, u8 * pBuffer)
{
        u8 Addr = 0, count = 0;
  GPIOC->BRR  = GPIO_Pin_9;//11  
        Addr = WriteAddr / I2C_PageSize;
        count = WriteAddr % I2C_PageSize;
        Addr = Addr << 1;
        Addr = Addr & 0x0F;   
        FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7 | Addr;
    if (!I2C_Start()) return FALSE;
    I2C_SendByte(FRAM_ADDRESS);//设置器件地址+段地址  
    if (!I2C_WaitAck())
        {
                I2C_Stop();  
                return FALSE;
        }
    I2C_SendByte(count);   //设置段内地址      
        I2C_WaitAck();         
           
        while(NumByteToWrite--)
        {
          I2C_SendByte(* pBuffer);
          I2C_WaitAck();
      pBuffer++;
        }
        I2C_Stop();
          //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
          //Systick_Delay_1ms(10);
        return TRUE;
}

//读出1串数据   
bool ReadFM24C04(u16 WriteAddr,u16 NumByteToRead, u8 * pBuffer)        
//bool I2C_FRAM_BufferRead(u8* pBuffer, u16 WriteAddr, u16 NumByteToRead)
{                 
        u8 Addr = 0, count = 0;
    Addr = WriteAddr / I2C_PageSize;
        count = WriteAddr % I2C_PageSize;
        Addr = Addr << 1;
        Addr = Addr & 0x0F;   
        FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7 | Addr;
         
        if (!I2C_Start()) return FALSE;
    I2C_SendByte(FRAM_ADDRESS);//设置器件地址+段地址  
    if (!I2C_WaitAck())  
        {
                I2C_Stop();  
                return FALSE;
        }
    I2C_SendByte(count);   //设置低起始地址      
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(FRAM_ADDRESS | 0x01);
    I2C_WaitAck();
    while(NumByteToRead)
    {
      *pBuffer = I2C_ReceiveByte();
      if(NumByteToRead == 1)I2C_NoAck();
      else I2C_Ack();  
      pBuffer++;
      NumByteToRead--;
    }
    I2C_Stop();
    return TRUE;
}
沙发
myworkmail| | 2010-6-10 15:06 | 只看该作者
LZ 是高手

使用特权

评论回复
板凳
myworkmail| | 2010-6-10 15:07 | 只看该作者
LZ 是高手,那几个宏定义的很巧,要是我回直接用什么Gpio_Set什么的

使用特权

评论回复
地板
Aaron888| | 2010-6-13 11:05 | 只看该作者
LZ问题解决没?要是解决了经验分享一下:lol

使用特权

评论回复
5
grant_jx| | 2010-6-13 16:04 | 只看该作者
本帖最后由 grant_jx 于 2010-6-13 16:05 编辑

代码是用GPIO来模拟实现I2C通讯,如可通讯但不稳定,应该重点检查你的时序!

特别是在操作工程中是否有中断之类的操作打断,影响到时序?

最简单的办法就是用示波器监视。

使用特权

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

本版积分规则

2

主题

35

帖子

1

粉丝