查看: 1306|回复: 0
打印 上一主题 下一主题

MDK:位区(bitband)操作新方法

[复制链接]
跳转到指定楼层
沙发
发表于 2016-6-20 19:23:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
利用MDK提供的关键字__attribute__((bitband)),可以很方便地进行Cortex-M3所提供的位区(bitband)操作。下面以USART的定义为例:

/* ------------------------ USART寄存器 ---------------------- */
typedef struct                                  // 状态寄存器结构
{
    u16 PE:1;                                   // 校验错误(r)
    u16 FE:1;                                   // 帧错误(r)
    u16 NE:1;                                   // 噪声错误标志(r)
    u16 ORE:1;                                  // 过载错误(r)
    u16 IDLE:1;                                 // 监测到总线空闲(r)
    u16 RXNE:1;                                 // 读数据寄存器非空(rc_w0)
    u16 TC:1;                                   // 发送完成(rc_w0)
    u16 TXE:1;                                  // 发送数据寄存器空(r)
    u16 LBD:1;                                  // LIN断开检测标志(rc_w0)
    u16 CTS:1;                                  // CTS 标志(rc_w0)
}USART_SR __attribute__((bitband));

typedef struct                                  // 控制寄存器1结构
{
    u16 SBK:1;                                  // 发送断开帧(rw 1:将要发送断开字符)
    u16 RWU:1;                                  // 接收唤醒(rw 1:接收器处于静默模式)
    u16 RE:1;                                   // 接收使能(rw)
    u16 TE:1;                                   // 发送使能(rw)
    u16 IDLEIE:1;                               // IDLE中断使能(rw)
    u16 RXNEIE:1;                               // 接收缓冲区非空中断使能(rw)
    u16 TCIE:1;                                 // 发送完成中断使能(rw)
    u16 TXEIE:1;                                // 发送缓冲区空中断使能(rw)
    u16 PEIE:1;                                 // PE中断使能(rw)
    u16 PS:1;                                   // 校验选择(rw 0:偶校验,1:奇校验)
    u16 PCE:1;                                  // 检验控制使能(rw)
    u16 WAKE:1;                                 // 唤醒的方法(rw 0:被空闲总线唤醒,1:被地址标记唤醒)
    u16 M:1;                                    // 字长(rw 0:8位,1:9位)
    u16 UE:1;                                   // USART使能(rw)
}USART_CR1 __attribute__((bitband));

typedef struct                                  // 控制寄存器2结构
{
    u16 ADDR:4;                                 // 本设备的USART节点地址(rw)
    u16 RESERVED1:1;
    u16 LBDL:1;                                 // LIN断开符检测长度(rw 0:10的断开符检测,1:11位)
    u16 LBDIE:1;                                // LIN断开符检测中断使能(rw)
    u16 RESERVED2:1;
    u16 LBCL:1;                                 // 最后一位时钟脉冲(rw )
    u16 MODE:2;                                 // 时钟相位(rw 0:在时钟的第一个边沿进行数据捕获,1:第二个)
                                                // 时钟极性(rw 0:总线空闲时CK引脚上保持低电平;1:高电平)
    u16 CLKEN:1;                                // 时钟使能(rw)
    u16 STOP:2;                                 // 停止位(rw)
    u16 LINEN:1;                                // LIN模式使能(rw)
}USART_CR2 __attribute__((bitband));

typedef struct                                  // 控制寄存器3结构
{
    u16 EIE:1;                                  // 错误中断使能(rw)
    u16 IREN:1;                                 // 红外模式使能(rw)
    u16 IRLP:1;                                 // 红外低功耗(rw)
    u16 HDSEL:1;                                // 半双工选择(rw)
    u16 NACK:1;                                 // 智能卡NACK使能(rw)
    u16 SCEN:1;                                 // 智能卡模式使能(rw)
    u16 DMAR:1;                                 // DMA使能接收(rw)
    u16 DMAT:1;                                 // DMA使能发送(rw)
    u16 RTSE:1;                                 // RTS使能(rw)
    u16 CTSE:1;                                 // CTS使能(rw)
    u16 CTSIE:1;                                // CTS中断使能(rw)   
}USART_CR3 __attribute__((bitband));

typedef struct                                  // 保护时间和预分频寄存器结构
{
    u16 PSC:8;                                  // 预分频器值(rw )
    u16 GT:8;                                   // 保护时间值(rw)
}USART_GTPR __attribute__((bitband));

typedef struct                                  // USART寄存器结构
{
    __IO USART_SR   SR;                         // 状态寄存器
    u16 RESERVED0;
    __IO u16        DR;                         // 数据寄存器
    u16 RESERVED1;
    __IO u16        BRR;                        // 波特比率寄存器
    u16 RESERVED2;
    __IO USART_CR1  CR1;                        // 控制寄存器1
    u16 RESERVED3;
    __IO USART_CR2  CR2;                        // 控制寄存器2
    u16 RESERVED4;
    __IO USART_CR3  CR3;                        // 控制寄存器3
    u16 RESERVED5;
    __IO USART_GTPR GTPR;                       // 保护时间和预分频寄存器
    u16 RESERVED6;
}USART_TypeDef;

#define PERIPH_BASE           0x40000000                            // 外围设备的基地址
#define APB1PERIPH_BASE       PERIPH_BASE                           // APB1设备的基地址
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)               // APB2设备的其地址

#define USART2_BASE           (APB1PERIPH_BASE + 0x4400)            // USART2基地址
#define USART3_BASE           (APB1PERIPH_BASE + 0x4800)            // USART3基地址
#define UART4_BASE            (APB1PERIPH_BASE + 0x4C00)            // UART4 基地址
#define UART5_BASE            (APB1PERIPH_BASE + 0x5000)            // UART5 基地址
#define USART1_BASE           (APB2PERIPH_BASE + 0x3800)            // USART1基地址

#define USART2                ((USART_TypeDef *) USART2_BASE)       // 定义USART2
#define USART3                ((USART_TypeDef *) USART3_BASE)       // 定义USART3
#define UART4                 ((USART_TypeDef *) UART4_BASE)        // 定义UART4
#define UART5                 ((USART_TypeDef *) UART5_BASE)        // 定义UART5
#define USART1                ((USART_TypeDef *) USART1_BASE)       // 定义USART1

    如果想给USART1的CR1寄存器的RXNEIE置位,直接这样操作就行了:
    USART1->CR1.RXNEIE = 1;
    MDK就能正确编译成位区操作地址,根本不需要自己去计算位区地址。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

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