敏矽微电子Cortex-M0学习笔记17-I2C从机通信实例

敏矽微电子Cortex-M0学习笔记17-I2C从机通信实例在从机模式下,I2C硬件时刻监视总线上是否出现4个已定义的从机地址。1-1 从机接收模式。要初始化从接收模式,对任一从机地址寄存器 和从屏蔽寄存

大家好,欢迎来到IT知识分享网。

敏矽微电子Cortex-M0学习笔记17-I2C从机通信实例

学习笔记

1、I2C从机模式

在上一节中说到了I2C的主机模式,接下来补充下从机模式的应用。在从机模式下,I2C硬件时刻监视总线上是否出现4个已定义的从机地址。如地址被检测到,就会发出中断请求。在中断程序中回应主机的请求。

1-1 从机接收模式

在从机接收模式下,从主机接收数据字节。要初始化从接收模式,对任一从机地址寄存器(ADR0-3) 和从屏蔽寄存器(MASK0-3)。具体的寄存器配置如下表格所示:

敏矽微电子Cortex-M0学习笔记17-I2C从机通信实例

图1 I2C从机模式配置寄存器

MASL位必须为0,并且I2CEN需置位去使能 I2C 功能。AA位必须置1以应答其自身的从机地址。STA、STO和SI位清 0。初始化ADR和CONSET后,I2C 接口开始等待,直到被其自身从机地址。如果方向位为0(W),则进入从接收模式。如果方向位为1(R),则进入从发送模式。接收到地址和方向位后,SI 位置位,可从状态寄存器(STAT) 读取一个有效状态代码。

1-2 从机发送模式

接收和处理第一个字节的方式与接收模式下相同。但是,在该模式下,方向位为 1,指示读操作。通过SDA发送串行数据,通过SCL输入串行时钟。起始和停止条件分别看作串行传输的开始和结束。在特定应用中,I2C可作为主机/从机。在从机模式,I2C 硬件查找自身从机地址。如果检测到其中一个地址,则请求中断。如果微控制器想成为总线主机,则在进入主机模式前,硬件将一直等待,直到总线空闲,这样就不会中断可能存在的从机操作。

1-3 从机接收发送简化流程

对于 I2C 从机接收发送,ME32F030R8T6还提供一套简化的状态标志来实现 I2C 的接收和发送。该方法无需查看I2C的状态代码,只需查看状态寄存器的SLVADDMATCH, SLVRXBUFFULL和SLVTXBUFEMPTY标志位。I2C从机初始化同上。I2C从机启动后,等待主机通讯请求。当从机接收到与自己匹配地址,SLVADDMATCH 状态置 1 并引发中断。当从主机接收到数据时,SLVRXBUFFULL标志位会被置1并产生中断,缓冲区数据读走后自动清零。如要发送数据,用户需在启动I2C后,存入发送数据,当数据被主机读走后, SLVTXBUFEMPTY标志位被置1并产生中断,用户需填入下一个将发送的数据。中断服务流程图如下:

敏矽微电子Cortex-M0学习笔记17-I2C从机通信实例

图2 从机接收流程

2、I2C从机操作

在例程LIB->common->Drivers->Source文件夹内有i2c_slave.c文件,这个就是提供的I2C从机模式的驱动文件,里面包含了一些常用的驱动函数。

2-1 从机模式初始化

初始化I2C为从机模式的例子。

1. 将自身的从属地址装入ADR。

2. 使能I2C中断。

3. 向寄存器CONSET写入0x42来置位EN和清除MASL位,并使能从机功能。

