星光召集令星允派F103测评·

星允派 F103第三回:人生无常大肠包小肠——死磕OLED

aramy

aramy

127 3

上回书搞定了串口,这次来尝试在Vscode+platformIO 里 Arduino 的开发环境下点亮OLED屏幕。


-硬件:这是一块0.96寸的OLED屏幕,有接排针,使用了4针,丝印标识了VCC、GND、SCL、SDA。所以是一块通过I2C通讯接口的oled屏幕。文档中没看见oled使用的是什么驱动,请教群里的老师得知,这是一块使用SSD1306驱动的128X64的单色oled屏幕。星允派 F103板子上预留了排母插座,看丝印是接到PB3、PB5的。

-扫描I2C接口:既然接口是I2C接口,按习惯,先扫描一下I2C接口上的硬件,看看是否能正常识别到硬件。 `

#include <Arduino.h>
#include <Wire.h>
#define PIN_SERIAL1_RX PA10
#define PIN_SERIAL1_TX PA9
HardwareSerial Serial1(USART1);

void setup()
{
  Wire.begin();
  pinMode(PIN_SERIAL1_RX, INPUT);
  pinMode(PIN_SERIAL1_TX, OUTPUT);
  Serial1.begin(115200);
  Serial1.setRx(PIN_SERIAL1_RX);
  Serial1.setTx(PIN_SERIAL1_TX);
}

void loop()
{
  int nDevices = 0;
  Serial1.println("Scanning...");
  for (byte address = 1; address < 127; ++address)
  {
    Wire.beginTransmission(address);
    byte error = Wire.endTransmission();

    if (error == 0)
    {
      Serial1.print("I2C device found at address 0x");
      if (address < 16)
      {
        Serial.print("0");
      }
      Serial1.print(address, HEX);
      Serial1.println("  !");
      ++nDevices;
    }
    else if (error == 4)
    {
      Serial1.print("Unknown error at address 0x");
      if (address < 16)
      {
        Serial1.print("0");
      }
      Serial1.println(address, HEX);
    }
  }
  if (nDevices == 0)
  {
    Serial1.println("No I2C devices found\n");
  }
  else
  {
    Serial1.println("done\n");
  }
  delay(5000); // Wait 5 seconds for next scan
}

这里找到一个“0x50”的I2C的硬件设备,但是这个明显不是OLED屏幕,因为SSD1306的OLED屏幕,地址应该是"0X78"。在代码中按图索骥,默认的I2C接口是PB6、PB7。查看电路图,发现这里接了个AT24C02的存储芯片。这里有点疑惑,I2C总线是可以接多个设备的,这里为啥不把OLED接到PB6、PB7上去。 尝试直接修改代码中的I2C初始化的语句,将初始化时管脚映射到PB3、PB5上去。但结果是不行的,无法找到对应的oled设备,STM32不支持管脚的随意映射。 Wire.begin(PB5,PB3);

-使用U8G2的模拟I2C:既然oled的管脚没有接到stm32硬件I2C的管脚上,没关系,还可以使用软件模拟I2C方式。这里想用U8G2的库来驱动OLED屏幕,U8G2自身就有模拟I2C的支持。 `

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>

// iic驱动方式
// U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/PB3, /* data=*/PB5, /* reset=*/U8X8_PIN_NONE);  // 使用软件IIC,SCL PB3,SDA PB5
    void
    setup(void)
{
  Serial.begin(115200);
  u8g2.begin();
  u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
}
void loop(void)
{
  u8g2.setFont(u8g2_font_unifont_t_chinese2); // use chinese2
  u8g2.firstPage();
  do
  {
    u8g2.setCursor(0, 20);
    u8g2.print("helloworld 356"); // Chinese "Hello World"
    u8g2.setCursor(40, 40);
    u8g2.print("大千世界!"); // Chinese "Hello World"
  } while (u8g2.nextPage());
  delay(1000);
}

写了个简单的驱动OLED屏幕的例子,编译烧写,屏幕没反应!这让我很诧异,反复检查代码,代码没有问题。检查硬件连接,硬件连接正常。一度怀疑模块故障了。于是将同样的代码,烧录到另外一块 nucleo_f411re的开发板上,屏幕点亮。使用的相同的代码,相同的管脚,相同的屏幕硬件。唯一不同的就是开发板的不同。 在群里经过各位老师的指点,感觉应该是platformIO 的锅。只能感慨人生无常大肠包小肠。

-死磕到底:这里还是蛮疑惑的,其实单独控制PB3、PB5管脚的高低电平是没有任何问题的。就是不知道platformIO 是在哪个环节拉跨的。手头没有逻辑分析仪,否则看看是否有I2C信号能进一步确认问题的症结。不过既然控制管脚的高低电平没有问题,那么模拟I2C本身就是通过控制高低电平来模拟I2C的通讯协议的,所以手搓管脚的高低电平,用来模拟I2C的通讯,来驱动OLED应该也是可行的。网上找了一下软件模拟I2C的代码。 最终还是驱动起来了OLED,但是这样的软件模拟I2C就不知道如何和U8G2库相结合了,U8G2库里诸如显示汉字等方便的特性就无法实现了。最后将工程附上,看看哪位老师能解决platformIO的这个问题。 hello2.zip

相关文章

优先推荐同专题、同标签和同作者内容,补足热门文章。

评论 3

登录 后参与评论

评论 3

Hugh
Hugh5月18日 22:15

下一个版本吧I2C引过来👍

Hugh
Hugh 回复 @Hugh5月18日 22:54

下一个版本:OLED,AT24C02,触摸屏触摸接口均使用I2C1。mark😁

aramy
aramy 回复 @Hugh5月19日 08:56

如果可以,串口也给多个选择,用跳线帽方式选择一下 串口1 或串口2