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

菜鸟新手求关注,STM32F103CBT6,I2C通信报错

[复制链接]
wuyankun 提问时间:2014-11-6 17:12 /
公司最近打算采用ST的单片机,其他单片机工程师比较忙,好吧,我只是个打杂的,于是被抓壮丁来处理,目标是使用I2C总线和一外设通信,想想也没啥难度。      于是,我参考网上的教程,配置了Keil的开发环境,参照了Keil给的I2C例子,写了个I2C通信代码,可是无法通信,非常着急,希望xdjm路过给打个赏,给找找虫子,非常感谢!
     简单的说是这样的,使用I2C2和外设相连,(I2C2连端口复用都没得)

     /* Includes ------------------------------------------------------------------*/#include "stm32f10x_lib.h"

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/
#define I2C2_SLAVE_ADDRESS7           0x00                //I2C2的地址,7位寻址
#define ADV7611_SLAVE_ADDRESS7        0x98                 //ADV7611的地址,7位寻址
#define BufferSize             2          //u16
#define ClockSpeed             400000         //2MHz
u8 I2C2_Buffer_Tx[BufferSize]={0,0};
u8 I2C2_Buffer_Rx[BufferSize]={0,0};
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
I2C_InitTypeDef  I2C_InitStructure;       
EXTI_InitTypeDef EXTI_InitStructure;
ErrorStatus HSEStartUpStatus;   
//自定义的配置功能函数
/* Private functions ---------------------------------------------------------*/
void RCC_Configuration(void);         //时钟,使用某功能前必须先激活该模块的时钟
void GPIO_Configuration(void);         //GPIO配置信息,使用哪种端口,输入,输出,和初始值
void NVIC_Configuration(void);         //中断配置信息
void ADV7611_Write(u8* pBuffer, u16 WriteAddrOffset, u16 NumByteToWrite);  //写ADV7611一段数据,字节对齐
void ADV7611_Read(u8* pBuffer, u16 ReadAddrOffset, u16 NumByteToRead);          //读ADV7611一段数据,字节对齐
void delay_ms(u16 time);//非精确的延时函数


int main(void)//主过程函数
{

  /* System clocks configuration ---------------------------------------------*/
  RCC_Configuration();
  /* NVIC configuration ------------------------------------------------------*/
  NVIC_Configuration();
  /* GPIO configuration ------------------------------------------------------*/
  GPIO_Configuration();


  //reset ADV7611 chips frist
  GPIO_ResetBits(GPIOA,GPIO_Pin_9);
  delay_ms(5);
  GPIO_SetBits(GPIOA,GPIO_Pin_9);
  delay_ms(5);


  /* I2C configuration ------------------------------------------------------*/
  I2C_Configuration();

        I2C2_Buffer_Tx[0]=0x00;         I2C2_Buffer_Tx[1]=0x00;
        ADV7611_Write(I2C2_Buffer_Tx, 0x400, 2);

  while (1)                                  
  {
  }
}


void RCC_Configuration(void)
{
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable PLL */
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }

  /* Enable peripheral clocks --------------------------------------------------*/
  /* GPIOB Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);       
  /* GPIOA Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  /* AFIO clock enable */
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);       
  /* I2C1 and I2C2 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE);
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the different GPIO ports.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void GPIO_Configuration(void) //配置GPIO的管脚功能
{
  GPIO_InitTypeDef GPIO_InitStructure;        //初始化的结构

  /* Configure I2C1 pins: SCL and SDA ----------------------------------------*/
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;       
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Configure I2C2 pins: SCL and SDA ----------------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

}

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
#ifdef  VECT_TAB_RAM
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else  /* VECT_TAB_FLASH  */  
  /* Set the Vector Table base location at 0x08000000 */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
#endif
}


void I2C_Configuration(void) //配置GPIO的管脚功能
{

  //配置I2C1的初始化参数
  /* I2C1 configuration ------------------------------------------------------*/
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//激活ACK
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//7bit的地址模式
  I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;//设置I2C的时钟频率
  /* Enable I2C1 and I2C2 ----------------------------------------------------*/
  I2C_Cmd(I2C1, ENABLE);
  I2C_Init(I2C1, &I2C_InitStructure); //初始化I2C1

  /* I2C2 configuration ------------------------------------------------------*/
  I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE_ADDRESS7;//设置I2C2的地址信息,其他的配置信息和I2C1相同
  I2C_Cmd(I2C2, ENABLE);
  I2C_Init(I2C2, &I2C_InitStructure);//初始化I2C2

}

