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

STM32F0 IIC slave mode  

[复制链接]
红玫瑰的偏爱 发布时间:2015-7-1 10:42
最近一直在研究STM32F0的IIC,因为项目要用到IIC,master/slave mode都需要,实现数据通信和IAP功能。
网上有关于这部分资料特别少,所以共享一下,只晒出初始化和中断部分的代码的框架。代码在附件 .c里面,
如果有不对的地方,欢迎指正,大家互相学习一下!

STM32F0相对于STM32F1和STM8S 有很大变化,支持时钟延长即I2C_CR1_NOSTRETCH,并且支持SMBUS。
1,初始化部分:配置时钟和引脚,不使用时钟延长的功能
2,I2C1_IRQHandler 主要处理中断事件
      在I2C_ISR_ADDR事件时,如果设置了多个地址,要判断是那个地址,并且要清除中断标志位。
        根据I2C1->ISR&I2C_ISR_DIR 的结果判断是发送数据还是接收数据。
   (1)发送数据,流程如下
         tx.png
        这里要区别一下I2C_ISR_TXIS,I2C_ISR_TXE,描述如下
       txe.png
               
    (2) 接收数据,流程如下
          RX.png

IIC SLAVE mode.zip

下载

1.84 KB, 下载次数: 901

评分

参与人数 1 ST金币 +10 收起 理由
沐紫 + 10 赞一个!

查看全部评分

1 收藏 5 评论39 发布时间:2015-7-1 10:42

举报

39个回答
5211314lzq 回答时间:2015-7-1 15:39:45
之前用IIC的库函数,不知道为什么总会出错,后来就自己写了
老谢啊啊啊 回答时间:2017-3-7 20:22:19
本帖最后由 ///.. 于 2017-3-7 20:23 编辑

我在网上找到你们的代码。我复制了一下。有些问题想了解一下
void I2C_GPIO_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;

        /* Enable GPIOA clock */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);   
        /*!< sEE_I2C Periph clock enable */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
        /*!< GPIO configuration */
        /*!< Configure sEE_I2C pins: SCL */
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
        GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain
        GPIO_Init(GPIOA , &GPIO_InitStruct);

        /*!< Configure sEE_I2C pins: SDA */
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
        GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* Connect PXx to I2C_SCL*/
        GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
        /* Connect PXx to I2C_SDA*/
        GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}

//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。

void I2C_Configuration(void)
{
        I2C_InitTypeDef I2C_InitStruct;
         NVIC_InitTypeDef NVIC_InitStructure;
        
        /* I2C configuration */
        I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
        I2C_InitStruct.I2C_DigitalFilter = 0x00;
        I2C_InitStruct.I2C_OwnAddress1 = ADDR;
        I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;   
        I2C_InitStruct.I2C_Timing = 0xb0420f13;                //100Kbits
        /* I2C Peripheral Enable */
        I2C_Cmd(I2C1, ENABLE);
        /* Apply I2C configuration after enabling it */
        I2C_Init(I2C1, &I2C_InitStruct);
        
    I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
    //---------------------------- Peripheral and DMA interrupts Initialization ------------------
    // Initialize I2C1 interrupts
    /* Enable the IRQ channel */
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   
    /* Configure NVIC for I2C1 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
    NVIC_Init(&NVIC_InitStructure);        
        
}

//下面是IIC中断函数的实现

void I2c_Init(void)
{
        I2C_GPIO_Configuration();
        I2C_Configuration();
}

void I2C1_IRQHandler(void)
{
        u32 AddCode;
//        I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
        __IO uint32_t I2CFlagStatus = 0x00000000;
        I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
        
//        printf("recv data\r\n");
        if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)
          {
                AddCode = (I2C1->ISR & 0xfe0000);                        //读取ADDCODE   32:17位
                printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );
               
            if(I2C1->ISR&I2C_ISR_DIR) //tx mode
        {
                        printf("发送模式 \r\n");
            Tx_count = 0;
                 I2C1->ISR |= I2C_ISR_TXE;
            I2C1->ICR |= I2C_ICR_ADDRCF;
                        
                        if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
                        {
                                Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
                                if(Rx_count>=Rx_MAX)
                                {
                                        Rx_count=0;
                                        //rx  ok
                                }
                                printf("Rx_buffer : %s\r\n",Rx_buffer);
                        }
        }
                if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
        {
                        printf("接收模式 \r\n");
                        Rx_count= 0;
                        I2C1->ICR |= I2C_ICR_ADDRCF;
        }
    }
        else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
        {
                Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
                if(Rx_count>=Rx_MAX)
        {
            Rx_count=0;
                        //rx  ok
        }
                printf("Rx_buffer : %s\r\n",Rx_buffer);
        }
        else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
        {
                I2C_SendData(I2C1,Tx_buffer[Tx_count++]);
                if(Tx_count >= Tx_MAX)
                {
                        Tx_count = 0;
                        //tx ok
                }
        }
        else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)
        {
                printf("停止检查标志位 \r\n");
                I2C1->ICR |= I2C_ICR_STOPCF;
                Rx_count = 0;
                Tx_count = 0;
        }
}

这个是可以匹配到ADDCODE ,但是没有接收到数据的,我没仔细看这个时序寄存器的配置。不知道是不是由于时序不匹配造成没有接收到数据,还是因为ack没有给出造成读不到数据的。
老谢啊啊啊 回答时间:2017-3-7 20:25:31
我在网上找到你们的代码。我复制了一下。有些问题想了解一下
void I2C_GPIO_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;

        /* Enable GPIOA clock */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);   
        /*!< sEE_I2C Periph clock enable */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
        /*!< GPIO configuration */
        /*!< Configure sEE_I2C pins: SCL */
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;//GPIO_Mode_IN
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
        GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//open-drain
        GPIO_Init(GPIOA , &GPIO_InitStruct);

        /*!< Configure sEE_I2C pins: SDA */
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
        GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* Connect PXx to I2C_SCL*/
        GPIO_PinAFConfig( GPIOA , GPIO_PinSource9, GPIO_AF_4);
        /* Connect PXx to I2C_SDA*/
        GPIO_PinAFConfig( GPIOA ,GPIO_PinSource10, GPIO_AF_4);
}

