I2C通信设备地址寻址实现
eetrendMcu 2023-11-20

在I2C中,通信是借助设备地址寻址实现的,大致可以分为两类:一对多、多对多通信。在多主机通信时,从机如果想接收多个主机的数据,就需要使用到从机多地址的功能。

本文是针对在MM32F013x上实现I2C多地址的功能应用。

配置方式

MM32F013x的多地址功能是通过配置I2C_SLAVMASK寄存器来实现的。通过I2C_SAR寄存器配置从机地址后,再配置I2C_SLAVMASK寄存器。MM32F013x是支持7位地址和10位地址格式的,所以需要按照自己的实际情况配置I2C_SLAVMASK寄存器的低九位,I2C_SLVRCVADDR寄存器会给出真实地址。

注意:在I2C中有些特殊地址是不会产生响应的。


寄存器描述


相关软件的实现

01、功能验证

制作一个主机设备发送16个字节的字符串,连接两块开发板的SDA/SCL,通过主机向从机发送数据,分别将目标地址设置为:0xA0、0xA2、0xA4、0xA6、0xA8、0xAA、0xAC、0xAE进行通信测试。

1.1 主机程序

void I2C_WRTest(void)
{
    Write(0x00, gTxData, 0x10);
    DELAY_Ms(100);
    Read(0x00, gRxData, 0x10);
    DELAY_Ms(100);
}

s32 main(void)
{
    DELAY_Init();
    I2C_WRInit();

    for(int i=0;i<8;i++)
    {
        I2C_Cmd(I2C1, DISABLE);
        I2C_SetDeviceAddr(I2C1, EEPROM_ADDR+2*i);
        I2C_Cmd(I2C1, ENABLE);
        I2C_WRTest();
    }
    While(1)
    {

    }
}

1.2 从机初始化部分

void I2C_NVIC_SlaveInit(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    GPIO_InitTypeDef  GPIO_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_1);
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //Need extra plus pull
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;  //I2C1 remap IO port
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;  // clock input
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    I2C_SlaveMode();
}

void I2C_NVIC_SlaveTest()
{
    u32 i;
    while( gTxFlag | gRxFlag);
    for(i = 0; i < 16; i++) 
    {
        printf("TX data%d is  : %x \r\n", i, gTxBuff[i]);
    }
    for(i = 0; i < 16; i++)
    {
        printf("RX data%d is  : %x \r\n", i, gRxBuff[i]);
    }
    gTxFlag = 1;
    gRxFlag = 1;
}

void I2C_SlaveMode()
{
    I2C_InitTypeDef I2C_InitStructure;
    I2C_StructInit(&I2C_InitStructure);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    I2C_DeInit(I2C1);
    I2C_InitStructure. Mode = (I2C_CR_MASTER >> 1); 
    I2C_InitStructure. OwnAddress = 0;
    I2C_InitStructure. Speed = I2C_CR_STD;
    I2C_InitStructure. ClockSpeed = 100000;
    I2C_Init(I2C1, &I2C_InitStructure);

    I2C_ITConfig( I2C1, I2C_IT_RD_REQ, ENABLE );//Read request
    I2C_ITConfig( I2C1, I2C_IT_RX_FULL, ENABLE );//Receive interrupt

    I2C_SendSlaveAddress(I2C1, 0xA8);

    I2C1->SLVMASK = 0x0F;
    I2C_Cmd(I2C1, ENABLE);
}

s32 main(void)
{
    CONSOLE_Init(115200);
    I2C_NVIC_SlaveInit();
    I2C_NVIC_SlaveTest();
    while(1) 
    {
    }
}

以上程序将设备配置为从机模式,使能读请求/接收缓冲非空中断,从机地址配置为0xA8,SLVMASK配置为0x0F,表示地址的低四位不进行比较,则从机设备可以从总线上接受地址为0xA0、0xA2、0xA4、0xA6、0xA8、0xAA、0xAC、0xAE的数据包。

1.3 从机多地址中断处理程序

