打印

怎样以最快的方式操作8位端口?

[复制链接]
4321|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
liaowei230509|  楼主 | 2011-6-22 10:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以低8位为例,可以这样操作(数据时data)
register nsigned char tmp;
tmp = GPIOx->ODR;
tmp &= 0xff00;
tmp |= data;
GPIOx->ODR = tmp;
这样操作用了4条指令,采用ODR应该是最简单最快速的方式了,能否采用BSSR和BRR寄存器一两条指令搞定?
沙发
liaowei230509|  楼主 | 2011-6-22 10:32 | 只看该作者
采用BSRR指令可以这样
register unsigned char tmp;
tmp = ~data;
tmp <<= 16;
tmp |= data;
GPIOx->BSRR = tmp;
我想到的是这样的,第一条语句应该要两条指令,那么就需要5条了
大家还有什么方法吗?

使用特权

评论回复
板凳
denike| | 2011-6-22 10:56 | 只看该作者
#define GPIOA_7_TO_0_PIN (0xFF<<0)
#define Data_OUT(x)    GPIOA->ODR = (GPIOA->ODR & ~GPIOA_7_TO_0_PIN) | (x << 0)

使用特权

评论回复
地板
liaowei230509|  楼主 | 2011-6-22 12:03 | 只看该作者
#define GPIOA_7_TO_0_PIN (0xFFODR & ~GPIOA_7_TO_0_PIN) | (x
denike 发表于 2011-6-22 10:56

你这种方法和我第一种有什么区别?只是写法不同而已,我那样写的目的是每条C语句都可翻译成一条汇编,你可以看看你的方法翻译成汇编后是几条指令,也是一样的

使用特权

评论回复
5
coolie2009| | 2011-7-13 11:21 | 只看该作者
register nsigned char tmp;
tmp = GPIOx->ODR;
tmp &= 0xff00;
tmp |= data;  ----->>>>如果在这里,其它地方(比如中断),修改了GPIOx高8bit的状态,就会被下面的语句给改回去。有风险,呵呵
GPIOx->ODR = tmp;

使用特权

评论回复
6
香水城| | 2011-7-13 11:29 | 只看该作者
本帖最后由 香水城 于 2011-7-14 18:35 编辑

去我的博客中看看: 使用BSRR和BRR寄存器直接操作STM32的I/O端口

使用特权

评论回复
7
STARM| | 2011-7-14 18:31 | 只看该作者

void foo(unsigned char dat)               // dat = 00-00-00-33
{
  asm("mvn r1, r0");                      // R1  = ff-ff-ff-CC
  asm("bfi R0, r1, #16, #8");             // dat = 00-CC-00-33
  GPIOA->BSRR = dat;                      // 两条指令
}                                         // 一条指令 bx lr


这样可以吗 ?






使用特权

评论回复
8
seawwh| | 2011-7-15 08:52 | 只看该作者
以低8位为例,可以这样操作(数据时data)
register nsigned char tmp;
tmp = GPIOx->ODR;
tmp &= 0xff00;
tmp |= data;
GPIOx->ODR = tmp;
这样操作用了4条指令,采用ODR应该是最简单最快速的方式了,能否采用BSSR和B ...
liaowei230509 发表于 2011-6-22 10:23



可以这样实现:
GPIOx->BSRR= 0x00FF0000 | data;   // data 是8位
原理:
  BSSR 的低16位操作优先。

使用特权

评论回复
9
liaowei230509|  楼主 | 2011-7-15 11:43 | 只看该作者
7# STARM
可以那样,其实你这种就是GPIOX-BSRR = ((~data)<<16)|data;这样就只有3条指令就可以实现了

使用特权

评论回复
10
liaowei230509|  楼主 | 2011-7-15 11:44 | 只看该作者
register nsigned char tmp;
tmp = GPIOx->ODR;
tmp &= 0xff00;
tmp |= data;  ----->>>>如果在这里,其它地方(比如中断),修改了GPIOx高8bit的状态,就会被下面的语句给改回去。有风险,呵呵
GPIOx->ODR = tmp; ...
coolie2009 发表于 2011-7-13 11:21

呵呵,说的没错,我现在都用BSRR的方式的了

使用特权

评论回复
11
liaowei230509|  楼主 | 2011-7-15 11:47 | 只看该作者
可以这样实现:
GPIOx->BSRR= 0x00FF0000 | data;   // data 是8位
原理:
  BSSR 的低16位操作优先。
seawwh 发表于 2011-7-15 08:52

应该是GPIOx->BSRR= 0xFFFF0000 | data; 这样吧?没错,这样很好,两条指令就可以搞定了,还是你厉害,呵呵

使用特权

评论回复
12
liaowei230509|  楼主 | 2011-7-15 11:49 | 只看该作者
本帖最后由 liaowei230509 于 2011-7-15 15:08 编辑
应该是GPIOx->BSRR= 0xFFFF0000 | data; 这样吧?没错,这样很好,两条指令就可以搞定了,还是你厉害,呵呵
liaowei230509 发表于 2011-7-15 11:47

不好意思,糊涂了,你那样写法是对的,我那样写把高8位清0了

使用特权

评论回复
13
STARM| | 2011-7-15 12:18 | 只看该作者
7# STARM  
可以那样,其实你这种就是GPIOX-BSRR = ((~data)
liaowei230509 发表于 2011-7-15 11:43


void foo(unsigned char data)
{
  GPIOA->BSRR = ((~data)<<16)|data;
}

data = 0x33;

bsrr = 0xFFCC0033 而不是 0x00CC0033;
汇编为

mvns R1, R0
orr.w r0, r0, r1, lsl #16

使用特权

评论回复
14
STARM| | 2011-7-15 12:21 | 只看该作者
void foo(unsigned char data)
{
  GPIOA->BSRR = ( (unsigned char)(~data) <<16 ) |data;
}

可以得出期望结果, 不过多了一条指令

汇编为
mvns R1, R0
uxtb R1, R1 <--- 调整为字节, 而不是半字
orr.w r0, r0, r1, lsl #16

使用特权

评论回复
15
liaowei230509|  楼主 | 2011-7-15 15:10 | 只看该作者
void foo(unsigned char data)
{
  GPIOA->BSRR = ( (unsigned char)(~data)
STARM 发表于 2011-7-15 12:21


GPIOA->BSRR = ( ((~data)&0xff) <<16 ) |data;
我是这样做的,结果是发现占用3条汇编指令,还是
GPIOA->BSRR = 0x00ff0000|data;这样最好

使用特权

评论回复
16
STARM| | 2011-7-15 16:28 | 只看该作者
GPIOA->BSRR = 0x00ff0000|data;
确实这样最好, 只需一条指令

使用特权

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

本版积分规则

6

主题

67

帖子

1

粉丝