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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8901|回復: 13
收起左側

關于OLED12864用IIC通訊顯示受晶振頻率影響解決方案 附單片機程序

  [復制鏈接]
ID:210139 發表于 2020-5-17 13:41 | 顯示全部樓層 |閱讀模式
關于OLED12864用IIC通訊顯示受晶振頻率影響解決方案
采用的單片機機STC8A8K64S4A12,同時STC15系列的也使用,測試過的
之前用軟件模擬IIC驅動OLED12864時,當把單片機晶振頻率調高時,OLED就不能正常顯示了
后來找到了一些IIC程序,采用了一下,得以解決這一問題

問題還是IIC驅動程序沒有寫好,用賣家的例程也不行,還是的自己修改一下

此版程序,通過測試,就算把晶振調到27MHZ,也能正常顯示

附件中有SPI通訊,軟件模擬IIC,基于STC8A8K的硬件IIC,驅動OLED12864
不過STC8的硬件IIC通訊,還是受到晶振頻率的影響,稍微修改了一下,比之前要好一點

貼出來的程序是單片機軟件模擬IIC驅動OLED12864
  1. #include "oled.h"
  2. #include "Font.h"
  3. #include "intrins.h"

  4. void Delay_OLED(u16 t)
  5. {
  6.         u16 i,j;
  7.         for(j=0;j<t;j++)
  8.         {
  9.                 for(i=0;i<1;i++)        //根據晶振頻率調整延時
  10.                 {
  11.                         _nop_();
  12.                         //_nop_();_nop_();
  13.                 }
  14.         }
  15. }

  16. /*********通過IIC寫一字節數據******/
  17. void IIC_Write_Byte(u8 Byte)
  18. {
  19.         u8 i;
  20.         for(i=0;i<8;i++)
  21.         {
  22.                 OLED_SDA = Byte &0X80;        ////改變數據
  23.                 OLED_SCL = 1;        //傳輸數據
  24.                 Delay_OLED(1);
  25.                 OLED_SCL = 0;
  26.                 Byte<<=1;
  27.                 Delay_OLED(1);
  28.         }
  29. }

  30. /********起始信號*********/
  31. void IIC_Start()
  32. {
  33.         OLED_SDA = 1;
  34.         OLED_SCL = 1;
  35.         Delay_OLED(1);
  36.         OLED_SDA = 0;
  37.         Delay_OLED(1);
  38.         OLED_SCL = 0;
  39.         Delay_OLED(1);
  40. }

  41. /********停止信號*********/
  42. void IIC_Stop()
  43. {
  44.         OLED_SCL = 0;
  45.         OLED_SDA = 0;
  46.         Delay_OLED(1);
  47.         OLED_SDA = 1;
  48.         Delay_OLED(1);
  49.         OLED_SCL = 1;
  50.         Delay_OLED(1);
  51. }

  52. /*********ACK信號********/
  53. bit IIC_ACK()
  54. {
  55.         u8 errtime=255;
  56.         OLED_SCL = 0;
  57.         OLED_SDA = 1;        //釋放總線
  58.         Delay_OLED(1);
  59.         OLED_SCL = 1;
  60.         Delay_OLED(1);
  61.         while(OLED_SDA)        //讀取 SDA上的電平,變為低電平,即有從機回復ACK信號
  62.         {
  63.                 errtime--;
  64.                 if(!errtime)        //超時退出
  65.                 {
  66.                         OLED_SCL=0;
  67.                         return 0;
  68.                 }
  69.         }
  70.         OLED_SCL=0;
  71.         return 1;
  72. }

  73. /***********向SSD1306寫一字節數據***********
  74. Dat:要寫入的數據/命令
  75. Cmd:數據/命令標志 0,表示命令;1,表示數據;
  76. ********************************************/
  77. void Write_OLED_Byte(u8 Dat,u8 Cmd)
  78. {
  79.         IIC_Start();
  80.         IIC_Write_Byte(0X78);
  81.         IIC_ACK();
  82.         if(Cmd ==1)        //數據
  83.                 IIC_Write_Byte(0X40);
  84.         else        //命令
  85.                 IIC_Write_Byte(0X00);
  86.         IIC_ACK();
  87.         IIC_Write_Byte(Dat);
  88.         IIC_ACK();
  89.         IIC_Stop();
  90. }

  91. /**********IIC_IO口初始化***********/
  92. void IIC_InitIO()
  93. {
  94.         OLED_SDA = 1;
  95.         OLED_SCL = 1;
  96. }
  97. //---------IIC 通訊----------------------------------------------------------
  98. /*********設置顯示坐標*********/
  99. void OLED_Set_PoS(u8 page,u8 column)
  100. {
  101.         Write_OLED_Byte(0XB0+page,OLED_CMD);
  102.         Write_OLED_Byte( ((column&0XF0)>>4)|0X10,OLED_CMD);
  103.         Write_OLED_Byte( column&0X0F,OLED_CMD);
  104. }

  105. ////開啟OLED顯示   
  106. //void OLED_Display_On(void)
  107. //{
  108. //        Write_OLED_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  109. //        Write_OLED_Byte(0X14,OLED_CMD);  //DCDC ON
  110. //        Write_OLED_Byte(0XAF,OLED_CMD);  //DISPLAY ON
  111. //}


  112. ////關閉OLED顯示     
  113. //void OLED_Display_Off(void)
  114. //{
  115. //        Write_OLED_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  116. //        Write_OLED_Byte(0X10,OLED_CMD);  //DCDC OFF
  117. //        Write_OLED_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
  118. //}

  119. /************操作整個屏幕************
  120. Input: Ins=0        清除整個屏幕
  121.            Ins=0XFF        全部顯示整個屏幕
  122. *************************************/
  123. void OLED_Screen_All(u8 Ins)
  124. {
  125.         u8 page,seg;
  126.         for(page=0;page<8;page++)
  127.         {
  128.                 OLED_Set_PoS(page,0);
  129.                 for(seg=0;seg<128;seg++)
  130.                 {
  131.                         Write_OLED_Byte(Ins,OLED_DAT);
  132.                         Delay_OLED(1);
  133.                 }
  134.                 Delay_OLED(1);
  135.         }
  136. }


  137. /*********OLED初始化***********/
  138. void OLED_Init()
  139. {
  140.         Delay_OLED(2000);  
  141.         
  142.         Write_OLED_Byte(0XD5,OLED_CMD);        //晶振頻率
  143.         Write_OLED_Byte(0X80,OLED_CMD);
  144.         Write_OLED_Byte(0XD9,OLED_CMD);        //
  145.         Write_OLED_Byte(0XF1,OLED_CMD);
  146.         Write_OLED_Byte(0XDB,OLED_CMD);        //
  147.         Write_OLED_Byte(0X40,OLED_CMD);
  148. //--地址設置
  149.         Write_OLED_Byte(0X20,OLED_CMD);        //設置尋址模式
  150.         Write_OLED_Byte(0X02,OLED_CMD);        //0X00--水平尋址;0X01--垂直尋址;0X02--頁面尋址
  151. //--硬件設置
  152.         Write_OLED_Byte(0X40,OLED_CMD);        //起始行
  153.         Write_OLED_Byte(0XA8,OLED_CMD);        //設置顯示比列;
  154.         Write_OLED_Byte(0X3F,OLED_CMD);        //1/64
  155.         Write_OLED_Byte(0XD3,OLED_CMD);        //設置補償
  156.         Write_OLED_Byte(0X00,OLED_CMD);
  157.         //顯示方向-引腳向上為正方向
  158.         Write_OLED_Byte(0XA1,OLED_CMD);        //段尋址,add0-->seg0
  159.         Write_OLED_Byte(0XC8,OLED_CMD);        //com掃描方向,com0-com63
  160.         //引腳在下為正方向
  161.         //Write_OLED_Byte(0XA0,OLED_CMD);        //段尋址,add127-->seg0
  162.         //Write_OLED_Byte(0XC0,OLED_CMD);        //com掃描方向,com63-com0
  163.         Write_OLED_Byte(0X8D,OLED_CMD);        //電荷泵設置
  164.         Write_OLED_Byte(0X14,OLED_CMD);        //REST=0X10,        0X14才能顯示內容
  165. //--基本命令
  166.         Write_OLED_Byte(0X81,OLED_CMD);        //設置對比度
  167.         Write_OLED_Byte(0XCF,OLED_CMD);        //0X00-0XFF,與數值成正比        RES=0X7F
  168.         Write_OLED_Byte(0XA4,OLED_CMD);        //整體顯示開啟,可用來測試液晶是否顯示正常
  169.                                                                         //0XA4跟隨RAM內容,0XA5不跟隨RAM的內容,一直是白屏全部顯示。
  170.         Write_OLED_Byte(0XA6,OLED_CMD);        //設置正顯0XA6,反顯0XA7
  171.         Write_OLED_Byte(0XAF,OLED_CMD);        //0XAE顯示關,0XAF顯示開
  172.         Write_OLED_Byte(0X2E,OLED_CMD);        //關閉滾屏
  173. //---清屏
  174.         OLED_Screen_All(0);        
  175.         Delay_OLED(100);
  176.         OLED_Screen_All(0XFF);        
  177.         Delay_OLED(2000);
  178.         OLED_Screen_All(0);
  179.         Delay_OLED(100);
  180. }

  181. ///***********垂直+水平滾屏***************/
  182. //void Ver_Lev_Screen()
  183. //{
  184. ////--垂直+水平滾屏-------------------------------------------------------------------
  185. //        Write_OLED_Byte(0XA3,OLED_CMD);        //設置垂直滾動區域
  186. //        Write_OLED_Byte(0X10,OLED_CMD);        //固定不動的行數,從頂部開始數
  187. //        Write_OLED_Byte(0X20,OLED_CMD);        //垂直滾動的行數,從固定行的下一行開始數
  188. //        
  189. //        Write_OLED_Byte(0X29,OLED_CMD);        //垂直+右移///0X2A=垂直+左移
  190. //        Write_OLED_Byte(0X00,OLED_CMD);        //空字節
  191. //        Write_OLED_Byte(0X06,OLED_CMD);        //水平移動起始頁
  192. //        Write_OLED_Byte(0X05,OLED_CMD);        //控制垂直+水平速率
  193. //        Write_OLED_Byte(0X07,OLED_CMD);        //水平移動結束頁
  194. //        Write_OLED_Byte(0X02,OLED_CMD);        //垂直滾動偏移量,只控制垂直速率,=0只有水平移動
  195. //        Write_OLED_Byte(0X2F,OLED_CMD);        //啟動滾屏
  196. ////---以上效果為,第一行為固定,第二三行垂直滾屏,第四行右移-------------------------
  197. //}

  198. /**************水平滾屏*****************/
  199. void Lev_Screen()
  200. {
  201.         Write_OLED_Byte(0X26,OLED_CMD);        //右移///0X27=左移
  202.         Write_OLED_Byte(0X00,OLED_CMD);        //空字節
  203.         Write_OLED_Byte(0X06,OLED_CMD);        //水平移動起始頁
  204.         Write_OLED_Byte(0X05,OLED_CMD);        //控制垂直+水平速率
  205.         Write_OLED_Byte(0X07,OLED_CMD);        //水平移動結束頁
  206.         Write_OLED_Byte(0X00,OLED_CMD);        //虛擬字節
  207.         Write_OLED_Byte(0XFF,OLED_CMD);        //虛擬字節
  208.         Write_OLED_Byte(0X2F,OLED_CMD);        //啟動滾屏
  209. }

  210. ///**************清除N個8*16區域**********/
  211. //void Clear8X16(u8 page, u8 column ,u8 N)
  212. //{
  213. //        u8 i,j,k;
  214. //        for(k=0;k<N;k++)
  215. //        {
  216. //                for(i=0;i<2;i++)
  217. //                {
  218. //                        OLED_Set_PoS(page+i,column+k*8);
  219. //                        for(j=8;j>0;j--)
  220. //                                Write_OLED_Byte(0X00,OLED_DAT);
  221. //                }
  222. //        }
  223. //}

  224. /*****************在(16行/2頁)*Wide列區域寫數據****************
  225. Input:        
  226.         *Buff@點陣數據        Num@字符個數,Wide@字體寬度
  227.         Wide=8時,為寫8*16的數據,字母,符號
  228.         Wide=16時,為寫宋體2號漢字
  229. **************************************************************/
  230. void Write_16xWide(u8 page,u8 column ,u8 *Buff,u8 Num,u8 Wide)
  231. {
  232.         u8 i,j,k;
  233.         for(k=0;k<Num;k++)
  234.         {
  235.                 for(i=0;i<2;i++)
  236.                 {
  237.                         OLED_Set_PoS(page+i,column+k*8);
  238.                         for(j=Wide;j>0;j--)
  239.                         {
  240.                                 Write_OLED_Byte(*Buff,OLED_DAT);
  241.                                 Buff++;
  242.                         }
  243.                 }
  244.         }
  245. }

  246. /**************寫宋體12號漢字 16*Wide ***********
  247. Input:        page@頁                column@列        *CH@字符串
  248.         可以顯示漢字,數字,字母,符號
  249.         page:0 2 4 6        column:0~15
  250. ************************************************/
  251. void Write_GB16X16(u8 page,u8 column ,u8 *CH)
  252. {
  253.         u8 a,k;
  254.         if( (*CH>=0X20) && (*CH<=0X7E) )        column=column;
  255.         else column*=8;
  256.         while( *CH != '\0')
  257.         {
  258.                 if( (*CH>=0X20) && (*CH<=0X7E) )        //數字,字母,符號        一行16個
  259.                 {
  260.                         k=*CH-0X20;
  261.                         for(a=0;a<2;a++)
  262.                         {
  263.                                 Write_16xWide(page,column*8, &ASCII_8X16[k][0],1,8);
  264.                         }
  265.                         CH+=1;
  266.                         column+=1;
  267.                 }        
  268.                 else        //漢字,一行 8個
  269.                 {
  270.                         for(a=0;a<FontNum;a++)
  271.                         {
  272.                                 if( (*CH == GB12Hanzi[a].Index[0]) && (*(CH+1)==GB12Hanzi[a].Index[1]) )
  273.                                         Write_16xWide(page,column,&GB12Hanzi[a].Msk[0],1,16);
  274.                         }
  275.                         CH+=2;
  276.                         column+=16;
  277.                 }
  278.         }
  279. }

  280. ///**************在8行/1頁**6列的區域寫字符***************
  281. //Input:        
  282. //        *CH@字符串        能寫21個字符
  283. //        page:0~7        column:0~20
  284. //*******************************************************/
  285. //void Write_GB6X8(u8 page,u8 column ,u8 *CH)
  286. //{
  287. //        u8 j,k;
  288. //        while( *CH != '\0')
  289. //        {
  290. //                if( (*CH>=0X20) && (*CH<=0X7E) )        //數字,字母,符號        一行16個
  291. //                {
  292. //                        k=*CH-0X20;
  293. //                        OLED_Set_PoS(page,column*6);
  294. //                        for(j=0;j<6;j++)
  295. //                                Write_OLED_Byte(ASCII_6X8[k][j],OLED_DAT);
  296. //                        CH+=1;
  297. //                        column+=1;
  298. //                }
  299. //        }
  300. //}


