久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 13664|回復: 12
打印 上一主題 下一主題
收起左側

STM8S驅動OLED12864

  [復制鏈接]
跳轉到指定樓層
樓主
ID:145459 發表于 2016-11-15 01:38 | 只看該作者 回帖獎勵 |正序瀏覽 |閱讀模式

這種OLED的液晶屏似乎很受電子愛好者的歡迎,原因大概是:
①這種屏小巧玲瓏,同樣是128*64點陣的液晶屏,這種屏的體積比以前那種LCD12864小了四分之一,作為DIY手表的屏幕剛剛好。
②功耗低,由于OLED是有機發光材料制作成的,沒有使用背光,所以功耗比使用LED作為背光的液晶屏,功耗要低很多。所以這塊液晶屏適合用于手表之類的手持設備。
③可以選擇的接口很多。接口和使用的液晶屏驅動芯片有關,大多數OLED12864使用的驅動芯片是SSD1306,這款驅動芯片提供給MCU的接口有5種,如下圖。本文使用I2C接口來驅動OLED,主要是因為I2C占用MCU的IO少,當然用SPI接口驅動OLED的也很多。

使用I2C接口時,D0腳作為I2C的SCLK時鐘信號線,D1,D2作為SDA數據信號線。D/C#引腳做為地址設定引腳,該引腳接地,OLED器件地址為0x78,該引腳上拉,OLED器件地址為0x7A。

當使用I2C時,SCLK和SDA引腳要加上拉電阻,關于上拉電阻要注意:
①如果I2C的速度很低,使用10K的上拉電阻是可以的,這個低速大概是100KHz
②如果I2C的速度很高,要達到300KHz左右,這個上拉電阻的阻值應該為4.7K

在淘寶上買的OLED模塊,有的直接焊接了10K的上拉電阻,這樣對于需要I2C高速通信的用戶來說,很不方便,不查看電路還以為是程序出了問題,很浪費時間。今天我就遇到了這個問題,查找了好長時間,手頭上又沒4.7K的電阻,只好又并了個10K的電阻。


上圖是SSD1306的顯存分布,y軸范圍是0~7,分為8個頁,x軸坐標是0~127.


上圖是對OLED寫入地址的設定.

SSD1306也有一些控制命令,詳情請查看SSD1306的數據手冊。

由于我的STM8L-DISCOVERY的芯片燒壞掉了,所以沒辦法再繼續用STM8L來寫程序了。去淘寶買了塊STM8S103F3的最小系統板,使用STM8L-DISCOVERY上的SWIM進行仿真調試。


