[外設篇]ESP8266-SDK教程(十)之DHT11、OLED1306


真誠分享,技術交友,歡迎交流。

Hi,大家好,寫這篇文章的時候“IAMLIUBO的神奇物聯網之旅”專欄關注人數已經有186人了,首先很感謝大家的關注和相信,開始寫第一篇的文章的時候也沒想過會有這么多人感興趣,看到關注的人數越來越多,當然對文章的質量也要有更高的要求,力求每篇文章沒有錯別字和錯誤的敘述,也希望大家可以幫我一起勘誤。寫這些文章的目的就是希望可以幫助更多人,當然也收獲了很多知友,也有很多知友加我微信咨詢一些問題,希望我的每一個回答都對你有所幫助,這篇文章是外設篇的第一篇,也是知友小牛最近在微信咨詢我的一點問題,這里就記錄成文章跟大家分享一下。

閑話少說,咱們開始來說正事,相信大家在做一些實際項目或者小發明創造的時候,多多少少都會用過溫濕度傳感器,或者說會采集溫濕度數據加以展示和判斷處理,那么我們這里說的DHT11就是一款非常不錯的溫濕度傳感器,是廣州奧松電子生產的一款溫濕度傳感器,在開發當中我是用的比較多的,上一張圖給大家看一下。

 

當然,這款傳感器尺寸不是很小,做一些對尺寸要求比較嚴格的產品還是不怎么推薦的,一般做比較小的產品,還是比較推薦盛思瑞的SHT系列,當然價格就不是那么美麗了,但是精度相對來說還是比較不錯的,當然對大小和空間都有要求的話推薦美信的DS18B20。

下面我們來看一下這款傳感器的具體參數:

 

 

上面這三個表,就可以很直觀的看出這款傳感器的參數了,這里就不再做過多的文字敘述了。

了解完了這些基本的,那我們再來看一下我們是如何從傳感器取到溫濕度的值呢?說到這里,那就不得不提一個概念了,相信搞嵌入式開發的都知道,那就是單總線通信方式,那么什么是單總線通信方式呢?它與其他通信方式又有什么不同呢?下面我們先來看一下百科:

單總線是美國DALLAS公司推出的外圍串行擴展總線技術。與 SPII²C串行數據通信方式不同.它采用單根 信號線,既傳輸 時鍾又傳輸數據,而且 數據傳輸是雙向的,具有節省I/O口線、資源結構簡單、成本低廉、便於總線擴展和維護等諸多優點。(百度百科)

簡單來說,就是雙方通信只通過一根線解決,不像其他通信方式有時鍾線和數據線,這樣的好處是極大的節省了I/O資源,當然這種通信方式的速率自然也會有所降低,像前面說的DS18B20也是采用單總線通信方式。

那么我們再來看一下DHT11通過單總線發送的數據格式,了解了數據格式可以更好的幫助我們理解程序是如何讀取溫濕度的,因為數據傳輸在硬件層就是電平高低,轉化為計算機語言就是0/1,我們就是通過DHT11發送的這些0/1中找出溫濕度的值:

 

可以看到一共是有40位數據的,每8位是一組,包含了溫濕度和校驗值,校驗值等於溫濕度的和,如果不理解,那么我們通過一個實際例子來看一下:

 