復制代碼

OLED12864

OLED12864
Z%%CJ_LKS2YH_G7S850E4S9.png

D-0.96OLED驅動程序.zip

141.08 KB, 下載次數: 235, 下載積分: 黑幣 -5

IIC驅動OLED程序

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

ID:446175 發表于 2021-4-14 22:22 | 顯示全部樓層
用樓主的程序直接點亮屏了,哈哈,謝謝
回復

使用道具 舉報

ID:94330 發表于 2021-4-19 08:55 | 顯示全部樓層
感謝樓主分享,測試成功
回復

使用道具 舉報

ID:963221 發表于 2021-9-2 16:06 | 顯示全部樓層
還是受速度影響.比如27M時候容易卡死,得斷電才可以不管怎么復位都不行
回復

使用道具 舉報

ID:137590 發表于 2021-10-9 21:29 | 顯示全部樓層
跟著芯片手冊驅動IIC OLED屏幕
回復

使用道具 舉報

ID:965325 發表于 2021-10-10 12:42 | 顯示全部樓層
沒啥特殊的,就是讀寫OLED的底層函數中加了延時。

回復

使用道具 舉報

ID:90718 發表于 2021-11-22 00:59 | 顯示全部樓層
有參考價值,非常感謝!
回復

使用道具 舉報