//IIC从模式配置,在配置时,需要设置地址,在这里设置为0XA0,而从设备的时钟属于被动模式,有IIC的主端确定。

void I2C_Configuration(void)
{
        I2C_InitTypeDef I2C_InitStruct;
         NVIC_InitTypeDef NVIC_InitStructure;
        
        /* I2C configuration */
        I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStruct.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
        I2C_InitStruct.I2C_DigitalFilter = 0x00;
        I2C_InitStruct.I2C_OwnAddress1 = ADDR;
        I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;   
        I2C_InitStruct.I2C_Timing = 0xb0420f13;                //100Kbits
        /* I2C Peripheral Enable */
        I2C_Cmd(I2C1, ENABLE);
        /* Apply I2C configuration after enabling it */
        I2C_Init(I2C1, &I2C_InitStruct);
        
    I2C1->CR1 |= (I2C_CR1_ADDRIE | I2C_CR1_STOPIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
    //---------------------------- Peripheral and DMA interrupts Initialization ------------------
    // Initialize I2C1 interrupts
    /* Enable the IRQ channel */
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   
    /* Configure NVIC for I2C1 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
    NVIC_Init(&NVIC_InitStructure);        
        
}

//下面是IIC中断函数的实现

void I2c_Init(void)
{
        I2C_GPIO_Configuration();
        I2C_Configuration();
}

void I2C1_IRQHandler(void)
{
        u32 AddCode;
//        I2C_ClearITPendingBit(I2C1, I2C_ISR_ADDR | I2C_ISR_STOPF |I2C_ISR_ADDCODE );
        __IO uint32_t I2CFlagStatus = 0x00000000;
        I2CFlagStatus = (uint32_t)(I2C1->ISR & (uint16_t)0x0000100FE);
        
//        printf("recv data\r\n");
        if ((I2CFlagStatus & I2C_ISR_ADDR) != 0)
          {
                AddCode = (I2C1->ISR & 0xfe0000);                        //读取ADDCODE   32:17位
                printf("匹配地址2 0x%x: \r\n",AddCode >> 17 );
               
            if(I2C1->ISR&I2C_ISR_DIR) //tx mode
        {
                        printf("发送模式 \r\n");
            Tx_count = 0;
                 I2C1->ISR |= I2C_ISR_TXE;
            I2C1->ICR |= I2C_ICR_ADDRCF;
                        
                        if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
                        {
                                Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
                                if(Rx_count>=Rx_MAX)
                                {
                                        Rx_count=0;
                                        //rx  ok
                                }
                                printf("Rx_buffer : %s\r\n",Rx_buffer);
                        }
        }
                if((I2C1->ISR&I2C_ISR_DIR)==0) //rx mode
        {
                        printf("接收模式 \r\n");
                        Rx_count= 0;
                        I2C1->ICR |= I2C_ICR_ADDRCF;
        }
    }
        else if(I2C_GetITStatus( I2C1, I2C_IT_RXNE) != 0)
        {
                Rx_buffer[Rx_count++]=I2C_ReceiveData(I2C1);
                if(Rx_count>=Rx_MAX)
        {
            Rx_count=0;
                        //rx  ok
        }
                printf("Rx_buffer : %s\r\n",Rx_buffer);
        }
        else if ((I2CFlagStatus & I2C_ISR_TXIS) != 0)
        {
                I2C_SendData(I2C1,Tx_buffer[Tx_count++]);
                if(Tx_count >= Tx_MAX)
                {
                        Tx_count = 0;
                        //tx ok
                }
        }
        else if ((I2CFlagStatus & I2C_ISR_STOPF) != 0)
        {
                printf("停止检查标志位 \r\n");
                I2C1->ICR |= I2C_ICR_STOPCF;
                Rx_count = 0;
                Tx_count = 0;
        }
}
你好我好大家好! 回答时间:2015-7-1 15:27:15
好东西,谢谢分享
wyxy163@126.com 回答时间:2015-7-1 20:19:19
提示: 作者被禁止或删除 内容自动屏蔽
莫林2020 回答时间:2015-7-1 20:36:05
这个不错
chifen 回答时间:2015-7-2 08:41:43
路过





stary666 回答时间:2015-7-2 09:07:00
好东西,,,,,,,,,,
党国特派员 回答时间:2015-7-2 09:13:46
好东西,谢谢分享 blank.png blank1.png blank2.png blank3.png blank4.png blank5.png blank6.png blank7.png blank8.png blank9.png
埃斯提爱慕 回答时间:2015-7-2 21:59:38
提示: 作者被禁止或删除 内容自动屏蔽
拜仁主将 回答时间:2016-2-2 10:56:11
看看你这例程 我自己写的没ack
铠袖一触 回答时间:2016-2-5 13:09:33
楼主可不可以留个联系方式,还请指点IIC从机通讯
zhangdaijin 回答时间:2016-2-6 06:37:35
谢谢LZ分享
123456Kelly 回答时间:2016-2-11 23:20:44
好东西,谢谢分享  ,借鉴一下,原来做slave模式时, 不知道如何判断上位机连续°数据
zcl201207 回答时间:2016-2-12 23:10:31
danshi 回答时间:2016-7-29 11:40:15
正好要用iic slave 学习学习
123下一页

所属标签

相似分享

官网相关资源

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