盼盼_dRglQm · 5 天前

【灵动Mini-F5265-OB】IIC几种方式驱动OLED屏

【前言】
OLED屏是最常用的显示外设之一,并且可以做到低功耗等等优秀的功能。本文采用OLED屏主控芯片为SSD1306,IIC协议。
【SSD1306地址】
SSD1306作为从机来与F5260进行通讯,SSD1306在发送或接受任何信息之前必须识别从机地址。设备将会响应从机地址,后面跟随着从机地址位(SA0位)和读写选择位(R/W#位),格式如下:
image.png
SA0 位为从机地址提供了一个位的拓展。0111100或0111101都可以做为SSD1306的从机地址。D/C#引脚作为SA0用于从机地址选择。R/W#为用来决定I2C总线接口的操作模式R/W#=1,读模式。R/W#=0写模式。即当我们向SSD1306写入数据时为0x78,而作为读时地址位为0x79。因此我们使用宏定义:
#define OLED_I2C_ADDRESS 0x78
【I2C总线写数据】
12C总线接口提供了写数据和命令到设备的接口。关于12C总线的写模式的时序请参考下图:
image.png
由于此次我们只需要向SSD1306写入指令与数据,因此,只需要考虑写入数即可。
【写指令】
根据上述的时序图,如果我们往SSD1306写入一个指令那么需要首先向总线写入SSD1306的地址,指令码,接下来写入数据。
由此我们构建写命令的函数如下:

/**
  * 函    数:OLED写命令
  * 参    数:Command 要写入的命令值,范围:0x00~0xFF
  * 返 回 值:无
  */
void OLED_WriteCommand(uint8_t Command)
{
    uint8_t commadDat[2];
    commadDat[0] = 0x00;
    commadDat[1] = Command;
    I2C_TxData_Polling(commadDat, 2);
}

【写数据】
写入数据与写入指令,不同点就是在于指令为0x40,其余都是相同的。因此构建代码如下:

/**
  * 函    数:OLED写数据
  * 参    数:Data 要写入数据的起始地址
  * 参    数:Count 要写入数据的数量
  * 返 回 值:无
  */
void OLED_WriteData(uint8_t *Data, uint8_t Count)
{
    uint8_t dat[1];
    dat[0]= 0x40;
    OLED_TxData_DMA_Polling(dat,1);
    OLED_TxData_DMA_Polling(Data,Count);
    I2C_GenerateSTOP(I2C1, ENABLE);
    while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
    {
    }
}

此函数,在DMA写入数据结束后,需要发送stop信号。
【代码移植】
构建好以上两个数据后,我们移植了江科大的OLED驱动。详细的代码见附件。
【测试效果】
移植好代码之后,我在主程序添加测试代码:

int main(void)
{
    PLATFORM_Init();
        OLED_Init();
        OLED_ShowString(0, 0, "hello world", OLED_8X16);
        OLED_Update();
    while (1)
    {
    }
}

效果:
368a326079473061ed2635cf68d5caf.jpg
【疑问】
我通过IIC的Polling、以及DMA_polling都是可以成功的驱动的,但是在DMA_Interrupt模式下,第一行的数据发送是正常的,显示也正常,但是发送到第二行就出现了错误,根据逻辑分析仪采集的数据如下:
发送第一行:
image.png
这里是正常的的
发送第二行数据时出错了错误
image.png

推荐阅读
关注数
0
文章数
8
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息