ID:1013122 發表于 2022-3-28 21:01 | 顯示全部樓層
謝謝。一直在找,非常棒的資源。
回復

使用道具 舉報

ID:630338 發表于 2022-4-5 16:13 | 顯示全部樓層
非常好的資源
回復

使用道具 舉報

ID:471636 發表于 2022-4-8 17:09 | 顯示全部樓層
對于軟件模擬I2C通訊來說,讀寫的延時很重要,更換單片機或者更改頻率,都會影響延時函數的實際運行值,可能會引起I2C通訊故障,樓主所謂的解決方案只是對某種單片機的某些頻率段試驗可行,并不能徹底解決問題。
5、6樓說的都對,其實就是按照手冊調延時。
回復

使用道具 舉報

ID:297903 發表于 2022-4-9 09:34 | 顯示全部樓層
要用I/O摸似II2C,只能自己調整延時來適應不的CPU頻率!!
回復

使用道具 舉報

ID:744744 發表于 2022-5-22 22:42 來自手機 | 顯示全部樓層
單片機運行時間不一樣,時序要調整,這個是正常的。
回復

使用道具 舉報

ID:1135948 發表于 2024-11-9 10:13 | 顯示全部樓層
學習一下
不知道能否點亮OLED
回復

使用道具 舉報

