打印
[STM32F0]

STM32F030K6

[复制链接]
6025|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 smartdog_1 于 2014-7-3 14:51 编辑

各位好:
      
         小弟用STM32F030K6 做I2C从机,利用TI 的SOC做主机,设定好从机地址之后,挂在驱动。
         
         在Keil中抓到了I2C中断,寄存器中的地址也是正确的。但是I2C总线的SCL被一直托低,同时SDA是高,导致SOC这边出现异常。MCU也没有正确给出ACK。
         使能了自动ACK。

         我用了CPAL I2C库,找了一大圈也没找到问题在哪儿。

         哪位知道的给个参考

沙发
mmuuss586| | 2014-7-3 15:10 | 只看该作者
先模拟吧,模拟成功了再改成硬件IIC的,ST的IIC弄起来比较麻烦的;

使用特权

评论回复
板凳
smartdog_1|  楼主 | 2014-7-3 16:30 | 只看该作者
mmuuss586 发表于 2014-7-3 15:10
先模拟吧,模拟成功了再改成硬件IIC的,ST的IIC弄起来比较麻烦的;

不会吧,模拟有点单疼哦

使用特权

评论回复
地板
香水城| | 2014-7-3 16:30 | 只看该作者
首先,可以在SCK线上传一个电阻,根据低电平的幅值来判断是主机、还是从机拉低了这条时钟线。

第二,F0的I2C有个很强大的“clock stretch”功能,但是这个功能,在F0作为I2C从设备时,需要在主机支持"clock stretch"时可以使能。最后把示波器上的波形贴个图,从起始位开始哦。

使用特权

评论回复
5
香水城| | 2014-7-3 16:46 | 只看该作者
本帖最后由 香水城 于 2014-7-3 16:47 编辑

F0的I2C作为从机时的【时钟延展特性】

使用特权

评论回复
6
cailantu| | 2014-7-3 16:58 | 只看该作者
学习了,感谢香水

使用特权

评论回复
7
smartdog_1|  楼主 | 2014-7-3 17:32 | 只看该作者
香水城 发表于 2014-7-3 16:30
首先,可以在SCK线上传一个电阻,根据低电平的幅值来判断是主机、还是从机拉低了这条时钟线。

第二,F0的I ...

可以确认是MCU拉低了SCL。将MCU的地址随便改成其他的之后,数据线不会被拉低。

CPAL中有这样的代码:
    /* If NACK Slave Own Address option bit selected */
    if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NACK_ADD) != 0)
    {
      /* Disable Acknowledgement of own Address */
      __CPAL_I2C_HAL_DISABLE_DEV(pDevInitStruct->CPAL_Dev);

      CPAL_LOG("\n\rLOG : I2C Device NACK Own Address Mode Enabled");
    }

#define __CPAL_I2C_HAL_DISABLE_DEV(device)              CPAL_I2C_DEVICE[(device)]->CR1 &= ~I2C_CR1_PE

很不能理解,明明是关闭自动ACK,为什么是Disable DEV 呢 ?

我将这一句换成
    /* If NACK Slave Own Address option bit selected */
    if ((pDevInitStruct->wCPAL_Options & CPAL_OPT_I2C_NACK_ADD) != 0)
    {
      /* Disable Acknowledgement of own Address */
      __CPAL_I2C_HAL_ENABLE_NACK(pDevInitStruct->CPAL_Dev);
      CPAL_LOG("\n\rLOG : I2C Device NACK Own Address Mode Enabled");
    }
    else
    {
        /* Enable Acknowledgement of own Address */
        __CPAL_I2C_HAL_ENABLE_ACK(pDevInitStruct->CPAL_Dev);
        CPAL_LOG("\n\rLOG : I2C Device ACK Own Address Mode Enabled");
    }
#define __CPAL_I2C_HAL_ENABLE_NACK(device)              CPAL_I2C_DEVICE[(device)]->CR2 |= I2C_CR2_NACK

#define __CPAL_I2C_HAL_DISABLE_NACK(device)             CPAL_I2C_DEVICE[(device)]->CR2 &= ~I2C_CR2_NACK

就会出现SCL被拉低,无ACK   SDA正常。

如果不替换,会出现SCL SDA 在ACK之后都被拉低。

波形暂时没附上,代会抓一个

使用特权

评论回复
8
smartdog_1|  楼主 | 2014-7-3 20:49 | 只看该作者
本帖最后由 smartdog_1 于 2014-7-3 21:12 编辑

目前的代码如下:

#defined  CPAL_I2C_DMA_PROGMODEL

   //初始化I2C 数据结构
    CPAL_I2C_DeInit(I2C_DevStructures[0]);
    CPAL_I2C_StructInit(I2C_DevStructures[0]);

