Robofun 機器人論壇

標題: DS3231(IIC)+OLED12864(IIC) 串接的問題 [打印本頁]

作者: KaoChin    時間: 2015-11-28 12:12
標題: DS3231(IIC)+OLED12864(IIC) 串接的問題
本帖最後由 KaoChin 於 2015-11-28 12:18 編輯

我想做一個簡單的實驗
只是把及時時鐘(RTC) DS3231 的數據,傳到 OLED12864 做成一個時鐘
藉此瞭解串接兩個 IIC 的程式技巧
板子為 MEGA 2560
OLED12664 使用的函數庫是 Adafruit_ssd1306syp

當然,遇到了一些問題,讀取RTC的動作,造成 OLED 無法繼續正常工作我想大致上的原因在於 記憶體位置的讀寫
所以我寫了一個程式用來 debug

程式規劃如下
int i;
loop 每一週期 i 就會增加 1
每個週期都會在 OLED 與 serial monitor 輸出 ith

並且在 i >5 時 開始讀取 RTC
並在 OLED 與 serial monitor 輸出 "ith"

程式如下
(只呈現 loop 的部分)

  1. void loop()
  2. {
  3.   i=i+1;

  4.   display.update();
  5.   Serial.print("i=");Serial.println(i);
  6.   //delay(1000);
  7.   display.clear();
  8.   display.setTextSize(2);
  9.   display.setTextColor(WHITE);
  10.   display.setCursor(0,0);
  11.   display.print(i, DEC);display.println("th");
  12.   if (i>255) i=0;
  13.   delay(100);
  14.   if (i>5){
  15.      Wire.beginTransmission(DS3231_I2C_ADDRESS);
  16.      Wire.write(0x01);
  17. //A  Wire.requestFrom(DS3231_I2C_ADDRESS, 1);
  18. //B  minute=Clock.getMinute();
  19. //C  Wire.endTransmission();
  20.      display.println();
  21.      display.println("WIRE test");
  22.      Serial.println("WIRE  test");
  23.   }
  24. }
複製代碼




其中
  1. Wire.beginTransmission(DS3231_I2C_ADDRESS);
  2. Wire.write(0x01);
  3. //A Wire.requestFrom(DS3231_I2C_ADDRESS, 1);
  4. //B minute=Clock.getMinute();
  5. //C Wire.endTransmission();
複製代碼

是讀取 RTC 的程式

執行結果1.
如果 A B C 三行程式,其中的一行"沒有"被 comment
那麼,OLED 的輸出在 i>5 之後將會停止
而 serial monitor 會一直輸出 ,i 會大於 5 一直繼續加上去,而 "WIRE test"這行字也會一直出現在 serial monitor2.
如果 A B C 三行程式,其中的一""被 comment
那麼,OLED 與 serial monitor 會一起一樣的正常輸出


換句話說,讀取RTC的動作,造成 OLED 無法繼續正常工作

曾經試著在 if 的 loop
1.關掉 iic 再 打開 iic 可是沒用
2.做 display.initialize(); (OLED 的初始化,他會重置相關記憶體,程式在最後) 也沒用

所以我在想,是不是讀取記憶體的指標位置變了,使得 OLED 無法運作
請問有人有經驗,方法,或建議 解決這個問題嗎?
感謝您的回覆