void I2C_Slave_Init(uint32_t SlaveAddress) { //使能I2C时钟并复位 SYSCON->PRESETCTRL_b.I2C_RST_N |= 1; SYSCON->SYSAHBCLKCTRL_b.I2C_CLK |= 1;  //清除I2C标志 I2C->CONCLR = 0xFF;     //从机地址 I2C->ADR0 = SlaveAddress; I2C->MASK0 = 0xFE; I2C->MASK1 = 0xFE; I2C->MASK2 = 0xFE; I2C->MASK3 = 0xFE;  //从机模式 I2C->CONSET = I2C_S_CONCLR_I2ENC|I2C_S_CONSET_AA;  //使能I2C中断 NVIC_EnableIRQ(I2C_IRQn); }

2-2 从机接收状态处理

状态代码: 0x0a

已接收自身的 SLA+W,已返回 ACK。 即将接收数据,并返回 ACK。

1. 向CONCLR 写入0x08 来清除SI 标志。

2. 初始化从机数据接收缓冲区。

3. 初始化从机数据接收缓冲区指针。

4. 退出。

状态代码: 0x13

前一次寻址使用自身从机地址;已接收数据字节;已返回 ACK。 即将接收更多数据。

1. 从DAT读取数据字节存入从机数据接收缓冲区。

2. 缓冲区指针加1。如果是最后一个数据,跳转到5。

3. 向CONCLR 写入0x0C 来清除SI 和AA标志。

4. 退出。 .

5. 向CONCLR 写入0x08 来清除SI 标志。

6. 缓冲区指针加1。

7. 退出。

2-3 从机发射状态处理

状态代码: 0x4a

已接收到自身从机地址和读操作位,已返回 ACK。将发送数据和接收 ACK 位。

1. 将从机发送缓冲区的第一个数据字节装入DAT。

2. 向CONCLR 写入0x09 来清除SI 和TXRX标志。

3. 初始化从机发送缓冲区。

4. 从机发送缓冲区指针加1。

5. 退出。

状态代码: 0x5c

已发送数据并接收了 ACK。将发送数据和接收 ACK 位。

1. 将从机发送缓冲区的第一个数据字节装入DAT。 .

2. 向CONCLR 写入0x08 来清除SI 标志。

3. 从机发送缓冲区指针加1。

4. 退出。

2-4 I2C中断服务程序

确定 I2C 的状态和处理该状态的状态程序。具体参考i2c_slave.c函数文件中的中断服务程序I2C_IRQHandler。当I2C总线监视到4个已定义的从机地址后便进入中断程序。

int main(void) { //init I2C pin PC_11_INIT (PC_11_I2C_SDA ); PC_10_INIT (PC_10_I2C_SCL ); I2C->CONCLR = 0xFF; // Initial I2C, Slave Address is 0x5A; I2C_Slave_Init(0x52); while(1); }
/***************************************************************************** * I2C_Slave.c: Sourse file for I2C comunication * ver 1.0 ******************************************************************************/ #include "CMSDK_CM0.h" #include "sys.h" #include "i2c_slave.h" //Slave communication protocol //i2c read //1. master start i2c with slave address, write flag //2. master write slave sub_addr //3. master restart i2c with slave address, read flag //4. slave send byte from sub_addr, and sub_addr increase //5. repeat step 4 //6. master stop i2c //i2c write //1. master start i2c with slave address, write flag //2. master write slave sub_addr //3. slave sreceive byte and put to sub_addr, and sub_addr increase //4. repeat step 3 //5. master stop i2c extern uint32_t SystemCoreClock; uint8_t Slave_Data_Memory[128] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, }; uint8_t I2CSlaveAddrMatch = 0; uint8_t I2CSlaveAddr; uint8_t I2CDataIndex=0; uint8_t I2CReceiveSubAddr = 0; /***************************************************************************** ** Function name: I2C initial ** ** Descriptions: I2C initial function ** ** parameters: ** SlaveAddress: Slave address in slave mode ** ** Returned value: None ** *****************************************************************************/ void I2C_Slave_Init(uint32_t SlaveAddress) { /*--- Enable I2C clock and de-assert reset ---*/ SYSCON->PRESETCTRL_b.I2C_RST_N |= 1; SYSCON->SYSAHBCLKCTRL_b.I2C_CLK |= 1; /*--- Clear flags ---*/ I2C->CONCLR = 0xFF; I2C->ADR0 = SlaveAddress; // Slave address I2C->MASK0 = 0xFE; // Slave address MASK // I2C->ADR1 = SlaveAddress; // Slave address I2C->MASK1 = 0xFE; // Slave address MASK // I2C->ADR2 = SlaveAddress; // Slave address I2C->MASK2 = 0xFE; // Slave address MASK // I2C->ADR3 = SlaveAddress; // Slave address I2C->MASK3 = 0xFE; // Slave address MASK I2C->CONSET = I2C_S_CONCLR_I2ENC|I2C_S_CONSET_AA; // Slave mode /* Enable the I2C Interrupt */ NVIC_EnableIRQ(I2C_IRQn); } /***************************************************************************** ** Function name: I2C_GetI2CStatus ** ** Descriptions: Get I2C Status ** ** parameters: None ** ** Returned value: None ** *****************************************************************************/ uint8_t I2C_GetI2CStatus( void ) { return (I2C->STAT); } /***************************************************************************** ** Function name: I2C_ReadFlag ** ** Descriptions: Read I2C Flag ** ** parameters: Read bit ** ** Returned value: None ** *****************************************************************************/ uint8_t I2C_ReadFlag( uint8_t I2C_CONSET ) { return(I2C->CONSET & I2C_CONSET); /* retuen flag */ } /***************************************************************************** ** Function name: I2C_SetFlag ** ** Descriptions: Set I2C Flag ** ** parameters: Set bit ** ** Returned value: None ** *****************************************************************************/ void I2C_SetFlag( uint8_t I2C_CONSET ) { I2C->CONSET = I2C_CONSET; /* Set flag */ } /***************************************************************************** ** Function name: I2C_ClearFlag ** ** Descriptions: Clear I2C Flag ** ** parameters: Clear bit ** ** Returned value: None ** *****************************************************************************/ void I2C_ClearFlag( uint32_t I2C_CONCLR ) { I2C->CONCLR = I2C_CONCLR; /* Clear flag */ } /***************************************************************************** * Function name: I2C_IRQHandler * * Descriptions: Use status to control process, slave mode * * parameters: None * Returned value: None * *****************************************************************************/ void I2C_IRQHandler(void) { if (I2C->STAT_b.SLVADDMATCH) { //i2c start I2C_ClearFlag(I2C_S_CONCLR_SLAADRC); I2CSlaveAddrMatch = 1; I2CSlaveAddr=I2C->DAT; I2CReceiveSubAddr = 0; I2CDataIndex ++; } if (I2CSlaveAddrMatch) { if (I2C->STAT_b.SLVRXBUFFULL ) { //i2c write if (I2CReceiveSubAddr != 1) { //get sub_addr I2CDataIndex=I2C->DAT; I2C->DAT=Slave_Data_Memory[I2CDataIndex]; I2CReceiveSubAddr = 1; } else { //receive data from master and put to data memory Slave_Data_Memory[I2CDataIndex]=I2C->DAT; I2CDataIndex++; } } else if(I2C->STAT_b.SLVTXBUFEMPTY) { //i2c read I2C->DAT=Slave_Data_Memory[I2CDataIndex]; I2CDataIndex++; } } else if(I2C->STAT_b.SLVTXBUFEMPTY) { //prepare first data at beginning I2CDataIndex=0; I2CSlaveAddrMatch = 0; I2CSlaveAddr=0; I2C->DAT=Slave_Data_Memory[I2CDataIndex]; } return; } 
敏矽微电子Cortex-M0学习笔记17-I2C从机通信实例

/***************************************************************************** * I2C_Slave.c: Sourse file for I2C comunication * ver 1.0 ******************************************************************************/ #include "CMSDK_CM0.h" #include "sys.h" #include "i2c_slave.h" //Slave communication protocol //i2c read //1. master start i2c with slave address, write flag //2. master write slave sub_addr //3. master restart i2c with slave address, read flag //4. slave send byte from sub_addr, and sub_addr increase //5. repeat step 4 //6. master stop i2c //i2c write //1. master start i2c with slave address, write flag //2. master write slave sub_addr //3. slave sreceive byte and put to sub_addr, and sub_addr increase //4. repeat step 3 //5. master stop i2c extern uint32_t SystemCoreClock; uint8_t Slave_Data_Memory[128] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, }; uint8_t I2CSlaveAddrMatch = 0; uint8_t I2CSlaveAddr; uint8_t I2CDataIndex=0; uint8_t I2CReceiveSubAddr = 0; /***************************************************************************** ** Function name: I2C initial ** ** Descriptions: I2C initial function ** ** parameters: ** SlaveAddress: Slave address in slave mode ** ** Returned value: None ** *****************************************************************************/ void I2C_Slave_Init(uint32_t SlaveAddress) { /*--- Enable I2C clock and de-assert reset ---*/ SYSCON->PRESETCTRL_b.I2C_RST_N |= 1; SYSCON->SYSAHBCLKCTRL_b.I2C_CLK |= 1; /*--- Clear flags ---*/ I2C->CONCLR = 0xFF; I2C->ADR0 = SlaveAddress; // Slave address I2C->MASK0 = 0xFE; // Slave address MASK // I2C->ADR1 = SlaveAddress; // Slave address I2C->MASK1 = 0xFE; // Slave address MASK // I2C->ADR2 = SlaveAddress; // Slave address I2C->MASK2 = 0xFE; // Slave address MASK // I2C->ADR3 = SlaveAddress; // Slave address I2C->MASK3 = 0xFE; // Slave address MASK I2C->CONSET = I2C_S_CONCLR_I2ENC|I2C_S_CONSET_AA; // Slave mode /* Enable the I2C Interrupt */ NVIC_EnableIRQ(I2C_IRQn); } /***************************************************************************** ** Function name: I2C_GetI2CStatus ** ** Descriptions: Get I2C Status ** ** parameters: None ** ** Returned value: None ** *****************************************************************************/ uint8_t I2C_GetI2CStatus( void ) { return (I2C->STAT); } /***************************************************************************** ** Function name: I2C_ReadFlag ** ** Descriptions: Read I2C Flag ** ** parameters: Read bit ** ** Returned value: None ** *****************************************************************************/ uint8_t I2C_ReadFlag( uint8_t I2C_CONSET ) { return(I2C->CONSET & I2C_CONSET); /* retuen flag */ } /***************************************************************************** ** Function name: I2C_SetFlag ** ** Descriptions: Set I2C Flag ** ** parameters: Set bit ** ** Returned value: None ** *****************************************************************************/ void I2C_SetFlag( uint8_t I2C_CONSET ) { I2C->CONSET = I2C_CONSET; /* Set flag */ } /***************************************************************************** ** Function name: I2C_ClearFlag ** ** Descriptions: Clear I2C Flag ** ** parameters: Clear bit ** ** Returned value: None ** *****************************************************************************/ void I2C_ClearFlag( uint32_t I2C_CONCLR ) { I2C->CONCLR = I2C_CONCLR; /* Clear flag */ } /***************************************************************************** * Function name: I2C_IRQHandler * * Descriptions: Use status to control process, slave mode * * parameters: None * Returned value: None * *****************************************************************************/ void I2C_IRQHandler(void) { if (I2C->STAT_b.SLVADDMATCH) { //i2c start I2C_ClearFlag(I2C_S_CONCLR_SLAADRC); I2CSlaveAddrMatch = 1; I2CSlaveAddr=I2C->DAT; I2CReceiveSubAddr = 0; I2CDataIndex ++; } if (I2CSlaveAddrMatch) { if (I2C->STAT_b.SLVRXBUFFULL ) { //i2c write if (I2CReceiveSubAddr != 1) { //get sub_addr I2CDataIndex=I2C->DAT; I2C->DAT=Slave_Data_Memory[I2CDataIndex]; I2CReceiveSubAddr = 1; } else { //receive data from master and put to data memory Slave_Data_Memory[I2CDataIndex]=I2C->DAT; I2CDataIndex++; } } else if(I2C->STAT_b.SLVTXBUFEMPTY) { //i2c read I2C->DAT=Slave_Data_Memory[I2CDataIndex]; I2CDataIndex++; } } else if(I2C->STAT_b.SLVTXBUFEMPTY) { //prepare first data at beginning I2CDataIndex=0; I2CSlaveAddrMatch = 0; I2CSlaveAddr=0; I2C->DAT=Slave_Data_Memory[I2CDataIndex]; } return; } 

敏矽微电子Cortex-M0学习笔记17-I2C从机通信实例

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/59380.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信