米尔电子
直播中

高增华

9年用户 542经验值
擅长:嵌入式技术
私信 关注

【Rico Board试用体验】8.Ricoboard开发板上SPI模拟与OLED显示

在Ricoboard开发板上使能SPI0和SPI4的方法相信大家已经了解,我这里不在重复,因为使用正常的spi器件无法驱动手里的OLED模块,所以才想到使用GPIO模拟SPI的方法,理论不多说直接说实现步骤。
1.添加kernel编译支持。
spi-gpio-kernel-config.png
2.选择合适的GPIO,这里直接使用SPI4的GPIO,如下图:
spi-gpio-spi4gpio.png
3.DTSI里面添加GPIO模拟SPI的设置
spi-gpio-kernel-dtsipng.png
4.添加SPIDev测试驱动
因为在config里面设置CONFIG_SPI_SPIDEV=y,无法编译出spidev设备节点,所以直接在Makefile里面修改obj-$(CONFIG_SPI_SPIDEV)                += spidev.o为obj-y                += spidev.o。
5.添加应用程序测试SPIDEV设备节点
spi-gpio-spidev.png
第一次和最后一次模拟处理的SPI的DO和D1是连接状态,中间一次是断开状态。测试结果如上图,pin连接如下图:
spi-gpio-pin.png
上面的步骤就可以保证我们模拟处理的SPI是可以正常通讯的,下面说说如何实现OELD的显示步骤。因为目前本职工作较忙,所以只是简单说一下实现步骤,相信有经验的人参考一下就可以实现这个功能。
OELD是一种非常高大尚的显示技术,据说苹果下一代产品就要使用OLED做显示屏,不过目前的OLED价格有点贵。
从技术上来讲实现难度并不大,只是可以参考的例子很少,在没有硬件支持的情况下自己将OLED点亮确实花费了一番功夫。
1.DTSI中OLED驱动加载
spi-gpio-kernel-dtsi-oeld.png
2.OLED接线方法
oled-pin.png
3.结果显示
oled-show.png
4.驱动代码实现
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include titions.h>
  8. #include
  9. #include
  10. #include

  11. #define SSD1306_CMD    0
  12. #define SSD1306_DAT    1

  13. #define SSD1306_WIDTH    128
  14. #define SSD1306_HEIGHT   64

  15. static uint8_t s_chDispalyBuffer[128][8];

  16. const uint8_t c_chFont1608[95][16] = {      
  17. {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
  18. {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xCC,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
  19. {0x00,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x00,0x00},/*""",2*/
  20. {0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x00,0x00},/*"//m.obk20.com/bbs/#",3*/
  21. {0x00,0x00,0x0E,0x18,0x11,0x04,0x3F,0xFF,0x10,0x84,0x0C,0x78,0x00,0x00,0x00,0x00},/*"$",4*/
  22. {0x0F,0x00,0x10,0x84,0x0F,0x38,0x00,0xC0,0x07,0x78,0x18,0x84,0x00,0x78,0x00,0x00},/*"%",5*/
  23. {0x00,0x78,0x0F,0x84,0x10,0xC4,0x11,0x24,0x0E,0x98,0x00,0xE4,0x00,0x84,0x00,0x08},/*"&",6*/
  24. {0x08,0x00,0x68,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
  25. {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x18,0x18,0x20,0x04,0x40,0x02,0x00,0x00},/*"(",8*/
  26. {0x00,0x00,0x40,0x02,0x20,0x04,0x18,0x18,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
  27. {0x02,0x40,0x02,0x40,0x01,0x80,0x0F,0xF0,0x01,0x80,0x02,0x40,0x02,0x40,0x00,0x00},/*"*",10*/
  28. {0x00,0x80,0x00,0x80,0x00,0x80,0x0F,0xF8,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00},/*"+",11*/
  29. {0x00,0x01,0x00,0x0D,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
  30. {0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80},/*"-",13*/
  31. {0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
  32. {0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x60,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00},/*"/",15*/
  33. {0x00,0x00,0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"0",16*/
  34. {0x00,0x00,0x08,0x04,0x08,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"1",17*/
  35. {0x00,0x00,0x0E,0x0C,0x10,0x14,0x10,0x24,0x10,0x44,0x11,0x84,0x0E,0x0C,0x00,0x00},/*"2",18*/
  36. {0x00,0x00,0x0C,0x18,0x10,0x04,0x11,0x04,0x11,0x04,0x12,0x88,0x0C,0x70,0x00,0x00},/*"3",19*/
  37. {0x00,0x00,0x00,0xE0,0x03,0x20,0x04,0x24,0x08,0x24,0x1F,0xFC,0x00,0x24,0x00,0x00},/*"4",20*/
  38. {0x00,0x00,0x1F,0x98,0x10,0x84,0x11,0x04,0x11,0x04,0x10,0x88,0x10,0x70,0x00,0x00},/*"5",21*/
  39. {0x00,0x00,0x07,0xF0,0x08,0x88,0x11,0x04,0x11,0x04,0x18,0x88,0x00,0x70,0x00,0x00},/*"6",22*/
  40. {0x00,0x00,0x1C,0x00,0x10,0x00,0x10,0xFC,0x13,0x00,0x1C,0x00,0x10,0x00,0x00,0x00},/*"7",23*/
  41. {0x00,0x00,0x0E,0x38,0x11,0x44,0x10,0x84,0x10,0x84,0x11,0x44,0x0E,0x38,0x00,0x00},/*"8",24*/
  42. {0x00,0x00,0x07,0x00,0x08,0x8C,0x10,0x44,0x10,0x44,0x08,0x88,0x07,0xF0,0x00,0x00},/*"9",25*/
  43. {0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x03,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
  44. {0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
  45. {0x00,0x00,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10,0x04,0x00,0x00},/*"<",28*/
  46. {0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x00,0x00},/*"=",29*/
  47. {0x00,0x00,0x10,0x04,0x08,0x08,0x04,0x10,0x02,0x20,0x01,0x40,0x00,0x80,0x00,0x00},/*">",30*/
  48. {0x00,0x00,0x0E,0x00,0x12,0x00,0x10,0x0C,0x10,0x6C,0x10,0x80,0x0F,0x00,0x00,0x00},/*"?",31*/
  49. {0x03,0xE0,0x0C,0x18,0x13,0xE4,0x14,0x24,0x17,0xC4,0x08,0x28,0x07,0xD0,0x00,0x00},/*"@",32*/
  50. {0x00,0x04,0x00,0x3C,0x03,0xC4,0x1C,0x40,0x07,0x40,0x00,0xE4,0x00,0x1C,0x00,0x04},/*"A",33*/
  51. {0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x11,0x04,0x0E,0x88,0x00,0x70,0x00,0x00},/*"B",34*/
  52. {0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x04,0x10,0x08,0x1C,0x10,0x00,0x00},/*"C",35*/
  53. {0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"D",36*/
  54. {0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x17,0xC4,0x10,0x04,0x08,0x18,0x00,0x00},/*"E",37*/
  55. {0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x17,0xC0,0x10,0x00,0x08,0x00,0x00,0x00},/*"F",38*/
  56. {0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x44,0x1C,0x78,0x00,0x40,0x00,0x00},/*"G",39*/
  57. {0x10,0x04,0x1F,0xFC,0x10,0x84,0x00,0x80,0x00,0x80,0x10,0x84,0x1F,0xFC,0x10,0x04},/*"H",40*/
  58. {0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x00,0x00,0x00,0x00},/*"I",41*/
  59. {0x00,0x03,0x00,0x01,0x10,0x01,0x10,0x01,0x1F,0xFE,0x10,0x00,0x10,0x00,0x00,0x00},/*"J",42*/
  60. {0x10,0x04,0x1F,0xFC,0x11,0x04,0x03,0x80,0x14,0x64,0x18,0x1C,0x10,0x04,0x00,0x00},/*"K",43*/
  61. {0x10,0x04,0x1F,0xFC,0x10,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x0C,0x00,0x00},/*"L",44*/
  62. {0x10,0x04,0x1F,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x1F,0xFC,0x10,0x04,0x00,0x00},/*"M",45*/
  63. {0x10,0x04,0x1F,0xFC,0x0C,0x04,0x03,0x00,0x00,0xE0,0x10,0x18,0x1F,0xFC,0x10,0x00},/*"N",46*/
  64. {0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"O",47*/
  65. {0x10,0x04,0x1F,0xFC,0x10,0x84,0x10,0x80,0x10,0x80,0x10,0x80,0x0F,0x00,0x00,0x00},/*"P",48*/
  66. {0x07,0xF0,0x08,0x18,0x10,0x24,0x10,0x24,0x10,0x1C,0x08,0x0A,0x07,0xF2,0x00,0x00},/*"Q",49*/
  67. {0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x11,0xC0,0x11,0x30,0x0E,0x0C,0x00,0x04},/*"R",50*/
  68. {0x00,0x00,0x0E,0x1C,0x11,0x04,0x10,0x84,0x10,0x84,0x10,0x44,0x1C,0x38,0x00,0x00},/*"S",51*/
  69. {0x18,0x00,0x10,0x00,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x00,0x18,0x00,0x00,0x00},/*"T",52*/
  70. {0x10,0x00,0x1F,0xF8,0x10,0x04,0x00,0x04,0x00,0x04,0x10,0x04,0x1F,0xF8,0x10,0x00},/*"U",53*/
  71. {0x10,0x00,0x1E,0x00,0x11,0xE0,0x00,0x1C,0x00,0x70,0x13,0x80,0x1C,0x00,0x10,0x00},/*"V",54*/
  72. {0x1F,0xC0,0x10,0x3C,0x00,0xE0,0x1F,0x00,0x00,0xE0,0x10,0x3C,0x1F,0xC0,0x00,0x00},/*"W",55*/
  73. {0x10,0x04,0x18,0x0C,0x16,0x34,0x01,0xC0,0x01,0xC0,0x16,0x34,0x18,0x0C,0x10,0x04},/*"X",56*/
  74. {0x10,0x00,0x1C,0x00,0x13,0x04,0x00,0xFC,0x13,0x04,0x1C,0x00,0x10,0x00,0x00,0x00},/*"Y",57*/
  75. {0x08,0x04,0x10,0x1C,0x10,0x64,0x10,0x84,0x13,0x04,0x1C,0x04,0x10,0x18,0x00,0x00},/*"Z",58*/
  76. {0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x40,0x02,0x40,0x02,0x40,0x02,0x00,0x00},/*"[",59*/
  77. {0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x80,0x00,0x60,0x00,0x1C,0x00,0x03,0x00,0x00},/*"",60*/
  78. {0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
  79. {0x00,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00},/*"^",62*/
  80. {0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01},/*"_",63*/
  81. {0x00,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
  82. {0x00,0x00,0x00,0x98,0x01,0x24,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xFC,0x00,0x04},/*"a",65*/
  83. {0x10,0x00,0x1F,0xFC,0x00,0x88,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"b",66*/
  84. {0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x00},/*"c",67*/
  85. {0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x11,0x08,0x1F,0xFC,0x00,0x04},/*"d",68*/
  86. {0x00,0x00,0x00,0xF8,0x01,0x44,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xC8,0x00,0x00},/*"e",69*/
  87. {0x00,0x00,0x01,0x04,0x01,0x04,0x0F,0xFC,0x11,0x04,0x11,0x04,0x11,0x00,0x18,0x00},/*"f",70*/
  88. {0x00,0x00,0x00,0xD6,0x01,0x29,0x01,0x29,0x01,0x29,0x01,0xC9,0x01,0x06,0x00,0x00},/*"g",71*/
  89. {0x10,0x04,0x1F,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"h",72*/
  90. {0x00,0x00,0x01,0x04,0x19,0x04,0x19,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"i",73*/
  91. {0x00,0x00,0x00,0x03,0x00,0x01,0x01,0x01,0x19,0x01,0x19,0xFE,0x00,0x00,0x00,0x00},/*"j",74*/
  92. {0x10,0x04,0x1F,0xFC,0x00,0x24,0x00,0x40,0x01,0xB4,0x01,0x0C,0x01,0x04,0x00,0x00},/*"k",75*/
  93. {0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"l",76*/
  94. {0x01,0x04,0x01,0xFC,0x01,0x04,0x01,0x00,0x01,0xFC,0x01,0x04,0x01,0x00,0x00,0xFC},/*"m",77*/
  95. {0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"n",78*/
  96. {0x00,0x00,0x00,0xF8,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0xF8,0x00,0x00},/*"o",79*/
  97. {0x01,0x01,0x01,0xFF,0x00,0x85,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"p",80*/
  98. {0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x05,0x01,0xFF,0x00,0x01},/*"q",81*/
  99. {0x01,0x04,0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x04,0x01,0x00,0x01,0x80,0x00,0x00},/*"r",82*/
  100. {0x00,0x00,0x00,0xCC,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x98,0x00,0x00},/*"s",83*/
  101. {0x00,0x00,0x01,0x00,0x01,0x00,0x07,0xF8,0x01,0x04,0x01,0x04,0x00,0x00,0x00,0x00},/*"t",84*/
  102. {0x01,0x00,0x01,0xF8,0x00,0x04,0x00,0x04,0x00,0x04,0x01,0x08,0x01,0xFC,0x00,0x04},/*"u",85*/
  103. {0x01,0x00,0x01,0x80,0x01,0x70,0x00,0x0C,0x00,0x10,0x01,0x60,0x01,0x80,0x01,0x00},/*"v",86*/
  104. {0x01,0xF0,0x01,0x0C,0x00,0x30,0x01,0xC0,0x00,0x30,0x01,0x0C,0x01,0xF0,0x01,0x00},/*"w",87*/
  105. {0x00,0x00,0x01,0x04,0x01,0x8C,0x00,0x74,0x01,0x70,0x01,0x8C,0x01,0x04,0x00,0x00},/*"x",88*/
  106. {0x01,0x01,0x01,0x81,0x01,0x71,0x00,0x0E,0x00,0x18,0x01,0x60,0x01,0x80,0x01,0x00},/*"y",89*/
  107. {0x00,0x00,0x01,0x84,0x01,0x0C,0x01,0x34,0x01,0x44,0x01,0x84,0x01,0x0C,0x00,0x00},/*"z",90*/
  108. {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x3E,0xFC,0x40,0x02,0x40,0x02},/*"{",91*/
  109. {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
  110. {0x00,0x00,0x40,0x02,0x40,0x02,0x3E,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
  111. {0x00,0x00,0x60,0x00,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00},/*"~",94*/
  112. };

  113. struct spi_device *spi_ssd1306_dev;

  114. static void ssd1306_write_byte(uint8_t chData, uint8_t chCmd)
  115. {
  116.     struct spi_transfer t;
  117.     struct spi_message m;

  118.     uint16_t data = chData;
  119.    
  120.     memset(&t,0,sizeof(struct spi_transfer));
  121.      
  122.     if (chCmd) {
  123.         data |= (1 << 8);
  124.     } else {
  125.         data &= ~(1 << 8);
  126.     }

  127.     t.tx_buf = &data;
  128.     t.len = 2;
  129.     t.bits_per_word = 9;
  130.     //t.cs_change = 1;
  131.     spi_message_init(&m);
  132.     spi_message_add_tail(&t, &m);
  133.     spi_sync(spi_ssd1306_dev, &m);
  134. }


  135. void ssd1306_display_on(void)
  136. {
  137.     ssd1306_write_byte(0x8D, SSD1306_CMD);  
  138.     ssd1306_write_byte(0x14, SSD1306_CMD);  
  139.     ssd1306_write_byte(0xAF, SSD1306_CMD);  
  140. }
  141.    
  142. /**
  143.   * @brief  OLED turns off
  144.   *         
  145.   * @param  None
  146.   *         
  147.   * @retval  None
  148. **/
  149. void ssd1306_display_off(void)
  150. {
  151.     ssd1306_write_byte(0x8D, SSD1306_CMD);  
  152.     ssd1306_write_byte(0x10, SSD1306_CMD);
  153.     ssd1306_write_byte(0xAE, SSD1306_CMD);  
  154. }

  155. void ssd1306_refresh_gram(void)
  156. {
  157.     uint8_t i, j;
  158.    
  159.     for (i = 0; i < 8; i ++) {  
  160.         ssd1306_write_byte(0xB0 + i, SSD1306_CMD);   
  161.         ssd1306_write_byte(0x02, SSD1306_CMD);
  162.         ssd1306_write_byte(0x10, SSD1306_CMD);     
  163.         for (j = 0; j < 128; j ++) {
  164.             ssd1306_write_byte(s_chDispalyBuffer[j][i], SSD1306_DAT);
  165.         }
  166.     }   
  167. }


  168. void ssd1306_clear_screen(uint8_t chFill)  
  169. {
  170.     memset(s_chDispalyBuffer,chFill, sizeof(s_chDispalyBuffer));
  171.     ssd1306_refresh_gram();
  172. }

  173. /**
  174.   * @brief  Draws a piont on the screen
  175.   *         
  176.   * @param  chXpos: Specifies the X position
  177.   * @param  chYpos: Specifies the Y position
  178.   * @param  chPoint: 0: the point turns off    1: the piont turns on
  179.   *         
  180.   * @retval None
  181. **/

  182. void ssd1306_draw_point(uint8_t chXpos, uint8_t chYpos, uint8_t chPoint)
  183. {
  184.     uint8_t chPos, chBx, chTemp = 0;
  185.    
  186.     if (chXpos > 127 || chYpos > 63) {
  187.         return;
  188.     }
  189.     chPos = 7 - chYpos / 8; //
  190.     chBx = chYpos % 8;
  191.     chTemp = 1 << (7 - chBx);
  192.    
  193.     if (chPoint) {
  194.         s_chDispalyBuffer[chXpos][chPos] |= chTemp;
  195.         
  196.     } else {
  197.         s_chDispalyBuffer[chXpos][chPos] &= ~chTemp;
  198.     }
  199. }
  200.       
  201. /**
  202.   * @brief  Fills a rectangle
  203.   *         
  204.   * @param  chXpos1: Specifies the X position 1 (X top left position)
  205.   * @param  chYpos1: Specifies the Y position 1 (Y top left position)
  206.   * @param  chXpos2: Specifies the X position 2 (X bottom right position)
  207.   * @param  chYpos3: Specifies the Y position 2 (Y bottom right position)
  208.   *         
  209.   * @retval
  210. **/

  211. void ssd1306_fill_screen(uint8_t chXpos1, uint8_t chYpos1, uint8_t chXpos2, uint8_t chYpos2, uint8_t chDot)  
  212. {  
  213.     uint8_t chXpos, chYpos;
  214.    
  215.     for (chXpos = chXpos1; chXpos <= chXpos2; chXpos ++) {
  216.         for (chYpos = chYpos1; chYpos <= chYpos2; chYpos ++) {
  217.             ssd1306_draw_point(chXpos, chYpos, chDot);
  218.         }
  219.     }   
  220.    
  221.     ssd1306_refresh_gram();
  222. }


  223. /**
  224.   * @brief Displays one character at the specified position   
  225.   *         
  226.   * @param  chXpos: Specifies the X position
  227.   * @param  chYpos: Specifies the Y position
  228.   * @param  chSize:
  229.   * @param  chMode
  230.   * @retval
  231. **/
  232. void ssd1306_display_char(uint8_t chXpos, uint8_t chYpos, uint8_t chChr, uint8_t chSize, uint8_t chMode)
  233. {         
  234.     uint8_t i, j;
  235.     uint8_t chTemp, chYpos0 = chYpos;
  236.    
  237.     chChr = chChr - ' ';                  
  238.     for (i = 0; i < chSize; i ++) {   
  239.         if (chMode) {
  240.             chTemp = c_chFont1608[chChr][i];
  241.         } else {
  242.             chTemp = ~c_chFont1608[chChr][i];
  243.         }
  244.         
  245.         for (j = 0; j < 8; j ++) {
  246.             if (chTemp & 0x80) {
  247.                 ssd1306_draw_point(chXpos, chYpos, 1);
  248.             } else {
  249.                 ssd1306_draw_point(chXpos, chYpos, 0);
  250.             }
  251.             chTemp <<= 1;
  252.             chYpos ++;
  253.             
  254.             if ((chYpos - chYpos0) == chSize) {
  255.                 chYpos = chYpos0;
  256.                 chXpos ++;
  257.                 break;
  258.             }
  259.         }      
  260.     }
  261. }   

  262. /**
  263.   * @brief  Displays a string on the screen
  264.   *         
  265.   * @param  chXpos: Specifies the X position
  266.   * @param  chYpos: Specifies the Y position
  267.   * @param  pchString: Pointer to a string to display on the screen
  268.   *         
  269.   * @retval  None
  270. **/
  271. void ssd1306_display_string(uint8_t chXpos, uint8_t chYpos, const uint8_t *pchString, uint8_t chSize, uint8_t chMode)
  272. {
  273.     while (*pchString != '\0') {      
  274.         if (chXpos > (SSD1306_WIDTH - chSize / 2)) {
  275.             chXpos = 0;
  276.             chYpos += chSize;
  277.             if (chYpos > (SSD1306_HEIGHT - chSize)) {
  278.                 chYpos = chXpos = 0;
  279.                 ssd1306_clear_screen(0x00);
  280.             }
  281.         }
  282.         
  283.         ssd1306_display_char(chXpos, chYpos, *pchString, chSize, chMode);
  284.         chXpos += chSize / 2;
  285.         pchString ++;
  286.     }
  287. }

  288. void ssd1306_init(void)
  289. {
  290. #if 1
  291.     ssd1306_write_byte(0xAE, SSD1306_CMD);//--turn off oled panel
  292.     ssd1306_write_byte(0x00, SSD1306_CMD);//---set low column address
  293.     ssd1306_write_byte(0x10, SSD1306_CMD);//---set high column address
  294.     ssd1306_write_byte(0x40, SSD1306_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  295.     ssd1306_write_byte(0x81, SSD1306_CMD);//--set contrast control register
  296.     ssd1306_write_byte(0xCF, SSD1306_CMD);// Set SEG Output Current Brightness
  297.     ssd1306_write_byte(0xA1, SSD1306_CMD);//--Set SEG/Column Mapping     
  298.     ssd1306_write_byte(0xC0, SSD1306_CMD);//Set COM/Row Scan Direction   
  299.     ssd1306_write_byte(0xA6, SSD1306_CMD);//--set normal display
  300.     ssd1306_write_byte(0xA8, SSD1306_CMD);//--set multiplex ratio(1 to 64)
  301.     ssd1306_write_byte(0x3f, SSD1306_CMD);//--1/64 duty
  302.     ssd1306_write_byte(0xD3, SSD1306_CMD);//-set display offset    Shift Mapping RAM Counter (0x00~0x3F)
  303.     ssd1306_write_byte(0x00, SSD1306_CMD);//-not offset
  304.     ssd1306_write_byte(0xd5, SSD1306_CMD);//--set display clock divide ratio/oscillator frequency
  305.     ssd1306_write_byte(0x80, SSD1306_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
  306.     ssd1306_write_byte(0xD9, SSD1306_CMD);//--set pre-charge period
  307.     ssd1306_write_byte(0xF1, SSD1306_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  308.     ssd1306_write_byte(0xDA, SSD1306_CMD);//--set com pins hardware configuration
  309.     ssd1306_write_byte(0x12, SSD1306_CMD);
  310.     ssd1306_write_byte(0xDB, SSD1306_CMD);//--set vcomh
  311.     ssd1306_write_byte(0x40, SSD1306_CMD);//Set VCOM Deselect Level
  312.     ssd1306_write_byte(0x20, SSD1306_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
  313.     ssd1306_write_byte(0x02, SSD1306_CMD);//
  314.     ssd1306_write_byte(0x8D, SSD1306_CMD);//--set Charge Pump enable/disable
  315.     ssd1306_write_byte(0x14, SSD1306_CMD);//--set(0x10) disable
  316.     ssd1306_write_byte(0xA4, SSD1306_CMD);// Disable Entire Display On (0xa4/0xa5)
  317.     ssd1306_write_byte(0xA6, SSD1306_CMD);// Disable Inverse Display On (0xa6/a7)
  318.     ssd1306_write_byte(0xAF, SSD1306_CMD);//--turn on oled panel
  319. #else
  320.            ssd1306_write_byte(0xAE, SSD1306_CMD);//--turn off oled panel
  321.     ssd1306_write_byte(0x00, SSD1306_CMD);//---set low column address
  322.     ssd1306_write_byte(0x10, SSD1306_CMD);//---set high column address
  323.     ssd1306_write_byte(0x40, SSD1306_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  324.     ssd1306_write_byte(0xB0, SSD1306_CMD);//    ssd1306_write_byte(0xC0, SSD1306_CMD);//Set COM/Row Scan Direction   

  325.     ssd1306_write_byte(0x81, SSD1306_CMD);//--set contrast control register
  326.     ssd1306_write_byte(0xCF, SSD1306_CMD);// Set SEG Output Current Brightness
  327.     ssd1306_write_byte(0xA1, SSD1306_CMD);//--Set SEG/Column Mapping     
  328.     ssd1306_write_byte(0xA6, SSD1306_CMD);//--set normal display
  329.     ssd1306_write_byte(0xA8, SSD1306_CMD);//--set multiplex ratio(1 to 64)
  330.     ssd1306_write_byte(0x3f, SSD1306_CMD);//--1/64 duty
  331.     ssd1306_write_byte(0xC8, SSD1306_CMD);//-set display offset    Shift Mapping RAM Counter (0x00~0x3F)
  332.     ssd1306_write_byte(0xD3, SSD1306_CMD);//-set display offset    Shift Mapping RAM Counter (0x00~0x3F)
  333.     ssd1306_write_byte(0xC0, SSD1306_CMD);//-not offset
  334.     ssd1306_write_byte(0xd5, SSD1306_CMD);//--set display clock divide ratio/oscillator frequency
  335.     ssd1306_write_byte(0x80, SSD1306_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
  336.     ssd1306_write_byte(0xD9, SSD1306_CMD);//--set pre-charge period
  337.     ssd1306_write_byte(0xF1, SSD1306_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  338.     ssd1306_write_byte(0xDA, SSD1306_CMD);//--set com pins hardware configuration
  339.     ssd1306_write_byte(0x12, SSD1306_CMD);
  340.     ssd1306_write_byte(0xDB, SSD1306_CMD);//--set vcomh
  341.     ssd1306_write_byte(0x40, SSD1306_CMD);//Set VCOM Deselect Level

  342.     ssd1306_write_byte(0x8D, SSD1306_CMD);//--set Charge Pump enable/disable
  343.     ssd1306_write_byte(0x10, SSD1306_CMD);//--set(0x10) disable

  344.     ssd1306_write_byte(0xAF, SSD1306_CMD);//--turn on oled panel

  345. #endif
  346.     ssd1306_display_on();
  347.     ssd1306_clear_screen(0xff);
  348.    
  349. }


  350. static int spi_ssd1306_probe(struct spi_device *spi)
  351. {
  352.         printk("=11=spi_ssd1306_proben");
  353.         spi_ssd1306_dev = spi;
  354.         spi_ssd1306_dev->bits_per_word = 9;
  355.        
  356.         ssd1306_init();
  357.         printk("=2=spi_ssd1306_proben");
  358.         ssd1306_clear_screen(0x00);
  359.         printk("=3=spi_ssd1306_proben");
  360.         ssd1306_display_off();
  361.         printk("=4=spi_ssd1306_proben");
  362.        
  363.         ssd1306_display_string(18, 0, "hello, Linux!", 16, 1);
  364.         ssd1306_display_string(0, 16, "this is a spi driver demo!", 16, 1);
  365.         ssd1306_refresh_gram();
  366.         ssd1306_display_on();
  367.         printk("=5=spi_ssd1306_proben");
  368.        
  369.         return 0;
  370. }


  371. static int spi_ssd1306_remove(struct spi_device *spi)
  372. {
  373.     printk("ssd1306_removen");
  374.    
  375.     ssd1306_clear_screen(0x00);
  376.     ssd1306_display_off();
  377.     return 0;
  378. }

  379. static const struct of_device_id ssd1306_dt_ids[] = {
  380.         { .compatible = "oled,ssd1306" },
  381.         {},
  382. };
  383. MODULE_DEVICE_TABLE(of, ssd1306_dt_ids);
  384. static struct spi_driver spi_ssd1306_driver = {
  385.     .driver = {
  386.         .name    = "spi_ssd1306",
  387.         .bus    = &spi_bus_type,
  388.         .owner    = THIS_MODULE,
  389.                                 .of_match_table = of_match_ptr(ssd1306_dt_ids),
  390.     },
  391.     .probe    = spi_ssd1306_probe,
  392.     .remove    = spi_ssd1306_remove,
  393. };


  394. static int __init spi_ssd1306_init(void)
  395. {
  396.         printk("=0000=spi_ssd1306_initn");
  397.     return spi_register_driver(&spi_ssd1306_driver);
  398. }


  399. static void __exit spi_ssd1306_exit(void)
  400. {
  401.     spi_unregister_driver(&spi_ssd1306_driver);
  402. }


  403. module_init(spi_ssd1306_init);
  404. module_exit(spi_ssd1306_exit);

  405. 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驱动初始化,数据传输实现。

更多回帖

发帖
×
20
完善资料,
赚取积分