這就是一個完整的數據包過來,我們如何解包和驗證,那么我們看一下代碼:

  1 static uint8_t ICACHE_FLASH_ATTR dht11ReadBit(void)
  2 {
  3     uint8_t retry=0;
  4     
  5     while(DHT11_IN&&retry<100)                                  //wait become Low level
  6     {
  7         retry++;
  8         tempHumDelay(1);
  9     }
 10 
 11     retry=0;
 12     while(!DHT11_IN&&retry<100)                                 //wait become High level
 13     {
 14         retry++;
 15         tempHumDelay(1);
 16     }
 17 
 18     tempHumDelay(40);                                         //wait 40us
 19 
 20     if(DHT11_IN)
 21         return 1;
 22     else
 23         return 0;
 24 }
 25 
 26 static uint8_t ICACHE_FLASH_ATTR hdt11ReadByte(void)
 27 {
 28     uint8_t i;
 29     uint8_t dat=0;
 30     
 31     for (i=0; i<8; i++)
 32     {
 33         dat<<=1;
 34         dat |= dht11ReadBit(); 
 35     }
 36 
 37     return dat;
 38 }
 39 
 40 static uint8_t ICACHE_FLASH_ATTR dht11ReadData(u8 * temperature, u8 * humidity)
 41 {
 42     uint8_t i;
 43     uint8_t buf[5];
 44     
 45     dht11Rst(); 
 46     if(0 == dht11Check()) 
 47     {
 48         for(i=0; i<5; i++)
 49         {
 50             buf[i] = hdt11ReadByte(); 
 51         }
 52         if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
 53         {
 54             *humidity=buf[0];
 55             *temperature=buf[2];
 56         }
 57     }
 58     else
 59     {
 60         return 1;
 61     }
 62 
 63     return 0;
 64 }
 65 
 66 uint8_t ICACHE_FLASH_ATTR dh11Read(uint8_t * temperature, uint8_t * humidity)
 67 {
 68     uint8_t ret = 0; 
 69     uint8_t cur_i = 0;
 70     uint8_t curTem = 0;
 71     uint8_t curHum = 0;
 72     uint16_t temMeans = 0;
 73     uint16_t hum_means = 0;
 74 
 75     ret = dht11ReadData(&curTem, &curHum);
 76 
 77     if(0 == ret) 
 78     {
 79         //Cycle store ten times stronghold
 80         if(MEAN_NUM > temphum_typedef.th_num)
 81         {
 82             temphum_typedef.th_bufs[temphum_typedef.th_num][0] = curTem;
 83             temphum_typedef.th_bufs[temphum_typedef.th_num][1] = curHum;
 84 
 85             temphum_typedef.th_num++;
 86         }
 87         else
 88         {
 89             temphum_typedef.th_num = 0;
 90 
 91             temphum_typedef.th_bufs[temphum_typedef.th_num][0] = curTem;
 92             temphum_typedef.th_bufs[temphum_typedef.th_num][1] = curHum;
 93 
 94             temphum_typedef.th_num++;
 95         }
 96     }
 97     else
 98     {
 99         return 1; 
100     }
101     
102     if(MEAN_NUM <= temphum_typedef.th_num) 
103     {
104         temphum_typedef.th_amount = MEAN_NUM;
105     }
106 
107     if(0 == temphum_typedef.th_amount) 
108     {
109         //Calculate Before ten the mean
110         for(cur_i = 0; cur_i < temphum_typedef.th_num; cur_i++)
111         {
112             temMeans += temphum_typedef.th_bufs[cur_i][0];
113             hum_means += temphum_typedef.th_bufs[cur_i][1];
114         }
115 
116         temMeans = temMeans / temphum_typedef.th_num;
117         hum_means = hum_means / temphum_typedef.th_num; 
118         
119         *temperature = temMeans;
120         *humidity = hum_means;
121     }
122     else if(MEAN_NUM == temphum_typedef.th_amount) 
123     {
124         //Calculate After ten times the mean
125         for(cur_i = 0; cur_i < temphum_typedef.th_amount; cur_i++) 
126         {
127             temMeans += temphum_typedef.th_bufs[cur_i][0];
128             hum_means += temphum_typedef.th_bufs[cur_i][1];
129         }
130 
131         temMeans = temMeans / temphum_typedef.th_amount; 
132         hum_means = hum_means / temphum_typedef.th_amount; 
133         
134         *temperature = (uint8_t)temMeans; 
135         *humidity = (uint8_t)hum_means; 
136     }
137 
138     return 0;
139 }

 

這就是我們讀溫濕度的主要代碼,大家可以看一下,我們是不是對40位的bit位的數據做了處理呢?后面我們會結合OLED顯示屏來實際測試一下,這里就先不做測試了。

說完了DHT11,我們再來了解一下SSD1306,其實這是一款OLED屏幕的控制芯片,目前在淘寶等常見的0.96吋小OLED顯示屏幕大多就是使用這款芯片的,當然還有一款功能一樣的替代芯片叫SHT1106,不過兩者指令兼容,所以會一款,另一款也就會了。這款主控芯片是香港晶門科技公司的,目前在一般小制作或者小創意上用這款主控的顯示屏幕還是比較多的,我也一直在使用,這款芯片最大只能控制128x64個像素點,所以有時候我們常說的OLED12864,多也是使用這塊主控的屏幕,當然這家公司也生產很多可以控制更多像素點的主控芯片,有興趣的可以去官網了解一下:

晶門科技有限公司​www.solomon-systech.com.cn

同樣的,我們先來了解一下,遺憾的是沒有找到官方的中文數據手冊,又怕某些翻譯的不太准確,所以這里就直接貼英文數據手冊的截圖了:

 

 

