位域(位段)
对于位域(位段)的使用可以节约内存的开支,使某些变量可以仅用1bit位来区分和表示;参考华大官方库的代码来解释;
【示例】实现如下两行代码:
M0P_SPI0->CR_f.SPEN = 1;
M0P_SPI0->CR = 0x00000080;
//仅对spen位置1,在32位寄存器中位于bit7,以上两行作用等价;
#define M0P_GPIO_BASE (M0P_PERIPH_BASE + 0x00020C00UL)
#define M0P_SPI0_BASE (M0P_PERIPH_BASE + 0x00000800UL)
#define M0P_SPI1_BASE (M0P_PERIPH_BASE + 0x00004800UL)
.
.
.
#define M0P_GPIO ((M0P_GPIO_TypeDef *)0x40020C00UL)
#define M0P_SPI0 ((M0P_SPI_TypeDef *)0x40000800UL)
#define M0P_SPI1 ((M0P_SPI_TypeDef *)0x40004800UL)
#define __IO volatile /*!< Defines 'read / write' permissions */
//将仍是立即数的外设地址转换为结构体指针(相应外设地址)
写法一:
typedef struct
{
union
{
__IO uint32_t CR; //32bit
stc_spi_cr_field_t CR_f; //32bit
};
union
{
__IO uint32_t SSN;
stc_spi_ssn_field_t SSN_f;
};
union
{
__IO uint32_t STAT;
stc_spi_stat_field_t STAT_f;
};
union
{
__IO uint32_t DATA;
stc_spi_data_field_t DATA_f;
};
union
{
__IO uint32_t CR2;
stc_spi_cr2_field_t CR2_f;
};
union
{
__IO uint32_t ICLR;
stc_spi_iclr_field_t ICLR_f;
};
}M0P_SPI_TypeDef;
typedef struct
{
__IO uint32_t SPR0 : 1;
__IO uint32_t SPR1 : 1;
__IO uint32_t CPHA : 1;
__IO uint32_t CPOL : 1;
__IO uint32_t MSTR : 1;
uint32_t RESERVED5 : 1;
__IO uint32_t SPEN : 1;
__IO uint32_t SPR2 : 1;
uint32_t RESERVED8 :23;
__IO uint32_t RSV : 1;
} stc_spi_cr_field_t;
写法二:
typedef struct
{
__IO uint32_t CR;
__IO uint32_t SSN;
__IO uint32_t STAT;
__IO uint32_t DATA;
__IO uint32_t CR2;
__IO uint32_t ICLR;
}M0P_SPI_TypeDef;
union
{
__IO uint32_t CR;
stc_spi_cr_field_t CR_f;
};
.
.
.
//如上
//省略其他寄存器;
枚举用法
typedef enum en_spi_status
{
SpiIf = 0x80u, ///<传输结束中断标志
SpiSserr = 0x20u, ///<从机模式错误标志
SpiMdf = 0x10u, ///<主机模式错误标志
SpiBusy = 0x08u, ///<SPI总线忙标志
SpiTxe = 0x04u, ///<发送缓冲器器空标志
SpiRxne = 0x02u, ///<接受缓冲器非空标志
}en_spi_status_t;
en_spi_status_t spiStatusVar = SpiIf;
//或
enum en_spi_status
{
SpiIf = 0x80u, ///<传输结束中断标志
SpiSserr = 0x20u, ///<从机模式错误标志
SpiMdf = 0x10u, ///<主机模式错误标志
SpiBusy = 0x08u, ///<SPI总线忙标志
SpiTxe = 0x04u, ///<发送缓冲器器空标志
SpiRxne = 0x02u, ///<接受缓冲器非空标志
}spiStatusVar,spiStatusVar2;
spiStatusVar = SpiIf;
spiStatusVar2 = SpiTxe;
1、枚举元素SpiIf(枚举常量)等只能在定义的时候赋值,不能单独拿出来赋值;
2、枚举元素不赋值时,编译器默认自动设为0,1,2…,枚举变量spiStatusVar的值仅限于花括号里的;
【注意】而结构体中各元素成员,如未被初始化的数值型被系统初始化为0,;字符型被系统初始化为‘/0’;指针型成员被系统初始化为NULL;
3、枚举名字en_spi_status可以不声明;
enum
{
SpiIf = 0x80u, ///<传输结束中断标志
SpiSserr = 0x20u, ///<从机模式错误标志
SpiMdf = 0x10u, ///<主机模式错误标志
SpiBusy = 0x08u, ///<SPI总线忙标志
SpiTxe = 0x04u, ///<发送缓冲器器空标志
SpiRxne = 0x02u, ///<接受缓冲器非空标志
}spiStatusVar,spiStatusVar2;
4、C语言结构体定义位域,从bit0开始,依次到最高bit位
【ref】https://www.cnblogs.com/risunlee/p/11507103.html