以下為display.initialize() 程式碼 (當然有宣告display 為 Adafruit_ssd1306syp 類別 )


  1. ool Adafruit_ssd1306syp::initialize()
  2. {
  3.         //setup the pin mode
  4.         pinMode(m_sda,OUTPUT);
  5.         pinMode(m_scl,OUTPUT);

  6.         //malloc the framebuffer.
  7.         //malloc(記憶體大小)
  8.         //m_pFramebuffer = (unsigned char*)malloc(SSD1306_FBSIZE);
  9.         //將 malloc(SSD1306_FBSIZE) 轉成 unsigned char "指標" 放在 m_pFramebuffer
  10.         m_pFramebuffer = (unsigned char*)malloc(SSD1306_FBSIZE);
  11.         if(m_pFramebuffer == 0){
  12.                 return false;
  13.         }
  14.         //void *memset(void *s, int c, size_t n);

  15.    //memset 設定位元組中的位元值,
  16.         //設定的方式從s 開始將n 個位元組設定成為c 的位元值並回傳s,
  17.    //開始將n 個位元組設定成為c 的位元值並回傳s,經常運用的範圍是在將位元組的位元值清為0。
  18.         memset(m_pFramebuffer,0,SSD1306_FBSIZE);//clear it.

  19.         //write command to the screen registers.
  20.         writeCommand(SSD1306_CMD_DISPLAY_OFF);//display off
  21.         writeCommand(0x00);//Set Memory Addressing Mode
  22.         writeCommand(0x10);//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
  23.         writeCommand(0x40);//Set Page Start Address for Page Addressing Mode,0-7
  24.         writeCommand(0xB0);//Set COM Output Scan Direction
  25.         writeCommand(0x81);//---set low column address
  26.         writeCommand(0xCF);//---set high column address
  27.         writeCommand(0xA1);//--set start line address
  28.         writeCommand(0xA6);//--set contrast control register
  29.         writeCommand(0xA8);
  30.         writeCommand(0x3F);//--set segment re-map 0 to 127
  31.         writeCommand(0xC8);//--set normal display
  32.         writeCommand(0xD3);//--set multiplex ratio(1 to 64)
  33.         writeCommand(0x00);//
  34.         writeCommand(0xD5);//0xa4,Output follows RAM content;0xa5,Output ignores RAM content
  35.         writeCommand(0x80);//-set display offset
  36.         writeCommand(0xD9);//-not offset
  37.         writeCommand(0xF1);//--set display clock divide ratio/oscillator frequency
  38.         writeCommand(0xDA);//--set divide ratio
  39.         writeCommand(0x12);//--set pre-charge period
  40.         writeCommand(0xDB);//
  41.         writeCommand(0x40);//--set com pins hardware configuration
  42.         writeCommand(0x8D);//--set vcomh
  43.         writeCommand(0x14);//0x20,0.77xVcc
  44.         writeCommand(0xAF);//--set DC-DC enable
  45.         writeCommand(SSD1306_CMD_DISPLAY_ON);//--turn on oled panel

  46.         delay(10);//wait for the screen loaded.
  47.         return true;
複製代碼

作者: 超新手    時間: 2015-11-29 06:35
沒看到 Clock.getMinute(); 是怎麼寫的
不過, 先改成這看看
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0x01);
Wire.endTransmission(); // 移到這邊
Wire.requestFrom(DS3231_I2C_ADDRESS, 1);
minute=Clock.getMinute();
也就是把 ABC 變成 CAB
作者: KaoChin    時間: 2015-11-29 09:50
感謝樓上的建議

今天早上想了一下,還有一個可能的原因是
一開始先讓 OLED 跑, RTC 不跑
系統只有一個 IIC device 動作(RTC 可以視為不存在)。。。板子內建的上拉電位夠力
但是,RTC 加入後,系統變成兩個 device
由於 OLED 串接於 RTC 之後,OLED 上拉電位不夠
所以,OLED 就無法動作了

等下去買兩個 10K Ohm 電阻來試試!
作者: KaoChin    時間: 2015-11-30 10:25
筆記一下,以上的方法都沒用 @@
作者: 超新手    時間: 2015-11-30 10:46
本帖最後由 超新手 於 2015-11-30 10:53 編輯

請問一下
如果改成 CAB 的執行結果會怎樣?也是不會一直執行嗎?

因為你沒把 Clock.getMinute(); 內容 PO 出來
它應該是類似
while(Wire.available()) {
Wire.read();
.....
}
作者: KaoChin    時間: 2015-12-1 13:43
請問一下
如果改成 CAB 的執行結果會怎樣?也是不會一直執行嗎?

因為你沒把 Clock.getMinute(); 內容 PO ...
超新手 發表於 2015-11-30 10:46


不能執行事實上
ABC 只要存在任何一條,就無法執行
Clock.getMinute() 內容沒有關係
作者: 超新手    時間: 2015-12-1 13:54
我是說, 我程式順序改成 CAB
你可以看一下 Wire 範例 SFRRanger_reader
其實程式應該要寫成
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0x01);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 1);
.........
Wire.available())   
reading = Wire.read();
作者: KaoChin    時間: 2015-12-2 10:01
改過了,都沒用,就算只有以下三行(依順序,我一開始就是這樣寫的,後來才換順序看看),也是不能跑
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0x01);
Wire.endTransmission();
作者: 超新手    時間: 2015-12-2 12:30
剛剛查了Adafruit_ssd1306syp的 library
如果你也是同一個libray的話
https://github.com/Miyeah/Arduin ... Adafruit_ssd1306syp
它是用 i/o 去模擬 i2c,
但是 Wire 是用 ic 本身硬體的 i2c
切來切去會不正常, 應該不算反常...




歡迎光臨 Robofun 機器人論壇 (https://robofun.net/forum/) Powered by Discuz! X3.2