其中我們做開發需要關注的就是上面提到的兩種通信方式了,可以看到是支持IIC和SPI通信方式的,還支持亮度調節,我這里其實最近重新擼了一下驅動,之前也是一直拿來別人寫好的直接用,最近比較想自己動手擼一下,於是也借鑒別人寫的,自己看着數據手冊重新寫了一下,當然過程沒那么順利,我這里是使用IIC通信的,但是由於ESP8266沒有硬件IIC,這刷新效果也是有點感人,其實最重要的也是采用了全局刷新方式,沒有寫局部刷新的驅動,就導致每次修改某一個地方,都會把所有的像素點重新寫一遍~自然這FPS就降下來了,后面再考慮優化吧,但是通過整個過程也是對工作方式有了更深的了解,呃呃呃,又講遠了。

我們再來看一下主要特性:

 

我們再來看一下尺寸,可以說是非常薄了,我們是不可能用手焊接的,一般買也是買別人把芯片跟顯示屏封裝好的模組的:

可以看到厚度只有0.3mm,這里給大家看一下跟屏幕封裝好的模組,這也是前不久做一款STM32 Mini開發板的顯示擴展板剩下的:

 

 

按理說接下來我們應該講一下如何去驅動這款芯片了,但是相比於溫濕度傳感器來說,就有點復雜了,而且也比較難講清楚,不過這里推薦大家看一下杜洋老師對這款芯片的視頻講解,戳看片觀看:

優酷視頻​v.youku.com

分了好幾集,上面卡片是第一集,大家可以看一下,個人認為講的還是比較不錯的。