void ADV7611_Write(u8* pBuffer, u16 WriteAddrOffset, u16 NumByteToWrite)
{
  u8 Offset_MSB = 0; u8 Offset_LSB = 0;

  /*wait I2C idle statues */
  while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
  /* Send I2C2 START condition */
  I2C_GenerateSTART(I2C2, ENABLE);        //I2C2产生开始信号(S),进入主发送模式
  /* Test on I2C2 EV5 and clear it */
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); //产生开始信息后,需要检测是否有EV5事件通知

  /* Send MDIN380 slave Address for write */
  I2C_Send7bitAddress(I2C2, ADV7611_SLAVE_ADDRESS7        , I2C_Direction_Transmitter);//发送从设备的地址,和传输方向(R?W?)

  /* Test on EV6 and clear it */
  while(! I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  //I2C_Cmd(I2C2, ENABLE);

  /*with 16bit BUS Mode,then MSB(A10...A8),LSB(A7...A0)*/
  Offset_MSB = (u8) ((WriteAddrOffset>>8)&0x0F);
  Offset_LSB = (u8) (WriteAddrOffset&0x00FF);

  /* Send the ADV7611's internal address (MSB) to write to */   
  I2C_SendData(I2C2, Offset_MSB);  

  /* Test on EV8 and clear it */
  while(! I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* Send the ADV7611's internal address (LSB) to write to */   
  I2C_SendData(I2C2, Offset_LSB);  

  /* Test on EV8 and clear it */
  while(! I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* While there is data to be written */
  while(NumByteToWrite--)  
  {
    /* Send the current byte */
    I2C_SendData(I2C2, *pBuffer);

    /* Point to the next byte to be written */
    pBuffer++;

    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  }

  /* Send STOP condition */
  I2C_GenerateSTOP(I2C2, ENABLE);

}

void delay_ms(u16 time)
{
  u16 i=0;
  while(time--)
  {       
                  i=12000;
                   while(i--);       
  }       
}



收藏 评论12 发布时间:2014-11-6 17:12

举报

12个回答
goswa 回答时间:2014-11-6 18:02:45
STM32F103 IIC硬件有BUG,建议采用IO模拟IIC通讯。
废鱼 回答时间:2014-11-7 15:43:28
楼上说的正确,我们都是用的IO模拟I2C通信。
wuyankun 回答时间:2014-11-9 20:20:23
goswa 发表于 2014-11-6 18:02
STM32F103 IIC硬件有BUG,建议采用IO模拟IIC通讯。

谢谢回复,可否提高一份参考代码给小弟,wuyankun1986@126.com,再次感谢
wuyankun 回答时间:2014-11-9 20:21:11
安 发表于 2014-11-7 15:43
楼上说的正确,我们都是用的IO模拟I2C通信。

谢谢,不知可否提供参考代码,方便的话,wuyankun1986@126.com
wuyankun 回答时间:2014-11-11 12:25:42
安 发表于 2014-11-10 09:23
https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=94048&highlight=I2C
http://www.stmcu. ...

谢谢,目前使用模拟器抓取波形,使用的模拟io的I2C方式,非常感谢
liwei5126 回答时间:2014-11-11 15:22:42
我是用IO模拟的I2C,你可以试试。
quillan-148562 回答时间:2014-11-13 17:16:09
你好 能否把你的adv7611代码参考一下?我最近想做adv7611的开发。 我的邮箱quillan2006@126.com
wuyankun 回答时间:2014-11-17 16:01:09
quillan-148562 发表于 2014-11-13 17:16
你好 能否把你的adv7611代码参考一下?我最近想做adv7611的开发。 我的邮箱

ADV7611有个论坛,上面有人贴出了完整代码,可以参考,我们这边项目还需要用MDIN380显示输出,所以没有办法验证正确性,我把代码转给你,是参考的
wuyankun 回答时间:2014-11-17 16:01:55
wuyankun 发表于 2014-11-11 12:25
谢谢,目前使用模拟器抓取波形,使用的模拟io的I2C方式,非常感谢

谢谢,我已经按照你们的Demo,写出可以正确I2C通信的代码,非常感谢!
natel 回答时间:2014-11-29 19:29:29
学习了
土豆来袭 回答时间:2014-11-29 20:56:15
重点看下应答信号

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版