发新帖我要提问
12
返回列表
打印

求助:STM32位段高效率的操作

[复制链接]
楼主: kami03372
手机看帖
扫描二维码
随时随地手机跟帖
21
香水城| | 2010-8-17 15:26 | 只看该作者 回帖奖励 |倒序浏览
真不好意思,你怎么只看5楼的回复,我在9楼的回复却不看?

原来你是有选择地看帖?

使用特权

评论回复
22
香水城| | 2010-8-17 15:26 | 只看该作者
CS_H和CS_L是什么信号?哪个引脚?具体什么操作?

使用特权

评论回复
23
winloop| | 2010-8-17 15:49 | 只看该作者
能简化代码量就很有诱惑力了

使用特权

评论回复
24
vigia| | 2010-8-17 17:48 | 只看该作者
细看了下5楼朋友的 回复.......心凉了..........
BitBand不能减少操作时间
仅仅是简化操作减小代码量......:'(
kami03372 发表于 2010-8-17 15:22


5楼的我来回复了,汗,最近老说话不清楚:L :L :L :L :L


我说的不能减少操作时间指的是:

使用BITBAND命令,虽然只有一条语句,但仍然是读寄存器值,改寄存器值和写寄存器值3个步骤,和3条语句的执行时间是一样的,从这方面来说只是减少了代码量,并没有节省操作时间。

但是!!!!

合理的使用BITBAND可以节省大量的其他的操作时间,比如移位,比如比较,比如赋值。。。就像我第三个PPT贴的那个例子。

从你的应用看,使用BITBAND应该可以节省大量的时间的,因为你用了大量的比较和移位操作。不过我暂时没有时间帮你仔细看代码。。。。。

使用特权

评论回复
25
kami03372|  楼主 | 2010-8-17 19:26 | 只看该作者
真不好意思,你怎么只看5楼的回复,我在9楼的回复却不看?

原来你是有选择地看帖?
香水城 发表于 2010-8-17 15:26

都看了啊,呵呵!
CS_H,CS_L,就是B口的一个普通的IO,输出高低电平变化用,提供时钟CLOCK信号

按理说修改后的代码是比以前少了很多计算量,但实际运行次数确实是少了!

我在试试看看

使用特权

评论回复
26
kami03372|  楼主 | 2010-8-17 20:39 | 只看该作者
target1[7]=tempcount;
target1[5]=tempcount;
target1[3]=tempcount;
target1[1]=tempcount;
表达式左边是使用位域的地址,赋值固定的局部变量,这个时候很快,每秒470次左右
target1[7]=src1[28];
target1[5]=src2[28];
target1[3]=src3[28];
target1[1]=src4[28];
都使用位域以后,每秒执行次数还是在150次左右
target1[7]=buff[12];
target1[5]=buff[13];
target1[3]=buff[14];
target1[1]=buff[15];
表达式右边不使用位域,我直接用缓冲区的数据,随便赋值这样执行,测量还是150次左右。
时间貌似消耗在更新取值上面了
MDK的优化optimization,选择的是3级优化,optimize for time 也选上了
可能只能这样了啊

使用特权

评论回复
27
mcuisp| | 2010-8-17 21:23 | 只看该作者
呵呵,香版在捍卫arm公司的荣誉。
不知有津贴发否:victory:

使用特权

评论回复
28
香水城| | 2010-8-17 21:42 | 只看该作者
1)CS_H和CS_L的语句如果写得不好也会额外消耗时间。

2)如果CS_H和CS_L都是对同一端口操作,则会有数据访问相关性。为了消除这个影响,可以尝试在这2个语句之间插入其它语句,比如这样(以16楼的代码为例):
   target1[7]=*psrc>>7;
    target1[5]=*psrc1>>7;
    target1[3]=*psrc2>>7;
    target1[1]=*psrc3>>7;
    GPIOA->ODR =tempdata1;
   
    target1[7]=*psrc>>6;
    CS_H;
    target1[5]=*psrc1>>6;
    CS_L;
    target1[3]=*psrc2>>6;
    target1[1]=*psrc3>>6;
这样不会改变你的程序逻辑,但减小或消除了数据访问相关性的影响。

3)看看生成的汇编码,有没有不合理的地方?

使用特权

评论回复
29
香水城| | 2010-8-17 21:43 | 只看该作者
呵呵,香版在捍卫arm公司的荣誉。
不知有津贴发否:victory:
mcuisp 发表于 2010-8-17 21:23


哈哈,我这不是捍卫谁的荣誉,这是捍卫真理,:lol

使用特权

评论回复
30
kami03372|  楼主 | 2010-8-17 22:32 | 只看该作者
30# 香水城


1、CS_H和CS_L语句   #define CS_H {GPIOB->BSRR=GPIO_Pin_1;}
                               #define CS_L {GPIOB->BRR=GPIO_Pin_1;}

2、3两项明天我在修改测测看看!

使用特权

评论回复
31
kami03372|  楼主 | 2010-8-18 16:44 | 只看该作者
今天使用串口,把每秒循环体执行的次数发送出来,精确的数据如下:

tempdata1=(((*psrc)&0x01)<<7)|(((*psrc1)&0x01)<<5)|(((*psrc2)&0x01)
               <<3)| (((*psrc3)&0x01)<<1);
GPIOA->ODR =tempdata1;
CS_H;   //#define CS_H {GPIOB->BSRR=GPIO_Pin_1;}
CS_L;   //#define CS_L{GPIOB->BRR=GPIO_Pin_1;}