#ifdef CPAL_I2C_DMA_PROGMODEL
    I2C_DevStructures[0]->wCPAL_Options = CPAL_OPT_I2C_NACK_ADD | CPAL_OPT_I2C_WAKEUP_STOP | CPAL_OPT_DMARX_TCIT;
    I2C_DevStructures[0]->CPAL_ProgModel = CPAL_PROGMODEL_DMA;
#elif defined (CPAL_I2C_IT_PROGMODEL)
    SLAVESTRUCTURE.wCPAL_Options =  CPAL_OPT_I2C_NACK_ADD | CPAL_OPT_I2C_WAKEUP_STOP;
    SLAVESTRUCTURE.CPAL_ProgModel = CPAL_PROGMODEL_INTERRUPT;
#else
#error "Please select one of the programming model (in main.h)"
#endif

    /* Configure Own address 1 */
    I2C_DevStructures[0]->pCPAL_I2C_Struct->I2C_OwnAddress1 = OWNADDRESS;

    /* Set I2C Speed */
    I2C_DevStructures[0]->pCPAL_I2C_Struct->I2C_Timing = SLAVE_I2C_TIMING;

    /* Select Slave Mode */
    I2C_DevStructures[0]->CPAL_Mode = CPAL_MODE_SLAVE;

    /* Initialize I2Cx Device*/
    CPAL_I2C_Init(I2C_DevStructures[0]);

    /* Infinite loop */
    while (1)
    {
        /* Reset BufferRX value */
        memset(BufferRX, 0, (uint16_t)BufferSize);

        /* Initialize Transfer parameters */
        I2C_DevStructures[0]->pCPAL_TransferRx = &sRxStructure;
        sRxStructure.wNumData = BufferSize;
        sRxStructure.pbBuffer = (uint8_t*)BufferRX;
        delay(10);

        /* Read operation */
        CPAL_I2C_Read(I2C_DevStructures[0]);

        /* Enter Stop Mode and wait for interrupt to wake up */
        //PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
                __WFI();

        /* Wait until communication finishes */
        while ((I2C_DevStructures[0]->CPAL_State != CPAL_STATE_READY)
                        && (I2C_DevStructures[0]->CPAL_State != CPAL_STATE_ERROR));

        /* Configure SystemClock*/        
        Restore_Configuration();

        /* Configure and enable the systick timer to generate an interrupt each 1 ms */
        SysTick_Config((SystemCoreClock / 1000));

        /* If are received correctly */
        if (Compare_bBuffer((uint8_t*)BufferTX, BufferRX, BufferSize) == PASSED )
        {
            /* Update LCD Display */
            //LCD_DisplayStringLine(Line9, MESSAGE6);
        }
        else
        {
            /* Update LCD Display */
            //LCD_DisplayStringLine(Line9, MESSAGE10);
        }
        delay(50);
    }

在第九个时钟周期之后,SCL SDA都被托低,即使关闭了NOSTRETCH 也是一样。

使用特权

评论回复
9
smartdog_1|  楼主 | 2014-7-4 12:46 | 只看该作者
等了很久。。。哪位大哥给指点一下

使用特权

评论回复
10
香水城| | 2014-7-4 17:06 | 只看该作者
从波形看到,主设备对从地址为0x6c的设备,即STM32F030寻址,并且是读操作的企图(方向位为1)。然后SCK和SDA两根线就都处于地电平了。

首先,还是那句话,串个电阻,通过看低电平的幅值才是说明谁把SCK拉低的最直接证据。仅仅主设备换了对另外一个地址的从设备的寻址就没有问题,不是直接证据。

第二,根据5楼的信息,从设备在地址匹配事件后(ADDR标志置位),如果F030的I2C ISR没有软件清零ADDRCF;或者ADDR标志清零了,但是从设备要发送的数据还没有写进TXDR,都会发生以上波形看到的时钟延展

使用特权

评论回复
11
smartdog_1|  楼主 | 2014-7-10 16:06 | 只看该作者
Sorry,这几天在弄CUPS部分,MCU这块一直没有回复。

MCU目前是这样的:移除了CPAL库,直接使用ST 提供的API,使能了 slave byte control之后,MCU能够正确给出ACK。但是这块得先放一下,过段时间把CUPS搞定之后再来将详细的解决方法贴出来。

帖子就暂时不结了。

使用特权

