打印
[STM32F1]

STM32F103VC I2C问题,请解答

[复制链接]
1585|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我采用STM32F103, 外设为I2C接口的ADC,I2C接口为103的PB6,PB7( 即 pin92和pin93)。
i2C总线为100k;
i2C的一个操作过程
(1)addr+w
(2)写命令字 cmd,(1)(2)算是写命令字的动作,在此分开是为了说明问题;
(3)restart,读结果,总共读回来8个字节(4路adc,没路返回16bit),stop;

现在问题有几点:
(a)写命令的时候,即上面的步骤2,总线上没有波形,但是如果在写命令字前插入断点,然后在运行,总线上可以量到波形,这是为何?(备注:通过点亮led,可以确认写命令部分确实执行了。在2前加了延时也是不行的)
(b)如果2前打断点,执行的3后,第一次结果是正确的;但是当程序执行第二遍,结果就不对了。通过量测波形,发现总线上cpu没有给出ack(ack=1),但是写程序是有ack。换言之,cpu第一次有给ack,第二次就没有ack了。这是为何,附上第一次和第二次的波形图;同时附上部分程序,请论坛专家,帮忙分析一下。
C:\Users\Administrator\Desktop\first_read_ok.png

C:\Users\Administrator\Desktop\second_read_problem.png

代码:
void i2cGpioConfig(void)
{
    // Enable peripheral clocks
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    //RCC_PCLK1Config(RCC_HCLK_Div16);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE);
   
    GPIO_InitTypeDef GPIO_InitStructure;
   
    // Configure I2C1 pins: SCL and SDA joystick
    GPIO_InitStructure.GPIO_Pin = AD7993_SCL_PIN | AD7993_SDA_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
   
    //ad_busy
    GPIO_InitStructure.GPIO_Pin =  AD7993_BUSY_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
   
    // Configure I2C2 pins: SCL and SDA  arraykey
    GPIO_InitStructure.GPIO_Pin = ADP5585_SCL_PIN | ADP5585_SDA_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
   
}

void i2cConfig(void)
{
    I2C_InitTypeDef I2C_InitStructure;
   
    // I2C1 configuration
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = AD7993_JOY_ADDRESS;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000;
   
    I2C_Cmd(I2C1, ENABLE);
    I2C_Init(I2C1, &I2C_InitStructure);
   
    // I2C2 configuration
    I2C_InitStructure.I2C_OwnAddress1 = ADP5585_KEYS_ADDRESS;
   
    I2C_Cmd(I2C2, ENABLE);
    I2C_Init(I2C2, &I2C_InitStructure);
}

   I2C_GenerateSTART(I2Cx, ENABLE);       
    //while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
    while(!((UINT16)(I2Cx->SR1) & (UINT16)0X0001)); //SB
    while(!((UINT16)(I2Cx->SR2) & (UINT16)0X0011) == 0X0011); //BUSY+MSL

    I2C_Send7bitAddress(I2Cx, i2cAddr, I2C_Direction_Transmitter);
    //while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    while(!((UINT16)(I2Cx->SR1) & (UINT16)0X0082) == 0X0082); //ADDR+TXB
    while(!((UINT16)(I2Cx->SR2) & (UINT16)0X0007) == 0X0007); //BUSY+MSL+TRA
   
        I2C_SendData(I2Cx, configAddr); //发送控制指令(接收数据)
   
        //while(!I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    while(!((UINT16)(I2Cx->SR1) & (UINT16)0X0084) == 0X0084); //TXB BTF
    while(!((UINT16)(I2Cx->SR2) & (UINT16)0X0007) == 0X0007); //BUSY+MSL+TRA
   
        //restart
          I2C_GenerateSTART(I2Cx, ENABLE);
          while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
          //EV5
          I2C_Send7bitAddress(I2Cx, i2cAddr, I2C_Direction_Receiver);
          //发送读地址
          //while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
    while(!((UINT16)(I2Cx->SR1) & (UINT16)0X0044) == 0X0044); //BTF+RxEN
    while(!((UINT16)(I2Cx->SR2) & (UINT16)0X0003) == 0X0003); //BUSY+MSL
   
    for(UINT8 dataIndex = 0; dataIndex<len; dataIndex++)       
    {
        while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)));
        tmpValue[dataIndex] = I2C_ReceiveData(I2Cx);
        I2C_AcknowledgeConfig(I2Cx, ENABLE);
        }               
        //关闭应答和停止条件产生
   
    I2C_AcknowledgeConfig(I2Cx, DISABLE);
    I2C_GenerateSTOP(I2Cx, ENABLE);


沙发
ruyeecheung|  楼主 | 2015-5-8 23:14 | 只看该作者
图片不太会上传,再试下。

first_read_ok.png (228.35 KB )

first_read_ok.png

second_read_problem.png (220.55 KB )

second_read_problem.png

使用特权

评论回复
板凳
ruyeecheung|  楼主 | 2015-5-9 12:31 | 只看该作者
各位大侠,没搞过st的i2c吗?会不会芯片有bug?好着急啊!@香水城 @grant_jx @mmuuss586 @icecut

使用特权

评论回复
地板
ruyeecheung|  楼主 | 2015-5-11 08:40 | 只看该作者
没人用过103的i2c吗?

使用特权

评论回复
5
香水城| | 2015-5-19 13:47 | 只看该作者
第一,我看到LZ操作F1 I2C的代码是基于自己写的驱动,那么对各个寄存器的操作,包括读取状态寄存器SR,操作控制寄存器CR,都有一定的时序限制。就是说,需要参考你所用芯片的勘误手册中关于I2C模块的描述。

第二,为了简便,比如不想看勘误手册上的blablabla,请使用ST为I2C驱动封装的CPAL库。

使用特权

评论回复
6
309030106| | 2015-5-20 21:48 | 只看该作者
可能是时序,或者延时问题

使用特权

评论回复
7
airwill| | 2015-5-21 06:38 | 只看该作者
加入断点, 就有波形. 这就应该是个延时问题.
1. 增加适当的延时.
2. 发起总线写指令前, 先判断总线访问条件, 判断状态寄存器

使用特权

评论回复
8
crystal1987| | 2015-5-21 09:41 | 只看该作者
楼主,之前也遇到过这个问题,然后我将SCL和SDA的初始化频率,GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;中的50MHZ,修改成2MHZ通信就正常啦。原因是:因为IIC的通信频率100K,,IO口的初始化频率为使用频率的10陪左右,所以设置成2MHZ会合适点。不过我使用的是F100的板子,你可以试试,希望对你有用。

使用特权

评论回复
9
周董| | 2015-5-21 09:41 | 只看该作者
103没有用过额。。。帮顶。。。

使用特权

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

本版积分规则

6

主题

88

帖子

0

粉丝