MM32F013x——I2C从机多地址应用

demi的头像
demi 发布于:周二, 01/26/2021 - 15:35 ,关键词:

在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的数据包。

转自:灵动微电子

围观 245