评论回复
12
smartdog_1|  楼主 | 2014-7-16 09:00 | 只看该作者
目前关于应答的问题已经搞定了,从新加入CPAL库,实现从机接收数据。
CPAL的代码使用如下,给需要的人一个参考
        /* Start CPAL communication configuration ***********************************/
    /* Initialize local Reception structures */
    sRxStructure.wNumData = 2;               /* Maximum Number of data to be received */
    sRxStructure.pbBuffer = RxBuffer;   /* Common Rx buffer for all received data */
    sRxStructure.wAddr1 = 0;            /* Not needed */
    sRxStructure.wAddr2 = 0;            /* Not needed */

    /* Initialize local Transmission structures */
    sTxStructure.wNumData = 4;               /* Maximum Number of data to be transmission */
    sTxStructure.pbBuffer = TxBuffer;   /* Common Rx buffer for all received data */
    sTxStructure.wAddr1 = OWN_ADDRESS;  /* The own board address */
    sTxStructure.wAddr2 = 0;            /* Not needed */

    /* Set SYSCLK as I2C clock source */
    RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);

    /* Configure the device structure */
    CPAL_I2C_StructInit(&I2C1_DevStructure);      /* Set all fields to default values */
    I2C1_DevStructure.CPAL_Mode = CPAL_MODE_SLAVE;

    I2C1_DevStructure.wCPAL_Options =  CPAL_OPT_NO_MEM_ADDR | CPAL_OPT_DMATX_TCIT |
                                       CPAL_OPT_DMARX_TCIT | CPAL_OPT_I2C_WAKEUP_STOP;
    I2C1_DevStructure.CPAL_ProgModel = CPAL_PROGMODEL_DMA;

    I2C1_DevStructure.pCPAL_I2C_Struct->I2C_Timing = I2C_TIMING;
    I2C1_DevStructure.pCPAL_I2C_Struct->I2C_OwnAddress1 = OWN_ADDRESS;
    I2C1_DevStructure.pCPAL_TransferRx = &sRxStructure;
    I2C1_DevStructure.pCPAL_TransferTx = &sTxStructure;

    /* Initialize CPAL device with the selected parameters */
    CPAL_I2C_Init(&I2C1_DevStructure);
但是目前还有一个问题没有解决:主机读MCU时,MCU如何应答数据,在CPAL库中暂时没找到适合应答的地方,如果哪位前辈做过这块,麻烦给个指点.小弟不胜感激

使用特权

评论回复
13
smartdog_1|  楼主 | 2014-7-17 18:03 | 只看该作者
本帖最后由 smartdog_1 于 2014-7-17 18:37 编辑

IIC的问题基本解决了,分享一下心得,虽然这个帖子已经没人关注了。。。。。
1、CPAL中并没有完善对SLAVE模式时,应答机制。Master读时,需要自行添加相关的状态标志,然后在主循环中将数据发送出去
2、Slaver 响应完 Master的一次读操作之后,需要重新初始化IIC控制器。(具体需要重置哪个寄存器,没去深究,直接重新初始化了,简单方便)
3、利用CPAL作为从机时,Master写支持的还OK
4、CPAL在读取OAR1 OAR2时,存在很明显的Bug,在代码中显而易见,有哪位使用的可以自行修改
5、CPAL对于 STM32F030K6 器件不支持,需要手动修改一些地方,还算比较简单,就不最赘述了

最后不得不说,新器件 + CPAL 真是个坑,如果不是想偷懒,自己写寄存器,就不会那么麻烦了。。。。。

说明:本人使用的CPAL版本是 1.1.0 / 16-January-2014 ,以后的版本可能会修正这些问题

使用特权

评论回复
14
chindis| | 2015-1-19 23:02 | 只看该作者
我很需要

使用特权

评论回复
15
睿翼1992| | 2015-3-17 15:36 | 只看该作者

使用特权

评论回复
16
xktesla| | 2015-8-5 23:27 | 只看该作者
smartdog_1 发表于 2014-7-17 18:03
IIC的问题基本解决了,分享一下心得,虽然这个帖子已经没人关注了。。。。。
1、CPAL中并没有完善对SLAVE模 ...

大哥能不能给个CPAL的简单例子,双机通信,想要个最简单的,一个发,一个收。641018299@qq.com。小弟万分感谢!!!

使用特权

评论回复
17
wuhaiduo| | 2015-8-23 18:09 | 只看该作者
香水城 发表于 2014-7-3 16:30
首先,可以在SCK线上传一个电阻,根据低电平的幅值来判断是主机、还是从机拉低了这条时钟线。

第二,F0的I ...

stm32f030k6t6 的串口怎么也配置不成  PB6 PB7

使用特权

评论回复
18
破天#mcu| | 2017-8-7 10:35 | 只看该作者
代理兆易创新(GD)32-bit ARM架构,Cortex-M3、M4内核MCU,可提供技术支持等服务;
GD32F130系列 M3内核与STM32F030/051系列,硬件pin to pin兼容;烧录器、寄存器、开发环境完全兼容;
欢迎来电咨询探讨,邱先生 电话:136 8955 5135;

使用特权

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

本版积分规则

33

主题

229

帖子

1

粉丝