位带操作简介

位带操作的概念其实30年前就有了,那还是 8051单片机开创的先河,如今ARM CM3 将此能力进化,可以说,这里的位带操作是8051 位寻址区的威力大幅加强版。即如果要改写某个寄存器的某一位,通过改写这一位映射的地址即可。东芝的TT_M3HQ开发板也是ARM CM3的MCU,实现了位带操作,就可以如同51单片机控制GPIO口一样的方便。

位带操作的优越性

初学51时,对某一个IO口进行输出操作,或者读取输入时,可以通过如下方式:

#define LED P1^0
#define KEY P1^2 LED = 0; //输出0 if(KEY == 0) //读取按键输入
{ }

对于东芝TMPM3HQFDFG,如果没有位带操作,我们需要使用如下函数来实现读取和输入。在txz_gpio.c和txz_gpio.h两个库文件中,我们可以了解到写函数和读函数的使用方法。

写函数:

gpio_t port;

//PK4输出低电平
gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_4, GPIO_Mode_DATA, GPIO_PIN_RESET); //PK4输出高电平
gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_4, GPIO_Mode_DATA, GPIO_PIN_SET);

读函数:

//读取PV3输入

gpio_pinstate_t key_status;
gpio_t port;
gpio_read_bit(&port, KEY_PORT, KEY_PIN, GPIO_Mode_DATA, &key_status);

而如果实现了位带操作,我们只需要使用两个宏就可以实现:

PK4输出:PKout(4) = 0;
读取PV3输入:in = PVin(3);

实现按键按下LED闪烁:

   if(PVin(3) == GPIO_PIN_RESET)	//按键按下LED闪烁
{
PKout(4) = 1; //点亮
delay_ms(50); PKout(4) = 0; //熄灭
delay_ms(50);
}

是不是很简单呢?通过查看官方txz_gpio.c库文件中输出和输入函数的实现,可以看出是使用的位带方式,但是看着不是很简洁,有没有更简单一些的实现方法呢?

位带操作的实现

新建sys.h,主要通过宏定义的方式实现IO的输出和输入。

#ifndef  __SYS_H__
#define __SYS_H__ #include "TMPM3HQ.h"
#include "TMPM3Hy.h" #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) #define PORTx_BASE(group) (0x400C0000UL + (uint32_t)((0x0000100UL) * (group)))
#define PORTx_MODE_BASE(group) ((uint32_t)(PORTx_BASE(group)) + (uint32_t)(GPIO_Mode_DATA)) #define PORTA_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_A)
#define PORTB_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_B)
#define PORTC_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_C)
#define PORTD_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_D)
#define PORTE_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_E)
#define PORTF_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_F)
#define PORTG_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_G)
#define PORTH_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_H)
#define PORTJ_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_J)
#define PORTK_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_K)
#define PORTL_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_L)
#define PORTM_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_M)
#define PORTN_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_N)
#define PORTP_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_P)
#define PORTR_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_R)
#define PORTT_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_T)
#define PORTU_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_U)
#define PORTV_ODR_ADDR PORTx_MODE_BASE(GPIO_PORT_V) #define PAout(n) BIT_ADDR(PORTA_ODR_ADDR, n)
#define PBout(n) BIT_ADDR(PORTB_ODR_ADDR, n)
#define PCout(n) BIT_ADDR(PORTC_ODR_ADDR, n)
#define PDout(n) BIT_ADDR(PORTD_ODR_ADDR, n)
#define PEout(n) BIT_ADDR(PORTE_ODR_ADDR, n)
#define PFout(n) BIT_ADDR(PORTF_ODR_ADDR, n)
#define PGout(n) BIT_ADDR(PORTG_ODR_ADDR, n)
#define PHout(n) BIT_ADDR(PORTH_ODR_ADDR, n)
#define PJout(n) BIT_ADDR(PORTJ_ODR_ADDR, n)
#define PKout(n) BIT_ADDR(PORTK_ODR_ADDR, n)
#define PLout(n) BIT_ADDR(PORTL_ODR_ADDR, n)
#define PMout(n) BIT_ADDR(PORTM_ODR_ADDR, n)
#define PNout(n) BIT_ADDR(PORTN_ODR_ADDR, n)
#define PPout(n) BIT_ADDR(PORTP_ODR_ADDR, n)
#define PRout(n) BIT_ADDR(PORTR_ODR_ADDR, n)
#define PTout(n) BIT_ADDR(PORTT_ODR_ADDR, n)
#define PUout(n) BIT_ADDR(PORTU_ODR_ADDR, n)
#define PVout(n) BIT_ADDR(PORTV_ODR_ADDR, n) //实现指定管脚置位和复位
/*
PORTx_SET(GPIO_PORT_K, 5);
PORTx_CLR(GPIO_PORT_K, 4);
*/
#define PORTx_SET(group, pin) (*((__IO uint32_t *)PORTx_MODE_BASE(group)) |= (uint32_t)(0x0000001UL<< pin))
#define PORTx_CLR(group, pin) (*((__IO uint32_t *)PORTx_MODE_BASE(group)) &= ~((uint32_t)(0x0000001UL<< pin))) /*
//实现指定管脚置位和复位
#define PORTx_SET(group, pin) (BIT_ADDR(PORTx_MODE_BASE(group), pin)=1)
#define PORTx_CLR(group, pin) (BIT_ADDR(PORTx_MODE_BASE(group), pin)=0)
*/ //读取指定引脚的输入状态
#define READ_PIN(group, pin) ((*((__IO uint32_t *)(PORTx_MODE_BASE(group))) & (uint32_t)(0x0000001UL<< pin)) >> pin) //输入状态 = GPIO_PIN_RESET or GPIO_PIN_SET
#define PAin(pin) READ_PIN(GPIO_PORT_A, pin)
#define PBin(pin) READ_PIN(GPIO_PORT_B, pin)
#define PCin(pin) READ_PIN(GPIO_PORT_C, pin)
#define PDin(pin) READ_PIN(GPIO_PORT_D, pin)
#define PEin(pin) READ_PIN(GPIO_PORT_E, pin)
#define PFin(pin) READ_PIN(GPIO_PORT_F, pin)
#define PGin(pin) READ_PIN(GPIO_PORT_G, pin)
#define PHin(pin) READ_PIN(GPIO_PORT_H, pin)
#define PJin(pin) READ_PIN(GPIO_PORT_J, pin)
#define PKin(pin) READ_PIN(GPIO_PORT_K, pin)
#define PLin(pin) READ_PIN(GPIO_PORT_L, pin)
#define PMin(pin) READ_PIN(GPIO_PORT_M, pin)
#define PNin(pin) READ_PIN(GPIO_PORT_N, pin)
#define PPin(pin) READ_PIN(GPIO_PORT_P, pin)
#define PRin(pin) READ_PIN(GPIO_PORT_R, pin)
#define PTin(pin) READ_PIN(GPIO_PORT_T, pin)
#define PUin(pin) READ_PIN(GPIO_PORT_U, pin) #define PVin(pin) READ_PIN(GPIO_PORT_V, pin) #endif

