2915|1

282

帖子

2

TA的资源

一粒金砂(高级)

楼主
 

【GD32L233C-START评测】12. 硬件IIC驱动OLED [复制链接]

之前的帖子可以参考:

 

【GD32L233C-START评测】1.开箱

【GD32L233C-START评测】2.手把手创建新工程

【GD32L233C-START评测】3.移植FreeRTOS到GD32L233

【GD32L233C-START评测】4. 移植RT-Thread到GD32L233

【GD32L233C-START评测】5. IIC驱动OLED

【GD32L233C-START评测】6. 获取RTC时间并通过OLED显示

【GD32L233C-START评测】7. PWM驱动LED

【GD32L233C-START评测】8. TRNG真随机数生成

【GD32L233C-START评测】9. CRC检验

【GD32L233C-START评测】10. ADC读取芯片内部温度

【GD32L233C-START评测】11.DAC输出电压值_ADC读取外部电压值

 

在我第5篇帖子里,我使用软件IIC完成了OLED的驱动,第6篇帖子里加上了RTC来显示时间,本帖将用硬件IIC来完成OLED的显示以及时间显示。

为什么用硬件IIC呢?第一点硬件IIC实现逻辑相对软件IIC而言少了IIC通信逻辑部分,相对而言要简单很多;第二点就是硬件IIC速度比软件IIC的速度快很多。

 

一、了解硬件IIC

要成功使用硬件IIC,我们首先需要了解硬件IIC的相关知识,查看数据手册内容,参考是《用户手册》第21章21. 内部集成电路总线接口I2C)

硬件I2C有四种工作模式:

 从机发送
 从机接收
 主机发送
 主机接收

本帖主要是对OLED的操作,不需要读,而且OLED是作为从机被控制的,所以我们的单片机将作为主机发送数据,只工作在这一个模式下。

关于IIC数据通信的有效性以及格式,原理以及通信时序等重要信息等都在《用户手册》中有详细的描述,不懂得小伙伴可以自行阅读。

 

二、接口信息

查看《用户手册》了解了IIC的通信原理以及相关寄存器之后,我们需要查看《数据手册》了解IIC相关的接口配置,方便程序编写。

GD32L233C开发板引出的IIC接口是PB10以及PB11,我们直接查找《数据手册》中这两个引脚的复用信息即可。

如下图:

复用可选时AF4,其中

PB10  --  AF5  --  I2C1的SCL

PB11  --  AF4  --  I2C1的SDA

 

三、软件代码

1、初始化GPIO

初始化GPIO主要是设置PB10以及PB11位复用端口,复用IIC功能

void i2c_gpio_config(void)
{
	/* enable GPIOB clock */
    rcu_periph_clock_enable(RCU_GPIOB);
	
    /* connect PB10 to I2C1_SCL */
    gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_10);
    /* connect PB11 to I2C1_SDA */
    gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_11);
    /* configure GPIO pins of I2C1 */
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_11);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
}

2、初始化硬件IIC

初始化硬件IIC,需要设置:

IIC主机的IIC地址,设置位0x72,用宏I2C_OWN_ADDRESS7表示

IIC从机的IIC地址,也就是OLED的地址,位0x78,用宏I2C_SLAVE_OLED_ADDRESS7表示

硬件IIC每次传输的数据个数,OLED有写数据寄存器0x40和写命令寄存器0x00,每次需要想这两个寄存器中写入数据,所以是2个字节,用I2C_DATA_BYTES表示。

void i2c_config(void)
{
	/* enable I2C1 clock */
    rcu_periph_clock_enable(RCU_I2C1);
	
    /* configure I2C timing */
    i2c_timing_config(I2C1, 0, 0x3, 0);
    i2c_master_clock_config(I2C1, 0x13, 0x36);

    /* configure I2C address */
    i2c_address_config(I2C1, I2C_OWN_ADDRESS7, I2C_ADDFORMAT_7BITS);
    /* configure slave address */
    i2c_master_addressing(I2C1, I2C_SLAVE_OLED_ADDRESS7, I2C_MASTER_TRANSMIT);
    /* configure number of bytes to be transferred */
    i2c_transfer_byte_number_config(I2C1, I2C_DATA_BYTES);
    /* enable I2C1 */
    i2c_enable(I2C1);
}

3、OLED写命令与写数据函数实现

因为之前使用的是软件IIC,本次使用硬件IIC,所以我用了一个宏定义对硬件IIC代码和硬件IIC代码进行区分,需要使用硬件IIC或者软件IIC的时候只需要修改一些宏定义即可,如下:

