日常Debug之:大小端引发的显示问题,以及避免摧残灵魂的方法。

一、环境:

IAR8.30、AT32F403Avet7、ST7735S(128*160 4线硬件SPI, RGB565)

二、现象:

单片机上电后,HSI低速配置ST7735S,刷屏正常,颜色正常,但是只有4帧。

然后配置时钟HSE到240MHZ,目测达到一二直帧往上,但是颜色显示不正常,如下:

0XF800(本应显示RED确显示BLUE)猜测可能是设置成BGR模式了。

那么将错就错 0x001F 本应显示RED,却显示成了GREEN。这就其怪了。

将颜色设置为0x07e0,应该是RGB中的一个吧,前面显示了B、G,这回该显示RED了吧,可是显示出了紫色。尼马?!!!

写成表格如下

数值与问题颜色
数值 0xf800 0x07e0 0x001f
颜色 蓝   绿

看来问题不是简单的RGB设置问题。

三、问题排查:

我又反复检查了一遍ST7735S的配置:

 ST7735_WriteCommand(ST7735_COLMOD);//0x3A
  ST7735_DELAY(1);
  ST7735_WriteData(0x55);

日常Debug之:大小端引发的显示问题,以及避免摧残灵魂的方法。_第1张图片

ST7735_WriteCommand(ST7735_MADCTL);

ST7735_WriteData(0xa0);

日常Debug之:大小端引发的显示问题,以及避免摧残灵魂的方法。_第2张图片

设置没有问题。

检查操作步骤,发现出现:

1、上电后先刷屏,刷不同的颜色。

2、全屏显示图片。

而步骤1使用的函数是:

void ST7735_DrawRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color)
{
  ST7735_SetAddressWindow(x, y, x + width - 1, y + height - 1);
  ST7735_WriteCommand(ST7735_RAMWR);
  ST7735_DELAY(1);
  // Write the color data
  for (uint16_t i = 0; i < width * height; i++)
  {
    ST7735_WriteData(color>>8);
    ST7735_WriteData(color&0xff);
  }
}

而步骤2使用的函数是:

void ST7735_DrawImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *image)
{
  ST7735_SetAddressWindow(x, y, x + width - 1, y + height - 1);

  ST7735_WriteCommand(ST7735_RAMWR);
  for (uint32_t i = 0; i < width * height; i++)
  {

    ST7735_WriteData(image[i * 2]);
    ST7735_WriteData(image[i * 2 + 1]);
  }
}

那么对比可知,是大小端的问题。

由于颜色是uint16_t类型,占用2个字节。假设地址从0x0000开始,到0x0001结束。颜色值为0x8001。

相像中的排列为(大端):

地址 0x0000 0x0001
内容 0x80 0x01

实际上(小端):

地址 0x0000 0x0001
内容 0x01 0x80

可以看到步骤2使用的函数取值使用:

ST7735_WriteData(image[i * 2]);
ST7735_WriteData(image[i * 2 + 1]);

先取0x0000 再取 0x0001。

所以回归到最开始的现像:

数值 0xf800 0x07e0 0x001f
颜色 蓝   绿

实际为:

       

数值 0x00f8 0xe007 0x1f00
颜色 蓝   绿

所以破案了。

四、避坑,一个好的方法:

颜色值不是两个字节吗,可以一次读入到一个变量uint16中再通过>> 、&运算,避免大小端。

你可能感兴趣的:(日常BUG,单片机,DEBUG,ST7735S,显示器)