//上面代码,数据采用这种最先的输出方法
//每秒执行次数152次
tempdata1=(((*psrc)&0x01)<<7)|(((*psrc1)&0x01)<<5)|(((*psrc2)&0x01)
                <<3)|(((*psrc3)&0x01)<<1);
GPIOA->ODR =tempdata1;
(*((uint32*)(0x40010C10)))=GPIO_Pin_1;
(*((uint32*)(0x40010C14)))=GPIO_Pin_1;

//上面的代码,改变了那个GPIOB-Pin1的输出方法,直接使用BSRR和BRR的地址
//每秒执行次数177次
target1[7]=*psrc>>7;
target1[5]=*psrc1>>7;
target1[3]=*psrc2>>7;
target1[1]=*psrc3>>7;
GPIOA->ODR =tempdata1;
(*((uint32*)(0x40010C10)))=GPIO_Pin_1;
(*((uint32*)(0x40010C14)))=GPIO_Pin_1;

//上面代码,使用了位域,target1为temdata1的位域
//每秒执行次数137次,有所下降
GPIOA->ODR=(((*psrc)&0x02)<<6)|(((*psrc1)&0x02)
           <<4)|(((*psrc2)&0x02)<<2)|(((*psrc3)&0x02));
(*((uint32*)(0x40010C10)))=GPIO_Pin_1;
(*((uint32*)(0x40010C14)))=GPIO_Pin_1;

//上面代码,放弃了位域,把数据的整理和输出放在同一个表达式里面
//每秒执行次数190次//这个是目前为止,执行次数最多的形式。
//后来在朋友的提示下,
//增加了位域和联合体,如下
typedef struct _Osrsdata
{
uint8 Bit0:1;
uint8 Bit1:1;
uint8 Bit2:1;
uint8 Bit3:1;
uint8 Bit4:1;
uint8 Bit5:1;
uint8 Bit6:1;
uint8 Bit7:1;
}OneCorSrs;


typedef union Srs_dataAll
{
OneCorSrs     SignleColor;
uint8 outputbuff;
}OUTPUTDATA;


OUTPUTDATA   Outputdata[4];

Outputdata[0].outputbuff=*psrc;
Outputdata[1].outputbuff=*psrc1;
Outputdata[2].outputbuff=*psrc2;
Outputdata[3].outputbuff=*psrc3;


GPIOA->ODR=(Outputdata[0].SignleColor.Bit0<<7)|(Outputdata
               [1].SignleColor.Bit0<<5)|(Outputdata[2].SignleColor.Bit0<<3)|
                     (Outputdata[3].SignleColor.Bit0<<1);

(*((uint32*)(0x40010C10)))=GPIO_Pin_1;
(*((uint32*)(0x40010C14)))=GPIO_Pin_1;

//使用了如上形式,每秒的执行次数达
//到了306次:)这个够用了,数据正
//确性还没验证,稍后验证!








使用特权

评论回复
32
kami03372|  楼主 | 2010-8-18 16:56 | 只看该作者
谢谢大家的帮助!:)
这里有几点疑问!
1、GPIOB->BSRR=GPIO_Pin_1与(*((uint32*)(0x40010C10)))=GPIO_Pin_1;
    这两种方法的执行速度有差距,后者比前者更快速,这点可能是库函数的原因,毕竟
    直接访问内存区域最快,猜测!
2、在上面1的基础上我尝试把GPIOA->ODR =tempdata1;这个数据输出修改成
    (*((uint32*)(0x4001080c)))=tempdata1;也是直接使用了GPIOA->ODR的地
    址,但是速度却慢了,不懂中。
3、target1[7]=*psrc>>7;这个形式,表达式左边使用了位域,计算量明显减少很多
    ,但是实际测试结果还是下降一些,不懂!
4、表达式不要太复杂,好像以前有人这样教我
     GPIOA->ODR=(((*psrc)&0x02)<<6)|(((*psrc1)&0x02)<<4)|(((*psrc2)
       &0x02)<<2)|(((*psrc3)&0x02));
    但是这样都写在一起的方法是最快的,可能是有R32个寄存器,对付这个有余,猜测
    玩的




使用特权

评论回复
33
kami03372|  楼主 | 2010-8-18 17:02 | 只看该作者
速度是越快越好,不知道大家还有什么方法可以在提速,说出来,我可以试试!
谢谢大家了!

使用特权

评论回复
34
香水城| | 2010-8-18 18:26 | 只看该作者
关于32楼的疑问,请对照编译出来的汇编指令。

我知道的,这里有几个因素:
1)GPIOB->BSRR  这是一个结构体的分量,要看编译器如何处理;GPIOA->ODR也是是一个结构体的分量。
2)target1[7]是一个数组,也要看编译器如何处理。
3)关于位域和联合体的处理,同样要看编译器如何处理。

还要看优化是怎么做的。

使用特权

评论回复
35
mcuisp| | 2010-8-19 08:36 | 只看该作者
要速度,用汇编。

   A人如是说。

使用特权

评论回复
36
kami03372|  楼主 | 2010-8-19 19:56 | 只看该作者
汇编不会啊,哎

使用特权

评论回复
37
kami03372|  楼主 | 2010-8-19 19:57 | 只看该作者
以后得学学~

使用特权

评论回复
38
28182900| | 2013-1-25 16:20 | 只看该作者
交谈中请勿轻信汇款、中奖信息、陌生电话,勿使用外挂软件。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则