1

我正在做一个涉及 Arduino Mega (2560) 和 Waveshare ePaper 显示器的小项目(或者我认为是这样)。

我已经让它与库(epd7in5)一起正常工作,并且我已经将两个图像添加到PROGMEM. 但是,一旦我添加了第三张图像(因此在 中添加了第三个条目PROGMEM),ePaper 屏幕就不再启动了。在库中添加一些调试表明代码卡在特定的SPI.transfer().

编辑:理论 当闪存中有太多数据时,SPI 是否可能不兼容?我读过它,64kb 是最大值。我在两张图片上略高于这一点,但在三张图片上则明显高于这一点。这可能会破坏SPI吗?如果是这样:我可以修复它吗?

我添加了下面的代码和库中SPI.transfer()失败的特定部分。

主文件

删除与 dummy3 相关的代码可确保 dummy3 数组无法编译。仅使用 dummy1 和 dummy2 一切正常。添加 dummy3 并且程序卡在epd.Init().

#include <SPI.h>
#include <epd7in5.h>
#include "imagedata.h"

Epd epd;

void debug(String);

void setup() {
  Serial.begin(9600);
  debug("Serial begin");

  if (epd.Init() != 0) {
    debug("INIT FAILED!");
    return;
  }

  debug("Changing image");
  epd.DisplayFrame(dummy1);  //DisplayFrame by default includes WaitUntilIdle.
  debug("dummy1 on ePaper");
  delay(1000);
  debug("Changing image");
  epd.DisplayFrame(dummy2);
  debug("dummy2 on ePaper");
  delay(1000);
  debug("Changing image");
  epd.DisplayFrame(dummy3);
  debug("dummy2 on ePaper");
  epd.SendCommand(POWER_OFF); 
  debug("POWER_OFF");
}

void loop() {
}

void debug(String message) {
  Serial.print(millis());
  Serial.print("\t");
  Serial.println(message);
}

图像数据.cpp

我已经删除了实际的图像数据,因为它很多。两个图像产生的总闪存为 67326 字节(约占 2560 总闪存的 26%)。三个图像的总闪存为 98052 字节(约占 2560 总闪存的 38%)。头文件只包含声明。

#include "imagedata.h"
#include <avr/pgmspace.h>

const unsigned char dummy1[30726] PROGMEM = {...data...};
const unsigned char dummy2[30726] PROGMEM = {...data...};
const unsigned char dummy3[30726] PROGMEM = {...data...};

epd7in5.cpp

我已经添加了调试功能。SendData 也包括在内并使用调试。

void Epd::debug(String message) {
  Serial.print(millis());
  Serial.print("\t");
  Serial.print("EPD");
  Serial.print("\t");
  Serial.println(message);
}

int Epd::Init(void) {
  if (IfInit() != 0) {
    return -1;
  }

  debug("Resetting");
  Reset();

  debug("SendCommand(POWER_SETTING);");
  SendCommand(POWER_SETTING);
  debug("SendData(0x37);");
  SendData(0x37);
  debug("SendData(0x00);");
  SendData(0x00);

  debug("SendCommand(PANEL_SETTING);");
  SendCommand(PANEL_SETTING);
  SendData(0xCF);
  SendData(0x08);

  SendCommand(BOOSTER_SOFT_START);
  SendData(0xc7);
  SendData(0xcc);
  SendData(0x28);

  SendCommand(POWER_ON);
  WaitUntilIdle();

  SendCommand(PLL_CONTROL);
  SendData(0x3c);

  SendCommand(TEMPERATURE_CALIBRATION);
  SendData(0x00);

  SendCommand(VCOM_AND_DATA_INTERVAL_SETTING);
  SendData(0x77);

  SendCommand(TCON_SETTING);
  SendData(0x22);

  SendCommand(TCON_RESOLUTION);
  SendData(0x02);  //source 640
  SendData(0x80);
  SendData(0x01);  //gate 384
  SendData(0x80);

  SendCommand(VCM_DC_SETTING);
  SendData(0x1E);  //decide by LUT file

  SendCommand(0xe5);  //FLASH MODE
  SendData(0x03);

  return 0;
}

void Epd::SendData(unsigned char data) {
  debug("DigitalWrite(dc_pin, HIGH);");
  DigitalWrite(dc_pin, HIGH);
  debug("SpiTransfer(data);");
  SpiTransfer(data);
}

epdif.cpp

这是不继续的 SPI 传输部分。

void EpdIf::SpiTransfer(unsigned char data) {
    digitalWrite(CS_PIN, LOW);
    SPI.transfer(data);
    digitalWrite(CS_PIN, HIGH);
}

该项目的串口打印如下...

0   Serial begin
0   EPD Resetting
400 EPD SendCommand(POWER_SETTING);
400 EPD SendData(0x37);
400 EPD DigitalWrite(dc_pin, HIGH);
435 EPD SpiTransfer(data);

因此,一旦它运行SpiTransfer,代码就会停止工作。似乎它处于无限循环中,SPI.transfer();但我不知道这将如何发生。我看不出怎么PROGMEM会干扰传输,我还有足够的闪存...

有什么办法可以解决这个问题?我需要更改 SPI 中的问题吗?还是我需要以不同的方式存储我的数据PROGMEM?我有点不知所措。

提前感谢您的帮助,非常感谢。

4

1 回答 1

0

您的问题不在于 SPI(本身)。

它与您在程序中拥有的数据量和读取数据量有关。如果您使用超过 64k 的 Progmem,您会遇到 2 组不同的问题:

  1. 以可靠的方式读取数据

阅读程序应该pgm_read_xxx_far对 65536 之后的任何地址使用宏。Epd::DisplayFrame使用 pgm_read_byte(&frame_buffer[i]);所以你在库级别上有问题。我不熟悉这个库,所以我不确定是否有一个替代函数可以调用,并在从 PROGMEM 中读取它之后自己提供缓冲区 pgm_read_byte_far。这是问题的简单部分

  1. 首先将所述数据输入 PROGMEM

Arduino 内核和 avr 编译器本身假设所有指针都只有 16 位。将数据放入 PROGMEM 使其出现在运行程序的最终可执行文件中的 arduino 核心和可执行代码之前。

正确执行此操作的可靠方法是使用自定义链接器脚本,它将让您的数据不碍事,并将其放在所有可执行代码之后。这将很难,恐怕我无法提供有关如何实现这一目标的任何信息。

或者,您可以尝试使用 _attribute__((section(".fini2")))来使用该.fini2部分。有些人以前做过,而且对他们有用。

你会这样使用它:

const unsigned char __attribute__((section(".fini2"))) dummy1[30726] = {...data...};

最后一种选择是根本不使用PROGMEM,并拥有某种用于数据的外部存储(例如一些SDCard)。这很可能是解决该问题的最简单方法。

资料来源:这个优秀的帖子和westfw在 arduino 论坛上的精彩见解: https ://forum.arduino.cc/index.php?topic=485507.0

于 2020-01-09T17:31:23.367 回答