RT THREAD OLED IIC驱动移植
1.硬件环境
MCU:STM32F103C8T6
OLED:SSD1306 0.96
关键用u8g2的话内存开销太大了,所以正好学习一下IIC驱动
2.程序开发
2.1 开启IIC
记得下载后在MSH中查看是否真的开启了IIC总线
2.2程序移植
首先需要明确一点 rtt和传统驱动的区别
rtthread把地址和读写位是分开的,底层发送的数据是将地址左移1位再或上读写位,如果你发0xa0,左移后再或上写,这个数据不对了,应该发0x50左移后变成0xa0再或上写就对了,相关的解释网址如下:
https://club.rt-thread.org/ask/question/8065.html
其实我当时在驱动AT24C256的时候是十分困惑的,为什么在文档里写的0xa0为什么在程序中要设置为0x50,直到我自己真正动手驱动的时候才知道了原因
所以既然OLED的从机地址是0x78,对应0111 1000
那我们右移一位 0011 1100变成0x3c
然后在整个驱动的过程中最终要的还是写指令的操作,代码如下:
static rt_err_t WriteCmd(struct rt_i2c_bus_device *bus, rt_uint8_t data)
{
rt_uint8_t buf[2];
struct rt_i2c_msg msgs;
buf[0] = 0x00;
buf[1] = data;
msgs.addr = OLED_ADDR;
msgs.flags = RT_I2C_WR;
msgs.buf = buf;
msgs.len = 2;
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_err_t WriteDat(struct rt_i2c_bus_device *bus, rt_uint8_t data)
{
rt_uint8_t buf[2];
struct rt_i2c_msg msgs;
buf[0] = 0x40;
buf[1] = data;
msgs.addr = OLED_ADDR;
msgs.flags = RT_I2C_WR;
msgs.buf = buf;
msgs.len = 2;
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
初始化函数
void OLED_INIT(void)
{
rt_thread_mdelay(100);
WriteCmd(i2c_bus,0xAE);
WriteCmd(i2c_bus,0x20);
WriteCmd(i2c_bus,0x10);
WriteCmd(i2c_bus,0xb0);
WriteCmd(i2c_bus,0xc8);
WriteCmd(i2c_bus,0x00);
WriteCmd(i2c_bus,0x10);
WriteCmd(i2c_bus,0x40);
WriteCmd(i2c_bus,0x81);
WriteCmd(i2c_bus,0xff);
WriteCmd(i2c_bus,0xa1);
WriteCmd(i2c_bus,0xa6);
WriteCmd(i2c_bus,0xa8);
WriteCmd(i2c_bus,0x3F);
WriteCmd(i2c_bus,0xa4);
WriteCmd(i2c_bus,0xd3);
WriteCmd(i2c_bus,0x00);
WriteCmd(i2c_bus,0xd5);
WriteCmd(i2c_bus,0xf0);
WriteCmd(i2c_bus,0xd9);
WriteCmd(i2c_bus,0x22);
WriteCmd(i2c_bus,0xda);
WriteCmd(i2c_bus,0x12);
WriteCmd(i2c_bus,0xdb);
WriteCmd(i2c_bus,0x20);
WriteCmd(i2c_bus,0x8d);
WriteCmd(i2c_bus,0x14);
WriteCmd(i2c_bus,0xaf);
}
下载程序后看到一片花就对了
其余相关函数都放进来了
void OLED_FILL(unsigned char fill_data)
{
unsigned char m,n;
for(m=0;m<8;m++){
WriteCmd(i2c_bus,0xb0+m);
WriteCmd(i2c_bus,0x00);
WriteCmd(i2c_bus,0x10);
for(n=0;n<128;n++){
WriteDat(i2c_bus,fill_data);
}
}
}
void OLED_CLS(void)
{
OLED_FILL(0x00);
}
void OLED_SetPos(unsigned char x, unsigned char y)
{
WriteCmd(i2c_bus,0xb0+y);
WriteCmd(i2c_bus,((x&0xf0)>>4)|0x10);
WriteCmd(i2c_bus,(x&0x0f)|0x01);
}
const unsigned char F6x8[][6] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00},
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00},
{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14},
{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12},
{0x00, 0x62, 0x64, 0x08, 0x13, 0x23},
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50},
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00},
{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00},
{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00},
{0x00, 0x14, 0x08, 0x3E, 0x08, 0x14},
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08},
{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00},
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08},
{0x00, 0x00, 0x60, 0x60, 0x00, 0x00},
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02},
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E},
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00},
{0x00, 0x42, 0x61, 0x51, 0x49, 0x46},
{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31},
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10},
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39},
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30},
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03},
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36},
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E},
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00},
{0x00, 0x00, 0x56, 0x36, 0x00, 0x00},
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00},
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14},
{0x00, 0x00, 0x41, 0x22, 0x14, 0x08},
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06},
{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E},
{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C},
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36},
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22},
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C},
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41},
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01},
{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A},
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F},
{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00},
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01},
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41},
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40},
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F},
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F},
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E},
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06},
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E},
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46},
{0x00, 0x46, 0x49, 0x49, 0x49, 0x31},
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01},
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F},
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F},
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F},
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63},
{0x00, 0x07, 0x08, 0x70, 0x08, 0x07},
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43},
{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00},
{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55},
{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00},
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04},
{0x00, 0x40, 0x40, 0x40, 0x40, 0x40},
{0x00, 0x00, 0x01, 0x02, 0x04, 0x00},
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78},
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38},
{0x00, 0x38, 0x44, 0x44, 0x44, 0x20},
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F},
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18},
{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02},
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C},
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78},
{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00},
{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00},
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00},
{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00},
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78},
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78},
{0x00, 0x38, 0x44, 0x44, 0x44, 0x38},
{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18},
{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC},
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08},
{0x00, 0x48, 0x54, 0x54, 0x54, 0x20},
{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20},
{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C},
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C},
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C},
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44},
{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C},
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44},
{0x14, 0x14, 0x14, 0x14, 0x14, 0x14}
};
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[])
{
unsigned char c = 0,i = 0,j = 0;
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 126)
{
x = 0;
y++;
}
OLED_SetPos(x,y);
for(i=0;i<6;i++)
WriteDat(i2c_bus,F6x8[c][i]);
x += 6;
j++;
}
}
2.3程序执行效果
3.所有代码
因为我是放到mian.c中测试用的,有需求的话自行封装
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#define OLED_I2C_BUS_NAME "i2c1"
#define OLED_ADDR 0x3c
static struct rt_i2c_bus_device *i2c_bus=RT_NULL;
static rt_err_t WriteCmd(struct rt_i2c_bus_device *bus, rt_uint8_t data)
{
rt_uint8_t buf[2];
struct rt_i2c_msg msgs;
buf[0] = 0x00;
buf[1] = data;
msgs.addr = OLED_ADDR;
msgs.flags = RT_I2C_WR;
msgs.buf = buf;
msgs.len = 2;
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_err_t WriteDat(struct rt_i2c_bus_device *bus, rt_uint8_t data)
{
rt_uint8_t buf[2];
struct rt_i2c_msg msgs;
buf[0] = 0x40;
buf[1] = data;
msgs.addr = OLED_ADDR;
msgs.flags = RT_I2C_WR;
msgs.buf = buf;
msgs.len = 2;
if (rt_i2c_transfer(bus, &msgs, 1) == 1)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
void OLED_INIT(void)
{
rt_thread_mdelay(100);
WriteCmd(i2c_bus,0xAE);
WriteCmd(i2c_bus,0x20);
WriteCmd(i2c_bus,0x10);
WriteCmd(i2c_bus,0xb0);
WriteCmd(i2c_bus,0xc8);
WriteCmd(i2c_bus,0x00);
WriteCmd(i2c_bus,0x10);
WriteCmd(i2c_bus,0x40);
WriteCmd(i2c_bus,0x81);
WriteCmd(i2c_bus,0xff);
WriteCmd(i2c_bus,0xa1);
WriteCmd(i2c_bus,0xa6);
WriteCmd(i2c_bus,0xa8);
WriteCmd(i2c_bus,0x3F);
WriteCmd(i2c_bus,0xa4);
WriteCmd(i2c_bus,0xd3);
WriteCmd(i2c_bus,0x00);
WriteCmd(i2c_bus,0xd5);
WriteCmd(i2c_bus,0xf0);
WriteCmd(i2c_bus,0xd9);
WriteCmd(i2c_bus,0x22);
WriteCmd(i2c_bus,0xda);
WriteCmd(i2c_bus,0x12);
WriteCmd(i2c_bus,0xdb);
WriteCmd(i2c_bus,0x20);
WriteCmd(i2c_bus,0x8d);
WriteCmd(i2c_bus,0x14);
WriteCmd(i2c_bus,0xaf);
}
void OLED_FILL(unsigned char fill_data)
{
unsigned char m,n;
for(m=0;m<8;m++){
WriteCmd(i2c_bus,0xb0+m);
WriteCmd(i2c_bus,0x00);
WriteCmd(i2c_bus,0x10);
for(n=0;n<128;n++){
WriteDat(i2c_bus,fill_data);
}
}
}
void OLED_CLS(void)
{
OLED_FILL(0x00);
}
void OLED_SetPos(unsigned char x, unsigned char y)
{
WriteCmd(i2c_bus,0xb0+y);
WriteCmd(i2c_bus,((x&0xf0)>>4)|0x10);
WriteCmd(i2c_bus,(x&0x0f)|0x01);
}
const unsigned char F6x8[][6] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00},
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00},
{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14},
{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12},
{0x00, 0x62, 0x64, 0x08, 0x13, 0x23},
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50},
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00},
{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00},
{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00},
{0x00, 0x14, 0x08, 0x3E, 0x08, 0x14},
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08},
{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00},
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08},
{0x00, 0x00, 0x60, 0x60, 0x00, 0x00},
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02},
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E},
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00},
{0x00, 0x42, 0x61, 0x51, 0x49, 0x46},
{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31},
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10},
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39},
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30},
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03},
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36},
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E},
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00},
{0x00, 0x00, 0x56, 0x36, 0x00, 0x00},
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00},
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14},
{0x00, 0x00, 0x41, 0x22, 0x14, 0x08},
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06},
{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E},
{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C},
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36},
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22},
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C},
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41},
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01},
{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A},
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F},
{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00},
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01},
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41},
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40},
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F},
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F},
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E},
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06},
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E},
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46},
{0x00, 0x46, 0x49, 0x49, 0x49, 0x31},
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01},
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F},
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F},
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F},
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63},
{0x00, 0x07, 0x08, 0x70, 0x08, 0x07},
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43},
{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00},
{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55},
{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00},
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04},
{0x00, 0x40, 0x40, 0x40, 0x40, 0x40},
{0x00, 0x00, 0x01, 0x02, 0x04, 0x00},
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78},
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38},
{0x00, 0x38, 0x44, 0x44, 0x44, 0x20},
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F},
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18},
{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02},
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C},
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78},
{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00},
{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00},
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00},
{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00},
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78},
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78},
{0x00, 0x38, 0x44, 0x44, 0x44, 0x38},
{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18},
{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC},
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08},
{0x00, 0x48, 0x54, 0x54, 0x54, 0x20},
{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20},
{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C},
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C},
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C},
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44},
{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C},
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44},
{0x14, 0x14, 0x14, 0x14, 0x14, 0x14}
};
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[])
{
unsigned char c = 0,i = 0,j = 0;
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 126)
{
x = 0;
y++;
}
OLED_SetPos(x,y);
for(i=0;i<6;i++)
WriteDat(i2c_bus,F6x8[c][i]);
x += 6;
j++;
}
}
int main(void)
{
rt_err_t result=RT_NULL;
i2c_bus=(struct rt_i2c_bus_device *)rt_device_find("i2c1");
if(i2c_bus==RT_NULL){
rt_kprintf("no device \n");
}else{
rt_kprintf("find device \n");
OLED_INIT();
OLED_CLS();
OLED_ShowStr(0,3,"i am king");
}
return RT_EOK;
}
相关操作不应该全部放在main.c里面,本文仅做测试。 学习了一下还是挺爽的,下期再见
|