硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1715|回复: 6
收起左侧

分享一个类似于位带操作IO的方法(读改写)

[复制链接]

4

主题

52

回帖

64

积分

初级会员

积分
64
发表于 2019-6-18 09:46:56 | 显示全部楼层 |阅读模式
本帖最后由 cortex 于 2019-6-18 09:48 编辑

用过F4或者F7的知道,F7或者F7以上的不支持位带操作。对单个IO操作只能用度改写,一般形式如下:
  1. 读改写方式:
复制代码
如果以前F4平台使用了位带操作,但是由于产品要求,需要用更高性能的F7。问题来了,需要修改大量的对IO操作的函数。

通过我的总结,发现可用用读改写的方式稍微修改,就和位带操作有点类似了:
1、定义如下结构体,作用就是把一个32位变量分成32个部分,每一个部分占用1位,可以直接操作某一位而不改变另外的位。操作方法其实也是读改写的方式,只不过是写法简单了。
  1. typedef struct
  2. {
  3.         uint32_t BIT0  : 1;
  4.         uint32_t BIT1  : 1;
  5.         uint32_t BIT2  : 1;
  6.         uint32_t BIT3  : 1;
  7.         uint32_t BIT4  : 1;
  8.         uint32_t BIT5  : 1;
  9.         uint32_t BIT6  : 1;
  10.         uint32_t BIT7  : 1;
  11.         uint32_t BIT8  : 1;
  12.         uint32_t BIT9  : 1;
  13.         uint32_t BIT10 : 1;
  14.         uint32_t BIT11 : 1;
  15.         uint32_t BIT12 : 1;
  16.         uint32_t BIT13 : 1;
  17.         uint32_t BIT14 : 1;
  18.         uint32_t BIT15 : 1;
  19.         uint32_t BIT16 : 1;
  20.         uint32_t BIT17 : 1;
  21.         uint32_t BIT18 : 1;
  22.         uint32_t BIT19 : 1;
  23.         uint32_t BIT20 : 1;
  24.         uint32_t BIT21 : 1;
  25.         uint32_t BIT22 : 1;
  26.         uint32_t BIT23 : 1;
  27.         uint32_t BIT24 : 1;
  28.         uint32_t BIT25 : 1;
  29.         uint32_t BIT26 : 1;
  30.         uint32_t BIT27 : 1;
  31.         uint32_t BIT28 : 1;
  32.         uint32_t BIT29 : 1;
  33.         uint32_t BIT30 : 1;
  34.         uint32_t BIT31 : 1;
  35. }Bit_Type;


  36. //输出寄存器
  37. #define PAout(pin)         (*(Bit_Type *)&GPIOA->ODR).BIT ## pin
  38. #define PBout(pin)         (*(Bit_Type *)&GPIOB->ODR).BIT ## pin
  39. #define PCout(pin)         (*(Bit_Type *)&GPIOC->ODR).BIT ## pin
  40. #define PDout(pin)         (*(Bit_Type *)&GPIOD->ODR).BIT ## pin
  41. #define PEout(pin)         (*(Bit_Type *)&GPIOE->ODR).BIT ## pin
  42. #define PFout(pin)         (*(Bit_Type *)&GPIOF->ODR).BIT ## pin
  43. #define PGout(pin)         (*(Bit_Type *)&GPIOG->ODR).BIT ## pin
  44. #define PHout(pin)         (*(Bit_Type *)&GPIOH->ODR).BIT ## pin
  45. #define PIout(pin)         (*(Bit_Type *)&GPIOI->ODR).BIT ## pin
  46. #define PJout(pin)         (*(Bit_Type *)&GPIOJ->ODR).BIT ## pin
  47. #define PKout(pin)         (*(Bit_Type *)&GPIOK->ODR).BIT ## pin

  48. //输入寄存器
  49. #define PAin(pin)         (*(Bit_Type *)&GPIOA->IDR).BIT ## pin
  50. #define PBin(pin)         (*(Bit_Type *)&GPIOB->IDR).BIT ## pin
  51. #define PCin(pin)         (*(Bit_Type *)&GPIOC->IDR).BIT ## pin
  52. #define PDin(pin)         (*(Bit_Type *)&GPIOD->IDR).BIT ## pin
  53. #define PEin(pin)         (*(Bit_Type *)&GPIOE->IDR).BIT ## pin
  54. #define PFin(pin)         (*(Bit_Type *)&GPIOF->IDR).BIT ## pin
  55. #define PGin(pin)         (*(Bit_Type *)&GPIOG->IDR).BIT ## pin
  56. #define PHin(pin)         (*(Bit_Type *)&GPIOH->IDR).BIT ## pin
  57. #define PIin(pin)         (*(Bit_Type *)&GPIOI->IDR).BIT ## pin
  58. #define PJin(pin)         (*(Bit_Type *)&GPIOJ->IDR).BIT ## pin
  59. #define PKin(pin)         (*(Bit_Type *)&GPIOK->IDR).BIT ## pin
