【前言】
OLED屏是最常用的显示外设之一,并且可以做到低功耗等等优秀的功能。本文采用OLED屏主控芯片为SSD1306,IIC协议。
【SSD1306地址】
SSD1306作为从机来与F5260进行通讯,SSD1306在发送或接受任何信息之前必须识别从机地址。设备将会响应从机地址,后面跟随着从机地址位(SA0位)和读写选择位(R/W#位),格式如下:
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总线的写模式的时序请参考下图:
由于此次我们只需要向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)
{
}
}
效果:
【疑问】
我通过IIC的Polling、以及DMA_polling都是可以成功的驱动的,但是在DMA_Interrupt模式下,第一行的数据发送是正常的,显示也正常,但是发送到第二行就出现了错误,根据逻辑分析仪采集的数据如下:
发送第一行:
这里是正常的的
发送第二行数据时出错了错误