搜索
bottom↓
回复: 103

请教,在STM32里进行bit的行列变换,有什么好算法?

[复制链接]

出0入0汤圆

发表于 2009-11-14 14:07:49 | 显示全部楼层 |阅读模式
假设有这样一个结构:

struct TEST
{
    UI8 b0
    UI8 b1
    UI8 b2
    UI8 b3
    UI8 b4
    UI8 b5
    UI8 b6
    UI8 b7
};

定义了2个变量:
TEST t1,t2;

其中t1里的8个字节的数值已确定。

现在要进行这样的变换:

用t1中每个字节的bit0合成为一个新的字节,赋值给t1的b0.

t1中8个字节的bit1,合成为一个字节,赋值给t2中的b1....

依次类推,t1中每个字节的bit7,合成的字节赋值给t2的b7.


不知道以上的描述是否清楚。

也可以这样理解:

把t1看成一个8bit * 8bit的2维数组,对这个数组进行“行列变换”。

在stm32中,用什么样的算法才最节省时间呢?(占用内存大小及程序空间大小无限制,只要速度快)

阿莫论坛20周年了!感谢大家的支持与爱护!!

该献的血还是要献的。你不献他不献。难道让我去献? --- 出自坛友:lovejp1981

出0入0汤圆

发表于 2009-11-15 00:56:08 | 显示全部楼层
定义一个长度为16K字节的表格,查表8次,逻辑或运算16次完成。

出0入0汤圆

发表于 2009-11-15 10:21:02 | 显示全部楼层
简单的做法是使用位带操作实现。

出0入0汤圆

发表于 2009-11-15 11:30:38 | 显示全部楼层
8个595加163之类的加MUX....

出0入0汤圆

 楼主| 发表于 2009-11-16 15:35:59 | 显示全部楼层
1楼的方法好像实现不了吧。

3楼的方法要增加硬件成本,不可。

2楼的方法可行,但是要用到多次运算和循环,目前想找到更快的方法

出0入0汤圆

发表于 2009-11-16 17:46:00 | 显示全部楼层
ulong dat_b0[512] = {
                     0x00000000,0x00000000, //00000000
                     0x00000000,0x00000001, //00000001
                     0x00000000,0x00000100, //00000010
                     0x00000000,0x00000101, //00000011
                     0x00000000,0x00010000, //00000100
                     .....................
                     0x01010101,0x01010101, //11111111
                     }

ulong dat_b1[512] = {
                     0x00000000,0x00000000, //00000000
                     0x00000000,0x00000002, //00000001
                     0x00000000,0x00000200, //00000010
                     0x00000000,0x00000202, //00000011
                     0x00000000,0x00020000, //00000100
                     .....................
                     0x02020202,0x02020202, //11111111
                     }

ulong dat_b2[512] = {
                     0x00000000,0x00000000, //00000000
                     0x00000000,0x00000004, //00000001
                     0x00000000,0x00000400, //00000010
                     0x00000000,0x00000404, //00000011
                     0x00000000,0x00040000, //00000100
                     .....................
                     0x04040404,0x04040404, //11111111
                     }

                     :
                     :
                     :
                     :

ulong dat_b7[512] = {
                     0x00000000,0x00000000, //00000000
                     0x00000000,0x00000080, //00000001
                     0x00000000,0x00008000, //00000010
                     0x00000000,0x00008080, //00000011
                     0x00000000,0x00800000, //00000100
                     .....................
                     0x80808080,8080808080, //11111111
                     }



struct TEST rotate(t1) //数组参数传递格式可能不当,请意会。
{
  ulong dh=0,dl=0;
  uint  temp;
  temp = t1.b0<<1;
  dh |= dat_b0[temp];
  dl |= dat_b0[++temp];
  temp = t1.b1<<1;
  dh |= dat_b1[temp];
  dl |= dat_b1[++temp];
  temp = t1.b2<<1;
  dh |= dat_b2[temp];
  dl |= dat_b2[++temp];
  temp = t1.b3<<1;
  dh |= dat_b3[temp];
  dl |= dat_b3[++temp];
  temp = t1.b4<<1;
  dh |= dat_b4[temp];
  dl |= dat_b4[++temp];
  temp = t1.b5<<1;
  dh |= dat_b5[temp];
  dl |= dat_b5[++temp];
  temp = t1.b6<<1;
  dh |= dat_b6[temp];
  dl |= dat_b6[++temp];
  temp = t1.b7<<1;
  dh |= dat_b7[temp];
  dl |= dat_b7[++temp];

  t2.b0 = dl;
  t2.b1 = dl>>8;
  t2.b2 = dl>>16;
  t2.b3 = dl>>24;
  t2.b4 = dh;
  t2.b5 = dh>>8;
  t2.b6 = dh>>16;
  t2.b7 = dh>>24;  
  return t2;//这里不会写结构变量返回的格式,请意会。
}

出0入0汤圆

发表于 2009-11-16 17:55:18 | 显示全部楼层
16次查表和16次或运算,应该是较快的方法,只是点空间大点,16K表格

出0入0汤圆

发表于 2009-11-16 17:56:41 | 显示全部楼层
思考……

出0入0汤圆

 楼主| 发表于 2009-11-18 13:23:55 | 显示全部楼层
先学习学习5楼的思路。。。

出0入0汤圆

发表于 2009-11-18 17:32:26 | 显示全部楼层
没弄懂,思考并等更好的方法

出0入0汤圆

发表于 2009-11-18 18:12:50 | 显示全部楼层
用STM32的段位功能会不会快点呢
两个32位指针 好不好呵呵

