C语言实现双字节在数组中按比特位移动

        先说一下应用场合,在LED点阵显示屏中,为了节省flash空间,常用一个bit位来标记哪个灯是否点亮。为了做出比较炫的效果,比如16 * 16像素gif动画边边移动边跳跃。就应用到该思想。

        双字节是16bit位,数组的bit位是数组长度乘以8(类型指的是uint8_t),比如uint8_t a[5]长度则是5 * 8 = 40。该函数的思想就是这双字节的16bit位在在数组a[5]中40bit位中移动。当然16bit位在数组中可以移出部分或者移出全部bit位。如下图所示三个中情况。



        代码如下所示:

#include <stdio.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;

#define VALID_LENGTH	16	//双字节中的有效长度					

/********************************************************************************
p:数组指针
n:数组的有效长度
c:需要移动的双字节
matrixStartPos:游标需要在数组的中bit位中的起始位置,比如26,则相当于起始位置指向
数组下标为3 = 26 / 8,bit为5 = 7 - 26 % 8的那个地方。
doubleByteStartPos:指向双字节的bit位置范围为(0~15),该变量后面会移动
width:从双字节中doubleByteStartPos起始位置开始,截取的bit位的个数
********************************************************************************/
void DoubleByteShiftInMatrix(uint8_t *p, uint8_t n, uint16_t c, uint16_t matrixStartPos, uint8_t doubleByteStartPos, uint8_t width)
{
	uint16_t matrix[] = {0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
						 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff};
	uint8_t startBytePos = matrixStartPos / 8;		//需要覆盖的首字节
	uint8_t remainBits	= 8 - matrixStartPos % 8;	//指需要覆盖的首字节中剩余多少bit位可以被覆盖
	uint8_t count = 0;								//计算当前已经覆盖了多少bit位
	while (count < width)							//当已经覆盖的bit位小于字节的宽度,覆盖仍需继续
	{
		if (remainBits >= width - count)			//当前字节剩余的bit位个数大于等于剩余需要覆盖的bit个数时,标志着覆盖进入尾声
		{
			p[startBytePos] &= ~(matrix[width - count -1 ] << (remainBits + count - width));//覆盖之前把当前的相对应bit位清零,下一行则表示对相对应的bit进行填充				 
			p[startBytePos] |=  (((c >> (VALID_LENGTH - doubleByteStartPos - width + count)) & matrix[width - count - 1]) << (remainBits + count - width));
			count = width;							//这个地方其本质的函数是count = count + (width - count);所以可以简化成了这样,也可以用break
		}
		else
		{
			p[startBytePos] &= ~matrix[remainBits - 1];	//覆盖之前把相对应的bit位清零,下一行则是从双字节的“起始位置”截图remainBits长度填充当前数组剩余的remainBits位
			p[startBytePos] |= ((c >> (VALID_LENGTH - doubleByteStartPos - remainBits)) & matrix[remainBits - 1]);
			count += remainBits;						//当前回合已经填充了remainBits的长度,进行统计
			doubleByteStartPos += remainBits;			//填充了remainBits长度后,双字节的起始位置也进行往后移动
			startBytePos++;								//填充完了一个字节,准备填充下一个字节
			remainBits = 8;								//新字节剩余填充位置为8
		}
	}
}

int main()
{
	uint8_t p[] = {0x00, 0x00, 0x00, 0x00, 0x00};
	int i = 0;
	DoubleByteShiftInMatrix(p, 5, 0xffff, 38, 14, 2);
	for (; i<5; i++)
	{
		printf("%d=%02x\r\n", i, p[i]);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值