从for循环中的字节中提取半字节

时间:2014-04-17 11:03:37

标签: c for-loop embedded pic32 nibble

我遇到了一些DMA中断处理程序的问题我已经适应了MicroChip PIC32嵌入式芯片上的LCD显示器。

我的内存有限,需要为我的彩色LCD提供帧缓冲。决定使用16种颜色并使用每个像素的半字节。我创建了一个如下所示的数组:

unsigned char GraphicsFrame[FRAME_HEIGHT][LINE_LENGTH/2]; 

在我的中断处理程序中,我将4位半字节转换为16位值,通过并行端口和DMA传输发送到LCD。我在中断处理程序中使用一个查找表来实现这一点但是在调试时我会进入General_Exception_Handler并且它指向一个问题,就像我提取4位半字节并将其转换为16位值一样:

for( i=0,j=0; i<30; i++, lineX++ )
{
    // not particularly elegant, perhaps look at a better way
    if     ((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x0) lineBuffer[j++] = (unsigned short int)RGBBlack;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x1) lineBuffer[j++] = (unsigned short int)RGBBlue;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x2) lineBuffer[j++] = (unsigned short int)RGBRed;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x3) lineBuffer[j++] = (unsigned short int)RGBGreen;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x4) lineBuffer[j++] = (unsigned short int)RGBCyan;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x6) lineBuffer[j++] = (unsigned short int)RGBYellow;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x7) lineBuffer[j++] = (unsigned short int)RGBKaneGreen;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0xF) lineBuffer[j++] = (unsigned short int)RGBWhite;

    if     ((GraphicsFrame[line][i] & 0x0F) == 0x0) lineBuffer[j++] = (unsigned short int)RGBBlack;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x1) lineBuffer[j++] = (unsigned short int)RGBBlue;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x2) lineBuffer[j++] = (unsigned short int)RGBRed;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x3) lineBuffer[j++] = (unsigned short int)RGBGreen;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x4) lineBuffer[j++] = (unsigned short int)RGBCyan;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x5) lineBuffer[j++] = (unsigned short int)RGBMagenta;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x6) lineBuffer[j++] = (unsigned short int)RGBYellow;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x7) lineBuffer[j++] = (unsigned short int)RGBKaneGreen;
    else if((GraphicsFrame[line][i] & 0x0F) == 0xF) lineBuffer[j++] = (unsigned short int)RGBWhite;
}

我正在尝试将DMA设置为使用另一个包含60个像素的数组一次传输60个像素(60 x 16位):

unsigned short int lineBuffer[60];

任何人都可以通过我提取半字节并转换它的方式发现问题吗?没有任何警告或错误,所以没有任何东西在跳出来!

感谢任何帮助,谢谢

1 个答案:

答案 0 :(得分:1)

就我发布的内容而言,它看起来还不错。唯一可疑的是linelineX变量。似乎没有使用它们。此外,如果您想迭代2D数组的第一维,您可能必须使用嵌套for循环。

帖子的其余部分是代码审核,而不是答案:

发布的代码不是查找表。考虑这样做:

const uint16_t COLOR_TABLE [COLORS_N] = 
{
  RGBBlack,      // 0x0
  RGBBlue,       // 0x1
  RGBRed,        // 0x2
  RGBGreen,      // 0x3
  RGBCyan,       // 0x4
  undefined,     // 0x5
  RGBYellow,     // 0x6
  RGBKaneGreen,  // 0x7
  undefined,     // 0x8
  undefined,     // 0x9
  undefined,     // 0xA
  undefined,     // 0xB
  undefined,     // 0xC
  undefined,     // 0xD
  undefined,     // 0xE
  RGBWhite,      // 0xF
};

...

uint8_t line_iterator=0;

for(uint8_t i=0; i<LINE_LENGTH/2; i++)
{
  uint8_t nibble;

  nibble = (uint8_t) ((GraphicsFrame[line][i]) >> 4) & 0x0F);
  lineBuffer[line_iterator] =  COLOR_TABLE[nibble];

  nibble = (uint8_t) (GraphicsFrame[line][i] & 0x0F);
  lineBuffer[line_iterator + 1] =  COLOR_TABLE[nibble];

  line_iterator += 2;
}

对上述评论:

  • 此查找表将显着提高可读性和程序速度。如果这是一个ISR,你肯定必须使用这样的表。
  • 由于它是嵌入式系统,因此应使用stdint.h中的整数类型。
  • 谨防隐式整数促销。
  • 保持for循环简单,避免混淆。如果需要多个迭代器,请使用自解释变量名称。
  • 请勿使用像30这样的“幻数”。