void I2C1_IRQHandler(void)
{
    u16 stop_flag, start_flag;
    if(I2C_GetITStatus(I2C1, I2C_IT_RD_REQ)) 
    { 
        I2C_ClearITPendingBit(I2C1,I2C_IT_RD_REQ);   
        //The master has sent a read request from the slave
        I2C1->DR = (u8)gTxBuff[gTxCnt];
        I2C_TX_EmptyCheck(I2C1);
        while(!(I2C1->SR & 0x4));
        I2C_GenerateSTOP( I2C1, ENABLE );

        gTxCnt ++;
        if(gTxCnt == 16) 
        {
            gTxCnt = 0;
        }
        gTxFlag = 0;
    }
    // interrupt receive
    if(I2C_GetITStatus(I2C1, I2C_IT_RX_FULL)) 
    { 
        //Master sends slave receive
        gRxBuff[gRxCnt++] = I2C_ReceiveData(I2C1);
        while(!(I2C1->SR & 0x4));
        I2C_GenerateSTOP( I2C1, ENABLE );
        if(gRxCnt == 16)
        {
            gRxCnt = 0;
        }
        gRxFlag = 0;
    }
    stop_flag = I2C1->STOP;
    start_flag = I2C1->START;
    if((stop_flag  & start_flag) != ((u32)RESET)) //slave receive
    {
        I2C_ClearITPendingBit(I2C1,I2C_IT_STOP_DET);
        I2C_ClearITPendingBit(I2C1,I2C_IT_STOP_DET);   
    }
}

1.4 测试结果

通过UART1打印接收及发送的结果发现每次结果都如下图所示:


波形如下:









结合上述结果与调试过程,可知从机可以接收地址为:0xA0、0xA2、0xA4、0xA6、0xA8、0xAA、0xAC、0xAE的数据包。

声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 【7.24 深圳】2025国际AI+IoT生态发展大会/2025全球 MCU及嵌入式技术论坛


  • 相关技术文库
  • 工业
  • 安防
  • 航空
  • CAN
  • 单片机的I2C和SPI通信的含义

    I2C和SPI是两种不同的通信协议。 当我们听到这个协议时,它似乎是不可实现的。事实上,协议只是人们定义的一个标准。我们只需要按照这个标准去做。例如,如果公司说我们早上9点上班,我们9点上班,或者我们扣...

    前天
  • 浅析基于MB86R01的汽车数字化虚拟仪表设计

    随着汽车、通信、信息电器、医疗、军事等行业的巨大的智能化需要,嵌入式软件及系统发展迅速。微处理器从8位到16位、32位甚至64位,从支持单一品种的CPU芯片到支持多品种的,从单一内核到除了内核外还提供其它功能...

    07-08
  • 基于蓝牙技术的汽车驾驶盘控制系统

    摘 要:介绍了一种基于蓝牙技术的方向盘控制系统设计方案。利用蓝牙传输技术实现汽车方向盘面板开关电子化优化设计,克服传统驾驶过程中需要低头找开关的弊端,使得大部分操作在方向盘上实现,汽车驾驶更便捷。控制...

    07-08
  • 逆变器有何注意事项?安装逆变器风扇有何要点?

    逆变器是一种转换器,在工业应用中,逆变器具有重要意义。对于逆变器,小编曾对逆变器的安装、离网逆变器等知识有所介绍。为增进大家对逆变器的认识,本文将对逆变器使用注意事项以及逆变器风扇安装注意事项予以解...

    07-07
  • 电气火灾监控系统

    电气火灾监控系统,特点在于漏电监控方面属于先期预报警系统。与传统火灾自动报警系统不同的是,电气火灾监控系统早期报警是为了避免损失,而传统火灾自动报警系统是为了减少损失。所以,这就是说为什么不管是新建...

    07-04
  • 基于C8051F500的数控恒流源设计

    本文给出了一种基于C8051F021和RA8835实现的低成本液晶显示方案。随着电子产品设计技术的不断发展,电子产品的设计,尤其是人机交互界面的设计日益趋向人性化。这其中的液晶显示屏以其具有能显示复杂文字及图形、显...

    07-02
  • 大佬带你谈谈步进电机,啥又是直流电机

    电机是诸多电子设备中都存在,由此可见电机的重要性。在往期文章中,小编对伺服电机、变频电机都有所介绍。为增进大家对电机的了解,本文将对步进电机和直流电机加以阐述。如果你对电机相关内容具有兴趣,不妨继续...

    06-27
  • 同步、异步电机有何区别?高、低速电机是什么?

    电机是工业设备中的重要存在之一,对于电机,大家应当有所了解。为增进大家对电机的了解,本文将对同步电机、异步电机、同步电机和异步电机的区别、高速电机和低速电机予以介绍。如果你对电机具有兴趣,不妨继续往...

    06-27
  • 步进电机知识详解,再不怕看不懂步进电机了!

    点击技成培训置顶,每日7:30准时为您推送

    06-26
下载排行榜
更多
评测报告
更多
广告