讨论一下字节倒序的最快算法??
诸位.我想实现一个字节的倒序,例如11001100---->00110011.使用C语言实现
uint8 B2B(uint8xx)
{
uint8 yy=0;
yy=((xx<<7)&0x80)|((xx<<5)&0x40)|((xx<<3)&0x20)|((xx<<1)&0x10)|((xx>>7)&0x01)|((xx>>5)&0x02)|((xx>>3)&0x04)|((xx>>1)&0x08);
return yy;
}
似乎很繁琐,那位有更好的办法,实现最快的变换速度! 最新的cortex内核支持一条汇编指令直接完成倒序。1个还是2个时钟周期,最快了。avr的话用几条汇编也应该比c的快点吧!个人陋解。 哦.基于目前的情况,使用C51的思路,有无更快的办法,讨教 查表 楼主贴出来的代码感觉编译出来代码量会比较大,用循环应该好点。至于速度那种快用编译后软件仿真一下就知道了。
uint8_t B2B(uint8_txx)
{
uint8_t yy = 0;
uint8_t i = 1;
do
{
if ((xx & i) > 0)
{
yy++;
}
yy = yy << 1;
i = i << 1;
}
while (i != 0);
return yy;
} 看看这个
sbit A_0=ACC^0;//方便位操作
sbit A_1=ACC^1;
sbit A_2=ACC^2;
sbit A_3=ACC^3;
sbit A_4=ACC^4;
sbit A_5=ACC^5;
sbit A_6=ACC^6;
sbit A_7=ACC^7;
sbit B_0=B^0;//方便位操作
sbit B_1=B^1;
sbit B_2=B^2;
sbit B_3=B^3;
sbit B_4=B^4;
sbit B_5=B^5;
sbit B_6=B^6;
sbit B_7=B^7;
unsigned char SetData(unsigned char DataByte)
{
ACC=DataByte;
B_0=A_7;
B_1=A_6;
B_2=A_5;
B_3=A_4;
B_4=A_3;
B_5=A_2;
B_6=A_1;
B_7=A_0;
return B;
}
基于51的 查表,一条语句解决 return tab;
缺点:表需要占用256个字节的空间 试验证明使用ilcvm的方法速度上要慢于我所用的办法.
查表是最快的le ,好办法,也可行. 位操作暂不考虑 xx=~xx;
或
xx=xx^0xff; 论速度的话,应该不会有比查表更快的了 假设x为 0b00001011
x = ((x & 0x55) << 1) | ((x & 0xaa) >> 1);
x = ((x & 0x33) << 2) | ((x & 0xcc) >> 2);
x = ((x & 0x0f) << 4) | ((x & 0xf0) >> 4);
x = x >> 4;
这时x为00001101,就这样用位运算速度很快。 查表的话可以分两半来查,兼顾速度和空间。 使用查表已经满足要求,多谢大家. admvip 的算法不正确 对于这个问题,我集中归纳了一下,放在我的博客上,请大家浏览. 既然追求速度,如果用查表法就类似
uint8 B2B3(uint8xx)
{
returnzjdx;
}
这样的函数的,用inline或宏才能更快,调用函数开销太大。
#define B2B3(v) zjdx
实测在12MHz,标准51下,调用一次5楼的位函数用时29us,调用B2B3函数用时19us,使用B2B3宏用时5us 。 《高效程序的奥秘》("Hacker's Delight", [美] Henry S. Warren, Jr. 著)第7章上面有讲这个内容。 7楼写得是一个4位翻转的算法,类推一下就能得到8位的
x = ((x & 0x55) << 1) | ((x & 0xaa) >> 1);
x = ((x & 0x33) << 2) | ((x & 0xcc) >> 2);
x = ((x & 0x0f) << 4) | ((x & 0xf0) >> 4);
这就是1字节位翻转的算法,7楼x=x>>4是4位反转的算法,舍弃低4位,去掉这一句就是8位的算法,演算一下就知道了。
原始位置:1 2 3 4 5 6 7 8
第一步后:2 1 4 3 6 5 8 7 //交换相邻的位
第二步后:4 3 2 1 8 7 6 5 //交换相邻的2位
第三步后:8 7 6 5 4 3 2 1 //交换相邻的4位,3条语句,26个时钟周期完成,目的实现!!!
网上很多的,位操作 and 技巧 百度上搜一下。 各位高手让我大开眼界啊 各位DX让我大开眼界 我特别喜欢急速快感,楼上的同志们智慧在闪耀 只是最快吗?有其他要求吗?
感觉硬件算法最快,代码量最小............呵呵
将PA口与PB口对调连接..........PA设置为输出,PB设置为输入
uint8 B2B(uint8xx)
{
PORTA = xx;
return PINB;
} 哈哈,我就记得曾经在21ic上讨论了这个问题。提出了一个和楼上一样的“馊主意”。 回22楼:
确实快,不过牺牲硬件资源(用了16个口线)。
楼主要的是如何用C语言实现,也就是如何用软件实现。 【18楼】 admvip不错 18L的方法,看起来不错,但编译代码也不少...
在ICCAVR中编译出26条指令
如果嵌入汇编的话,使用循环移位,应该只用16条指令... 速度和大小兼顾的方法,半字节查表,而且一般的单片机都支持半字节交换。
unsigned char rev_tab[]={0x00,0x08,0x04,0x0c,0x02,0x0a,0x06,0x0e,0x01,0x09,0x05,0x0d,0x03,0x0b,0x07,0x0f};
unsigned char reverse(unsigned char a)
{
return rev_tab << 4 | rev_tab;
} avr中两次查表花的代码也不小了..
还是循环位移代码少... 很早以前讨论过这个问题了http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=1908616 比较损的方法,只要两个周期,看了别用砖头砸我
端口PA0接到PB7,PA1--PB6,PA2--PB5 把端口A和B以以上方法连上,然后
OUT PORTA,R16
IN R16,PINB
只要两个周期就够了哈哈,不过要占16个IO口。 蝶形交换是比较有效率的算法
对其进行稍加改进,可以实现任意位序交换
之前用其实现了洗牌交换
用了三次子蝶形交换 方法1:
源数->R16,结果->R17,花费16T
asm("ROR R16");
asm("ROL R17");//1
asm("ROR R16");
asm("ROL R17");//2
asm("ROR R16");
asm("ROL R17");//3
asm("ROR R16");
asm("ROL R17");//4
asm("ROR R16");
asm("ROL R17");//5
asm("ROR R16");
asm("ROL R17");//6
asm("ROR R16");
asm("ROL R17");//7
asm("ROR R16");
asm("ROL R17");//8
===========================
方法2:源数->R16,结果->R16,花费15T
asm("swap R16 ");
asm("movR17,R16 ");
asm("lslR17 ");
asm("lslR17 ");
asm("lsrR16 ");
asm("lsrR16 ");
asm("andi R17,0xcc ");
asm("andi R16,0x33 ");
asm("or R16,R17 ");
asm("movR17,R16 ");
asm("lslR17 ");
asm("lsrR16 ");
asm("andi R17,0xaa ");
asm("andi R16,0x55 ");
asm("or R16,R17 "); 好贴!! mark! niu 以前用cpld的剩余资源用硬件实现这个东西,就2个寄存器,速度应该算快的。 asm("swap %a");
a = ((a << 2) & 0xcc) | ((a>> 2) & 0x33);
a = ((a << 1) & 0xaa) | ((a>> 1) & 0x55);
混合编程,结果跟【32楼】 snoopyzz 的方法二是一样的,15T 再来个任意序的,16T
unsigned char x,y;
x=PINB;
asm("bst %x,0"); asm("bld %y,7");
asm("bst %x,1"); asm("bld %y,6");
asm("bst %x,2"); asm("bld %y,5");
asm("bst %x,3"); asm("bld %y,4");
asm("bst %x,4"); asm("bld %y,3");
asm("bst %x,5"); asm("bld %y,2");
asm("bst %x,6"); asm("bld %y,1");
asm("bst %x,7"); asm("bld %y,0");
PORTC=y;
以上是倒序的另一方法,只要改变右边的数字顺序就可以用16T完成任意顺序转换。
AVR的T类似51的进位位C。 LTOR:MOV R0, #8
MOV R1, #0
LOOP:MOV A, R7
RLC A
MOV R7, A
MOV A, R1
RRC A
MOV R1, A
DJNZR0, LOOP
MOV R7, A
RET
END mark 忘了标记 位操作 http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4039405 mark了,正在用18楼的算法。 mark了 Mark fft REIT
const unsigned char Table = //字节倒序查询表
{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF,};
LCD_BUS = Table | (Table <<4);
有一次我把液晶屏画反了,就是这样补救的
页:
[1]