STM32设置为I2C从机模式

慈云数据 2024-04-23 技术支持 76 0

STM32设置为I2C从机模式

目录

  • STM32设置为I2C从机模式
    • 前言
    • 1 硬件连接
    • 2 软件编程
    • 3 运行测试
      • 3.1 I2C连续写入
      • 3.2 I2C连续读取
      • 3.3 I2C单次读写测试
      • 4 总结

        前言

        STM32的I2C作为主机的情况相信很多同学都用过,网上也有很多教程,但是作为从设备使用的例子应该不多,本文通过硬件和软件的层面,介绍如何把STM32设置为一个I2C从机。

        1 硬件连接

        测试芯片:STM32F103ZET6

        测试方法:用一个USB转I2C的工具接到STM32的I2C引脚上,通过上位机工具进行读写操作。如果没有这个工具,也可以用另外一个stm32或者其他设备测试通讯,同时也可以借助示波器或者逻辑分析仪来辅助调试。

        硬件连接:

        STM32这边使用硬件I2C1(PB6、PB7),并外接上拉电阻。

        在这里插入图片描述

        在这里插入图片描述

        2 软件编程

        根据STM32数据参考手册,I2C作为从设备时发送和接收的流程如下:

        在这里插入图片描述

        在这里插入图片描述

        测试例程:定义一个256字节的buffer用来存放I2C从机的数据,默认赋初值0-255,然后通过中断的方式实现I2C数据读写。

        示例代码如下:

        #include "stm32f10x.h"
        #include "stm32f10x_gpio.h"
        #include "stm32f10x_rcc.h"
        #include "stm32f10x_i2c.h"
        #include "misc.h"
        #define I2CSLAVE_ADDR           0x40 
            return i2c1_ram[adr];
        }
        void Set_I2C1_Ram(uint8_t adr, uint8_t val) 
        {
            i2c1_ram[adr] = val;
            return;
        }
        void I2C1_Ram_Init(void) 
        {
            uint16_t i;
            for (i = 0; i SR1;
                I2C1->SR2;
            }
            /* STOPF Flag clear */
            while((I2C1->SR1&I2C_SR1_STOPF) == I2C_SR1_STOPF) 
            {
                I2C1->SR1;
                I2C1->CR1 |= 0x1;
            }
        }
        void I2C1_EV_IRQHandler(void) 
        {
            uint8_t wert;
            uint32_t event;
            /* Reading last event */
            event = I2C_GetLastEvent(I2C1);
            /* Event handle */
            if(event == I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) 
            {
                // Master has sent the slave address to send data to the slave
                i2c1_mode = I2C1_MODE_SLAVE_ADR_WR;
            }
            else if(event == I2C_EVENT_SLAVE_BYTE_RECEIVED) 
            {
                // Master has sent a byte to the slave
                wert = I2C_ReceiveData(I2C1);
                // Check address
                if(i2c1_mode == I2C1_MODE_SLAVE_ADR_WR) 
                {
                    i2c1_mode = I2C1_MODE_ADR_BYTE;
                    // Set current ram address
                    i2c1_ram_adr = wert;
                }
                else 
                {
                    i2c1_mode = I2C1_MODE_DATA_BYTE_WR;
                    // Store data in RAM
                    Set_I2C1_Ram(i2c1_ram_adr, wert);
                    // Next ram adress
                    i2c1_ram_adr++;
                }
            }
            else if(event == I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED) 
            {
                // Master has sent the slave address to read data from the slave
                i2c1_mode = I2C1_MODE_SLAVE_ADR_RD;
                // Read data from RAM
                wert = Get_I2C1_Ram(i2c1_ram_adr);
                // Send data to the master
                I2C_SendData(I2C1, wert);
                // Next ram adress
                i2c1_ram_adr++;
            }
            else if(event == I2C_EVENT_SLAVE_BYTE_TRANSMITTED) 
            {
                // Master wants to read another byte of data from the slave
                i2c1_mode = I2C1_MODE_DATA_BYTE_RD;
                // Read data from RAM
                wert = Get_I2C1_Ram(i2c1_ram_adr);
                // Send data to the master
                I2C_SendData(I2C1, wert);
                // Next ram adress
                i2c1_ram_adr++;
            }
            else if(event == I2C_EVENT_SLAVE_STOP_DETECTED) 
            {
                // Master has STOP sent
                I2C1_ClearFlag();
                i2c1_mode = I2C1_MODE_WAITING;
            }
        }
        void I2C1_ER_IRQHandler(void) 
        {
            if (I2C_GetITStatus(I2C1, I2C_IT_AF)) 
            {
                I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
            }
        }
        

        3 运行测试

        3.1 I2C连续写入

        通过上位机工具写入:

        请添加图片描述

        通过逻辑分析仪抓取波形:

        请添加图片描述

        3.2 I2C连续读取

        通过上位机工具连续读取256字节:

        在这里插入图片描述

        通过逻辑分析仪抓取波形:

        在这里插入图片描述

        在这里插入图片描述

        3.3 I2C单次读写测试

        通过上位机工具读取原值,再写入新值,最后再读取新值:

        请添加图片描述

        通过逻辑分析仪抓取波形:

        请添加图片描述

        4 总结

        通过上位机工具的测试以及逻辑分析仪的解析,STM32的硬件I2C从机通信正常且稳定,读写速度测试了100k和400k,没有发现问题,至此测试完成。

        好了,关于STM32如何设置从机模式就介绍到这里,如果你们有什么问题,欢迎评论区留言。

        需要完整源码工程的同学可以自行下载:源码下载地址

        另外还有一篇HAL库版本的博客:STM32设置为I2C从机模式(HAL库版本)

        如果这篇文章能够帮到你,就…懂的。

        请添加图片描述

微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon