利用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就能正确编译成位区操作地址,根本不需要自己去计算位区地址。
|