#define BITBAND(addr) (INT32U*)((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5))
INT32U *pdst=BITBAND((INT32U)&t1), *psrc;
for(i=0;i<8;i++)
{
  *psrc=BITBAND((INT32U)&t2)+i;
  for(j=0;j<8;j++)
  {
    *pdst++=*psrc;
    *psrc+=8;
  }
}

出0入0汤圆

发表于 2009-11-19 17:00:26 | 显示全部楼层
实在没想出好办法,觉得把变量定义成数组会更好处理
头像被屏蔽

出0入0汤圆

发表于 2009-11-20 13:15:53 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2009-11-20 14:53:39 | 显示全部楼层
STM32的位操作比51核心更高效,怎么能说比51差多了?
头像被屏蔽

出0入0汤圆

发表于 2009-11-20 17:07:05 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
头像被屏蔽

出0入0汤圆

发表于 2009-11-20 18:00:06 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
头像被屏蔽

出0入0汤圆

发表于 2009-11-20 18:31:07 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2009-11-25 15:01:45 | 显示全部楼层
stm32  位操作不可能更高效, 不过 stm32 的移位运算非常高效, 可以用它来提高速度
也就是个 64 位整数的运算嘛

出0入0汤圆

 楼主| 发表于 2009-11-25 15:14:27 | 显示全部楼层
====================
不过 stm32 的移位运算非常高效
====================
这个我以前做过测试,对1024个8bit的字节移位,为了加快速度改成对256个32bit的整数移位,结果速度没有什么提升。

不知道是我自己的代码有问题还是怎么回事儿。


=================
也就是个 64 位整数的运算嘛
=================
能否具体指点一下?

出0入0汤圆

发表于 2009-11-25 15:51:02 | 显示全部楼层
使用乘法很方便的,简单的写个方法
long <= t1.b3-t1.b0  // t1低四字节
long = (long & 0x01010101) * 0x01020408;  // 结果低四位在最高字节中
再处理高四位后合并低四位,其余的也类似处理

出0入0汤圆

发表于 2009-11-25 16:08:04 | 显示全部楼层
19楼的思路不错!!

结果对不对还要验证一下。

出0入0汤圆

 楼主| 发表于 2009-11-25 16:43:41 | 显示全部楼层
=================
long = (long & 0x01010101) * 0x01020408;
=================
这里的long是不是用32bit就可以了?

出0入0汤圆

发表于 2009-11-25 17:05:14 | 显示全部楼层
四字节就是32bit啊,这个没什么歧义吧
验证的话用计算器就可以了

出0入0汤圆

发表于 2009-11-25 17:22:19 | 显示全部楼层
用计算器验证了几个数,确实都是对的。

不错,妙!

出0入0汤圆

发表于 2009-11-25 18:15:14 | 显示全部楼层
我是来学习19楼的思路的
头像被屏蔽

出0入0汤圆

发表于 2009-11-25 19:17:15 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2009-11-25 19:34:06 | 显示全部楼层
请教一下,0x01020408 是怎么算出来的?
头像被屏蔽

出0入0汤圆

发表于 2009-11-25 19:46:34 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2009-11-25 19:52:10 | 显示全部楼层
【27楼】 bbs2009 ,你只完成了一个字节,还有7个字节要处理。
头像被屏蔽

出0入0汤圆

发表于 2009-11-25 20:54:54 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2009-11-25 21:07:38 | 显示全部楼层
【1楼】 cowboy

积分:2458
派别:
等级:------
来自:
定义一个长度为16K字节的表格,查表8次,逻辑或运算16次完成。  
   



又见查表高手。

出0入0汤圆

发表于 2009-11-25 21:24:58 | 显示全部楼层
参考 ARM Cortex-M3 权威指南

位带操作

IAR环境

typedef struct _TEST
{
    u8 b0 ;
    u8 b1 ;
    u8 b2 ;
    u8 b3 ;
    u8 b4 ;
    u8 b5 ;
    u8 b6 ;
    u8 b7 ;
}TEST;

#define ram_ADDR_BASE   0x20000000
#define bit_ADDR_BASE   0x22000000
#define t1_ADDR_OFFSET  0x00000000
#define t2_ADDR_OFFSET  0x00000008

__no_init TEST  t1 @ ram_ADDR_BASE+t1_ADDR_OFFSET;
__no_init TEST  t2 @ ram_ADDR_BASE+t2_ADDR_OFFSET;

  t1.b0 = 0x01;
  t1.b1 = 0x02;
  t1.b2 = 0x03;
  t1.b3 = 0x04;
  t1.b4 = 0x10;
  t1.b5 = 0x20;
  t1.b6 = 0x30;
  t1.b7 = 0x40;
  
for(u16 ii=0; ii<8 ; ii++)
{
  for(u16 jj=0; jj<8; jj++)
  {
    *(vu32 *)(bit_ADDR_BASE+(t2_ADDR_OFFSET*32)+ ii*0x20 + jj*0x04)=\
     *(u32 *)(bit_ADDR_BASE+(t1_ADDR_OFFSET*32)+ jj*0x20 + ii*0x04);
  }
}
printf("%02x,%02x,%02x,%02x  %02x,%02x,%02x,%02x \n\r",t2.b0,t2.b1,t2.b2,t2.b3,t2.b4,t2.b5,t2.b6,t2.b7);

------------------------------------------------------------------------------------------------------------
输出:05,06,08,00  50,60,80,00
头像被屏蔽

出0入0汤圆

