Cortex-M0模仿位带操作使用

Cortex-M3/M4有位带区(BIT-BAND),可以进行位带操作,而Cortex-M0是没有此功能区域的。

必须说明一点,BIT-BAND的本质可以说是空间换时间。是为追求速度而设置的功能。像STM32F0XX这些Cortex-M0系列的MCU,如果追求速度,还是老老实实操作BSRR/BRR这类专门的寄存器。

如果不介意速度损失,单纯想做出类似"位带"操作(比如:PAout(0)= 0,可让GPIOA.0拉低),还是可以的。

以STM32F0XX为例,因为16个IO为一组(比如PA0~PA15),则可定义一个包含16个位的结构体

typedef struct
{
    u16 bit0 : 1;
    u16 bit1 : 1;
    u16 bit2 : 1;
    u16 bit3 : 1;
    u16 bit4 : 1;
    u16 bit5 : 1;
    u16 bit6 : 1;
    u16 bit7 : 1;
    u16 bit8 : 1;
    u16 bit9 : 1;
    u16 bit10 : 1;
    u16 bit11 : 1;
    u16 bit12 : 1;
    u16 bit13 : 1;
    u16 bit14 : 1;
    u16 bit15 : 1;
} Bits16_TypeDef;

 这样,对各个IO的读取和赋值可以定义成以下宏:"模仿位带宏"

#define PAin(n) ( ( GPIOA->IDR&(1 << (n)) )>>n )
#define PBin(n) ( ( GPIOB->IDR&(1 << (n)) )>>n )
#define PCin(n) ( ( GPIOC->IDR&(1 << (n)) )>>n )
#define PDin(n) ( ( GPIOD->IDR&(1 << (n)) )>>n )
#define PEin(n) ( ( GPIOE->IDR&(1 << (n)) )>>n )
#define PFin(n) ( ( GPIOF->IDR&(1 << (n)) )>>n )

#define PAout(n)  ( ((Bits16_TypeDef *)(&(GPIOA->ODR)))->bit##n )
#define PBout(n)  ( ((Bits16_TypeDef *)(&(GPIOB->ODR)))->bit##n )
#define PCout(n)  ( ((Bits16_TypeDef *)(&(GPIOC->ODR)))->bit##n )
#define PDout(n)  ( ((Bits16_TypeDef *)(&(GPIOD->ODR)))->bit##n )
#define PEout(n)  ( ((Bits16_TypeDef *)(&(GPIOE->ODR)))->bit##n )
#define PFout(n)  ( ((Bits16_TypeDef *)(&(GPIOF->ODR)))->bit##n )

这样,就可以类似Cortex-M3/M4那样操作了。在STM32F030上测试OK。使用限制是:PXout(n)中的n只能是0~15,不能是变量。

对比一下STM32F0XX对应的库函数

/**
  * @brief  Reads the specified input port pin.
  * @param  GPIOx: where x can be (A, B, C, D or F) to select the GPIO peripheral.
  * @param  GPIO_Pin: specifies the port bit to read.
  * @note   This parameter can be GPIO_Pin_x where x can be:(0..15) for GPIOA,
  *         GPIOB or GPIOC,(0..2) for GPIOD and(0..3) for GPIOF.
  * @retval The input port pin value.
  */
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
    uint8_t bitstatus = 0x00;

    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

    if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
    {
        bitstatus = (uint8_t)Bit_SET;
    }
    else
    {
        bitstatus = (uint8_t)Bit_RESET;
    }
    return bitstatus;
}

/**
  * @brief  Sets or clears the selected data port bit.
  * @param  GPIOx: where x can be (A, B, C, D or F) to select the GPIO peripheral.
  * @param  GPIO_Pin: specifies the port bit to be written.
  * @param  BitVal: specifies the value to be written to the selected bit.
  *          This parameter can be one of the BitAction enumeration values:
  *            @arg Bit_RESET: to clear the port pin
  *            @arg Bit_SET: to set the port pin
  * @note   The GPIO_Pin parameter can be GPIO_Pin_x where x can be: (0..15) for GPIOA,
  *         GPIOB or GPIOC,(0..2) for GPIOD and(0..3) for GPIOF.
  * @retval None
  */
void GPIO_WriteBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
{
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
    assert_param(IS_GPIO_BIT_ACTION(BitVal));

    if (BitVal != Bit_RESET)
    {
        GPIOx->BSRR = GPIO_Pin;
    }
    else
    {
        GPIOx->BRR = GPIO_Pin ;
    }
}

考虑到Cortex-M0为3级流水线RISC处理器,搞不好我的"模仿位带宏"速度更快,至少时间稳健性更好。

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值