#define OLED_IIC_TYPE_SW          0U  /*IIC for software*/
#define OLED_IIC_TYPE_HW          1U  /*IIC for hardware*/
#define OLED_IIC_TYPE             OLED_IIC_TYPE_HW

写数据函数实现:

void OLED_WrDat(unsigned char IIC_Data)
{
#if(OLED_IIC_TYPE == OLED_IIC_TYPE_HW)
	uint8_t i2c_transmitter[2]={0x40, IIC_Data};
	uint8_t i;
	
	i2c_transmitter[0] = 0x40;
	i2c_transmitter[1] = IIC_Data;
	    /* wait until I2C bus is idle */
    while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
    /* send a start condition to I2C bus */
    i2c_start_on_bus(I2C1);
    /* wait until the transmit data buffer is empty */
    I2C_STAT(I2C1) |= I2C_STAT_TBE;
    while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));

    for(i = 0; i < 2; i++) {
        /* data transmission */
        i2c_data_transmit(I2C1, i2c_transmitter[i]);
        /* wait until the TI bit is set */
        while(!i2c_flag_get(I2C1, I2C_FLAG_TI));
    }
    /* wait for transfer complete flag */
    while(!i2c_flag_get(I2C1, I2C_FLAG_TC));
    /* send a stop condition to I2C bus */
    i2c_stop_on_bus(I2C1);
    /* wait until stop condition generate */
    while(!i2c_flag_get(I2C1, I2C_FLAG_STPDET));
    /* clear the STPDET bit */
    i2c_flag_clear(I2C1, I2C_FLAG_STPDET);
#elif(OLED_IIC_TYPE == OLED_IIC_TYPE_SW)
	IIC_Start();
	IIC_Send_Byte(0x78);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x40);			//write data
	IIC_Wait_Ack();
	IIC_Send_Byte(IIC_Data);
	IIC_Wait_Ack();
	IIC_Stop();
#endif
}

写命令函数实现

void OLED_WrCmd(unsigned char IIC_Command)
{
#if(OLED_IIC_TYPE == OLED_IIC_TYPE_HW)
	uint8_t i2c_transmitter[2]={0x00, IIC_Command};
	uint8_t i;
	
	i2c_transmitter[0] = 0x00;
	i2c_transmitter[1] = IIC_Command;
	    /* wait until I2C bus is idle */
    while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
    /* send a start condition to I2C bus */
    i2c_start_on_bus(I2C1);
    /* wait until the transmit data buffer is empty */
    I2C_STAT(I2C1) |= I2C_STAT_TBE;
    while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));

    for(i = 0; i < 2; i++) {
        /* data transmission */
        i2c_data_transmit(I2C1, i2c_transmitter[i]);
        /* wait until the TI bit is set */
        while(!i2c_flag_get(I2C1, I2C_FLAG_TI));
    }
    /* wait for transfer complete flag */
    while(!i2c_flag_get(I2C1, I2C_FLAG_TC));
    /* send a stop condition to I2C bus */
    i2c_stop_on_bus(I2C1);
    /* wait until stop condition generate */
    while(!i2c_flag_get(I2C1, I2C_FLAG_STPDET));
    /* clear the STPDET bit */
    i2c_flag_clear(I2C1, I2C_FLAG_STPDET);
#elif(OLED_IIC_TYPE == OLED_IIC_TYPE_SW)
	IIC_Start();
	IIC_Send_Byte(0x78);            //Slave address,SA0=0
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);			//write command
	IIC_Wait_Ack();
	IIC_Send_Byte(IIC_Command);
	IIC_Wait_Ack();
	IIC_Stop();
#endif
}

 

4、OLED显示代码

OLED的显示代码没有变化,直接参考我第6篇帖子即可:【GD32L233C-START评测】6. 获取RTC时间并通过OLED显示

 

四、效果展示

显示效果如下,视频拍倒了,见谅

 

五、源代码

源代码分享如下,有需要的小伙伴可以参考。

GD32L233C_Prj_OLED_HW_IIC.zip (784.54 KB, 下载次数: 31)

 

 

 

此帖出自GD32 MCU论坛

最新回复

i2c_data_transmit(I2C1, i2c_transmitter);大佬,这句话在for循环里没有改数组索引,发的只是首地址的数据   详情 回复 发表于 2022-6-24 09:08
点赞 关注
 

回复
举报

8

帖子

0

TA的资源

一粒金砂(中级)

沙发
 

i2c_data_transmit(I2C1, i2c_transmitter);大佬,这句话在for循环里没有改数组索引,发的只是首地址的数据

此帖出自GD32 MCU论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表