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

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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版