下面我們來看一下我這擼的驅動代碼的,目前支持IIC通信和中英文顯示,由於手頭沒有SPI接口的屏幕,也沒法測試,所以有機會再更新SPI通信方式的。

  1 /*
  2  * MIT License
  3  *
  4  * Copyright (c) 2018 imliubo
  5  *
  6  * Github  https://github.com/imliubo
  7  * Website https://www.makingfun.xyz
  8  * Zhihu   https://www.zhihu.com/people/MAKINGFUNXYZ
  9  *
 10  * Permission is hereby granted, free of charge, to any person obtaining a copy
 11  * of this software and associated documentation files (the "Software"), to deal
 12  * in the Software without restriction, including without limitation the rights
 13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 14  * copies of the Software, and to permit persons to whom the Software is
 15  * furnished to do so, subject to the following conditions:
 16  *
 17  * The above copyright notice and this permission notice shall be included in all
 18  * copies or substantial portions of the Software.
 19  *
 20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 26  * SOFTWARE.
 27  */
 28 #include "modules/ssd1306.h"
 29 
 30 #if defined(SSD1306_USE_I2C)
 31 int ICACHE_FLASH_ATTR
 32 HAL_I2C_Mem_Write( uint16_t DevAddress, uint16_t MemAddress, uint8_t pData, uint16_t Size )
 33 {
 34     i2c_master_start();
 35     i2c_master_writeByte( DevAddress );
 36     if ( !i2c_master_checkAck() )
 37     {
 38         i2c_master_stop();
 39         return(0);
 40     }
 41 
 42     i2c_master_writeByte( MemAddress );
 43     if ( !i2c_master_checkAck() )
 44     {
 45         i2c_master_stop();
 46         return(0);
 47     }
 48 
 49     i2c_master_writeByte( pData );
 50     if ( !i2c_master_checkAck() )
 51     {
 52         i2c_master_stop();
 53         return(0);
 54     }
 55 
 56     i2c_master_stop();
 57     return(1);
 58 }
 59 
 60 
 61 void ssd1306_Reset( void )
 62 {
 63     /* for I2C - do nothing */
 64 }
 65 
 66 
 67 /* Send a byte to the command register */
 68 void ssd1306_WriteCommand( uint8_t byte )
 69 {
 70     HAL_I2C_Mem_Write( SSD1306_I2C_ADDR, 0x00, byte, 1 );
 71 }
 72 
 73 
 74 /* Send data */
 75 void ssd1306_WriteData( uint8_t buffer, size_t buff_size )
 76 {
 77     HAL_I2C_Mem_Write( SSD1306_I2C_ADDR, 0x40, buffer, buff_size );
 78 }
 79 
 80 #elif defined(SSD1306_USE_SPI)
 81 
 82 #else
 83 #error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro"
 84 #endif
 85 
 86 
 87 /* Screenbuffer */
 88 static uint8_t SSD1306_Buffer[SSD1306_WIDTH * SSD1306_HEIGHT / 8];
 89 
 90 /* Screen object */
 91 static SSD1306_t SSD1306;
 92 
 93 /* Initialize the oled screen */
 94 void ssd1306_Init( void )
 95 {
 96     /* Reset OLED */
 97     ssd1306_Reset();
 98 
 99     /* Wait for the screen to boot */
100     os_delay_us( 60000 );
101     os_delay_us( 40000 );
102 
103 /*     // Init OLED */
104     ssd1306_WriteCommand( 0xAE );   /* display off */
105 
106     ssd1306_WriteCommand( 0x20 );   /* Set Memory Addressing Mode */
107     ssd1306_WriteCommand( 0x10 );   /*
108                                      * 00,Horizontal Addressing Mode; 01,Vertical Addressing Mode;
109                                      * 10,Page Addressing Mode (RESET); 11,Invalid
110                                      */
111 
112     ssd1306_WriteCommand( 0xB0 );   /* Set Page Start Address for Page Addressing Mode,0-7 */
113 
114 #ifdef SSD1306_MIRROR_VERT
115     ssd1306_WriteCommand( 0xC0 );   /* Mirror vertically */
116 #else
117     ssd1306_WriteCommand( 0xC8 );   /* Set COM Output Scan Direction */
118 #endif
119 
120     ssd1306_WriteCommand( 0x00 );   /* ---set low column address */
121     ssd1306_WriteCommand( 0x10 );   /* ---set high column address */
122 
123     ssd1306_WriteCommand( 0x40 );   /* --set start line address - CHECK */
124 
125     ssd1306_WriteCommand( 0x81 );   /* --set contrast control register - CHECK */
126     ssd1306_WriteCommand( 0xFF );
127 
128 #ifdef SSD1306_MIRROR_HORIZ
129     ssd1306_WriteCommand( 0xA0 );   /* Mirror horizontally */
130 #else
131     ssd1306_WriteCommand( 0xA1 );    /*--set segment re-map 0 to 127 - CHECK */
132 #endif
133 
134 #ifdef SSD1306_INVERSE_COLOR
135     ssd1306_WriteCommand( 0xA7 );   /* --set inverse color */
136 #else
137     ssd1306_WriteCommand( 0xA6 );   /* --set normal color */
138 #endif
139 
140     ssd1306_WriteCommand( 0xA8 );   /* --set multiplex ratio(1 to 64) - CHECK */
141     ssd1306_WriteCommand( 0x3F );   /*  */
142 
143     ssd1306_WriteCommand( 0xA4 );   /* 0xa4,Output follows RAM content;0xa5,Output ignores RAM content */
144 
145     ssd1306_WriteCommand( 0xD3 );   /* -set display offset - CHECK */
146     ssd1306_WriteCommand( 0x00 );   /* -not offset */
147 
148     ssd1306_WriteCommand( 0xD5 );   /* --set display clock divide ratio/oscillator frequency */
149     ssd1306_WriteCommand( 0xF0 );   /* --set divide ratio */
150 
151     ssd1306_WriteCommand( 0xD9 );   /* --set pre-charge period */
152     ssd1306_WriteCommand( 0x22 );   /*  */
153 
154     ssd1306_WriteCommand( 0xDA );   /* --set com pins hardware configuration - CHECK */
155     ssd1306_WriteCommand( 0x12 );
156 
157     ssd1306_WriteCommand( 0xDB );   /* --set vcomh */
158     ssd1306_WriteCommand( 0x20 );   /* 0x20,0.77xVcc */
159 
160     ssd1306_WriteCommand( 0x8D );   /* --set DC-DC enable */
161     ssd1306_WriteCommand( 0x14 );   /*  */
162     ssd1306_WriteCommand( 0xAF );   /* --turn on SSD1306 panel */
163 
164 
165     /* Clear screen */
166     ssd1306_Fill( Black );
167 
168     /* Flush buffer to screen */
169     ssd1306_UpdateScreen();
170 
171     /* Set default values for screen object */
172     SSD1306.CurrentX    = 0;
173     SSD1306.CurrentY    = 0;
174 
175     SSD1306.Initialized = 1;
176 }
177 
178 
179 /* Fill the whole screen with the given color */
180 void ssd1306_Fill( SSD1306_COLOR color )
181 {
182     /* Set memory */
183     uint32_t i;
184 
185     for ( i = 0; i < sizeof(SSD1306_Buffer); i++ )
186     {
187         SSD1306_Buffer[i] = (color == Black) ? 0x00 : 0xFF;
188     }
189 }
190 
191 
192 /* Write the screenbuffer with changed to the screen */
193 void ssd1306_UpdateScreen( void )
194 {
195     uint8_t i, j;
196     for ( i = 0; i < 8; i++ )
197     {
198         ssd1306_WriteCommand( 0xB0 + i );
199         ssd1306_WriteCommand( 0x00 );
200         ssd1306_WriteCommand( 0x10 );
201         for ( int j = 0; j < 128; j++ )
202         {
203             /* code */
204             ssd1306_WriteData( SSD1306_Buffer[j + SSD1306_WIDTH * i], SSD1306_WIDTH );
205         }
206     }
207 }
208 
209 
210 /*
211  *    Draw one pixel in the screenbuffer
212  *    X => X Coordinate
213  *    Y => Y Coordinate
214  *    color => Pixel color
215  */
216 void ssd1306_DrawPixel( uint8_t x, uint8_t y, SSD1306_COLOR color )
217 {
218     if ( x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT )
219     {
220         /* Don't write outside the buffer */
221         return;
222     }
223 
224     /* Check if pixel should be inverted */
225     if ( SSD1306.Inverted )
226     {
227         color = (SSD1306_COLOR) !color;
228     }
229 
230     /* Draw in the right color */
231     if ( color == White )
232     {
233         SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8);
234     } else {
235         SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8) );
236     }
237 }
238 
239 
240 /*
241  * Draw 1 char to the screen buffer
242  * ch         => char om weg te schrijven
243  * Font     => Font waarmee we gaan schrijven
244  * color     => Black or White
245  */
246 char ssd1306_WriteChar( char ch, FontDef Font, SSD1306_COLOR color )
247 {
248     uint32_t i, b, j;
249 
250     /* Check remaining space on current line */
251     if ( SSD1306_WIDTH <= (SSD1306.CurrentX + Font.FontWidth) ||
252          SSD1306_HEIGHT <= (SSD1306.CurrentY + Font.FontHeight) )
253     {
254         /* Not enough space on current line */
255         return(0);
256     }
257 
258     /* Use the font to write */
259     for ( i = 0; i < Font.FontHeight; i++ )
260     {
261         os_printf("Font: %d\n",ch);
262         b = Font.data[(ch - 32) * Font.FontHeight + i];
263         for ( j = 0; j < Font.FontWidth; j++ )
264         {
265             if ( (b << j) & 0x8000 )
266             {
267                 ssd1306_DrawPixel( SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color );
268             } else {
269                 ssd1306_DrawPixel( SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) !color );
270             }
271         }
272     }
273 
274     /* The current space is now taken */
275     SSD1306.CurrentX += Font.FontWidth;
276 
277     /* Return written char for validation */
278     return(ch);
279 }
280 
281 /*
282  * Draw 1 Chinese char to the screen buffer
283  * ch         => char 
284  * color     => Black or White
285  */
286 char ssd1306_WriteZhChar( signed char ch[], SSD1306_COLOR color ){
287 
288 
289     uint32_t  b, j, k, data[32];
290 
291     /* Check remaining space on current line */
292     if ( SSD1306_WIDTH <= (SSD1306.CurrentX + 16) ||
293          SSD1306_HEIGHT <= (SSD1306.CurrentY + 16) )
294     {
295         /* Not enough space on current line */
296         return(0);
297     }
298 
299     for (int i = 0; i < 20; ++i)
300     {
301         if ((ZhFont16x16[i].Index[0] == ch[0]) && (ZhFont16x16[i].Index[1] == ch[1]) && (ZhFont16x16[i].Index[2] == ch[2]) )
302         {
303             for (int z = 0; z < ZH_CN_HEIGHT_WIDTH; z++)
304             {
305                 data[z] = ZhFont16x16[i].Msk[z];
306 
307             }
308         }
309     }
310 
311     for ( int i = 0; i < ZH_CN_HEIGHT_WIDTH; i++ )
312     {
313 
314         b = data[i];
315         for ( j = 0; j < ZH_CN_HEIGHT_WIDTH; j++ )
316         {
317             //os_printf("Font: %d\n",Font.FontWidth);
318             if ( (b << j) & 0x8000 )
319             {
320                 ssd1306_DrawPixel( SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color );
321             } else {
322                 ssd1306_DrawPixel( SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) !color );
323             }
324         }
325     }
326 
327     /* The current space is now taken */
328     SSD1306.CurrentX += ZH_CN_HEIGHT_WIDTH;
329 
330     /* Return written char for validation */
331      return(*ch);   
332 }
333 
334 
335 /* Write full string to screenbuffer */
336 char ssd1306_WriteString( char* str, FontDef Font, SSD1306_COLOR color )
337 {
338     /* Write until null-byte */
339     while ( *str )
340     {
341         if ( ssd1306_WriteChar( *str, Font, color ) != *str )
342         {
343             /* Char could not be written */
344             
345             return(*str);
346         }
347 
348         /* Next char */
349         str++;
350     }
351 
352     /* Everything ok */
353     return(*str);
354 }
355 
356 /* Write full Chinese string to screenbuffer */
357 char ssd1306_WriteZhString( signed char *str, SSD1306_COLOR color ){
358 
359     /* Write until null-byte */
360     while ( *str )
361     {
362         ssd1306_WriteZhChar( (signed char *)str, color );
363         /* Next char */
364         str = str + 3;
365 
366     }
367     /* Everything ok */
368     return(*str);
369 
370 }
371 
372 
373 /* Position the cursor */
374 void ssd1306_SetCursor( uint8_t x, uint8_t y )
375 {
376     SSD1306.CurrentX    = x;
377     SSD1306.CurrentY    = y;
378 }

 