实际应用

LED初始化为普通输出:

#define LED_ON 	PKout(4)=1
#define LED_OFF PKout(4)=0 void LED_Init(void)
{
gpio_t port;
port.p_pk_instance = TSB_PK; //GPIOK gpio_init(&port, GPIO_PORT_K); //初始化GPIOK
gpio_func(&port, GPIO_PORT_K, GPIO_PORT_4, GPIO_PK4_OUTPUT, GPIO_PIN_OUTPUT);
//初始化熄灭
gpio_write_bit(&port, GPIO_PORT_K, GPIO_PORT_4, GPIO_Mode_DATA, GPIO_PIN_RESET);
//LED_OFF; //位带操作方式
}

KEY初始化为上拉输入:

#define KEY_IN 	PVin(3)

void KEY_Init(void)
{
gpio_t port; port.p_pv_instance = TSB_PV; gpio_init(&port, GPIO_PORT_V); gpio_func(&port, GPIO_PORT_V, GPIO_PORT_3, GPIO_PV3_INPUT, GPIO_PIN_INPUT); //输入模式
gpio_SetPullUp(&port, GPIO_PORT_V, GPIO_PORT_3, GPIO_PIN_SET); //上拉
}

main.c主函数实现按键按下LED闪烁:

#include "main.h"

int main(void)
{
LED_Init();
delay_init();
KEY_Init(); while(1)
{
if(KEY_IN == GPIO_PIN_RESET)
{
LED_ON;
delay_ms(50);
LED_OFF;
delay_ms(50);
}
}
}

总结

有了上面的代码,我们就可以像 51/AVR 一样操作东芝TT_M3HQ开发板的 IO 口了。


推荐阅读


  • 我的个人博客:www.wangchaochao.top
  • 我的公众号:mcu149

东芝MCU实现位带操作的更多相关文章

  1. STM32—位带操作

    STM32中的位带操作: 名字为位带操作,实际上是对位的操作,位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见. 51 单片机中通过关键字 sbit 来实现位定义, STM32 ...

  2. STM32之GPIO端口位带操作

    #ifndef __SYS_H #define __SYS_H #include "stm32f10x.h" //位带操作 //把“位带地址+位序号”转换别名地址宏 #define ...

  3. STM32位带操作总结---浅显易懂

    正在准备做毕业设计,配置LED_Config()的时候,又看到了位带操作的宏定义,我又嘀咕了,什么是位带操作,一年前在使用位带操作的时候,就查阅过好多资料,Core-M3也看过,但是对于博主这种“低能 ...

  4. STM32F030系列实现仿位带操作

    1.闲言 最近开发的时候,用到了STM32F030F4P6型号的单片机,它只有20个引脚,价格非常便宜,但是功能齐全:定时器.外部中断.串口.IIC.SPI.DMA和WWDG等等,应用尽有,非常适合用 ...

  5. 第13章 GPIO—位带操作

    第13章     GPIO—位带操作 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...

  6. 玩转X-CTR100 l STM32F4 l 基础例程printf、LED、蜂鸣器、拨码开关、位带操作

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]      本文介绍X-CTR100控制器基础板载资源 ...

  7. 玩转X-CTR100 | STM32F4 l GPIO位带操作

    更多塔克创新资讯欢迎登陆[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]       STM32F4位带概念,及位带的GPIO操作实践应用. 原理介 ...

  8. 关于STM32位带操作随笔

    以前在学习STM32时候关注过STM32的位带操作,那时候只是知道位带是啥,用来干嘛用,说句心里话,并没有深入去学习,知其然而不知其所以然.但一直在心中存在疑惑,故今日便仔细看了一下,写下心得供日后参 ...

  9. GPIO—位带操作

    GPIO—位带操作本章参考资料:< STM32F4xx 中文参考手册>存储器和总线构架章节. GPIO 章节,< Cortex®-M4 内核编程手册> 2.2.5 Bit-ba ...

随机推荐

  1. win10 安装 MySQL-5.7.28 记录

    目录 一.安装前准备 二.安装步骤 三.安装时踩的坑 一.安装前准备 1.云盘下载安装包以及客户端工具 下载地址:MySQL-5.7.28 + SQLyog 2.官网下载安装包 下载地址:https: ...

  2. 腾讯面试官问我Java中boolean类型占用多少个字节?我说一个,面试官让我回家等通知

    本文首发于微信公众号:程序员乔戈里 什么是boolean类型,根据官方文档的描述: boolean: The boolean data type has only two possible value ...

  3. 自古逢秋悲寂寥,奈何今秋热成雕?Python使用Pyecharts统计全国温度Top10并绘图

    秋词-刘禹锡 自古逢秋悲寂寥, 我言秋日胜春朝. 晴空一鹤排云上, 便引诗情到碧霄. 古人谈及秋天,都是悲凉寂寥,那么-.我好想回到古代的秋天啊!明明到了秋天,为什么最近的气温比夏天还热. 之前做天气 ...

  4. js-编程练习题-输出年月日以及练习字符串分割,检索,转换整数(int)

    这是在慕课网上看到的编程题-如有侵权,请联系本人删除. 当然:题是他们的,做题是我的...嘿嘿嘿 某班的成绩出来了,现在老师要把班级的成绩打印出来. 效果图: XXXX年XX月X日 星期X--班级总分 ...

  5. ubuntu 下 shell 搜索命令

    一.在当前目录及其子目录查找以mesos开头,并以.jar结尾的文件,并打印出来 sudo find ./ -name mesos*.jar -print 二.whereis, locate 也有类似 ...

  6. GRPC的metadata使用

    文章目录 一.简析 1.创建metadata 2.发送metadata 3.接收metadata 二.代码举例 1.proto文件编写 2.server端编写 3.client端编写 三.实际使用举例 ...

  7. POJ2528 Mayor's poster

    The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign h ...

  8. HDU1224-Free DIY Tour(SPFA+路径还原)

    Weiwei is a software engineer of ShiningSoft. He has just excellently fulfilled a software project w ...

  9. Dubbo学习系列之七(分布式订单ID方案)

    既然选择,就注定风雨兼程! 开始吧! 准备:Idea201902/JDK11/ZK3.5.5/Gradle5.4.1/RabbitMQ3.7.13/Mysql8.0.11/Lombok0.26/Erl ...

  10. 每周一练 之 数据结构与算法(LinkedList)

    这是第三周的练习题,原本应该先发第二周的,因为周末的时候,我的母亲大人来看望她的宝贝儿子,哈哈,我得带她看看厦门这座美丽的城市呀. 这两天我抓紧整理下第二周的题目和答案,下面我把之前的也列出来: 1. ...