ID:961114 發表于 2024-11-12 14:55 | 顯示全部樓層
過年新玩具get√ ^o^ 第一次玩彩色的OLED,跟TFT彩屏的用法幾乎一樣_嗶哩嗶哩_bilibili  https://www.bilibili.com/video/B ... 229259e6d079df11d14
51hei20241112-145448.png
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美日韩中文在线 | 久久国产一区 | 亚洲国产欧美91 | 亚洲一区在线免费观看 | 综合二区 | 国产成人99久久亚洲综合精品 | 日日日视频 | 久久精品国产v日韩v亚洲 | 波多野结衣中文字幕一区二区三区 | 久久中文字幕一区 | 高清免费av | 蜜臀av日日欢夜夜爽一区 | 一区二区视频在线 | 玖草资源 | 亚洲一区二区三区免费视频 | 欧美日韩国产高清 | 国产中的精品av涩差av | 美女视频一区二区三区 | 精品无码久久久久久国产 | 超碰成人av | 日韩国产一区二区三区 | 蜜桃精品噜噜噜成人av | 嫩草影院网址 | 99在线资源 | 国产精品毛片一区二区在线看 | 精品91视频 | 国产一级毛片视频 | 91免费观看在线 | 亚洲日韩中文字幕 | 欧美一区二区三区日韩 | 日韩精品一区二区三区视频播放 | 色屁屁在线观看 | 亚洲欧美精品久久 | 国产精品揄拍一区二区久久国内亚洲精 | 久久久久久国产精品mv | 欧美日韩在线视频一区 | www九色| 午夜精品一区二区三区在线观看 | 日韩波多野结衣 | 亚洲精品一区二区三区蜜桃久 | 天天躁日日躁狠狠的躁天龙影院 |