你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32的I2C 让人蛋疼

[复制链接]
paifeng253625-2 提问时间:2012-6-25 17:49 /
         最近在做一个项目,STM32RBT6通过I2C控制AD5933芯片的程序,该程序在pic16f877芯片上正常控制AD5933,但是当你移植到STM32RBT6上面的时候,就不能工作了。一直没找到原因,上面时序、延时、输入输出设置都改过了,就是不行。这让我很蛋疼,准备考虑换MCU(PIC)的问题!
        这是关于PIC控制AD5933的I2C部分的代码。如果移植到STM32上面,该怎么弄呢?求教!如果移植到stm32上,该怎么弄?
#include "pic.h"
#include "delay.h"
#include "math.h"

//---------------------------------------
//名称: 启动I2C总线函数 
//-----------------------------------------
void i2cstart(void)
{   
   scl=1;
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   sda=1;
   delay();
   sda=0;
   delay();
   scl=0;
   delay();
}
//---------------------------------------
//名称: 终止I2C总线函数 
//-----------------------------------------
void i2cstop(void)
{
   sda=0;
   sda=0; 
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP"); 
   scl=1;
   delay();
   sda=1;
   delay();
   scl=0;
   delay();
}
//---------------------------------------
//名称: 从I2C总线读入一位数据函数 
//-----------------------------------------
void bitin(void)
{
   eepromdi=1;   scl=1;
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   eepromdi=sda;
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   scl=0;
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
}
//---------------------------------------
//名称: 向I2C总线写入一位数据函数 
//-----------------------------------------
void bitout(void)
{
   sda=eepromdo;
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   scl=1;
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   scl=0;
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
   asm("NOP");
}
//---------------------------------------
//名称: 向I2C总线写入一字节函数 
//-----------------------------------------
void i2cwrite(unsigned char sedata)
{
   unsigned char k;
   for(k=0;k
收藏 评论4 发布时间:2012-6-25 17:49

举报

4个回答
青檬 回答时间:2012-6-27 22:53:39

RE:STM32的I2C 让人蛋疼

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
#include "i2c_ee.h"
#include"delay.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define I2C_Speed              10000
#define I2C1_SLAVE_ADDRESS7    0xA0
#define I2C_PageSize           4

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u16 EEPROM_ADDRESS;
/* Private function prototypes -----------------------------------------------*/
void I2C_Configuration(void);

/*******************************************************************************
* Function Name : I2C_Configuration
* Description    : I2C Configuration
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
/* Configure I2C1 pins: SCL and SDA */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//设置 I2C为 I2C模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//I2C快速模式 Tlow / Thigh = 2
   
I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;//设置第一个设备地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//使能应答
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//应答 7位地址
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//设置时钟频率
/* I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);//使能I2C外设
/* Apply I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStructure);
}
/*******************************************************************************
* Function Name : I2C_EE_Init
* Description    : Initializes peripherals used by the I2C EEPROM driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_Init()
{
/* I2C configuration */
I2C_Configuration();
/* depending on the EEPROM Address selected in the i2c_ee.h file */
#ifdef EEPROM_Block0_ADDRESS
/* Select the EEPROM Block0 to write on */
EEPROM_ADDRESS = EEPROM_Block0_ADDRESS;
#endif
#ifdef EEPROM_Block1_ADDRESS
/* Select the EEPROM Block1 to write on */
EEPROM_ADDRESS = EEPROM_Block1_ADDRESS;
#endif
#ifdef EEPROM_Block2_ADDRESS
/* Select the EEPROM Block2 to write on */
EEPROM_ADDRESS = EEPROM_Block2_ADDRESS;
#endif
#ifdef EEPROM_Block3_ADDRESS
/* Select the EEPROM Block3 to write on */
EEPROM_ADDRESS = EEPROM_Block3_ADDRESS;
#endif
}
/*******************************************************************************
* Function Name : I2C_EE_BufferWrite
* Description    : Writes buffer of data to the I2C EEPROM.
* Input          : - pBuffer : pointer to the buffer containing the data to be
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the EEPROM.
* Output         : None
* Return         : None
pBuffer:指向要写入数据数组的指针
WriteAddr:24c02中要写入数据的首地址
NumByteToWrite:写入的字节数
*******************************************************************************/
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)//将缓冲器的数据写入EEPROM
{
u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
Addr = WriteAddr % I2C_PageSize;//写入地址是每页的第几位
count = I2C_PageSize - Addr;//在开始的一页要写入的个数
NumOfPage = NumByteToWrite / I2C_PageSize;//要写入的页数
NumOfSingle = NumByteToWrite % I2C_PageSize;//不足一页的个数
I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
/* If WriteAddr is I2C_PageSize aligned */
if(Addr == 0) //写入地址是页的开始
{
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage == 0) //数据小于一页
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据
      I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
    }
    /* If NumByteToWrite > I2C_PageSize */
    else //数据大于等于一页
    {
      while(NumOfPage--)//要写入的页数
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); //写一页的数据
    I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
        WriteAddr += I2C_PageSize;
        pBuffer += I2C_PageSize;
      }
      if(NumOfSingle!=0)//剩余数据小于一页
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据
        I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
      }
    }
}
/* If WriteAddr is not I2C_PageSize aligned */
else //写入地址不是页的开始
{
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage== 0) //数据小于一页
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据
      I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
    }
    /* If NumByteToWrite > I2C_PageSize */
    else//数据大于等于一页
    {
      NumByteToWrite -= count;
      NumOfPage = NumByteToWrite / I2C_PageSize; //重新计算要写入的页数
      NumOfSingle = NumByteToWrite % I2C_PageSize;//重新计算不足一页的个数
      
      if(count != 0)//在此处count一定不为0,此判断条件好象有点多余
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, count);//将开始的空间写满一页
        I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
        WriteAddr += count;
        pBuffer += count;
      }
      
      while(NumOfPage--)//要写入的页数
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);//写一页的数据
        I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
        WriteAddr += I2C_PageSize;
        pBuffer += I2C_PageSize;
      }
      if(NumOfSingle != 0)//剩余数据小于一页
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); //写少于一页的数据
        I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
      }
    }
}
}
/*******************************************************************************
* Function Name : I2C_EE_ByteWrite
* Description    : Writes one byte to the I2C EEPROM.
* Input          : - pBuffer : pointer to the buffer containing the data to be
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
* Output         : None
* Return         : None
pBuffer:指向要写入数据数组的指针
WriteAddr:24c02中要写入数据的首地址
*******************************************************************************/
void I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)//写一个字节到EEPROM
{
/* Send STRAT condition */
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //检查最近一次 I2C事件是否是输入的事件
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
      
/* Send the EEPROM's internal address to write to */
I2C_SendData(I2C1, WriteAddr);//通过外设 I2Cx发送地址
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件
/* Send the byte to be written */
I2C_SendData(I2C1, *pBuffer); //通过外设 I2Cx发送数据
   
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件
/* Send STOP condition */
I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件
}
/*******************************************************************************
* Function Name : I2C_EE_PageWrite
* Description    : Writes more than one byte to the EEPROM with a single WRITE
*                  cycle. The number of byte can't exceed the EEPROM page size.
* Input          : - pBuffer : pointer to the buffer containing the data to be
*                    written to the EEPROM.
*                  - WriteAddr : EEPROM's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the EEPROM.
* Output         : None
* Return         : None
pBuffer:指向要写入数据数组的指针
WriteAddr:24c02中要写入数据的首地址
NumByteToWrite:写入的字节数
*******************************************************************************/
void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)//写少于一页的数据
{
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //检查最近一次 I2C事件是否是输入的事件
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //检查最近一次 I2C事件是否是输入的事件
/* Send the EEPROM's internal address to write to */   
I2C_SendData(I2C1, WriteAddr); //通过外设 I2Cx发送地址
/* Test on EV8 and clear it */
while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //检查最近一次 I2C事件是否是输入的事件
/* While there is data to be written */
while(NumByteToWrite--)
{
    /* Send the current byte */
    I2C_SendData(I2C1, *pBuffer); //通过外设 I2Cx发送数据
    /* Point to the next byte to be written */
    pBuffer++;
    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件
}
/* Send STOP condition */
I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件
}
/*******************************************************************************
* Function Name : I2C_EE_BufferRead
* Description    : Reads a block of data from the EEPROM.
* Input          : - pBuffer : pointer to the buffer that receives the data read
*                    from the EEPROM.
*                  - ReadAddr : EEPROM's internal address to read from.
*                  - NumByteToRead : number of bytes to read from the EEPROM.
* Output         : None
* Return         : None
pBuffer:指向要保存读出数据的数组的指针
ReadAddr:24c02中要读出数据的首地址
NumByteToRead:读出的字节数
*******************************************************************************/
void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)//将EEPROM的数据读入缓冲器
{
I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件
/* In the case of a single data transfer disable ACK before reading the data */
if(NumByteToRead==1)
{
    I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能
}
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
/* Clear EV6 by setting again the PE bit */
I2C_Cmd(I2C1, ENABLE);//使能或者失能 I2C外设
/* Send the EEPROM's internal address to write to */
I2C_SendData(I2C1, ReadAddr); //通过外设 I2Cx发送地址
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件
/* Send STRAT condition a second time */
I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件
/* Send EEPROM address for read */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);//向指定的从 I2C设备传送地址字,选择接收方向
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
/* While there is data to be read */
while(NumByteToRead)
{
    /* Test on EV7 and clear it */
    if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) //检查最近一次 I2C事件是否是输入的事件
    {
      if(NumByteToRead == 2)
      {
        /* Disable Acknowledgement */
        I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能
      }
      if(NumByteToRead == 1)
      {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件
      }
      
      /* Read a byte from the EEPROM */
      *pBuffer = I2C_ReceiveData(I2C1);//返回通过 I2Cx最近接收的数据
      /* Point to the next location where the byte read will be saved */
      pBuffer++;
      
      /* Decrement the read bytes counter */
      NumByteToRead--;   
    }   
}
/* Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(I2C1, ENABLE);//使能或者失能指定 I2C的应答功能
}
/*******************************************************************************
* Function Name : I2C_EE_WaitEepromStandbyState
* Description    : Wait for EEPROM Standby state
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void I2C_EE_WaitEepromStandbyState(void) //EEPROM设为待命状态     
{
vu16 SR1_Tmp = 0;
do
{
    /* Send START condition */
    I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件
    /* Read I2C1 SR1 register */
    SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);//读取指定的 I2C寄存器 I2C_SR1 并返回其值
    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字 ,选择发送方向
}while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));//地址发送结束
/* Clear AF flag */
I2C_ClearFlag(I2C1, I2C_FLAG_AF);//清除 I2Cx的应答错误标志位
}
青檬 回答时间:2012-6-27 22:54:22

RE:STM32的I2C 让人蛋疼

使用stm32的固件库,很好用的,我在做eeprom,没问题的
paifeng253625-2 回答时间:2012-6-29 14:34:13

回复:STM32的I2C 让人蛋疼

回复第 3 楼 于2012-06-27 22:54:22发表:
使用stm32的固件库,很好用的,我在做eeprom,没问题的 

问题我自己已经找到并解决了,不过还是谢谢你!
原因是I2C的时序问题!
paifeng253625-2 回答时间:2012-6-29 14:34:25

回复:STM32的I2C 让人蛋疼

回复第 3 楼 于2012-06-27 22:54:22发表:
使用stm32的固件库,很好用的,我在做eeprom,没问题的 

问题我自己已经找到并解决了,不过还是谢谢你!
原因是I2C的时序问题!

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版