在Ricoboard
开发板上使能SPI0和SPI4的方法相信大家已经了解,我这里不在重复,因为使用正常的spi器件无法驱动手里的OLED模块,所以才想到使用GPIO模拟SPI的方法,理论不多说直接说实现步骤。
1.添加kernel编译支持。
2.选择合适的GPIO,这里直接使用SPI4的GPIO,如下图:
3.DTSI里面添加GPIO模拟SPI的设置
4.添加SPIDev测试驱动
因为在config里面设置CONFIG_SPI_SPIDEV=y,无法编译出spidev设备节点,所以直接在Makefile里面修改obj-$(CONFIG_SPI_SPIDEV) += spidev.o为obj-y += spidev.o。
5.添加应用程序测试SPIDEV设备节点
第一次和最后一次模拟处理的SPI的DO和D1是连接状态,中间一次是断开状态。测试结果如上图,pin连接如下图:
上面的步骤就可以保证我们模拟处理的SPI是可以正常通讯的,下面说说如何实现OELD的显示步骤。因为目前本职工作较忙,所以只是简单说一下实现步骤,相信有经验的人参考一下就可以实现这个功能。
OELD是一种非常高大尚的显示技术,据说苹果下一代产品就要使用OLED做显示屏,不过目前的OLED价格有点贵。
从技术上来讲实现难度并不大,只是可以参考的例子很少,在没有硬件支持的情况下自己将OLED点亮确实花费了一番功夫。
1.DTSI中OLED驱动加载
2.OLED接线方法
3.结果显示
4.驱动代码实现
- #include
- #include
- #include
- #include
- #include
- #include
- #include titions.h>
- #include
- #include
- #include
- #define SSD1306_CMD 0
- #define SSD1306_DAT 1
- #define SSD1306_WIDTH 128
- #define SSD1306_HEIGHT 64
- static uint8_t s_chDispalyBuffer[128][8];
- const uint8_t c_chFont1608[95][16] = {
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
- {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xCC,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
- {0x00,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x00,0x00},/*""",2*/
- {0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x00,0x00},/*"//m.obk20.com/bbs/#",3*/
- {0x00,0x00,0x0E,0x18,0x11,0x04,0x3F,0xFF,0x10,0x84,0x0C,0x78,0x00,0x00,0x00,0x00},/*"$",4*/
- {0x0F,0x00,0x10,0x84,0x0F,0x38,0x00,0xC0,0x07,0x78,0x18,0x84,0x00,0x78,0x00,0x00},/*"%",5*/
- {0x00,0x78,0x0F,0x84,0x10,0xC4,0x11,0x24,0x0E,0x98,0x00,0xE4,0x00,0x84,0x00,0x08},/*"&",6*/
- {0x08,0x00,0x68,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
- {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x18,0x18,0x20,0x04,0x40,0x02,0x00,0x00},/*"(",8*/
- {0x00,0x00,0x40,0x02,0x20,0x04,0x18,0x18,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
- {0x02,0x40,0x02,0x40,0x01,0x80,0x0F,0xF0,0x01,0x80,0x02,0x40,0x02,0x40,0x00,0x00},/*"*",10*/
- {0x00,0x80,0x00,0x80,0x00,0x80,0x0F,0xF8,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00},/*"+",11*/
- {0x00,0x01,0x00,0x0D,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
- {0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80},/*"-",13*/
- {0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
- {0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x60,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00},/*"/",15*/
- {0x00,0x00,0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"0",16*/
- {0x00,0x00,0x08,0x04,0x08,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"1",17*/
- {0x00,0x00,0x0E,0x0C,0x10,0x14,0x10,0x24,0x10,0x44,0x11,0x84,0x0E,0x0C,0x00,0x00},/*"2",18*/
- {0x00,0x00,0x0C,0x18,0x10,0x04,0x11,0x04,0x11,0x04,0x12,0x88,0x0C,0x70,0x00,0x00},/*"3",19*/
- {0x00,0x00,0x00,0xE0,0x03,0x20,0x04,0x24,0x08,0x24,0x1F,0xFC,0x00,0x24,0x00,0x00},/*"4",20*/
- {0x00,0x00,0x1F,0x98,0x10,0x84,0x11,0x04,0x11,0x04,0x10,0x88,0x10,0x70,0x00,0x00},/*"5",21*/
- {0x00,0x00,0x07,0xF0,0x08,0x88,0x11,0x04,0x11,0x04,0x18,0x88,0x00,0x70,0x00,0x00},/*"6",22*/
- {0x00,0x00,0x1C,0x00,0x10,0x00,0x10,0xFC,0x13,0x00,0x1C,0x00,0x10,0x00,0x00,0x00},/*"7",23*/
- {0x00,0x00,0x0E,0x38,0x11,0x44,0x10,0x84,0x10,0x84,0x11,0x44,0x0E,0x38,0x00,0x00},/*"8",24*/
- {0x00,0x00,0x07,0x00,0x08,0x8C,0x10,0x44,0x10,0x44,0x08,0x88,0x07,0xF0,0x00,0x00},/*"9",25*/
- {0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x03,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
- {0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
- {0x00,0x00,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10,0x04,0x00,0x00},/*"<",28*/
- {0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x00,0x00},/*"=",29*/
- {0x00,0x00,0x10,0x04,0x08,0x08,0x04,0x10,0x02,0x20,0x01,0x40,0x00,0x80,0x00,0x00},/*">",30*/
- {0x00,0x00,0x0E,0x00,0x12,0x00,0x10,0x0C,0x10,0x6C,0x10,0x80,0x0F,0x00,0x00,0x00},/*"?",31*/
- {0x03,0xE0,0x0C,0x18,0x13,0xE4,0x14,0x24,0x17,0xC4,0x08,0x28,0x07,0xD0,0x00,0x00},/*"@",32*/
- {0x00,0x04,0x00,0x3C,0x03,0xC4,0x1C,0x40,0x07,0x40,0x00,0xE4,0x00,0x1C,0x00,0x04},/*"A",33*/
- {0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x11,0x04,0x0E,0x88,0x00,0x70,0x00,0x00},/*"B",34*/
- {0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x04,0x10,0x08,0x1C,0x10,0x00,0x00},/*"C",35*/
- {0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"D",36*/
- {0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x17,0xC4,0x10,0x04,0x08,0x18,0x00,0x00},/*"E",37*/
- {0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x17,0xC0,0x10,0x00,0x08,0x00,0x00,0x00},/*"F",38*/
- {0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x44,0x1C,0x78,0x00,0x40,0x00,0x00},/*"G",39*/
- {0x10,0x04,0x1F,0xFC,0x10,0x84,0x00,0x80,0x00,0x80,0x10,0x84,0x1F,0xFC,0x10,0x04},/*"H",40*/
- {0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x00,0x00,0x00,0x00},/*"I",41*/
- {0x00,0x03,0x00,0x01,0x10,0x01,0x10,0x01,0x1F,0xFE,0x10,0x00,0x10,0x00,0x00,0x00},/*"J",42*/
- {0x10,0x04,0x1F,0xFC,0x11,0x04,0x03,0x80,0x14,0x64,0x18,0x1C,0x10,0x04,0x00,0x00},/*"K",43*/
- {0x10,0x04,0x1F,0xFC,0x10,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x0C,0x00,0x00},/*"L",44*/
- {0x10,0x04,0x1F,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x1F,0xFC,0x10,0x04,0x00,0x00},/*"M",45*/
- {0x10,0x04,0x1F,0xFC,0x0C,0x04,0x03,0x00,0x00,0xE0,0x10,0x18,0x1F,0xFC,0x10,0x00},/*"N",46*/
- {0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"O",47*/
- {0x10,0x04,0x1F,0xFC,0x10,0x84,0x10,0x80,0x10,0x80,0x10,0x80,0x0F,0x00,0x00,0x00},/*"P",48*/
- {0x07,0xF0,0x08,0x18,0x10,0x24,0x10,0x24,0x10,0x1C,0x08,0x0A,0x07,0xF2,0x00,0x00},/*"Q",49*/
- {0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x11,0xC0,0x11,0x30,0x0E,0x0C,0x00,0x04},/*"R",50*/
- {0x00,0x00,0x0E,0x1C,0x11,0x04,0x10,0x84,0x10,0x84,0x10,0x44,0x1C,0x38,0x00,0x00},/*"S",51*/
- {0x18,0x00,0x10,0x00,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x00,0x18,0x00,0x00,0x00},/*"T",52*/
- {0x10,0x00,0x1F,0xF8,0x10,0x04,0x00,0x04,0x00,0x04,0x10,0x04,0x1F,0xF8,0x10,0x00},/*"U",53*/
- {0x10,0x00,0x1E,0x00,0x11,0xE0,0x00,0x1C,0x00,0x70,0x13,0x80,0x1C,0x00,0x10,0x00},/*"V",54*/
- {0x1F,0xC0,0x10,0x3C,0x00,0xE0,0x1F,0x00,0x00,0xE0,0x10,0x3C,0x1F,0xC0,0x00,0x00},/*"W",55*/
- {0x10,0x04,0x18,0x0C,0x16,0x34,0x01,0xC0,0x01,0xC0,0x16,0x34,0x18,0x0C,0x10,0x04},/*"X",56*/
- {0x10,0x00,0x1C,0x00,0x13,0x04,0x00,0xFC,0x13,0x04,0x1C,0x00,0x10,0x00,0x00,0x00},/*"Y",57*/
- {0x08,0x04,0x10,0x1C,0x10,0x64,0x10,0x84,0x13,0x04,0x1C,0x04,0x10,0x18,0x00,0x00},/*"Z",58*/
- {0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x40,0x02,0x40,0x02,0x40,0x02,0x00,0x00},/*"[",59*/
- {0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x80,0x00,0x60,0x00,0x1C,0x00,0x03,0x00,0x00},/*"",60*/
- {0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
- {0x00,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00},/*"^",62*/
- {0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01},/*"_",63*/
- {0x00,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
- {0x00,0x00,0x00,0x98,0x01,0x24,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xFC,0x00,0x04},/*"a",65*/
- {0x10,0x00,0x1F,0xFC,0x00,0x88,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"b",66*/
- {0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x00},/*"c",67*/
- {0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x11,0x08,0x1F,0xFC,0x00,0x04},/*"d",68*/
- {0x00,0x00,0x00,0xF8,0x01,0x44,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xC8,0x00,0x00},/*"e",69*/
- {0x00,0x00,0x01,0x04,0x01,0x04,0x0F,0xFC,0x11,0x04,0x11,0x04,0x11,0x00,0x18,0x00},/*"f",70*/
- {0x00,0x00,0x00,0xD6,0x01,0x29,0x01,0x29,0x01,0x29,0x01,0xC9,0x01,0x06,0x00,0x00},/*"g",71*/
- {0x10,0x04,0x1F,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"h",72*/
- {0x00,0x00,0x01,0x04,0x19,0x04,0x19,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"i",73*/
- {0x00,0x00,0x00,0x03,0x00,0x01,0x01,0x01,0x19,0x01,0x19,0xFE,0x00,0x00,0x00,0x00},/*"j",74*/
- {0x10,0x04,0x1F,0xFC,0x00,0x24,0x00,0x40,0x01,0xB4,0x01,0x0C,0x01,0x04,0x00,0x00},/*"k",75*/
- {0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"l",76*/
- {0x01,0x04,0x01,0xFC,0x01,0x04,0x01,0x00,0x01,0xFC,0x01,0x04,0x01,0x00,0x00,0xFC},/*"m",77*/
- {0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"n",78*/
- {0x00,0x00,0x00,0xF8,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0xF8,0x00,0x00},/*"o",79*/
- {0x01,0x01,0x01,0xFF,0x00,0x85,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"p",80*/
- {0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x05,0x01,0xFF,0x00,0x01},/*"q",81*/
- {0x01,0x04,0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x04,0x01,0x00,0x01,0x80,0x00,0x00},/*"r",82*/
- {0x00,0x00,0x00,0xCC,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x98,0x00,0x00},/*"s",83*/
- {0x00,0x00,0x01,0x00,0x01,0x00,0x07,0xF8,0x01,0x04,0x01,0x04,0x00,0x00,0x00,0x00},/*"t",84*/
- {0x01,0x00,0x01,0xF8,0x00,0x04,0x00,0x04,0x00,0x04,0x01,0x08,0x01,0xFC,0x00,0x04},/*"u",85*/
- {0x01,0x00,0x01,0x80,0x01,0x70,0x00,0x0C,0x00,0x10,0x01,0x60,0x01,0x80,0x01,0x00},/*"v",86*/
- {0x01,0xF0,0x01,0x0C,0x00,0x30,0x01,0xC0,0x00,0x30,0x01,0x0C,0x01,0xF0,0x01,0x00},/*"w",87*/
- {0x00,0x00,0x01,0x04,0x01,0x8C,0x00,0x74,0x01,0x70,0x01,0x8C,0x01,0x04,0x00,0x00},/*"x",88*/
- {0x01,0x01,0x01,0x81,0x01,0x71,0x00,0x0E,0x00,0x18,0x01,0x60,0x01,0x80,0x01,0x00},/*"y",89*/
- {0x00,0x00,0x01,0x84,0x01,0x0C,0x01,0x34,0x01,0x44,0x01,0x84,0x01,0x0C,0x00,0x00},/*"z",90*/
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x3E,0xFC,0x40,0x02,0x40,0x02},/*"{",91*/
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
- {0x00,0x00,0x40,0x02,0x40,0x02,0x3E,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
- {0x00,0x00,0x60,0x00,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00},/*"~",94*/
- };
- struct spi_device *spi_ssd1306_dev;
- static void ssd1306_write_byte(uint8_t chData, uint8_t chCmd)
- {
- struct spi_transfer t;
- struct spi_message m;
- uint16_t data = chData;
-
- memset(&t,0,sizeof(struct spi_transfer));
-
- if (chCmd) {
- data |= (1 << 8);
- } else {
- data &= ~(1 << 8);
- }
- t.tx_buf = &data;
- t.len = 2;
- t.bits_per_word = 9;
- //t.cs_change = 1;
- spi_message_init(&m);
- spi_message_add_tail(&t, &m);
- spi_sync(spi_ssd1306_dev, &m);
- }
- void ssd1306_display_on(void)
- {
- ssd1306_write_byte(0x8D, SSD1306_CMD);
- ssd1306_write_byte(0x14, SSD1306_CMD);
- ssd1306_write_byte(0xAF, SSD1306_CMD);
- }
-
- /**
- * @brief OLED turns off
- *
- * @param None
- *
- * @retval None
- **/
- void ssd1306_display_off(void)
- {
- ssd1306_write_byte(0x8D, SSD1306_CMD);
- ssd1306_write_byte(0x10, SSD1306_CMD);
- ssd1306_write_byte(0xAE, SSD1306_CMD);
- }
- void ssd1306_refresh_gram(void)
- {
- uint8_t i, j;
-
- for (i = 0; i < 8; i ++) {
- ssd1306_write_byte(0xB0 + i, SSD1306_CMD);
- ssd1306_write_byte(0x02, SSD1306_CMD);
- ssd1306_write_byte(0x10, SSD1306_CMD);
- for (j = 0; j < 128; j ++) {
- ssd1306_write_byte(s_chDispalyBuffer[j][i], SSD1306_DAT);
- }
- }
- }
- void ssd1306_clear_screen(uint8_t chFill)
- {
- memset(s_chDispalyBuffer,chFill, sizeof(s_chDispalyBuffer));
- ssd1306_refresh_gram();
- }
- /**
- * @brief Draws a piont on the screen
- *
- * @param chXpos: Specifies the X position
- * @param chYpos: Specifies the Y position
- * @param chPoint: 0: the point turns off 1: the piont turns on
- *
- * @retval None
- **/
- void ssd1306_draw_point(uint8_t chXpos, uint8_t chYpos, uint8_t chPoint)
- {
- uint8_t chPos, chBx, chTemp = 0;
-
- if (chXpos > 127 || chYpos > 63) {
- return;
- }
- chPos = 7 - chYpos / 8; //
- chBx = chYpos % 8;
- chTemp = 1 << (7 - chBx);
-
- if (chPoint) {
- s_chDispalyBuffer[chXpos][chPos] |= chTemp;
-
- } else {
- s_chDispalyBuffer[chXpos][chPos] &= ~chTemp;
- }
- }
-
- /**
- * @brief Fills a rectangle
- *
- * @param chXpos1: Specifies the X position 1 (X top left position)
- * @param chYpos1: Specifies the Y position 1 (Y top left position)
- * @param chXpos2: Specifies the X position 2 (X bottom right position)
- * @param chYpos3: Specifies the Y position 2 (Y bottom right position)
- *
- * @retval
- **/
- void ssd1306_fill_screen(uint8_t chXpos1, uint8_t chYpos1, uint8_t chXpos2, uint8_t chYpos2, uint8_t chDot)
- {
- uint8_t chXpos, chYpos;
-
- for (chXpos = chXpos1; chXpos <= chXpos2; chXpos ++) {
- for (chYpos = chYpos1; chYpos <= chYpos2; chYpos ++) {
- ssd1306_draw_point(chXpos, chYpos, chDot);
- }
- }
-
- ssd1306_refresh_gram();
- }
- /**
- * @brief Displays one character at the specified position
- *
- * @param chXpos: Specifies the X position
- * @param chYpos: Specifies the Y position
- * @param chSize:
- * @param chMode
- * @retval
- **/
- void ssd1306_display_char(uint8_t chXpos, uint8_t chYpos, uint8_t chChr, uint8_t chSize, uint8_t chMode)
- {
- uint8_t i, j;
- uint8_t chTemp, chYpos0 = chYpos;
-
- chChr = chChr - ' ';
- for (i = 0; i < chSize; i ++) {
- if (chMode) {
- chTemp = c_chFont1608[chChr][i];
- } else {
- chTemp = ~c_chFont1608[chChr][i];
- }
-
- for (j = 0; j < 8; j ++) {
- if (chTemp & 0x80) {
- ssd1306_draw_point(chXpos, chYpos, 1);
- } else {
- ssd1306_draw_point(chXpos, chYpos, 0);
- }
- chTemp <<= 1;
- chYpos ++;
-
- if ((chYpos - chYpos0) == chSize) {
- chYpos = chYpos0;
- chXpos ++;
- break;
- }
- }
- }
- }
- /**
- * @brief Displays a string on the screen
- *
- * @param chXpos: Specifies the X position
- * @param chYpos: Specifies the Y position
- * @param pchString: Pointer to a string to display on the screen
- *
- * @retval None
- **/
- void ssd1306_display_string(uint8_t chXpos, uint8_t chYpos, const uint8_t *pchString, uint8_t chSize, uint8_t chMode)
- {
- while (*pchString != '\0') {
- if (chXpos > (SSD1306_WIDTH - chSize / 2)) {
- chXpos = 0;
- chYpos += chSize;
- if (chYpos > (SSD1306_HEIGHT - chSize)) {
- chYpos = chXpos = 0;
- ssd1306_clear_screen(0x00);
- }
- }
-
- ssd1306_display_char(chXpos, chYpos, *pchString, chSize, chMode);
- chXpos += chSize / 2;
- pchString ++;
- }
- }
- void ssd1306_init(void)
- {
- #if 1
- ssd1306_write_byte(0xAE, SSD1306_CMD);//--turn off oled panel
- ssd1306_write_byte(0x00, SSD1306_CMD);//---set low column address
- ssd1306_write_byte(0x10, SSD1306_CMD);//---set high column address
- ssd1306_write_byte(0x40, SSD1306_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
- ssd1306_write_byte(0x81, SSD1306_CMD);//--set contrast control register
- ssd1306_write_byte(0xCF, SSD1306_CMD);// Set SEG Output Current Brightness
- ssd1306_write_byte(0xA1, SSD1306_CMD);//--Set SEG/Column Mapping
- ssd1306_write_byte(0xC0, SSD1306_CMD);//Set COM/Row Scan Direction
- ssd1306_write_byte(0xA6, SSD1306_CMD);//--set normal display
- ssd1306_write_byte(0xA8, SSD1306_CMD);//--set multiplex ratio(1 to 64)
- ssd1306_write_byte(0x3f, SSD1306_CMD);//--1/64 duty
- ssd1306_write_byte(0xD3, SSD1306_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
- ssd1306_write_byte(0x00, SSD1306_CMD);//-not offset
- ssd1306_write_byte(0xd5, SSD1306_CMD);//--set display clock divide ratio/oscillator frequency
- ssd1306_write_byte(0x80, SSD1306_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
- ssd1306_write_byte(0xD9, SSD1306_CMD);//--set pre-charge period
- ssd1306_write_byte(0xF1, SSD1306_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
- ssd1306_write_byte(0xDA, SSD1306_CMD);//--set com pins hardware configuration
- ssd1306_write_byte(0x12, SSD1306_CMD);
- ssd1306_write_byte(0xDB, SSD1306_CMD);//--set vcomh
- ssd1306_write_byte(0x40, SSD1306_CMD);//Set VCOM Deselect Level
- ssd1306_write_byte(0x20, SSD1306_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
- ssd1306_write_byte(0x02, SSD1306_CMD);//
- ssd1306_write_byte(0x8D, SSD1306_CMD);//--set Charge Pump enable/disable
- ssd1306_write_byte(0x14, SSD1306_CMD);//--set(0x10) disable
- ssd1306_write_byte(0xA4, SSD1306_CMD);// Disable Entire Display On (0xa4/0xa5)
- ssd1306_write_byte(0xA6, SSD1306_CMD);// Disable Inverse Display On (0xa6/a7)
- ssd1306_write_byte(0xAF, SSD1306_CMD);//--turn on oled panel
- #else
- ssd1306_write_byte(0xAE, SSD1306_CMD);//--turn off oled panel
- ssd1306_write_byte(0x00, SSD1306_CMD);//---set low column address
- ssd1306_write_byte(0x10, SSD1306_CMD);//---set high column address
- ssd1306_write_byte(0x40, SSD1306_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
- ssd1306_write_byte(0xB0, SSD1306_CMD);// ssd1306_write_byte(0xC0, SSD1306_CMD);//Set COM/Row Scan Direction
- ssd1306_write_byte(0x81, SSD1306_CMD);//--set contrast control register
- ssd1306_write_byte(0xCF, SSD1306_CMD);// Set SEG Output Current Brightness
- ssd1306_write_byte(0xA1, SSD1306_CMD);//--Set SEG/Column Mapping
- ssd1306_write_byte(0xA6, SSD1306_CMD);//--set normal display
- ssd1306_write_byte(0xA8, SSD1306_CMD);//--set multiplex ratio(1 to 64)
- ssd1306_write_byte(0x3f, SSD1306_CMD);//--1/64 duty
- ssd1306_write_byte(0xC8, SSD1306_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
- ssd1306_write_byte(0xD3, SSD1306_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
- ssd1306_write_byte(0xC0, SSD1306_CMD);//-not offset
- ssd1306_write_byte(0xd5, SSD1306_CMD);//--set display clock divide ratio/oscillator frequency
- ssd1306_write_byte(0x80, SSD1306_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
- ssd1306_write_byte(0xD9, SSD1306_CMD);//--set pre-charge period
- ssd1306_write_byte(0xF1, SSD1306_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
- ssd1306_write_byte(0xDA, SSD1306_CMD);//--set com pins hardware configuration
- ssd1306_write_byte(0x12, SSD1306_CMD);
- ssd1306_write_byte(0xDB, SSD1306_CMD);//--set vcomh
- ssd1306_write_byte(0x40, SSD1306_CMD);//Set VCOM Deselect Level
- ssd1306_write_byte(0x8D, SSD1306_CMD);//--set Charge Pump enable/disable
- ssd1306_write_byte(0x10, SSD1306_CMD);//--set(0x10) disable
-
- ssd1306_write_byte(0xAF, SSD1306_CMD);//--turn on oled panel
- #endif
- ssd1306_display_on();
- ssd1306_clear_screen(0xff);
-
- }
- static int spi_ssd1306_probe(struct spi_device *spi)
- {
- printk("=11=spi_ssd1306_proben");
- spi_ssd1306_dev = spi;
- spi_ssd1306_dev->bits_per_word = 9;
-
- ssd1306_init();
- printk("=2=spi_ssd1306_proben");
- ssd1306_clear_screen(0x00);
- printk("=3=spi_ssd1306_proben");
- ssd1306_display_off();
- printk("=4=spi_ssd1306_proben");
-
- ssd1306_display_string(18, 0, "hello, Linux!", 16, 1);
- ssd1306_display_string(0, 16, "this is a spi driver demo!", 16, 1);
- ssd1306_refresh_gram();
- ssd1306_display_on();
- printk("=5=spi_ssd1306_proben");
-
- return 0;
- }
- static int spi_ssd1306_remove(struct spi_device *spi)
- {
- printk("ssd1306_removen");
-
- ssd1306_clear_screen(0x00);
- ssd1306_display_off();
- return 0;
- }
- static const struct of_device_id ssd1306_dt_ids[] = {
- { .compatible = "oled,ssd1306" },
- {},
- };
- MODULE_DEVICE_TABLE(of, ssd1306_dt_ids);
- static struct spi_driver spi_ssd1306_driver = {
- .driver = {
- .name = "spi_ssd1306",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(ssd1306_dt_ids),
- },
- .probe = spi_ssd1306_probe,
- .remove = spi_ssd1306_remove,
- };
- static int __init spi_ssd1306_init(void)
- {
- printk("=0000=spi_ssd1306_initn");
- return spi_register_driver(&spi_ssd1306_driver);
- }
- static void __exit spi_ssd1306_exit(void)
- {
- spi_unregister_driver(&spi_ssd1306_driver);
- }
- module_init(spi_ssd1306_init);
- module_exit(spi_ssd1306_exit);
- MODULE_LICENSE("GPL");
5.改进方案
a.此次点亮的OLED模块是3-wire模式,4-wire和IIC模式后面有时间在尝试实现。
b.此次OELD显示的字符串是直接写在驱动中,后面有时间会尝试通过fileoption的方式在应用层实现输入显示内容。
c.因为时间关系,并没有详细按照OLED的文档进行解析,驱动中初始化,ON,OFF等等功能是如何实现的,后面有时间会补上。
6.特别感谢
这里特别感谢hackfun同学,非常感谢他无私,非常耐心的帮我理顺实现思路。
知识点总结:
1.DTSI中如何设置GPIO模拟SPI
2.T*I中如何在驱动中设置某个GPIO为“输出”,状态为“高”。
3.这种SPI协议驱动的器件,知道如何正确的使用示波器非常重要,非常重要,非常重要。
4.OLED驱动初始化,数据传输实现。