第一次遇到,超過2000字不能發表的情況,大概是程序太長了。我把程序上傳到GitHub了,剛剛摸索著使用這個國外的網站進行代碼托管,由于是全英文的網站,還不是很會用。

  1. /*硬件連接*/
  2. // PB4--SCL   PB5--SDA
  3. /****************************************************************************************
  4. *開發環境:IAR for stm8 v6.5.3
  5. *硬件平臺:STM8S103F3
  6. *功能說明:通過硬件I2C等待的方法,
  7. *作    者:茗風
  8. ****************************************************************************************/
  9. #include"iostm8s103f3.h"
  10. #include"stdbool.h"
  11. #include"stdint.h"

  12. /******************************************************************************************************
  13. * 名 稱: uint8_t I2C_ReadOneByteDataFromSlave(uint8_t address)
  14. * 功 能:從I2C從設備中讀取一字節的數據
  15. * 入口參數:address:讀取數據的寄存器地址
  16. * 出口參數:返回一個從I2C從設備指定地址讀到的數據
  17. * 說 明:
  18. * 范 例:無
  19. ******************************************************************************************************/
  20. uint8_t I2C_ReadOneByteDataFromSlave(uint8_t slave_address,uint8_t address)
  21. {
  22.   volatile uint8_t t;
  23.   //----------I2C起始信號--------------
  24.   I2C_CR2_START=1;//產生一個起始條件
  25.   while(!(I2C_SR1_SB==1));//讀SR1寄存器,清除SB標志位
  26. //  _5NOPS;//根據數據手冊,檢測到標志位后,需插入5個NOP進行延時
  27.   
  28.   //-------發送寫I2C從器件地址---------
  29.   I2C_DR=slave_address;//發送從設備地址
  30.   while(!(I2C_SR1_ADDR==1));//讀SR1寄存器,清除ADDR標志位
  31. // _5NOPS;//根據數據手冊,檢測到標志位后,需插入5個NOP進行延時
  32.   if(I2C_SR3_TRA==0)return 1;//讀SR3寄存器,清除ADDR標志位
  33.   //  0: Data bytes received
  34.   //  1: Data bytes transmitted
  35.   
  36.   //-----寫I2C從器件寄存器地址--------
  37.   I2C_DR=address;
  38.   while(!(I2C_SR1_BTF==1));//等待地址發送完成
  39. //  _5NOPS;//根據數據手冊,檢測到標志位后,需插入5個NOP進行延時
  40.   
  41.   //--------I2C重復起始信號-----------
  42.   I2C_CR2_START=1;//重復產生一個起始條件
  43.   while(!(I2C_SR1_SB==1));//讀SR1寄存器,清除SB標志位
  44. //  _5NOPS;//根據數據手冊,檢測到標志位后,需插入5個NOP進行延時
  45.   
  46.   //-------發送讀I2C從器件地址---------
  47.   I2C_DR=0xD1;//發送從設備地址
  48.   while(!(I2C_SR1_ADDR==1));//讀SR1寄存器,清除ADDR標志位
  49. //  _5NOPS;//根據數據手冊,檢測到標志位后,需插入5個NOP進行延時
  50.   if(I2C_SR3_TRA==1)return 1;//讀SR3寄存器,清除ADDR標志位
  51.   
  52.   //-------------停止信號-------------
  53.   I2C_CR2_ACK=0;//ACK位控制著ACK信號,此位為0可以產生一個NOACK信號
  54.   I2C_CR2_STOP=1;
  55.   
  56.   //-------------等待接收到數據-------------
  57.   while(!(I2C_SR1_RXNE==1));//等待地址發送完成
  58.   
  59.   //-------------讀取數據-------------
  60.   t=I2C_DR;
  61.   
  62.   return t;
  63. }
  64. /******************************************************************************************************
  65. * 名 稱:void I2C_WriteOneByteDataToSlave(uint8_t address,uint8_t dat)
  66. * 功 能:寫入一字節的數據到I2C設備中
  67. * 入口參數:address:寫入的數據存儲地址    dat:待寫入的數據
  68. * 出口參數:無
  69. * 說 明: 通過MSTM8L硬件寫入I2C設備一個字節的數據
  70. * 范 例:無
  71. ******************************************************************************************************/
  72. uint8_t I2C_WriteOneByteDataToSlave(uint8_t slave_address,uint8_t address,uint8_t dat)
  73. {
  74.   volatile uint8_t t;
  75.   I2C_CR2_ACK=1;
  76.   //----------I2C起始信號--------------
  77.   I2C_CR2_START=1;//產生一個起始條件
  78.   while(!(I2C_SR1_SB==1));
  79. // _5NOPS;//根據數據手冊,檢測到標志位后,需插入5個NOP進行延時
  80.   I2C_DR=slave_address;
  81.   
  82.   //--------寫I2C從器件地址-----------
  83.   while(!(I2C_SR1_ADDR==1));
  84. //  _5NOPS;//根據數據手冊,檢測到標志位后,需插入5個NOP進行延時
  85.   if(I2C_SR3_TRA==0)return 1;//讀SR3寄存器,清除ADDR標志位
  86.   
  87.   //-----寫I2C從器件寄存器地址--------
  88.   while(!(I2C_SR1_TXE==1));
  89.   I2C_DR=address;
  90.   
  91.   //-------寫I2C數據到寄存器中--------
  92.   while(!(I2C_SR1_TXE==1));
  93.   I2C_DR=dat;
  94.   while(!(I2C_SR1_TXE==1));
  95.   while(!(I2C_SR1_BTF==1));
  96. // _5NOPS;//根據數據手冊,檢測到標志位后,需插入5個NOP進行延時
  97.   
  98.   //-------------停止信號-------------
  99.   I2C_CR2_STOP=1;
  100.   return 0;
  101. }
  102. /******************************************************************************************************
  103. * 功    能:從I2C從設備讀取多個字節數據
  104. * 入口函數:
  105. * 出口函數:
  106. * 說    明:
  107. * 范    例:
  108. * 日    期:
  109. ******************************************************************************************************/
  110. uint8_t I2C_ReadMultiBytesFromSlave(uint8_t slave_address,uint8_t address,uint8_t *rxbuf,uint8_t len)
  111. {
  112.   volatile uint8_t i=0;
  113.   
  114.   if(len==0)return 1;//如果寫入字節長度為0退出
  115.   
  116.   I2C_CR2_ACK=1;
  117.   //----------I2C起始信號--------------
  118.   I2C_CR2_START=1;//產生一個起始條件
  119.   while(!(I2C_SR1_SB==1));//讀SR1寄存器,清除SB標志位
  120.   
  121.   //-------發送寫I2C從器件地址---------
  122.   I2C_DR=slave_address;//發送從設備地址
  123.   while(!(I2C_SR1_ADDR==1));//讀SR1寄存器,清除ADDR標志位
  124.   if(I2C_SR3_TRA==0)return 1;//讀SR3寄存器,清除ADDR標志位
  125.   //  0: Data bytes received
  126.   //  1: Data bytes transmitted
  127.   
  128.   //-----寫I2C從器件寄存器地址--------
  129.   I2C_DR=address;
  130.   while(!(I2C_SR1_BTF==1));//等待地址發送完成
  131.   
  132.   //--------I2C重復起始信號-----------
  133.   I2C_CR2_START=1;//重復產生一個起始條件
  134.   while(!(I2C_SR1_SB==1));//讀SR1寄存器,清除SB標志位
  135.   
  136.   //-------發送讀I2C從器件地址---------
  137.   I2C_DR=0xD1;//發送從設備地址
  138.   while(!(I2C_SR1_ADDR==1));//讀SR1寄存器,清除ADDR標志位
  139.   if(I2C_SR3_TRA==1)return 1;//讀SR3寄存器,清除ADDR標志位
  140.   //-------------讀取數據-------------
  141.   if(len>1)
  142.   {
  143.       for( i=len;i>1;i-- )
  144.       {
  145.         while(!(I2C_SR1_RXNE==1));//等待I2C_DR接收到數
  146.         *rxbuf++ = I2C_DR;  
  147.       }
  148.   }

  149.   //-------------停止信號-------------
  150.   I2C_CR2_ACK=0;//ACK位控制著ACK信號,此位為0可以產生一個NOACK信號
  151.   I2C_CR2_STOP=1;
  152.   
  153.   while(!(I2C_SR1_RXNE==1));//等待I2C_DR接收到數
  154.   *rxbuf++ = I2C_DR;
  155.   
  156.   return 0;
  157. }
  158. /******************************************************************************************************
  159. * 名     稱:IIC_init()
  160. * 功     能:初始化I2C,系統主頻位8MHz,I2C通信速度333KHz
  161. * 入口 參數:無
  162. * 出口 參數:無
  163. * 說     明:PB4--SCL   PB5--SDA
  164. * 范     例:無
  165. ******************************************************************************************************/
  166. void I2C_Init(void)
  167. {
  168.   //----打開IIC外設時鐘----
  169.   I2C_CR1_PE=0;
  170.   I2C_CR2_ACK=1;
  171.   
  172.   //----I2C輸入時鐘頻率選擇----
  173.   I2C_FREQR_FREQ=0x08;//8MHz
  174.   /*  The allowed range is between 1 MHz and 16 MHz
  175.   000000: not allowed
  176.   000001: 1 MHz
  177.   000010: 2 MHz
  178.   ...
  179.   010000: 16 MHz                                 */
  180.   
  181.   //----配置時鐘控制寄存器----
  182.   I2C_CCRH=0;
  183.   I2C_CCRH_F_S=1; //Fast mode I2C
  184.   I2C_CCRH_DUTY=0;
  185. /* If DUTY = 0:
  186. Period(I2C) = 3* CCR * tMASTER
  187. thigh = CCR * tMASTER
  188. tlow = 2 * CCR * tMASTER*/
  189.   I2C_CCRL=7;    //SCL高電平時間配置
  190.   //I2C的SCK時鐘設置為400KHz,則SCK周期為2.5us   2.5us/0.125/3=7   
  191.   //因為I2C_FREQR_FREQ=0x08,即I2C輸入時鐘頻率為8M,周期為0.125us  
  192.   //CCR=7時,SCK的低電平時間為2*tlow=2*7*0.125us=1.75us,SCk高電平時間為thigh=7*0.125us=0.875us
  193.   //所以CCR=7時,SCK輸出頻率為380KHz
  194.   
  195.   //----配置上升時間寄存器----
  196.   I2C_TRISER_TRISE=5;//in standard mode, the maximum allowed SCL rise time is 1000 ns.
  197.   //1 us / 0.125 us = 8
  198.   //+1
  199.   I2C_CR1_PE=1;//
  200. }
  201. #define  Write_CMD_TO_OLED12864(byte)  I2C_WriteOneByteDataToSlave(0x78,0x00,byte)
  202. #define  Write_DAT_TO_OLED12864(byte)  I2C_WriteOneByteDataToSlave(0x78,0x40,byte)

  203. /************************************6*8的點陣************************************/
  204. const uint8_t ASCII_6X8[92][6] =           //水平尋址
  205. {
  206.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },   // sp
  207.     { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 },   // !
  208.     { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 },   // "
  209.     { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // #
  210.     { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 },   // $
  211.     { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 },   // %
  212.     { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 },   // &
  213.     { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 },   // '
  214.     { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 },   // (
  215.     { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 },   // )
  216.     { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 },   // *
  217.     { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 },   // +
  218.     { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 },   // ,
  219.     { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 },   // -
  220.     { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },   // .
  221.     { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 },   // /
  222.     { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E },   // 0
  223.     { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 },   // 1
  224.     { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2
  225.     { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 },   // 3
  226.     { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 },   // 4
  227.     { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5
  228.     { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 },   // 6
  229.     { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7
  230.     { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8
  231.     { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E },   // 9
  232.     { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 },   // :
  233.     { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 },   // ;
  234.     { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 },   // <
  235.     { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 },   // =
  236.     { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 },   // >
  237.     { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 },   // ?
  238.     { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E },   // @
  239.     { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C },   // A
  240.     { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 },   // B
  241.     { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C
  242.     { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C },   // D
  243.     { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 },   // E
  244.     { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 },   // F
  245.     { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A },   // G
  246.     { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H
  247.     { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 },   // I
  248.     { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 },   // J
  249.     { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K
  250.     { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 },   // L
  251.     { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F },   // M
  252.     { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F },   // N
  253.     { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E },   // O
  254.     { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 },   // P
  255.     { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E },   // Q
  256.     { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 },   // R
  257.     { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 },   // S
  258.     { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 },   // T
  259.     { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F },   // U
  260.     { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F },   // V
  261.     { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F },   // W
  262.     { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 },   // X
  263.     { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y
  264.     { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z
  265.     { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 },   // [
  266.     { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 },   // 55
  267.     { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 },   // ]
  268.     { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 },   // ^
  269.     { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 },   // _
  270.     { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 },   // '
  271.     { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 },   // a
  272.     { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 },   // b
  273.     { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 },   // c
  274.     { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F },   // d
  275.     { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 },   // e
  276.     { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 },   // f
  277.     { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C },   // g
  278.     { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 },   // h
  279.     { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 },   // i
  280.     { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 },   // j
  281.     { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 },   // k
  282.     { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 },   // l
  283.     { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 },   // m
  284.     { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 },   // n
  285.     { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 },   // o
  286.     { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 },   // p
  287.     { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC },   // q
  288.     { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 },   // r
  289.     { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 },   // s
  290.     { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 },   // t
  291.     { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C },   // u
  292.     { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C },   // v
  293.     { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C },   // w
  294.     { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 },   // x
  295.     { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C },   // y
  296.     { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 },   // z
  297.     { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }    // horiz lines
  298. };

  299. //漢字 “楠楠,我愛你!”先掃描這串漢字的上半部分,再掃描下半部分
  300. uint8_t Hzk1[]=   //本數據由PCtoLCD取模軟件產生,手動改了一下漢字下半部分數據位置
  301. {
  302.    //楠楠,我愛你!
  303.   0x84,0x64,0xFF,0x24,0xFA,0x0A,0x5A,0xEF,0x5A,0x0A,0xFA,0x00,/*"楠",0up*/
  304.   0x84,0x64,0xFF,0x24,0xFA,0x0A,0x5A,0xEF,0x5A,0x0A,0xFA,0x00,/*"楠",1up*/
  305.   0x00,0x00,0x00,0x00,0x00,0x00,/*",",2up*/
  306.   0x10,0x12,0x12,0xFF,0x91,0x10,0xFF,0x10,0x90,0x52,0x14,0x00,/*"我",3up*/
  307.   0x32,0x56,0x5A,0xD2,0x76,0x5A,0x51,0x51,0x59,0x55,0x31,0x00,/*"愛",4up*/
  308.   0x20,0x10,0xFC,0x03,0x10,0xCF,0x04,0xF4,0x04,0x54,0x8C,0x00,/*"你",5up*/
  309.   0x00,0x00,0x7C,0x00,0x00,0x00,/*"!",6up*/
  310.   0x00,0x00,0x0F,0x00,0x0F,0x01,0x01,0x07,0x01,0x09,0x0F,0x00,/*"楠",0*/
  311.   0x00,0x00,0x0F,0x00,0x0F,0x01,0x01,0x07,0x01,0x09,0x0F,0x00,/*"楠",1*/
  312.   
  313.   0x04,0x03,0x00,0x00,0x00,0x00,/*",",2*/
  314.   0x02,0x02,0x09,0x0F,0x00,0x04,0x02,0x03,0x04,0x08,0x0E,0x00,/*"我",3*/
  315.   0x08,0x04,0x0A,0x09,0x0B,0x05,0x05,0x05,0x0B,0x08,0x08,0x00,/*"愛",4*/
  316.   0x00,0x00,0x0F,0x00,0x02,0x01,0x08,0x0F,0x00,0x00,0x03,0x00,/*"你",5*/
  317.   0x00,0x00,0x02,0x00,0x00,0x00/*"!",6*/
  318. };



  319. /******************************************************************************************************
  320. * 功    能:清屏
  321. * 入口函數:
  322. * 出口函數:
  323. * 說    明:
  324. * 范    例:
  325. * 日    期:2016年11月1日
  326. ******************************************************************************************************/
  327. void OLED12864_Clear(void)
  328. {
  329.   uint8_t x,y;
  330.   for(y=0;y<8;y++)
  331.   {
  332.     //設置地址
  333.     Write_CMD_TO_OLED12864(0xB0+y);
  334.     Write_CMD_TO_OLED12864(0x00);
  335.     Write_CMD_TO_OLED12864(0x10);
  336.     for(x=0;x<128;x++)
  337.     {
  338.       Write_DAT_TO_OLED12864(0x00);         
  339.     }
  340.   }
  341. }
  342. /******************************************************************************************************
  343. * 功    能:OLED12864初始化配置
  344. * 入口函數:
  345. * 出口函數:
  346. * 說   明:設置顯示坐標
  347. * 作   者:茗風
  348. * 日   期:2016年11月1日
  349. ******************************************************************************************************/
  350. void OLED_Set_Pos(uint8_t x, uint8_t y)
  351. {
  352.   if(y>7)return 1;//y軸
  353.         Write_CMD_TO_OLED12864(0xB0+y);//y軸坐標,0xB0為y軸起始地址
  354.   Write_CMD_TO_OLED12864((x&0x0F)+0x00);//x軸坐標低位
  355.         Write_CMD_TO_OLED12864(((x&0xF0)>>4)+0x10);//x軸坐標高位
  356. }
  357. ///******************************************************************************************************
  358. //* 功    能        :向OLED12864寫一串字符函數
  359. //* 入口參數        :x  x軸坐標,取值范圍(0~127)
  360. //*             y  y軸坐標,取值范圍(0~7)
  361. //*             *s 一串字符
  362. //* 出口參數        :無
  363. //* 說    明        :顯示6*8一組標準ASCII字符串,顯示的坐標(x,y),y為頁范圍0~7
  364. //* 編寫日期  :2016年11月1日
  365. //* 作    者  :茗風
  366. //******************************************************************************************************/
  367. uint8_t OLED12864_Display_Char(uint8_t _char)
  368. {
  369.   uint8_t  i=0;
  370.    
  371.   _char -= 32;//計算ASCII字符在F6x8[][]數組中的位置
  372.      
  373.   for(i=0; i<6; i++)
  374.   {
  375.     Write_DAT_TO_OLED12864(ASCII_6X8[_char][i]);  
  376.   }   
  377.   return 0;
  378. }

  379. ///******************************************************************************************************
  380. //* 功    能        :向OLED12864寫一串字符函數
  381. //* 入口參數        :x  x軸坐標,取值范圍(0~127)
  382. //*             y  y軸坐標,取值范圍(0~7),一共兩行
  383. //*             *s 一串字符
  384. //* 出口參數        :無
  385. //* 說    明        :顯示6*8一組標準ASCII字符串,顯示的坐標(x,y),y為頁范圍0~7
  386. //* 編寫日期  :2016年11月1日
  387. //* 作    者  :茗風
  388. //******************************************************************************************************/
  389. uint8_t OLED12864_Display_String(uint8_t x,uint8_t y,uint8_t *s)
  390. {
  391. //  uint8_t c=0, i=0;
  392.   OLED_Set_Pos(x,y);   
  393.   while (*s != '\0')
  394.   {   
  395. //    c = *s-32;//計算ASCII字符在F6x8[][]數組中的位置
  396. //    if(x>126) {x=0; y++;}   
  397.     OLED12864_Display_Char(*s++);  
  398. //    x += 6;
  399. //    s++;//指向字符串的指針自增,指向下一個字符
  400.   }  
  401.   return 0;
  402. }
  403. ///******************************************************************************************************
  404. //* 功    能        :OLED12864顯示一個uint16_t類型的數據
  405. //* 入口參數        :x  x軸坐標,取值范圍(0~127)
  406. //*             y  y軸坐標,取值范圍(0~7),一共兩行
  407. //*             number 寫入的字符
  408. //* 出口參數        :無
  409. //* 說    明        :
  410. //* 編寫日期  :2016年10月22日
  411. //* 作    者  :茗風
  412. //******************************************************************************************************/
  413. void LCD1602_Display_Number(uint8_t x,uint8_t y,uint32_t _number)
  414. {
  415. //  uint8_t tmp=0;
  416.   OLED_Set_Pos(x,y);  
  417.   
  418.   if(_number<10)  //9
  419.   {
  420.      OLED12864_Display_Char(_number%10+48);
  421.   }
  422.   else if(_number<100) //98
  423.   {
  424.      OLED12864_Display_Char(_number/10+48);
  425.      OLED12864_Display_Char(_number%10+48);
  426.   }
  427.   else if(_number<1000) //988
  428.   {
  429.      OLED12864_Display_Char(_number/100+48);
  430.      OLED12864_Display_Char(_number%100/10+48);
  431.      OLED12864_Display_Char(_number%10+48);
  432.   }
  433.   else if(_number<10000) //9999
  434.   {
  435.      OLED12864_Display_Char(_number/1000+48);
  436.      OLED12864_Display_Char(_number%1000/100+48);
  437.      OLED12864_Display_Char(_number%100/10+48);
  438.      OLED12864_Display_Char(_number%10+48);
  439.   }
  440.   else if(_number<100000) //99999
  441.   {
  442.      OLED12864_Display_Char(_number/10000+48);
  443.      OLED12864_Display_Char(_number%10000/1000+48);
  444.      OLED12864_Display_Char(_number%1000/100+48);
  445.      OLED12864_Display_Char(_number%100/10+48);
  446.      OLED12864_Display_Char(_number%10+48);
  447.   }
  448.   else if(_number<1000000) //999999
  449.   {
  450.      OLED12864_Display_Char(_number/100000+48);
  451.      OLED12864_Display_Char(_number%100000/10000+48);
  452.      OLED12864_Display_Char(_number%10000/1000+48);
  453.      OLED12864_Display_Char(_number%1000/100+48);
  454.      OLED12864_Display_Char(_number%100/10+48);
  455.      OLED12864_Display_Char(_number%10+48);
  456.   }
  457.   else if(_number<10000000) //999999
  458.   {
  459.      OLED12864_Display_Char(_number/1000000+48);
  460.      OLED12864_Display_Char(_number%1000000/100000+48);
  461.      OLED12864_Display_Char(_number%100000/10000+48);
  462.      OLED12864_Display_Char(_number%10000/1000+48);
  463.      OLED12864_Display_Char(_number%1000/100+48);
  464.      OLED12864_Display_Char(_number%100/10+48);
  465.      OLED12864_Display_Char(_number%10+48);
  466.   }
  467. }
  468. ///******************************************************************************************************
  469. //*  功  能   :顯示一行漢字,漢字大小為12*12,先寫上半部分8個像素,再寫下半部分4個像素
  470. //*  入口參數 :x,y:漢字寫入的地址坐標   s:寫的漢字數組  len:漢字數組中的數據個數
  471. //*  出口參數 : 0:寫字串成功     1:坐標越界      2:字符越界
  472. //*  說  明   :注意,本函數暫時只能一次寫小于一行的漢字,多行需要分開寫
  473. //*  范  例   :無
  474. //* 日     期:2016年10月31日
  475. //******************************************************************************************************/
  476. uint8_t OLED12864_Display_SimplifiedChinese(uint8_t x,uint8_t y,uint8_t *s,uint16_t len)
  477. {
  478.     static uint8_t i=0;
  479.   
  480.     len=len/2;//分上半部分和下半部分寫入
  481.     //先寫上半部分8個像素
  482.     OLED_Set_Pos(x,y);
  483.     for(i=0;i<len;i++)
  484.     {      
  485.       Write_DAT_TO_OLED12864(*s++);
  486.     }
  487.     //再寫下半部分4個像素
  488.     OLED_Set_Pos(x,y+1);
  489.     for(i=0;i<len;i++)
  490.     {
  491.       Write_DAT_TO_OLED12864(*s++);
  492.     }
  493.     return 0;
  494. }
  495. /******************************************************************************************************
  496. * 功    能:draw one picture
  497. * 入口函數:
  498. * 出口函數:
  499. * 說    明:
  500. * 范    例:
  501. * 日    期:2016年10月31日
  502. ******************************************************************************************************/
  503. //void OLED12864_Draw_One_Picture(void)
  504. //{
  505. //  uint8_t x,y;
  506. //  uint16_t i=0;
  507. //  for(y=0;y<8;y++)
  508. //  {
  509. //    Write_CMD_TO_OLED12864(0xb0+y);
  510. //    Write_CMD_TO_OLED12864(0x00);
  511. //    Write_CMD_TO_OLED12864(0x10);
  512. //    for(x=0;x<128;x++)
  513. //    {
  514. //      Write_DAT_TO_OLED12864(0x00);         
  515. //    }
  516. //  }
  517. //  for(y=0;y<8;y++)
  518. //  {
  519. //    Write_CMD_TO_OLED12864(0xb0+y);
  520. //    Write_CMD_TO_OLED12864(0x00);
  521. //    Write_CMD_TO_OLED12864(0x10);
  522. //    for(x=0;x<128;x++)
  523. //    {
  524. //      Write_DAT_TO_OLED12864(show1[i++]);
  525. //      delay_100us(1000);         
  526. //    }
  527. //  }
  528. //}
  529. /******************************************************************************************************
  530. *  名    稱:void delay_100us(uint8_t x_us)
  531. *  功    能:延時100us
  532. *  入口參數:無
  533. *  出口參數:無
  534. *  說    明:
  535. *  范    例:無
  536. ******************************************************************************************************/
  537. void delay_100us(uint16_t x_us)
  538. {
  539.   uint8_t j;
  540.   while(x_us--)
  541.   {
  542.     for(j=0;j<33;j++);//2*40個指令周期
  543.   }
  544.   //delay_10ms共消耗 x_ms*2*255+2*x_ms個指令周期  
  545.   //*2*40+2*x_ms=80us+
  546.   //16M/8/2=1M 一個指令周期為1us
  547. }
  548. /******************************************************************************************************
  549. * 功    能:OLED12864初始化配置
  550. * 入口函數:
  551. * 出口函數:
  552. * 說    明:
  553. * 范    例:
  554. * 日    期:2016年10月31日
  555. ******************************************************************************************************/
  556. void OLED12864_Init(void)
  557. {
  558.   delay_100us(100);
  559.         Write_CMD_TO_OLED12864(0xAE); //display off
  560.         Write_CMD_TO_OLED12864(0x20);        //Set Memory Addressing Mode       
  561.         Write_CMD_TO_OLED12864(0x10);        //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
  562.         Write_CMD_TO_OLED12864(0xB0);        //Set Page Start Address for Page Addressing Mode,0-7
  563.         Write_CMD_TO_OLED12864(0xC8);        //Set COM Output Scan Direction
  564.         Write_CMD_TO_OLED12864(0x00);//---set low column address
  565.         Write_CMD_TO_OLED12864(0x10);//---set high column address
  566.         Write_CMD_TO_OLED12864(0x40);//--set start line address
  567.         Write_CMD_TO_OLED12864(0x81);//--set contrast control register
  568.         Write_CMD_TO_OLED12864(0x7F);
  569.         Write_CMD_TO_OLED12864(0xA1);//--set segment re-map 0 to 127
  570.         Write_CMD_TO_OLED12864(0xA6);//--set normal display
  571.         Write_CMD_TO_OLED12864(0xA8);//--set multiplex ratio(1 to 64)
  572.         Write_CMD_TO_OLED12864(0x3F);//
  573.         Write_CMD_TO_OLED12864(0xA4);//0xa4,Output follows RAM content;0xa5,Output ignores RAM content
  574.         Write_CMD_TO_OLED12864(0xD3);//-set display offset
  575.         Write_CMD_TO_OLED12864(0x00);//-not offset
  576.         Write_CMD_TO_OLED12864(0xD5);//--set display clock divide ratio/oscillator frequency
  577.         Write_CMD_TO_OLED12864(0xF0);//--set divide ratio
  578.         Write_CMD_TO_OLED12864(0xD9);//--set pre-charge period
  579.         Write_CMD_TO_OLED12864(0x22); //
  580.         Write_CMD_TO_OLED12864(0xDA);//--set com pins hardware configuration
  581.         Write_CMD_TO_OLED12864(0x12);
  582.         Write_CMD_TO_OLED12864(0xDB);//--set vcomh
  583.         Write_CMD_TO_OLED12864(0x20);//0x20,0.77xVcc
  584.         Write_CMD_TO_OLED12864(0x8D);//--set DC-DC enable
  585.         Write_CMD_TO_OLED12864(0x14);//
  586.         Write_CMD_TO_OLED12864(0xAF);//--turn on oled panel
  587.   OLED12864_Clear();//清屏操作
  588.   OLED12864_Display_String(0,3,"nan nan 5201314!");
  589.   OLED12864_Display_SimplifiedChinese(30,0,Hzk1,sizeof(Hzk1));//楠楠,我愛你!
  590. //  LCD1602_Display_Number(30,5,5201314);
  591. }
  592. void main(void)
  593. {
  594.   CLK_CKDIVR =0x01;  //16M/2^1=8M
  595.   I2C_Init();
  596.   OLED12864_Init();
  597.   while(1)
  598.   {
  599.     //asm("wfi");
  600.   }
  601. }
復制代碼




評分

參與人數 1黑幣 +10 收起 理由
YJGG + 10 謝謝分享

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏6 分享淘帖 頂 踩
回復

使用道具 舉報

13#
ID:412650 發表于 2021-7-23 00:12 | 只看該作者
感謝樓主,在樓主代碼的幫助下,終于點亮了OLED
不過小弟剛開始接觸C及單片機,有個地方想請教一下
下面代碼的“_char”是什么意思,是怎么實現的計算ASCII字符在數組中的位置呢?
感謝!!

u8 OLED12864_Display_Char(u8 _char)
{
  u8 i=0;
   
  _char -= 32;//計算ASCII字符在F6x8[][]數組中的位置
     
  for(i=0; i<8; i++)
  {
    Write_DAT_TO_OLED12864(ASCII_6X8[_char][i]);  
  }   
  return 0;
}
回復

使用道具 舉報

12#
ID:951974 發表于 2021-7-21 12:41 | 只看該作者
ganbc 發表于 2017-12-19 13:19
剛好在某寶上買了一個4針IIC的0.96雙色OLED屏。看上去和樓主的一樣。
用IAR編譯樓主的代碼時,報了一個錯 ...

我也是,不改的話報錯,但是改了后編譯是成功了,但是刷進去無顯示。。。
回復

使用道具 舉報

11#
ID:754694 發表于 2020-8-26 02:22 來自觸屏版 | 只看該作者
學習了,注釋很好理解~
回復

使用道具 舉報

10#
ID:123924 發表于 2020-6-22 23:50 | 只看該作者
正好在做移植,很詳細。多謝分享
回復

使用道具 舉報

9#
ID:402865 發表于 2018-9-27 22:47 | 只看該作者
樓主能提供完整工程和總體原理圖嗎
回復

使用道具 舉報

8#
ID:377647 發表于 2018-7-23 01:08 | 只看該作者
有原理圖嗎
回復

使用道具 舉報

7#
ID:186159 發表于 2018-6-20 15:13 | 只看該作者
GitHub位置鏈接  :
https://github.com/tugaozi/STM8_I2C_OLED
回復

使用道具 舉報

6#
ID:186159 發表于 2018-6-20 15:06 | 只看該作者
回復

使用道具 舉報

5#
ID:257024 發表于 2017-12-19 13:19 | 只看該作者
剛好在某寶上買了一個4針IIC的0.96雙色OLED屏。看上去和樓主的一樣。
用IAR編譯樓主的代碼時,報了一個錯誤:a void function may not return a value
把360行的語句:if (y>7) return 1; //y軸
改寫成:if (y>7) return; //y軸
就編譯成功了。
感謝樓主的分享。
回復

使用道具 舉報

地板
ID:257024 發表于 2017-12-17 02:12 | 只看該作者
不知道刷屏速度是否夠快。有空弄一個來玩玩。
回復

使用道具 舉報

板凳
ID:206664 發表于 2017-6-1 21:54 來自觸屏版 | 只看該作者
為什么我刷屏的時候,屏會閃?
回復

使用道具 舉報

沙發
ID:90140 發表于 2016-11-15 08:33 | 只看該作者
很詳細,謝謝樓主分享!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 四虎成人免费电影 | 国产一区二区欧美 | 超碰97人人人人人蜜桃 | 中国一级特黄真人毛片免费观看 | 九九综合 | 国产精品久久久久久久久久不蜜臀 | 久久精品欧美一区二区三区麻豆 | 国产欧美一区二区三区在线看 | 国产小视频精品 | 亚洲免费精品 | 一区二区三区国产好的精 | 午夜小电影 | 白浆在线 | 成人一级视频在线观看 | 日韩一区二区三区在线视频 | 亚洲中午字幕 | 久久99久久99精品免视看婷婷 | 中文字幕免费中文 | 日韩一及片 | 天天曰夜夜操 | 中文字幕在线观看 | 伊人免费网 | 视频一区在线播放 | 国产精品福利在线观看 | 99热视 | 国产欧美日韩综合精品一区二区 | 欧美午夜精品久久久久免费视 | 一本一道久久a久久精品综合 | 国产sm主人调教女m视频 | 久免费视频 | 欧美日日 | 欧美一区二区三区久久精品 | 毛片99| 久久久久久久久久久久久91 | 国产精品久久久久久久久久久久冷 | 久久国产精品久久久久久 | 国产高清视频在线观看 | 色婷婷一区二区三区四区 | 免费视频一区二区 | 亚洲国产精品久久久久 | 色综合区 |