发表于 2009-11-25 21:58:39 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2009-11-25 22:34:33 | 显示全部楼层
31楼的算法应该用指针操作,把循环中的计算统统去掉,只保留对指针的操作。如果可能不要用循环,直接像27楼那样把循环展开。

出0入22汤圆

发表于 2009-11-25 23:46:13 | 显示全部楼层
将来可能要用到~~~mark!

出0入0汤圆

发表于 2009-11-26 10:05:56 | 显示全部楼层
看了19楼有所启发

const unsigned long Table[16] = {0x00000000,0x00000001,0x00000100,0x00000101,
                                 0x00010000,0x00010001,0x00010100,0x00010101,
                                 0x01000000,0x01000001,0x01000100,0x01000101,
                                 0x01010000,0x01010001,0x01010100,0x01010101};
                                 
                                 
main()
{

    unsigned  char t1[8],i;
    union
    {
        unsigned long dat[2];
        unsigned char t2[8];
    } Tmp;
   
    Tmp.dat[0] = 0;
    Tmp.dat[1] = 0;
    i = 8;
    while(i--)
    {
        Tmp.dat[0] = (Tmp.dat[0] << 1) | Table[t1 & 0x0f];
        Tmp.dat[1] = (Tmp.dat[1] << 1) | Table[t1 >> 4];
    }
    while(1);
}   

要求更高的速度,把循环体内的两句重复写8次。谁能验证一下正确性和速度?

出0入0汤圆

发表于 2009-11-26 10:48:13 | 显示全部楼层
很不幸,楼上算法是错误的

出0入0汤圆

发表于 2009-11-26 11:15:46 | 显示全部楼层
是否大端、小端的问題?上面是按大端模式,如果STM32是按小端储存,要稍作改动。

出0入0汤圆

发表于 2009-11-26 11:25:42 | 显示全部楼层
有可能.上面我显示了一个字模a,变换后显示全亮

出0入0汤圆

发表于 2009-11-26 11:34:22 | 显示全部楼层
没看明白,再MARK

出0入0汤圆

发表于 2009-11-26 14:13:51 | 显示全部楼层
to 【26楼】 xiejun 伪程序

如果用类似我们平常手工计算乘法的竖式来表示就很清楚了

    1248   <- 模256
  X ABCD   <- A,B,C,D = {0,1}, 需要变换的数据
---------
    Exxx
   xFxx
  xxGx
xxxH
---------
xxxRxxx

R = E+F+G+H = 1D+2C+4B+8A  // 1,2,4,8: 对应每个需要变换的BIT在目的BIT位置的权值

to 【27楼】 bbs2009

你要比较M3与51的位处理能力,这样就缺少可比性,呵呵,你可以试试也用ASM写个M3代码比较下

to 【31楼】 helloshi

使用M3的Bit-banding来做这个事并不合适,还不如把数据加载到寄存器中作移位操作,无论如何象M3这种核尽量不要在存储器中作数据处理

to 【35楼】 cowboy

呵呵,M3有单周期的MUL和丰富高效的移位指令啊

出0入0汤圆

发表于 2009-12-25 10:06:24 | 显示全部楼层
看了贴子,不由佩服zjzhou 构思巧妙,不过大侠们都是聊聊数语,我就把具体实现贴上,方便后来人

        unsigned  char t1[8]={0x24,0x21,0xf0,0x7f,0x80,0x37,0xff,0x1f};//test data
        unsigned char t2[8];
    union
    {
        unsigned long l[2];
        unsigned char c[8];
    } Tmp;
    unsigned char i;
long Ll,Lh;
        for (i=0;i<8;i++)
                Tmp.c=t1;
        i=8;
        while(i--)
        {
                Ll=(Tmp.l[0]&0x01010101)*0x01020408;
                Lh=(Tmp.l[1]&0x01010101)*0x01020408;
                t2=unsigned char(((Lh&0x0F000000)>>20)|((Ll&0x0F000000)>>24));
                Tmp.l[0]>>=1;Tmp.l[1]>>=1;
        }

出0入8汤圆

发表于 2009-12-25 13:49:52 | 显示全部楼层
要给zjzhou来条裤子。

出0入0汤圆

发表于 2009-12-28 18:15:38 | 显示全部楼层
我同意,不要让这种好的算法贴子沉得太快

出0入0汤圆

发表于 2009-12-28 19:00:32 | 显示全部楼层
把 【41楼】 coldfish  的程序放到 MDK 下软件仿真了下, 选择的 STM32 芯片 8M 主频, 内部倍频到 72M 。


(原文件名:1.jpg)


(原文件名:2.jpg)


(原文件名:3.jpg)

0010 0100
0010 0001
1111 0000
0111 1111
1000 0000
0011 0111
1111 1111
0001 1111

结果正确, 这段代码两个断点之间运行时间 5.417 uS。

说实在的比较慢, 但是思路感觉还可以, 肯定是可以优化的。

出0入0汤圆

发表于 2009-12-28 21:29:19 | 显示全部楼层
示例程序如下:
#include <stdio.h>

