一、准备工程,随意建立一个
二、新建对应的文件,我只建立了hal_i2c.c和hal_i2c.h
三、编写初始化I2C主机代码
- /**
- *****************************************************************************
- * [url=home.php?mod=space&uid=67211]@name[/url] : I2C Master接口初始化
- *
- * @Brief : 硬件I2C方式
- *
- * @Input : none
- *
- * @Output : none
- *
- * @Return : none
- *****************************************************************************
- **/
- void HAL_I2CHardMasterInit(void)
- {
- uint32_t i2c_temp = 0;
-
- //I2C时钟源选择
- RCC->CCIPR &= ~RCC_CCIPR_I2C1SEL;
- RCC->CCIPR |= RCC_CCIPR_I2C1SEL_0; //System clock selected as I2C1 clock
-
- RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
- RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
-
- //
- //管脚复用
- //
- GPIOB->AFR[0] &= ~(GPIO_AFRL_AFSEL6 | GPIO_AFRL_AFSEL7);
- GPIOB->AFR[0] |= 0x01<<(4 * 6);
- GPIOB->AFR[0] |= 0x01<<(4 * 7);
-
- //
- //初始化管脚
- //
- GPIOB->MODER &= ~(GPIO_MODER_MODE6 | GPIO_MODER_MODE7);
- GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7);
- GPIOB->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEED6 | GPIO_OSPEEDER_OSPEED7);
- GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPD6 | GPIO_PUPDR_PUPD7);
-
- GPIOB->MODER |= (GPIO_MODER_MODE6_1 | GPIO_MODER_MODE7_1); //Alternate function mode
- GPIOB->OTYPER |= (GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7);
- GPIOB->OSPEEDR |= (GPIO_OSPEEDER_OSPEED6 | GPIO_OSPEEDER_OSPEED7);
- // GPIOB->PUPDR |= (GPIO_PUPDR_PUPD6_0 | GPIO_PUPDR_PUPD7_0);
-
- //
- //复位I2C设备
- //
- RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST;
- RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C1RST;
-
- //
- //初始化IIC寄存器
- //
- I2C_DEVICE->CR1 &= ~I2C_CR1_PE; /*!< Disable I2C */
- I2C_DEVICE->CR1 &= 0x00CFE0FF;
-
- /*!< 时钟延展功能 */
- #if HAL_I2C_NOSTRETCH_EN
- I2C_DEVICE->CR1 &= ~I2C_CR1_NOSTRETCH; /*!< Enable Nostretch */
- #else
- I2C_DEVICE->CR1 |= I2C_CR1_NOSTRETCH; /*!< Disable Nostretch */
- #endif
-
- I2C_DEVICE->TIMINGR = I2C_TIMING; /*!< Timing register */
- I2C_DEVICE->CR1 |= I2C_CR1_PE; /*!< Enable I2C */
-
- i2c_temp = 0;
- I2C_DEVICE->OAR1 = i2c_temp;
- i2c_temp = (uint32_t)(I2C_ADDRESS & 0x00FF);
- I2C_DEVICE->OAR1 |= i2c_temp; /*!< Slave Address */
- I2C_DEVICE->OAR1 |= I2C_OAR1_OA1EN; /*!< Own Address1 enable */
-
- I2C_DEVICE->CR2 &= 0x07FF7FFF;
- I2C_DEVICE->CR2 &= ~I2C_CR2_NACK; /*!< ACK enable */
- }
复制代码master的初始化和slave初始化差不多,具体大伙们可以对比
前面帖子
四、本例子提供如下函数
读取一个字节:HAL_I2CMasterHardReadData()
读取多个字节:HAL_I2CMasterHardReadMultiData()
写入一个字节:HAL_I2CMasterHardWriteData()
写入多个字节:HAL_I2CMasterHardWriteMultiData()
五、操作函数中,设备地址大于10bits的没有测试,还不知道行不行,寄存器地址大于0xFF的,已经测试,目前可用
六、目前测试SCL时钟频率有100K和400K
七、对应测试的slave使用的是
前面帖子的例子,稍作修改
- /**
- *****************************************************************************
- * @Name : 事件中断服务函数
- *
- * @Brief : none
- *
- * @Input : none
- *
- * @Output : none
- *
- * @Return : none
- *****************************************************************************
- **/
- I2C_DEVICE_EVENT_IRQ
- {
- u32 temp = 0;
- GPIOB->BSRR = GPIO_BSRR_BR_8;
- /*!< Read Event Flag */
- temp = I2C_DEVICE->ISR;
- i2c_dev.I2C_EventStatus = (uint32_t)(temp & I2C_STATUS_EVT_MASK);
- i2c_dev.I2C_ErrorStatus = (uint32_t)(temp & I2C_STATUS_ERR_MASK);
-
- /* ==================================================== */
- /* 地址适配中断 */
- /* ==================================================== */
- if ((i2c_dev.I2C_EventStatus & I2C_ISR_ADDR) != 0)
- {
- /*!< ************************************ */
- /*!< Enable Nostretch */
- /*!< ************************************ */
- #if I2C_NOSTRETCH_EN
- {
- if ((I2C_DEVICE->ISR & I2C_ISR_DIR) != 0) /*!< Slave enter transmitter mode, Host read data */
- {
- I2C_DEVICE->ISR |= I2C_ISR_TXE; /*!< set TXE bit */
- i2c_dev.I2C_DeviceFlag |= I2C_DEVICE_FLAG_DIR_SEND;
- }
- else /*!< Host write data (slave receive data from host) */
- {
- i2c_dev.I2C_DeviceFlag &= ~I2C_DEVICE_FLAG_DIR_SEND;
- }
- }
- /*!< ************************************ */
- /*!< Disable Nostretch */
- /*!< ************************************ */
- #else
- {
- if ((I2C_DEVICE->ISR & I2C_ISR_DIR) != 0) /*!< Slave enter transmitter mode, Host read data */
- {
- i2c_dev.I2C_DeviceFlag |= I2C_DEVICE_FLAG_DIR_SEND;
- I2C_DEVICE->ISR |= I2C_ISR_TXE; /*!< set TXE bit, I2C_TXDR empty */
- //
- //根据不同寄存器地址来填充data1
- //
- if (I2C_DEVICE_REGADDRESS == I2C_REG_TEST_ADD)
- {
- if (I2C_DEVICE_REGOFFSET < I2C_REG_TEST_SIZE)
- {
- I2C_DEVICE->TXDR = I2C_REG_TEST[I2C_DEVICE_REGOFFSET];
- I2C_DEVICE_REGOFFSET++;
- }
- else
- {
- I2C_DEVICE->TXDR = I2C_DEVICE_DR_NULL_S;
- }
- }
- else
- {
- I2C_DEVICE->TXDR = I2C_DEVICE_DR_NULL_R;
- }
- }
- else //Receiver mode
- {
- i2c_dev.I2C_DeviceFlag &= ~I2C_DEVICE_FLAG_DIR_SEND;
- }
- }
- #endif
- // I2C_ClearITPendingBit(I2C1, I2C_IT_ADDR); /*!< set ADDRCF */
- I2C_DEVICE->ICR = I2C_IT_ADDR; /*!< set ADDRCF */
- }
-
- /* ==================================================== */
- /* 从机发送数据中断 */
- /* ==================================================== */
- if ((i2c_dev.I2C_EventStatus & I2C_ISR_TXIS) != 0)
- {
- //
- //根据不同的寄存器地址来发送数据,主机读取数据
- //
- // printf ("Evt=%x
", i2c_dev.I2C_EventStatus);
- //
- //测试寄存器
- //
- if (I2C_DEVICE_REGADDRESS == I2C_REG_TEST_ADD) //read and write
- {
- if (I2C_DEVICE_REGOFFSET < I2C_REG_TEST_SIZE)
- {
- i2c_regtemp = I2C_REG_TEST[I2C_DEVICE_REGOFFSET];
- I2C_DEVICE_REGOFFSET++;
- }
- else
- {
- I2C_DEVICE_REGOFFSET = 0;
- i2c_regtemp = I2C_DEVICE_DR_NULL_S;
- }
- }
- else
- {
- i2c_regtemp = I2C_DEVICE_DR_NULL_R;
- }
-
- I2C_DEVICE->TXDR = i2c_regtemp;
- printf ("data=%02X
", i2c_regtemp);
- }
-
- /* ==================================================== */
- /* 从机接收数据中断 */
- /* ==================================================== */
- if ((i2c_dev.I2C_EventStatus & I2C_ISR_RXNE) != 0)
- {
- i2c_regtemp = I2C_DEVICE->RXDR;
-
- #if 0
- if (I2C_DEVICE_REGOFFSET < I2C_REG_TEST_SIZE)
- {
- I2C_REG_TEST[I2C_DEVICE_REGOFFSET] = i2c_regtemp;
- // printf ("data=%02X
", I2C_REG_TEST[I2C_DEVICE_REGOFFSET]);
- I2C_DEVICE_REGOFFSET++;
- }
- else
- {
- I2C_DEVICE_REGOFFSET = 0;
- }
- #else
- if (I2CFirstByteFlag > 1)
- {
- //
- //根据不同的寄存器偏移量进行接收主机数据,主机写入数据
- //
- // i2c_regtemp = I2C_DEVICE->RXDR;
-
- //
- //测试寄存器
- //
- if (I2C_DEVICE_REGADDRESS == I2C_REG_TEST_ADD) //read and write
- {
- if (I2C_DEVICE_REGOFFSET < I2C_REG_TEST_SIZE)
- {
- I2C_REG_TEST[I2C_DEVICE_REGOFFSET] = i2c_regtemp;
- // printf ("data=%02X
", I2C_REG_TEST[I2C_DEVICE_REGOFFSET]);
- I2C_DEVICE_REGOFFSET++;
- }
- else
- {
- I2C_DEVICE_REGOFFSET = 0;
- }
- }
-
- i2c_regtemp = 0;
- }
- else
- {
- // i2c_regtemp = I2C_DEVICE->RXDR;
- //
- //接收第一个地址字节,十六位寄存器地址,高8位类型,低8位偏移量
- //
- if (I2CFirstByteFlag == 0)
- {
- I2C_DEVICE_REGADDRESS = i2c_regtemp & 0xFF;
- I2CFirstByteFlag++;
- printf ("reg=%02X
", I2C_DEVICE_REGADDRESS);
- }
- else if (I2CFirstByteFlag == 1)
- {
- I2C_DEVICE_REGOFFSET = i2c_regtemp & 0xFF;
- I2CFirstByteFlag++;
- printf ("off=%02X
", I2C_DEVICE_REGOFFSET);
- }
- }
- #endif
- }
-
- /* ==================================================== */
- /* 非应答中断 */
- /* ==================================================== */
- if ((i2c_dev.I2C_EventStatus & I2C_ISR_NACKF) != 0)
- {
- // I2C_ClearITPendingBit(I2C_DEVICE, I2C_IT_NACKF);
- I2C_DEVICE->ICR = I2C_IT_NACKF;
- if (I2CFirstByteFlag != 0)
- {
- I2CFirstByteFlag = 0;
- }
- i2c_dev.I2C_DeviceFlag |= I2C_DEVICE_FLAG_NACK;
- }
-
- /* ==================================================== */
- /* 停止信号中断 */
- /* ==================================================== */
- if ((i2c_dev.I2C_EventStatus & I2C_ISR_STOPF) != 0)
- {
- if ((i2c_dev.I2C_DeviceFlag & I2C_DEVICE_FLAG_DIR_SEND) != 0) /*!< Slave send to host */
- {
- /*!< ************************************ */
- /*!< Enable Nostretch */
- /*!< ************************************ */
- #if I2C_NOSTRETCH_EN
-
- /*!< ************************************ */
- /*!< Disable Nostretch */
- /*!< ************************************ */
- #else
- I2C1->ISR |= I2C_ISR_TXE;
- I2C1->ISR |= I2C_ISR_TXIS;
- #endif
- i2c_dev.I2C_DeviceFlag &= ~I2C_DEVICE_FLAG_DIR_SEND;
- i2c_dev.I2C_DeviceFlag |= I2C_DEVICE_FLAG_READ;
- }
- else
- {
- i2c_dev.I2C_DeviceFlag |= I2C_DEVICE_FLAG_WRITE; //置操作标志
- }
- if (I2CFirstByteFlag != 0)
- {
- I2CFirstByteFlag = 0;
- }
- // I2C_ClearITPendingBit(I2C_DEVICE, I2C_IT_STOPF); /*!< set STOPCF */
- I2C_DEVICE->ICR = I2C_IT_STOPF; /*!< set STOPCF */
- }
-
-
- /* ==================================================== */
- /* 错误中断 */
- /* ==================================================== */
- //
- //总线错误
- //
- if ((i2c_dev.I2C_ErrorStatus & I2C_ISR_BERR) != 0)
- {
- I2C_DEVICE->ICR = I2C_ICR_BERRCF;
- i2c_dev.I2C_DeviceFlag |= I2C_DEVICE_FLAG_ERROR;
- }
- //
- //总裁失败
- //
- if ((i2c_dev.I2C_ErrorStatus & I2C_ISR_ARLO) != 0)
- {
- I2C_DEVICE->ICR = I2C_ICR_ARLOCF;
- i2c_dev.I2C_DeviceFlag |= I2C_DEVICE_FLAG_ERROR;
- }
- //
- //溢出
- //
- if ((i2c_dev.I2C_ErrorStatus & I2C_ISR_OVR) != 0)
- {
- I2C_DEVICE->ICR = I2C_ICR_OVRCF;
- i2c_dev.I2C_DeviceFlag |= I2C_DEVICE_FLAG_ERROR;
- }
-
- GPIOB->BSRR = GPIO_BSRR_BS_8;
- }
复制代码 主要修改是寄存器地址大于0xFF的操作,模拟eeprom的操作,详情可参考AT24C128/256/512协议部分
一周热门 更多>