建立C++版本的Stm32库

为什么使用C++?
以面向对象的方式思考,把Stm32的硬件模块当作对象。

在没有C++的情况下,我们作如下调用:

USART1->SR=0;
HAL_UART_Transmit(&huart1,"Hello",5,HAL_MAX_DELAY);
//这是ST官方HAL库

有了C++,我们可以这样:

USART1->SR=0;
USART1->Print("Hello");
//USART1是对象的指针,指向一个Usart对象

C的USART1指向一个结构体,其中的数据对应相应的寄存器,考虑下面这个结构体:

typedef struct
{
  __IO uint32_t SR;         /*!< USART Status register,                   Address offset: 0x00 */
  __IO uint32_t DR;         /*!< USART Data register,                     Address offset: 0x04 */
  __IO uint32_t BRR;        /*!< USART Baud rate register,                Address offset: 0x08 */
  __IO uint32_t CR1;        /*!< USART Control register 1,                Address offset: 0x0C */
  __IO uint32_t CR2;        /*!< USART Control register 2,                Address offset: 0x10 */
  __IO uint32_t CR3;        /*!< USART Control register 3,                Address offset: 0x14 */
  __IO uint32_t GTPR;       /*!< USART Guard time and prescaler register, Address offset: 0x18 */
} USART_TypeDef;

#define USART1                ((USART_TypeDef *) 0x40011000U)

USART1指向地址0x40011000U,结构体里的数据是按照顺序,连续储存的,
USART1->SR表示0x40011000U位置的一个无符号整型
USART1->DR表示0x40011000U+4位置的一个无符号整型
USART1->BRR表示0x40011000U+8位置的一个无符号整型

通过这种方式,可以访问串口1的实际寄存器。

C++的USART1应当指向一个对象,其对应的类的成员变量应当和上述USART_TypeDef结构体的数据一致:

class Usart
{
public:
    __IO u32 SR;         /*!< USART Status register,                   Address offset: 0x00 */
    __IO u32 DR;         /*!< USART Data register,                     Address offset: 0x04 */
    __IO u32 BRR;        /*!< USART Baud rate register,                Address offset: 0x08 */
    __IO u32 CR1;        /*!< USART Control register 1,                Address offset: 0x0C */
    __IO u32 CR2;        /*!< USART Control register 2,                Address offset: 0x10 */
    __IO u32 CR3;        /*!< USART Control register 3,                Address offset: 0x14 */
    __IO u32 GTPR;       /*!< USART Guard time and prescaler register, Address offset: 0x18 */
    void Baud(u32 b);

    void Reset();

    void Enable(Use_Mode mode);

    void PrintLn(const char *s);
    void PrintLn(u8 *s);

    void Clean(Usart_Status s);

    void SendHex(u8 *hex, u32 len);

    void Push(char c);
};

#define USART1                ((Usart *) 0x40011000U)

现在的USART1,每个成员变量对应实际寄存器,
USART1->SR表示0x40011000U位置的一个无符号整型
USART1->DR表示0x40011000U+4位置的一个无符号整型
USART1->BRR表示0x40011000U+8位置的一个无符号整型

这和C里面使用结构体没什么区别,但是,后面多了一堆成员函数,其储存位置在哪呢,如果是紧跟着最后一个成员变量那可不妙,因为这块区域是其它外设的寄存器。

成员变量是属于对象的,而成员函数属于类,也就是说,成员函数不占用内存空间,其储存位置还是在Flash,如果你尝试sizeof(Usart),会得到28,与sizeof(USART_TypeDef)一致。

C++的函数调用是一种怎样的机制呢?请看如下代码:

USART1->PrintLn("Hello");
USART2->PrintLn("Hello");

函数PrintLn是属于类的,只有一份拷贝,USART1USART2是两个对象的指针,指向两块内存区域,PrintLn是如何区分它们呢?事实上编译器做了一系列操作,可以理解为编译器多传递了一个参数给PrintLn,相当于:

PrintLn(USART1,"Hello");
PrintLn(USART2,"Hello");

只不过这个参数由编译器隐藏了,我们看不到。

使用C++还有很多好处,可以重载函数:

USART1->PrintLn("Hello");//发送字符串
USART1->PrintLn(256);//发送int
USART1->PrintLn(25.8f);//发送float

重载操作符:

*USART1<<"Hello";//发送字符串

值得注意,用来定义外设寄存器的类不能有虚函数,因为含有虚函数的类,实例化为对象的时候,除了给成员变量分配空间,还要额外的空间来储存虚函数指针表。

有兴趣的小伙伴请移步码云

https://gitee.com/drawtech/ArmCpp

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值