void transpose8(unsigned char i[8], unsigned char o[8]) {
        unsigned long x, y, t;

        x = (i[0] << 24) | (i[1] << 16) | (i[2] << 8) | i[3];
        y = (i[4] << 24) | (i[5] << 16) | (i[6] << 8) | i[7];

        t = (x & 0xf0f0f0f0) | ((y >> 4) & 0x0f0f0f0f);
        y = ((x << 4) & 0xf0f0f0f0) | (y & 0x0f0f0f0f);
        x = t;

        t = (x ^ (x >> 14)) & 0x0000cccc;
        x = x ^ t ^ (t << 14);
        t = (y ^ (y >> 14)) & 0x0000cccc;
        y = y ^ t ^ (t << 14);

        t = (x ^ (x >> 7)) & 0x00aa00aa;
        x = x ^ t ^ (t << 7);
        t = (y ^ (y >> 7)) & 0x00aa00aa;
        y = y ^ t ^ (t << 7);

        o[7] = x >> 24; o[6] = x >> 16; o[5] = x >> 8; o[4] = x;
        o[3] = y >> 24; o[2] = y >> 16; o[1] = y >> 8; o[0] = y;
}

int main(void) {
        int i;
        unsigned char t1[8]={0x24,0x21,0xf0,0x7f,0x80,0x37,0xff,0x1f};
        unsigned char t2[8];

        transpose8(t1, t2);
        for (i = 0; i < 8; i++)
                printf("0x%x ", t2);
        return EOF == putchar('\n');
}

运行结果:0x57 0x17 0x97 0x13 0x37 0xf6 0x32 0x2a

没专门对ARM-v7M优化,不过我觉得速度应该能接受了,应该比直接进行位操作分别操作每个
位的方法快一倍。

出0入0汤圆

发表于 2009-12-28 21:37:10 | 显示全部楼层
相当好的帖,再标记一次

出0入0汤圆

发表于 2009-12-28 21:50:17 | 显示全部楼层
啊啊~~~~~~ 啊啊?又一次质的飞跃。

出0入0汤圆

发表于 2009-12-28 22:06:30 | 显示全部楼层
顶【45楼】 minux 啊

出0入0汤圆

发表于 2009-12-28 22:12:39 | 显示全部楼层
好帖,收藏,强烈建议穿裤

出0入0汤圆

发表于 2009-12-28 22:24:13 | 显示全部楼层
mark!

出0入0汤圆

发表于 2009-12-28 23:50:44 | 显示全部楼层
手工验算了【45楼】 minux 啊啊? 的算法,十分强大
头像被屏蔽

出0入0汤圆

发表于 2009-12-29 09:35:24 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2009-12-29 09:53:53 | 显示全部楼层
to 【44楼】 lvhaian 安哥
什么时候用汇编优化看看。
5.417 uS*72M=390 周期
390/8=48,就是说一个循环要48个周期,应该有优化空间
Ll=(Tmp.l[0]&0x01010101)*0x01020408; 2  //AND操作和MUL操作都是单周期
Lh=(Tmp.l[1]&0x01010101)*0x01020408; 2
t2=unsigned char(((Lh&0x0F000000)>>20)|((Ll&0x0F000000)>>24)); 2个移位,1个或,1个赋值
Tmp.l[0]>>=1;Tmp.l[1]>>=1; 2个移位。
理论上10多个周期就可以了。有空再把汇编贴上来。

【45楼】 minux 啊啊? 的思路不错,学习一下

出0入0汤圆

发表于 2009-12-29 09:56:25 | 显示全部楼层
阿莫 给这个来个酷  好帖子啊

出0入0汤圆

发表于 2009-12-29 11:06:01 | 显示全部楼层
struct TEST
{
    UI8 b0
    UI8 b1
    UI8 b2
    UI8 b3
    UI8 b4
    UI8 b5
    UI8 b6
    UI8 b7
}; 定义成二维数组就好办了,用的时候与直接变换索引,

出0入0汤圆

发表于 2009-12-29 13:46:05 | 显示全部楼层
【53楼】 coldfish
32b * 32b的乘法是3-7个周期的…… 根据两个操作数的大小范围决定。
所谓Cortex-M3是单周期乘法最多只能到32b*16b.

出0入0汤圆

发表于 2009-12-29 14:00:11 | 显示全部楼层
强悍,再MARK

出0入0汤圆

发表于 2009-12-29 18:33:25 | 显示全部楼层
回复【57楼】minux 啊啊?
【53楼】 coldfish  
32b * 32b的乘法是3-7个周期的…… 根据两个操作数的大小范围决定。
所谓Cortex-M3是单周期乘法最多只能到32b*16b.
本贴被 minux 编辑过,最后修改时间:2009-12-29,14:18:09.

-----------------------------------------------------------------------

受教了,说实话,还没有直接用CM3的汇编写过程序呢

出0入0汤圆

发表于 2009-12-29 21:03:17 | 显示全部楼层
t1,t2 在位域中对应两个64个字的数组,做一次变换一共要传送64个位,就是64个字。用汇编写,不用循环,不用指针, 应该很快的。
头像被屏蔽

出0入0汤圆

发表于 2009-12-29 21:46:40 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2009-12-29 22:16:43 | 显示全部楼层
mark一下。

出0入0汤圆

发表于 2009-12-30 13:19:03 | 显示全部楼层
拿 【45楼】 minux 啊啊? 建立软件仿真下, 同样8M晶振下面, 倍频到 72M


(原文件名:1.png)


(原文件名:2.jpg)


速度质的飞跃, 虽然和 coldwish 的出来的值不一样, 但是我知道他们的答案都是正确的, 一个是顺序的, 一个是倒叙的。

这个无所谓了。

这个minux的代码只要 1.264uS , 只能说一句:  牛!!!

出0入0汤圆

发表于 2010-1-13 00:41:18 | 显示全部楼层
都是牛人~~

出0入0汤圆

