本帖最后由 gaoyang9992006 于 2025-8-8 10:50 编辑
经过几天的学习,终于掌握了硬件I2C库函数的使用方法,总结如下:
时钟启用,功能映射到引脚,引脚的IO的模式配置,I2C配置与启用。
- void I2CInit(void)
- {
- GPIO_Config_T gpioConfigStruct;
- I2C_Config_T i2cConfigStruct;
- /* Enable I2C related Clock */
- RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
- /* Connect I2C to SCL */
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_8, GPIO_AF_PIN1);
- /* Connect I2C to SDA */
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_9, GPIO_AF_PIN1);
- /* Config I2C1 GPIO */
- gpioConfigStruct.mode = GPIO_MODE_AF;
- gpioConfigStruct.speed = GPIO_SPEED_50MHz;
- gpioConfigStruct.outtype = GPIO_OUT_TYPE_OD;
- gpioConfigStruct.pupd = GPIO_PUPD_NO;
- gpioConfigStruct.pin = GPIO_PIN_8;
- GPIO_Config(GPIOB, &gpioConfigStruct);
- gpioConfigStruct.pin = GPIO_PIN_9;
- GPIO_Config(GPIOB, &gpioConfigStruct);
- /* Config I2C1 */
- I2C_Reset(I2C1);
- RCM_ConfigI2CCLK(RCM_I2C1CLK_SYSCLK);
- i2cConfigStruct.ack = I2C_ACK_ENABLE;
- i2cConfigStruct.ackaddress = I2C_ACK_ADDRESS_7BIT;
- i2cConfigStruct.address1 = 0XA0;
- i2cConfigStruct.analogfilter = I2C_ANALOG_FILTER_ENABLE;
- i2cConfigStruct.digitalfilter = I2C_DIGITAL_FILTER_0;
- i2cConfigStruct.mode = I2C_MODE_I2C;
- i2cConfigStruct.timing = 0x80100103;
- I2C_Config(I2C1, &i2cConfigStruct);
- /* Enable I2Cx */
- I2C_Enable(I2C1);
- }
I2C发送函数映射到OLED库的数据命令发送函数。
- //发送一个字节
- //mode:数据/命令标志 0,表示命令;1,表示数据;
- void OLED_WR_Byte(u8 dat,u8 mode)
- {
- /* I2C Send Configuration */
- I2C_HandlingTransfer(I2C1, 0x78, 2, I2C_RELOAD_MODE_AUTOEND, I2C_GENERATE_START_WRITE);
-
- if(mode){I2C_TxData(I2C1,0x40);}
- else{I2C_TxData(I2C1,0x00);}
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET);
- I2C_TxData(I2C1, dat);
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET);
- /* I2C Generate Stop signal */
- I2C_EnableGenerateStop(I2C1);
- /* I2C Clear Stop Flag */
- I2C_ClearIntFlag(I2C1, I2C_INT_FLAG_STOP);
-
- }
更新显存调用库函数
- //更新显存到OLED
- void OLED_Refresh(void)
- {
- u8 i,n;
- for(i=0;i<8;i++)
- {
- OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
- OLED_WR_Byte(0x00,OLED_CMD); //设置低列起始地址
- OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址
-
- for(n=0;n<128;n++)
- {
- I2C_HandlingTransfer(I2C1, 0x78, 2, I2C_RELOAD_MODE_AUTOEND, I2C_GENERATE_START_WRITE);
- I2C_TxData(I2C1,0x40);
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET);
- I2C_TxData(I2C1,OLED_GRAM[n][i]);
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_TXBE) == RESET);
- }
- /* I2C Generate Stop signal */
- I2C_EnableGenerateStop(I2C1);
- /* I2C Clear Stop Flag */
- I2C_ClearIntFlag(I2C1, I2C_INT_FLAG_STOP);
- }
- }
经过了上述的映射后,OLED的库函数就可以使用硬件I2C来驱动OLED屏幕了。
因为是没有焊接OLED的飞线,手头上找不到足够的杜邦线,都是用手捏着测试的,不方便拍照。先不放图了,等我找到足够多的杜邦线再来补图。
附录是该项目的工程文件源代码,供大家参考测试用。
补充图片

|