这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » Renesas » 瑞萨RA0单片机连载之六—面向对象之I2C驱动OLED

共1条 1/1 1 跳转至

瑞萨RA0单片机连载之六—面向对象之I2C驱动OLED

助工
2024-05-17 18:11:06     打赏

【前言】

OLED是非常常用的显示设备,可以由4线、3线的spi驱动,也可以使用2线的IIC来驱动。百问网提供了spi_OLED的驱动例程,这次使用IIC来驱动,并且使用基于面向对象的编程来实现。

【实现步聚】

1、配置IIC,打开RASC后,在栈中增加rau_master_I2C,并设置channel为0b20即通道2,选择SCL为P112与SDA为P110。

image.png

【注】,我原来设置了为通道0或者通道1,但是都与UART或的外接晶振的IO有冲突,所以只能选择这个通道但是他还是与tx、LED有冲突,如果自己的设计的话还需要考虑到IO的冲突问题。

2、生成代码后,我拷贝drv_oled.h/c以及driv_spi.h到工程之中。


image.png

3、在原来的OLED工程之中,是使用spi来驱动的,同时原来的RA5他的内存与频率相比RA0要高很多,需要进行很多的更改。首先添加回调函数,回调函数中判断接收状态,并更新:

void sau_i2c_master_callback(i2c_master_callback_args_t * p_args)
{
    switch (p_args->event)
    {
        case I2C_MASTER_EVENT_TX_COMPLETE:
        {
            gI2C1TxCplt = true;
            break;
        }
        case I2C_MASTER_EVENT_RX_COMPLETE:
        {
            gI2C1RxCplt = true;
            break;
        }
        default:
        {
            gI2C1TxCplt = gI2C1RxCplt = false;
            break;
        }
    }
}

4、接着修改发送等待超时函数,在我们向i2c总线发送数据结事后,我们需要用这个函数来判断是否发送结束的标志位。

static void I2C1WaitTxCplt(void)
{
    uint16_t wTimeOut = 10;
    while(!gI2C2TxCplt && wTimeOut)
    {
        HAL_Delay(1);
        wTimeOut--;
    }
    gI2C2TxCplt = false;
}

5、修改向ssd1306写入一个寄存器的功能函数,在这个函数中,我们要组装一个buff用于向i2c总线写入数据的,由于向ssd1306写入寄存器,第一个字节为0x00,所以组装为[0x00,cmd]。

static void OLEDDrvWriteReg(uint8_t ucData)
{
	uint8_t buff[2]= {0x00,0x00};
	buff[1] = ucData;
    fsp_err_t err = R_SAU_I2C_Write(&g_sau_i2c_master_ctrl, buff, 2, true);
    if (FSP_SUCCESS != err)
    {
        printf("%s %d\r\n", __FUNCTION__, __LINE__);
        return;
    }
    I2C1WaitTxCplt();
}

6、组装向ssd1306发送一整个buff的命令:

static void OLEDDrvWriteBuf(uint8_t* rbuf, uint16_t wSize)
{
	fsp_err_t err;
	
//		err =R_SAU_I2C_Write(&g_sau_i2c_master_ctrl, 0x40, 1, false);
//	if(FSP_SUCCESS != err)
//        printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
		rbuf[0] = 0x40;
    err = R_SAU_I2C_Write(&g_sau_i2c_master_ctrl, rbuf, 1024, true);
    if(FSP_SUCCESS != err)
        printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);

    I2C1WaitTxCplt();
}

【注】这里原来使用malloc进行了重新的内存申请,但是由于这个MCU的内存有限,我做了申请,好象一直不成功,先写成这样,其实buf中的0位是被清除掉了的,所以会有点问题,在后面我将重新这个驱动,这里先实现基本功能。

7、编写测试函数如下:

void led_blink(void)
{

	UartDevicesRegister();


	DisplayDevice *ptDispDev = OLEDGetDevice();
    if(ptDispDev == NULL)
    {
        printf("Failed to get OLED Display Device!\r\n");
        return;
    }

    ptDispDev->Init(ptDispDev);
    uint8_t *pBuf = (uint8_t*)ptDispDev->FBBase;
	while(1)
	{
	    	
		       for(uint16_t i=0; i<ptDispDev->dwSize; i++)
        {
            pBuf[i] = 0x00;
        }
        ptDispDev->Flush(ptDispDev);
				HAL_Delay(1);
        for(uint16_t i=0; i<ptDispDev->dwSize; i++)
        {
            pBuf[i] = 0xFF;
        }
        ptDispDev->Flush(ptDispDev);
				HAL_Delay(1);
		
	}
}

其中第一段是向整个屏写入了0x00即全屏为黑色,第二段是写入oxFF即全白。这样就实现了清屏-》全亮的效果。

【总结】

在面向对象的编程中,对OLED进行的封装,在使用的过程中,可以实现少量的低层代码的修改即中实现模块化的功能实现。下一步,我将补全字符、图片的功能。

附工程源码:

FSP_LED.zip




关键词: 刘工爱评测之瑞萨RA0单片机     瑞萨     单片机     连载         

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]