打印
[STM32F1]

如何实现快速操作对应IO口?如题

[复制链接]
2028|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gmgmgm|  楼主 | 2014-4-28 16:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 gmgmgm 于 2014-4-28 16:46 编辑

STM32F103的如何实同像STM8那样可以位定义后直接位操作?

已知下面是STM8 对应端口位定义 类似C51
_Bool PA0_ODR @PA_ODR:0;
_Bool PA1_ODR @PA_ODR:1;
_Bool PA2_ODR @PA_ODR:2;
_Bool PA3_ODR @PA_ODR:3;
_Bool PA4_ODR @PA_ODR:4;
_Bool PA5_ODR @PA_ODR:5;
_Bool PA6_ODR @PA_ODR:6;
_Bool PA7_ODR @PA_ODR:7;
有了上面的位定义,可以将一数据数轻松地进位移,速度快,
如将一8位数通过位移操作从PA0端口送出
in_data=0x23;
for(i=0;i<8;i++)
   {

   PA0_ODR=in_data&0x01;

   in_data>>=1;

   }

STM32却只能位移时多加一个判断操作,多了条指令,网上看了很多资料我知道下面是最快的操作了,有人知道还有更快的操作速度吗?
我知道的STM32F103操作上面那段函数如下
in_data=0x23;
for(i=0;i<8;i++)
   {

  if(in_data&0x01)   {GPIOA->BSRR = GPIO_BSRR_BS0;}//这里先判断,不能直接位操作,我是菜鸟,有没有可以省掉判断这一条指令?

else {GPIOA->BSRR = GPIO_BSRR_BR0;}

   in_data>>=1;

   }

请问,STM32 能不能像STM8那样直接把IO口对应定义好?


沙发
mmuuss586| | 2014-4-28 17:21 | 只看该作者
ARM和51内核不一样。
写1和0,操作的是不同的寄存器,没办法。
官方的位操作指令也是这样:
  if (BitVal != Bit_RESET)
  {
    GPIOx->BSRR = GPIO_Pin;
  }
  else
  {
    GPIOx->BRR = GPIO_Pin;
  }

使用特权

评论回复
板凳
error_dan| | 2014-4-28 19:12 | 只看该作者
位带操作。

使用特权

评论回复
地板
gmgmgm|  楼主 | 2014-4-28 22:55 | 只看该作者
mmuuss586 发表于 2014-4-28 17:21
ARM和51内核不一样。
写1和0,操作的是不同的寄存器,没办法。
官方的位操作指令也是这样:

刚接触STM32几天时间,为了达到快速操作端口目的,调了几天程序,终于明白了,谢谢!

使用特权

评论回复
5
jjjkkk00| | 2014-4-29 09:58 | 只看该作者
本帖最后由 jjjkkk00 于 2014-4-29 10:05 编辑

使用bitband功能,可能会满足的你需求。具体的你自己测试下。
优点是:对Bit-band区域的写操作Cortex-M3内核终仍然执行读-修改-写的 过程,但代码量得到简化,并能防止错误的写入。
缺点是:编程工作量增大,因为需要提前计算Bit-band地址。
其中以下缺点可以克服:【可读性】可以通过自定义的宏来改善,【Bit-band地址计算】Bit-band地址也可以用宏。

//BitBand的define使用举例: BitBand_SetVal(GPIOF_BASE, 0xC, 6, 1);//GPIO_SetBits(GPIOF, GPIO_Pin_6);
#define BitBand_SetVal(PPP, Offset, BitNo, Val)\
          (*(vu32*) (0x42000000 | ((PPP & 0x0FFFFFFF)<<5) | (Offset<<5) | (BitNo<<2)) = (Val))
#define BitBand_GetAddr(PPP, Offset, BitNo)\
          (0x42000000 | ((PPP & 0x0FFFFFFF)<<5) | (Offset<<5) | (BitNo<<2))
下面例举了一个GPIO的操作:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
  while (1)
  {
    GPIO_SetBits(GPIOF, GPIO_Pin_6|GPIO_Pin_7 | GPIO_Pin_8|GPIO_Pin_9);Delay_us(500);GPIO_ResetBits(GPIOF, GPIO_Pin_6|GPIO_Pin_7 | GPIO_Pin_8|GPIO_Pin_9);Delay_us(500);}
对应的bitband代码:
//使用bitband代码,直接操作bitband地址:通过GPIOF.06/07/08/09输出电平,驱动LED
  (*(vu32*)0x4242031C) = 1;//RCC_APB2...IOFEN
  
  (*(vu32*)0x42238060) = 1;//GPIOF_CRL...MODE6_0(0x4223806?)
  (*(vu32*)0x42238064) = 1;//GPIOF_CRL...MODE6_1
  (*(vu32*)0x42238068) = 0;//GPIOF_CRL...CNF6_0
  (*(vu32*)0x4223806C) = 0;//GPIOF_CRL...CNF6_1
  
  (*(vu32*)0x42238070) = 1;//GPIOF_CRL...MODE7_0(0x4223807?)
  (*(vu32*)0x42238074) = 1;//GPIOF_CRL...MODE7_1
  (*(vu32*)0x42238078) = 0;//GPIOF_CRL...CNF7_0
  (*(vu32*)0x4223807C) = 0;//GPIOF_CRL...CNF7_1
  
  (*(vu32*)0x42238080) = 1;//GPIOF_CRH...MODE8_0(0x4223808?)
  (*(vu32*)0x42238084) = 1;//GPIOF_CRH...MODE8_1
  (*(vu32*)0x42238088) = 0;//GPIOF_CRH...CNF8_0
  (*(vu32*)0x4223808C) = 0;//GPIOF_CRH...CNF8_1
  
  (*(vu32*)0x42238090) = 1;//GPIOF_CRH...MODE9_0(0x4223809?)
  (*(vu32*)0x42238094) = 1;//GPIOF_CRH...MODE9_1
  (*(vu32*)0x42238098) = 0;//GPIOF_CRH...CNF9_0
  (*(vu32*)0x4223809C) = 0;//GPIOF_CRH...CNF9_1

  while(1)
  {
    (*(vu32*)0x42238198) = 1;//GPIOF_ODR...Pin6
    (*(vu32*)0x4223819C) = 1;//GPIOF_ODR...Pin7
    (*(vu32*)0x422381A0) = 1;//GPIOF_ODR...Pin8
    (*(vu32*)0x422381A4) = 1;//GPIOF_ODR...Pin9
   
    Delay_us(500);
   
    (*(vu32*)0x42238198) = 0;//GPIOF_ODR...Pin6
    (*(vu32*)0x4223819C) = 0;//GPIOF_ODR...Pin7
    (*(vu32*)0x422381A0) = 0;//GPIOF_ODR...Pin8
    (*(vu32*)0x422381A4) = 0;//GPIOF_ODR...Pin9
   
    Delay_us(500);
  }


使用特权

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

本版积分规则

135

主题

766

帖子

2

粉丝