為了漢字顯示的和諧統一,目前僅支持16*16點陣的宋體,漢字顯示效果如下:

 

缺點:

  1. 不支持中英文混顯,就是寫中文和英文都有單獨的函數,如果想在一行中顯示中英文就可能需要分開寫。
  2. 刷新速度慢,其實這里也不全是全局刷新的原因,也是ESP8266沒有硬件IIC,只能使用模擬IICd的原因。

最后我們結合一下DHT11和SSD1306做一個桌面溫濕度顯示儀,主要代碼:

 1 uint8 temp,humd;
 2 os_timer_t DHT11_Read_timer;
 3 
 4 void ICACHE_FLASH_ATTR DHT11_Read(void)
 5 {
 6     char temp_buffer[10],humd_buffer[10];
 7     os_timer_disarm(&DHT11_Read_timer);//取消定時器
 8     dh11Read(&temp,&humd);
 9     os_printf("Temp: %d'C Humd: %d%\n",temp,humd);
10     os_sprintf(temp_buffer,":%d'",temp);
11     os_sprintf(humd_buffer,":%d%",humd);
12     ssd1306_SetCursor(0, 40);
13     ssd1306_WriteZhString("溫度",White);
14     ssd1306_SetCursor(30, 44);
15     ssd1306_WriteString(temp_buffer,Font_7x10,White);
16     ssd1306_SetCursor(64, 40);
17     ssd1306_WriteZhString("濕度",White);
18     ssd1306_SetCursor(94, 44);
19     ssd1306_WriteString(humd_buffer,Font_7x10,White);
20     ssd1306_UpdateScreen();
21     os_timer_arm(&DHT11_Read_timer, 5000, true);//使能定時器
22 }
23 
24 void user_init(void)
25 {
26     uart_init(115200, 115200);
27 
28     dh11Init();
29 
30     i2c_master_gpio_init();
31 
32     ssd1306_Init();
33 
34     ssd1306_Fill(Black);
35     ssd1306_SetCursor(8, 0);
36     ssd1306_WriteZhString("神奇物聯網之旅",White);
37     ssd1306_SetCursor(20, 16);
38     ssd1306_WriteString("IAMLIUBO",Font_11x18,White);
39     ssd1306_UpdateScreen();
40 
41     os_timer_disarm(&DHT11_Read_timer);//取消定時器
42     os_timer_setfn(&DHT11_Read_timer, (os_timer_func_t *) DHT11_Read,NULL);//定時回調函數
43     os_timer_arm(&DHT11_Read_timer, 5000, true);//使能定時器,設置時間為1s
44 
45 }

 

我們直接看一下效果:

 

最后附上我的Github倉庫,一些小的Demo沒有寫相應的文章,但是不斷更新,建議大家Star或者watch一下,以便及時獲得新的例程~

imliubo/makingfunxyz-esp8266​github.com

歡迎大家去我的倉庫點個star,有問題或者Bug可以提交issues,我看到后會第一時間回復,如果您對我的代碼有改進意見,也歡迎fork后提交PR,我會及時采納大家的意見。

夜深了,晚安。

QQ交流群:592587184


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM