2、I2C 硬件驱动 
(a)、 根据官方提供源码修改,并且将其封装在 HAL_i2c 库文件内; 
(b)、 该OLED 仅需要 写操作; 
(c)、 在发送 STOP 停止信号前需延时 5us 才能正常显示(后续再找原因)。 
 
/** 
  * @brief  Writes buffer of data to the I2C EEPROM. 
  * @param  pxIO :typedef struct { GPIO_TypeDef* xPort; uint16_t usScl; uint16_t usSda; }I2C_GPIO_t; 
  * @param  pBuffer : pointer to the buffer  containing the data to be written  
  *         to the EEPROM. 
  * @param  WriteAddr : EEPROM's internal address to write to. 
  * @param  NumByteToWrite : number of bytes to write to the EEPROM. 
  * @retval None 
  */ 
ErrorStatus I2C_WriteBuffer( const I2C_GPIO_t* pxIO, I2C_TypeDef* I2Cx, uint8_t DeviceAddr, uint8_t WriteAddr, uint16_t NumByteToWrite, uint8_t* pBuffer) 
{ 
        uint32_t I2C_Timeout; 
        uint16_t write_Num; 
         
        GPIO_InitTypeDef xGPIO_InitStruct; 
 
        xGPIO_InitStruct.GPIO_Pin  = pxIO->usScl | pxIO->usSda; 
        xGPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; 
        xGPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; 
        GPIO_Init( pxIO->xPort, &xGPIO_InitStruct ); 
 
        I2C_Cmd(I2Cx, DISABLE); 
        I2C_Send7bitAddress( I2Cx, DeviceAddr, I2C_Direction_Transmitter ); 
        I2C_Cmd(I2Cx, ENABLE); 
         
        xGPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; 
        GPIO_Init( pxIO->xPort, &xGPIO_InitStruct ); 
         
        I2C_SendData( I2Cx, WriteAddr ); 
        I2C_Timeout = 0x1000; 
         
        while ( ( I2C_GetFlagStatus( I2Cx, I2C_STATUS_FLAG_TFE ) ) == RESET ) { 
                if ( ( I2C_Timeout-- ) == 0 ) { 
                        return ERROR; 
                } 
        } 
         
        for ( write_Num=0; write_Num<NumByteToWrite; write_Num++ ) { 
                I2C_Timeout = 0x1000; 
         
                while ( ( I2C_GetFlagStatus( I2Cx, I2C_STATUS_FLAG_TFE ) ) == RESET ) { 
                        if ( ( I2C_Timeout-- ) == 0 ) { 
                                return ERROR; 
                        } 
                } 
                I2C_SendData( I2Cx, *( pBuffer + write_Num ) ); 
        } 
         
        /* 96MHz 工作频率下,延时5us. */ 
        for ( uint16_t i=480; i>0; i-- ); 
         
        I2C_GenerateSTOP( I2Cx, ENABLE ); 
        I2C_Timeout = 0x1000; 
         
        while ( ( I2C_GetITStatus( I2Cx, I2C_IT_STOP_DET ) ) == RESET ) { 
                if ( ( I2C_Timeout-- ) == 0 ) { 
                        return ERROR; 
                } 
        } 
         
        /* If all operations OK, return sEE_OK (0) */ 
  return SUCCESS; 
} 
 
 
3、OLED 程序模块 
仅提供 Cmd & Data 部分,大部分和网络上的大同小异,可参考(正点原子、中景园电子、etc)。这篇**主要是 MM32 的 I2C,完整驱动代码下载链接在文末。 
 
/** 
  * @brief  Write commands to the screen. 
  * @param  ucCmd    Write command to be written. 
  * @retval None. 
  */ 
static void Screen_WriteCmd( uint8_t ucCmd ) 
{ 
        I2C_WriteBuffer( &xConfig, I2C_DEVICE, I2C_ADDR, 0x00, 1, &ucCmd ); 
} 
 
/** 
  * @brief  Write data to the screen. 
  * @param  ucCmd    Write data to be written. 
  * @retval None. 
  */ 
static void Screen_WriteDat( uint8_t ucDat ) 
{ 
        I2C_WriteBuffer( &xConfig, I2C_DEVICE, I2C_ADDR, 0x40, 1, &ucDat ); 
} 
 
 
 |