复制代码


2、实现跑马灯的翻转,编写以下代码,可以看到LED是可以闪烁的。
  1. //定义宏(使用原子的板子,当然IO可以随意修改)
  2. #define LED0        PBout(1)
  3. #define LED1        PBout(0)

  4. //在main函数的while(1)里实现如下代码:
复制代码


3、其实汇编代码和读改写是一样的,也就是以下代码是等价的,只是方便写代码,不容易出错。汇编代码就不贴了
  1. PBout(0) = 0;  //等价于GPIOB->ODR &= ~(1<<0);

  2. PBout(0) = 1;  等价于GPIOB->ODR |= 1<<1;
复制代码


4、但是呢还是有个小缺陷,因为是宏定义,所以是不能实现如下操作方式的:
  1. n = 0;
  2. PBout(n) = 0;
  3. n = 1;
  4. PBout(n) = 0;
复制代码


好久之前就想到了次方法,只是没时间贴出来,不知道次方法有没有什么问题,望广大各大佬们指教!





回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
111801
QQ
发表于 2019-6-18 10:48:36 | 显示全部楼层
改用BSRR寄存器效果更好,支持原子操作。
回复

使用道具 举报

4

主题

52

回帖

64

积分

初级会员

积分
64
 楼主| 发表于 2019-6-18 11:15:44 | 显示全部楼层
eric2013 发表于 2019-6-18 10:48
改用BSRR寄存器效果更好,支持原子操作。

BSRR和BRR速度是最快的,没有读改写的操作
回复

使用道具 举报

23

主题

1434

回帖

1503

积分

至尊会员

积分
1503
发表于 2019-6-18 12:20:44 | 显示全部楼层
本帖最后由 missfox 于 2019-6-18 12:21 编辑

bitband操作,这位老铁的实现是最秀的,也是最简单的,网上的其它实现方式都有些臃肿,不过不适合M7内核,因为M7不支持bitband

MDK:位区(bitband)操作新方法
https://www.amobbs.com/thread-4414916-1-1.html

代码不规范,亲人两行泪!
回复

使用道具 举报

4

主题

52

回帖

64

积分

初级会员

积分
64
 楼主| 发表于 2019-6-18 14:15:35 | 显示全部楼层
missfox 发表于 2019-6-18 12:20
bitband操作,这位老铁的实现是最秀的,也是最简单的,网上的其它实现方式都有些臃肿,不过不适合M7内核, ...

还是广大网友厉害,各自借鉴。
回复

使用道具 举报

5

主题

582

回帖

597

积分

版主

Rank: 7Rank: 7Rank: 7

积分
597
发表于 2019-6-18 20:10:46 | 显示全部楼层
如果用mdk的话,可以给结构体指定一个位带属性,就会给你上述代码自动生成真正的位带操作
回复

使用道具 举报

5

主题

582

回帖

597

积分

版主

Rank: 7Rank: 7Rank: 7

积分
597
发表于 2019-6-18 20:11:22 | 显示全部楼层
missfox 发表于 2019-6-18 12:20
bitband操作,这位老铁的实现是最秀的,也是最简单的,网上的其它实现方式都有些臃肿,不过不适合M7内核, ...

是的 就是这种做法
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-11-11 03:17 , Processed in 0.223031 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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