东芝MCU实现位带操作
位带操作简介
位带操作的概念其实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 口了。
推荐阅读
- 使用系统定时器SysTick实现精确延时微秒和毫秒函数
- 东芝半导体最新ARM开发板——TT_M3HQ开箱评测
- STM32F407外部晶体改为25M后检测不到芯片的解决办法
- 详解串行通信协议及其FPGA实现
- 玄铁910是个啥?是芯片吗?
- 国产处理器的逆袭机会——RISC-V
- 真正的RISC-V开发板——VEGA织女星开发板开箱评测
- 我的个人博客:www.wangchaochao.top
- 我的公众号:mcu149
东芝MCU实现位带操作的更多相关文章
- STM32—位带操作
STM32中的位带操作: 名字为位带操作,实际上是对位的操作,位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见. 51 单片机中通过关键字 sbit 来实现位定义, STM32 ...
- STM32之GPIO端口位带操作
#ifndef __SYS_H #define __SYS_H #include "stm32f10x.h" //位带操作 //把“位带地址+位序号”转换别名地址宏 #define ...
- STM32位带操作总结---浅显易懂
正在准备做毕业设计,配置LED_Config()的时候,又看到了位带操作的宏定义,我又嘀咕了,什么是位带操作,一年前在使用位带操作的时候,就查阅过好多资料,Core-M3也看过,但是对于博主这种“低能 ...
- STM32F030系列实现仿位带操作
1.闲言 最近开发的时候,用到了STM32F030F4P6型号的单片机,它只有20个引脚,价格非常便宜,但是功能齐全:定时器.外部中断.串口.IIC.SPI.DMA和WWDG等等,应用尽有,非常适合用 ...
- 第13章 GPIO—位带操作
第13章 GPIO—位带操作 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...
- 玩转X-CTR100 l STM32F4 l 基础例程printf、LED、蜂鸣器、拨码开关、位带操作
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器基础板载资源 ...
- 玩转X-CTR100 | STM32F4 l GPIO位带操作
更多塔克创新资讯欢迎登陆[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] STM32F4位带概念,及位带的GPIO操作实践应用. 原理介 ...
- 关于STM32位带操作随笔
以前在学习STM32时候关注过STM32的位带操作,那时候只是知道位带是啥,用来干嘛用,说句心里话,并没有深入去学习,知其然而不知其所以然.但一直在心中存在疑惑,故今日便仔细看了一下,写下心得供日后参 ...
- GPIO—位带操作
GPIO—位带操作本章参考资料:< STM32F4xx 中文参考手册>存储器和总线构架章节. GPIO 章节,< Cortex®-M4 内核编程手册> 2.2.5 Bit-ba ...
随机推荐
- Linux之find命令
1.find命令的作用 主要用于操作系统文件.目录的查找. 2.find命令常用参数 -name #按文件名查找 -type #按文件类型查找:b/p/c/p/l/f -size #但文件大小查找,G ...
- 《Dotnet9》系列-开源C# WPF控件库3《HandyControl》强力推荐
大家好,我是Dotnet9小编,一个从事dotnet开发8年+的程序员.我最近开始写dotnet分享文章,希望能让更多人看到dotnet的发展,了解更多dotnet技术,帮助dotnet程序员应用do ...
- css3学习——一列固定宽度且居中
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- socket实现一个简单的echo服务
服务端的实现: public class EchoServer{ //创建一个serverSocket private final ServerSocket serverSocket; //创建一个构 ...
- iNeuOS 工业互联网 从网关到云端一体化解决方案。教你如何做PPT。
iNeuOS 专注打造云端操作系统,提供全新解决方案 (凑够150字) 核心组件包括:边缘网关(iNeuLink).设备容器(iNeuKernel).视图建模(iNeuView).机器 ...
- 用C在GBA上写光线追踪(0)配置开发编译环境
前段时间用C#写了一个光线追踪程序,可以渲染圆球,平面这种基本图形,反射,光照,阴影,都大致尝试做了一下. ↑ C#实现的光线追踪 ↑ GBA上C实现的光线追踪 然而,在我打算继续深入优化的时 ...
- hibernate绑定session
session session是一种单实例对象 简单说就是自己用 别人不能用.在一些项目中很多人一起来操作 所以我们可以把session与我们的本地线程一起绑定,本地线程的特点就是执行一次 从创建到销 ...
- luogu P4302 [SCOI2003]字符串折叠
题目描述 折叠的定义如下: 一个字符串可以看成它自身的折叠.记作S = S X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S) = SSSS-S(X个S). 如果A = A', B = ...
- SDCycleScrollView-简单的循环
cocoapods 导入SDCycleScrollView1 记得使用 SDWebImage 2 SDCycleScrollViewDelegate _cycleScrollerView = [SDC ...
- 【全栈修炼】OAuth2 修炼宝典
一.OAuth 概念 开放授权(OAuth)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. -- 维基百 ...