这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » MM32F013x上实现I2C多地址的功能应用

共4条 1/1 1 跳转至

MM32F013x上实现I2C多地址的功能应用

工程师
2021-02-06 23:44:48     打赏

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

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

1.配置方式

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

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

3.相关软件的实现3.1功能验证

制作一个主机设备发送16个字节的字符串,连接两块开发板的SDA/SCL,通过主机向从机发送数据,分别将目标地址设置为:0XA0、0XA2、0XA4、0XA6、0XA8、0XAA、0XAC、0XAE进行通信测试。

3.1.1主机程序
voidI2C_WRTest(void){Write(0x00,gTxData,0x10);DELAY_Ms(100);Read(0x00,gRxData,0x10);DELAY_Ms(100);}s32main(void){DELAY_Init();I2C_WRInit();for(inTI=0;i<8;i++)
   {
       I2C_Cmd(I2C1, DISABLE);
       I2C_SetDeviceAddr(I2C1, EEPROM_ADDR+2*i);
       I2C_Cmd(I2C1, ENABLE);
       I2C_WRTest();
   }
   While(1)
   {

   }
}
3.1.2从机初始化部分
voidI2C_NVIC_SlaveInit(void){NVIC_InitTypeDefNVIC_InitStructure;GPIO_InitTypeDefGPIO_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;//NeedextrapluspullGPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//I2C1remapIOportGPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;//clockinputGPIO_Init(GPIOB,&GPIO_InitStructure);I2C_SlaveMode();}voidI2C_NVIC_SlaveTest(){u32i;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);//ReadrequestI2C_ITConfig(I2C1,I2C_IT_RX_FULL,ENABLE);//ReceiveinterruptI2C_SendSlaveAddress(I2C1,0xA8);I2C1->SLVMASK=0x0F;I2C_Cmd(I2C1,ENABLE);}s32main(void){CONSOLE_Init(115200);I2C_NVIC_SlaveInit();I2C_NVIC_SlaveTest();while(1){}}

以上程序将设备配置为从机模式,使能读请求/接收缓冲非空中断,从机地址配置为0XA8,SLVMASK配置为0X0F,表示地址的低四位不进行比较,则从机设备可以从总线上接受地址为0XA0、0XA2、0XA4、0XA6、0XA8、0XAA、0XAC、0XAE的数据包。

3.1.3从机多地址中断处理程序
voidI2C1_IRQHandler(void){u16stop_flag,start_flag;if(I2C_GetITStatus(I2C1,I2C_IT_RD_REQ)){I2C_ClearITPendingBit(I2C1,I2C_IT_RD_REQ);//ThemasterhassentareadrequestfromtheslaveI2C1->DR=(u8)gTxBuff[gTxCnt];I2C_TX_EmptyCheck(I2C1);while(!(I2C1->SR&0x4));I2C_GenerateSTOP(I2C1,ENABLE);gTxCnt++;if(gTxCnt==16){gTxCnt=0;}gTxFlag=0;}//interruptreceiveif(I2C_GeTITStatus(I2C1,I2C_IT_RX_FULL)){//MastersendsslavereceivegRxBuff[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))//slavereceive{I2C_ClearITPendingBit(I2C1,I2C_IT_STOP_DET);I2C_ClearITPendingBit(I2C1,I2C_IT_STOP_DET);}}
3.1.4测试结果

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


结合上述结果与调试过程,可知从机可以接收地址为:0XA0、0XA2、0XA4、0XA6、0XA8、0XAA、0XAC、0XAE的数据包。

a



工程师
2021-02-06 23:59:00     打赏
2楼

应用起来还是可以的


工程师
2021-02-09 23:31:26     打赏
3楼

不错的


工程师
2021-02-12 22:46:26     打赏
4楼

应用做的非常不错的


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]