发表于 2010-4-8 12:19:28 | 显示全部楼层
PUBLIC  juzhen     
/* ///////////////////////////////////////////////////////////////////////////
; void juzhen (u8 *yuan,u8 *mud,u8 gao);  正常8字节矩阵转换
; buf = (buf<<1) | (buf[i+1]>>7).
; Resources:
;  R0,R1,R3: parameters
;  R5   :buf
;  R6   :buf[i+1]
;/////////////////////////////////////////////////////////////////////////// */
        RSEG CODE:CODE:NOROOT(2)
        THUMB
juzhen
        PUSH       {R3-R12}
a_main  
        MOV     R4,#0x00
        MOV     R5,#0x00
        MOV     R6,#0x00
        MOV     R7,#0x00
        MOV     R8,#0x00
        MOV     R9,#0x00
        MOV     R10,#0x00
        MOV     R11,#0x00
        
                               
        LDRB    R3,[R0,#+0]    ;第一个数
        BFI     R11,R3,#7,#1
        LSR     R3,R3,#1
        BFI     R10,R3,#7,#1
        LSR     R3,R3,#1
        BFI     R9,R3,#7,#1
        LSR     R3,R3,#1
        BFI     R8,R3,#7,#1
        LSR     R3,R3,#1
        BFI     R7,R3,#7,#1
        LSR     R3,R3,#1
        BFI     R6,R3,#7,#1
        LSR     R3,R3,#1
        BFI     R5,R3,#7,#1
        LSR     R3,R3,#1
        BFI     R4,R3,#7,#1
        CMP     R2,  #1
        BEQ.W     a_main_end
        
        LDRB    R3,[R0,#+1]  ;第二个数
        BFI     R11,R3,#6,#1
        LSR     R3,R3,#1
        BFI     R10,R3,#6,#1
        LSR     R3,R3,#1
        BFI     R9,R3,#6,#1
        LSR     R3,R3,#1
        BFI     R8,R3,#6,#1
        LSR     R3,R3,#1
        BFI     R7,R3,#6,#1
        LSR     R3,R3,#1
        BFI     R6,R3,#6,#1
        LSR     R3,R3,#1
        BFI     R5,R3,#6,#1
        LSR     R3,R3,#1
        BFI     R4,R3,#6,#1
        CMP     R2,  #2
        BEQ.W     a_main_end
        
        LDRB    R3,[R0,#+2]  ;第三个数
        BFI     R11,R3,#5,#1
        LSR     R3,R3,#1
        BFI     R10,R3,#5,#1
        LSR     R3,R3,#1
        BFI     R9,R3,#5,#1
        LSR     R3,R3,#1
        BFI     R8,R3,#5,#1
        LSR     R3,R3,#1
        BFI     R7,R3,#5,#1
        LSR     R3,R3,#1
        BFI     R6,R3,#5,#1
        LSR     R3,R3,#1
        BFI     R5,R3,#5,#1
        LSR     R3,R3,#1
        BFI     R4,R3,#5,#1
        CMP     R2,  #3
        BEQ.W     a_main_end
        
        LDRB    R3,[R0,#+3]  ;第四个数
        BFI     R11,R3,#4,#1
        LSR     R3,R3,#1
        BFI     R10,R3,#4,#1
        LSR     R3,R3,#1
        BFI     R9,R3,#4,#1
        LSR     R3,R3,#1
        BFI     R8,R3,#4,#1
        LSR     R3,R3,#1
        BFI     R7,R3,#4,#1
        LSR     R3,R3,#1
        BFI     R6,R3,#4,#1
        LSR     R3,R3,#1
        BFI     R5,R3,#4,#1
        LSR     R3,R3,#1
        BFI     R4,R3,#4,#1
        CMP     R2,  #4
        BEQ.W     a_main_end
        
        LDRB    R3,[R0,#+4]    ;第五个数
        BFI     R11,R3,#3,#1
        LSR     R3,R3,#1
        BFI     R10,R3,#3,#1
        LSR     R3,R3,#1
        BFI     R9,R3,#3,#1
        LSR     R3,R3,#1
        BFI     R8,R3,#3,#1
        LSR     R3,R3,#1
        BFI     R7,R3,#3,#1
        LSR     R3,R3,#1
        BFI     R6,R3,#3,#1
        LSR     R3,R3,#1
        BFI     R5,R3,#3,#1
        LSR     R3,R3,#1
        BFI     R4,R3,#3,#1
        CMP     R2,  #5
        BEQ.W     a_main_end
        
        LDRB    R3,[R0,#+5]  ;第六个数
        BFI     R11,R3,#2,#1
        LSR     R3,R3,#1
        BFI     R10,R3,#2,#1
        LSR     R3,R3,#1
        BFI     R9,R3,#2,#1
        LSR     R3,R3,#1
        BFI     R8,R3,#2,#1
        LSR     R3,R3,#1
        BFI     R7,R3,#2,#1
        LSR     R3,R3,#1
        BFI     R6,R3,#2,#1
        LSR     R3,R3,#1
        BFI     R5,R3,#2,#1
        LSR     R3,R3,#1
        BFI     R4,R3,#2,#1
        CMP     R2,  #6
        BEQ.W     a_main_end
        
        LDRB    R3,[R0,#+6]  ;第七个数
        BFI     R11,R3,#1,#1
        LSR     R3,R3,#1
        BFI     R10,R3,#1,#1
        LSR     R3,R3,#1
        BFI     R9,R3,#1,#1
        LSR     R3,R3,#1
        BFI     R8,R3,#1,#1
        LSR     R3,R3,#1
        BFI     R7,R3,#1,#1
        LSR     R3,R3,#1
        BFI     R6,R3,#1,#1
        LSR     R3,R3,#1
        BFI     R5,R3,#1,#1
        LSR     R3,R3,#1
        BFI     R4,R3,#1,#1
        CMP     R2,  #7
        BEQ.W     a_main_end
        
        LDRB    R3,[R0,#+7]  ;第八个数
        BFI     R11,R3,#0,#1
        LSR     R3,R3,#1
        BFI     R10,R3,#0,#1
        LSR     R3,R3,#1
        BFI     R9,R3,#0,#1
        LSR     R3,R3,#1
        BFI     R8,R3,#0,#1
        LSR     R3,R3,#1
        BFI     R7,R3,#0,#1
        LSR     R3,R3,#1
        BFI     R6,R3,#0,#1
        LSR     R3,R3,#1
        BFI     R5,R3,#0,#1
        LSR     R3,R3,#1
        BFI     R4,R3,#0,#1
        
a_main_end:
        STRB    R4,[R1,#+0]
        STRB    R5,[R1,#+1]  
        STRB    R6,[R1,#+2]
        STRB    R7,[R1,#+3]
        STRB    R8,[R1,#+4]
        STRB    R9,[R1,#+5]  
        STRB    R10,[R1,#+6]
        STRB    R11,[R1,#+7]
        
        POP       {R3-R12}
        BX          LR

出0入0汤圆

发表于 2010-4-8 12:21:25 | 显示全部楼层
STM32汇编转换。这个应该是最快的吧。STM8有玩的吗?有没有人有汇编的位操作的。
头像被屏蔽

出0入0汤圆

发表于 2010-4-8 17:39:04 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2010-4-28 11:07:28 | 显示全部楼层
mark~

出0入0汤圆

发表于 2010-4-29 00:41:35 | 显示全部楼层
用到过这玩意,系统中的LCD是横排的,微打是竖排的,所以打印时需要将显示的字库进行转置,当时因为是打印用的,所以对速度没有要求

LZ既然对速度的要求这么变态,占用内存大小及程序空间大小无限制,那就查表好了,
做个8维的表格,Tabe[256][256][256][256][256][256][256][256], 吼吼,一定快!

出0入0汤圆

发表于 2010-4-29 01:52:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-30 19:17:56 | 显示全部楼层
好贴,Mark。

出0入0汤圆

发表于 2010-7-23 15:13:32 | 显示全部楼层
stm8s可以用下面这个

typedef        struct
{
        u8        bit0        :1;
        u8        bit1        :1;
        u8        bit2        :1;
        u8        bit3        :1;
        u8        bit4        :1;
        u8        bit5        :1;
        u8        bit6        :1;
        u8        bit7        :1;
}        BIT_FIELD;
#define        TO_BITS(var)        (*(BIT_FIELD*)&var)

TO_BITS(t2.b0).bit0 = TO_BITS(t1.b0).bit0;
TO_BITS(t2.b0).bit1 = TO_BITS(t1.b1).bit0;
TO_BITS(t2.b0).bit2 = TO_BITS(t1.b2).bit0;
TO_BITS(t2.b0).bit3 = TO_BITS(t1.b3).bit0;
TO_BITS(t2.b0).bit4 = TO_BITS(t1.b4).bit0;
TO_BITS(t2.b0).bit5 = TO_BITS(t1.b5).bit0;
TO_BITS(t2.b0).bit6 = TO_BITS(t1.b6).bit0;
TO_BITS(t2.b0).bit7 = TO_BITS(t1.b7).bit0;
8条C语言完成一个字节(这样1条C语言用cosmic生成2条汇编,耗去3T/4T,也就是说最坏的情况下是32T一个字节,8字节就是256T)

在24MHZ晶振下,10.67us

如果t1的值可以被改变的话,那么可以用移位,2T*8*8=128T可以完成

说这是最笨的方法也好,但也并不慢了

出0入0汤圆

发表于 2010-7-26 12:44:06 | 显示全部楼层
hao

出0入0汤圆

发表于 2010-7-26 13:34:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-26 15:01:12 | 显示全部楼层
看不懂,标记一下。

出0入0汤圆

发表于 2010-7-26 18:14:27 | 显示全部楼层
19楼的算法确实很巧妙.乘数0x01020408中1的位置代表着权值,4个1把上一步与操作得到的4位尾数拼成了一个4bit的二进制数.
其实写成0x08040201也会得到一样的效果,只是顺序反一下.更多算法可以看看http://www-graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits

出0入0汤圆

发表于 2010-7-26 22:11:43 | 显示全部楼层
唉,看不懂,标记下,慢慢看

出0入0汤圆

发表于 2011-6-24 12:01:08 | 显示全部楼层
好贴,标记~!

出0入0汤圆

发表于 2011-6-24 14:09:36 | 显示全部楼层
回复【70楼】linnjing 五月的风
用到过这玩意,系统中的lcd是横排的,微打是竖排的,所以打印时需要将显示的字库进行转置,当时因为是打印用的,所以对速度没有要求
lz既然对速度的要求这么变态,占用内存大小及程序空间大小无限制,那就查表好了,
做个8维的表格,tabe[256][256][256][256][256][256][256][256], 吼吼,一定快!

-----------------------------------------------------------------------

不知道编译器支不支持这样的表格......还有存储空间能容纳么?

出0入0汤圆

发表于 2011-6-24 14:54:29 | 显示全部楼层
回复【70楼】linnjing  五月的风

做个8维的表格,tabe[256][256][256][256][256][256][256][256],&#160;吼吼,一定快!

-----------------------------------------------------------------------

256^8=18446744073709551616 BYTEs这么大的表,还是计算快

出0入0汤圆

发表于 2011-10-20 10:35:38 | 显示全部楼层
算法加上片子的能力才能达到最优化。

出0入0汤圆

发表于 2011-10-23 20:03:04 | 显示全部楼层
学习算法和精神!

出0入0汤圆

发表于 2011-11-20 22:04:09 | 显示全部楼层
非常感谢minux 啊啊?,你提供的算法我用在我自用的量产编程器上,速度很快,再次感谢,神一样的人

出0入0汤圆

发表于 2011-11-20 23:17:52 | 显示全部楼层
MARK 位矩阵转置

出0入0汤圆

发表于 2011-11-21 10:43:38 | 显示全部楼层
minux 啊啊,能否解释一下你的算法,多谢了

出0入0汤圆

发表于 2011-11-21 12:48:33 | 显示全部楼层
minux的算法,一本书上讲过。上面给出了这个函数C代码,一样。《高效程序的奥秘》翻译Henry S. Warren. Jr.的“Hacher's Delight"。不知道有没有电子版的。

出0入0汤圆

发表于 2011-11-21 13:29:00 | 显示全部楼层
找了一下。有电子版的。发上来。都是经验啊,我当工具书看了。受益匪浅啊。

高效程序的奥秘ourdev_697491ON0QLL.rar(文件大小:10.03M) (原文件名:高效程序的奥秘.rar)

出0入0汤圆

发表于 2011-12-16 21:47:38 | 显示全部楼层
非常有用!必须要MARK!我正在验证!

出0入0汤圆

发表于 2011-12-17 11:21:51 | 显示全部楼层
高人多多啊,矩阵转秩

出0入0汤圆

发表于 2012-4-4 17:24:13 | 显示全部楼层
MARK~~~~~~~

出0入0汤圆

发表于 2012-5-23 22:52:57 | 显示全部楼层
,好东西!

出0入0汤圆

发表于 2012-6-12 11:35:51 | 显示全部楼层
minux 发表于 2009-12-28 21:29
示例程序如下:
#include

果然厉害!高手!

出0入22汤圆

发表于 2012-6-12 12:33:14 | 显示全部楼层
不知道 UCGUI 是怎么实现这个算法的。

出0入0汤圆

发表于 2012-6-12 13:03:09 | 显示全部楼层
非常好的帖子

出0入0汤圆

发表于 2012-6-15 14:39:14 | 显示全部楼层
闲暇浏览到此,看看蛮有意思,最直观的举例就是这样的   
typedef union
{
        INT8U byte;
        struct
        {
                unsigned bit0:1;                       
                unsigned bit1:1;               
                unsigned bit2:1;       
                unsigned bit3:1;       
                unsigned bit4:1;
                unsigned bit5:1;
                unsigned bit6:1;
                unsigned bit7:1;
        };
}_BYTE;
struct TEST
{
        _BYTE b0;
        _BYTE b1;
        _BYTE b2;
        _BYTE b3;
        _BYTE b4;
        _BYTE b5;
        _BYTE b6;
        _BYTE b7;
};
struct TEST T1, T2;

void changedata()
{
                T1.b0.byte = 0x01;
                T1.b1.byte = 0x00;
                T1.b2.byte = 0x01;
                T1.b3.byte = 0x00;
                T1.b4.byte = 0x01;
                T1.b5.byte = 0x01;
                T1.b6.byte = 0x00;
                T1.b7.byte = 0x01;


                T2.b0.byte  = (INT8U)T1.b0.bit0;
                T2.b0.byte |= ((INT8U)T1.b1.bit0<<1);
                T2.b0.byte |= ((INT8U)T1.b2.bit0<<2);
                T2.b0.byte |= ((INT8U)T1.b3.bit0<<3);
                T2.b0.byte |= ((INT8U)T1.b4.bit0<<4);
                T2.b0.byte |= ((INT8U)T1.b5.bit0<<5);
                T2.b0.byte |= ((INT8U)T1.b6.bit0<<6);
                T2.b0.byte |= ((INT8U)T1.b7.bit0<<7);
}
其他数据依次类推,至于能否实现指针之类的共性特性做循环啥的就各自研究了。按举例T2.b0.byte = 0xb5;

出0入0汤圆

发表于 2012-6-19 09:26:53 | 显示全部楼层
修改下。小处理
typedef union
{
        INT8U byte;
        struct
        {
                unsigned bit0:1;                       
                unsigned bit1:1;               
                unsigned bit2:1;       
                unsigned bit3:1;       
                unsigned bit4:1;
                unsigned bit5:1;
                unsigned bit6:1;
                unsigned bit7:1;
        };
}_BYTE;
struct TEST
{
        _BYTE b0;
        _BYTE b1;
        _BYTE b2;
        _BYTE b3;
        _BYTE b4;
        _BYTE b5;
        _BYTE b6;
        _BYTE b7;
};
struct TEST T1, T2;

void changedata()
{
                T1.b0.byte = 0x24;
                T1.b1.byte = 0x21;
                T1.b2.byte = 0xF0;
                T1.b3.byte = 0x7F;
                T1.b4.byte = 0x80;
                T1.b5.byte = 0x37;
                T1.b6.byte = 0xEF;
                T1.b7.byte = 0x1F;

                memset(&T2.b0,0x00,sizeof(T2));

                T2.b0.byte  =  (INT8U)T1.b0.bit0;
                T2.b0.byte |= ((INT8U)T1.b1.bit0<<1);
                T2.b0.byte |= ((INT8U)T1.b2.bit0<<2);
                T2.b0.byte |= ((INT8U)T1.b3.bit0<<3);
                T2.b0.byte |= ((INT8U)T1.b4.bit0<<4);
                T2.b0.byte |= ((INT8U)T1.b5.bit0<<5);
                T2.b0.byte |= ((INT8U)T1.b6.bit0<<6);
                T2.b0.byte |= ((INT8U)T1.b7.bit0<<7);

                T2.b1.byte  =  (INT8U)T1.b0.bit1;
                T2.b1.byte |= ((INT8U)T1.b1.bit1<<1);
                T2.b1.byte |= ((INT8U)T1.b2.bit1<<2);
                T2.b1.byte |= ((INT8U)T1.b3.bit1<<3);
                T2.b1.byte |= ((INT8U)T1.b4.bit1<<4);
                T2.b1.byte |= ((INT8U)T1.b5.bit1<<5);
                T2.b1.byte |= ((INT8U)T1.b6.bit1<<6);
                T2.b1.byte |= ((INT8U)T1.b7.bit1<<7);

                T2.b2.byte  =  (INT8U)T1.b0.bit2;
                T2.b2.byte |= ((INT8U)T1.b1.bit2<<1);
                T2.b2.byte |= ((INT8U)T1.b2.bit2<<2);
                T2.b2.byte |= ((INT8U)T1.b3.bit2<<3);
                T2.b2.byte |= ((INT8U)T1.b4.bit2<<4);
                T2.b2.byte |= ((INT8U)T1.b5.bit2<<5);
                T2.b2.byte |= ((INT8U)T1.b6.bit2<<6);
                T2.b2.byte |= ((INT8U)T1.b7.bit2<<7);

                T2.b3.byte  =  (INT8U)T1.b0.bit3;
                T2.b3.byte |= ((INT8U)T1.b1.bit3<<1);
                T2.b3.byte |= ((INT8U)T1.b2.bit3<<2);
                T2.b3.byte |= ((INT8U)T1.b3.bit3<<3);
                T2.b3.byte |= ((INT8U)T1.b4.bit3<<4);
                T2.b3.byte |= ((INT8U)T1.b5.bit3<<5);
                T2.b3.byte |= ((INT8U)T1.b6.bit3<<6);
                T2.b3.byte |= ((INT8U)T1.b7.bit3<<7);

                T2.b4.byte  =  (INT8U)T1.b0.bit4;
                T2.b4.byte |= ((INT8U)T1.b1.bit4<<1);
                T2.b4.byte |= ((INT8U)T1.b2.bit4<<2);
                T2.b4.byte |= ((INT8U)T1.b3.bit4<<3);
                T2.b4.byte |= ((INT8U)T1.b4.bit4<<4);
                T2.b4.byte |= ((INT8U)T1.b5.bit4<<5);
                T2.b4.byte |= ((INT8U)T1.b6.bit4<<6);
                T2.b4.byte |= ((INT8U)T1.b7.bit4<<7);

                T2.b5.byte  =  (INT8U)T1.b0.bit5;
                T2.b5.byte |= ((INT8U)T1.b1.bit5<<1);
                T2.b5.byte |= ((INT8U)T1.b2.bit5<<2);
                T2.b5.byte |= ((INT8U)T1.b3.bit5<<3);
                T2.b5.byte |= ((INT8U)T1.b4.bit5<<4);
                T2.b5.byte |= ((INT8U)T1.b5.bit5<<5);
                T2.b5.byte |= ((INT8U)T1.b6.bit5<<6);
                T2.b5.byte |= ((INT8U)T1.b7.bit5<<7);

                T2.b6.byte  =  (INT8U)T1.b0.bit6;
                T2.b6.byte |= ((INT8U)T1.b1.bit6<<1);
                T2.b6.byte |= ((INT8U)T1.b2.bit6<<2);
                T2.b6.byte |= ((INT8U)T1.b3.bit6<<3);
                T2.b6.byte |= ((INT8U)T1.b4.bit6<<4);
                T2.b6.byte |= ((INT8U)T1.b5.bit6<<5);
                T2.b6.byte |= ((INT8U)T1.b6.bit6<<6);
                T2.b6.byte |= ((INT8U)T1.b7.bit6<<7);

                T2.b7.byte  =  (INT8U)T1.b0.bit7;
                T2.b7.byte |= ((INT8U)T1.b1.bit7<<1);
                T2.b7.byte |= ((INT8U)T1.b2.bit7<<2);
                T2.b7.byte |= ((INT8U)T1.b3.bit7<<3);
                T2.b7.byte |= ((INT8U)T1.b4.bit7<<4);
                T2.b7.byte |= ((INT8U)T1.b5.bit7<<5);
                T2.b7.byte |= ((INT8U)T1.b6.bit7<<6);
                T2.b7.byte |= ((INT8U)T1.b7.bit7<<7);

}

出0入0汤圆

发表于 2013-1-15 23:17:10 | 显示全部楼层
都是高手,慢慢学习
位操作算法
MARK

出0入0汤圆

发表于 2014-5-17 17:45:55 | 显示全部楼层
顶起来,都是牛人
1

出0入0汤圆

发表于 2014-7-20 16:15:02 | 显示全部楼层
神贴被顶出来了。

出0入0汤圆

发表于 2015-8-15 19:38:29 | 显示全部楼层
再顶神贴  
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-9-3 04:32

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表