打印
[MM32软件]

灵动 MM32 + I2C驱动 OLED

[复制链接]
2411|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kxsi|  楼主 | 2021-6-7 18:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、硬件资源
(1)主控:灵动微 MM32F103CxT6;
(2)屏幕: [灵动MM32 + I2C驱动 OLED];

二、代码设计
1、I2C 初始化
/**
  * @brief  Configures I2C Device port.
  * @param  ulSpeed I2C baudrate.
  * @retval None
  */
static void Config_I2cDevice ( uint32_t ulSpeed )
{
        GPIO_InitTypeDef xGPIO_InitStruct;
        I2C_InitTypeDef xI2C_InitStruct;
       
        /* Enable clock. */
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );       
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );
       
        /* Configure scl & sda GPIO parameters. */
        xGPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
        xGPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
        xGPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
        GPIO_Init( GPIOB, &xGPIO_InitStruct );
       
        /* Configure I2C parameters. */
        xI2C_InitStruct.I2C_ClockSpeed = ulSpeed;
        xI2C_InitStruct.I2C_Mode = I2C_Mode_MASTER;
        xI2C_InitStruct.I2C_OwnAddress = 0x0;
        if ( ulSpeed <= 100000 ) { /* Configure speed in standard mode */
                xI2C_InitStruct.I2C_Speed = I2C_Speed_STANDARD;
        } else { /* Configure speed in fast mode */
                xI2C_InitStruct.I2C_Speed = I2C_Speed_FAST;
        }
        I2C_Init( I2C1, &xI2C_InitStruct );
       
        /* Enable i2c1 port. */
        I2C_Cmd( I2C1, ENABLE );
}



使用特权

评论回复
沙发
kxsi|  楼主 | 2021-6-7 18:41 | 只看该作者
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 );
}


使用特权

评论回复
板凳
match007| | 2021-6-14 16:31 | 只看该作者
我要不要把IO模拟的方法给抛弃呢?
先MARK,哪天加班的时候,玩一玩

使用特权

评论回复
地板
chenqianqian| | 2021-6-15 07:29 | 只看该作者
用硬件IIC吧

使用特权

评论回复
5
HuangHongLun| | 2021-6-15 09:06 | 只看该作者
硬件I2C的驱动确实比软件模拟要方便快捷多了,以后应该多使用硬件,不使用软件。

使用特权

评论回复
6
菜鸟的第一步| | 2021-6-15 13:27 | 只看该作者
果然还是硬件香,软件模拟的虽然方便简单,但是太弱了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

45

主题

3310

帖子

2

粉丝