用C++做开单片机开发
0赞做了多年的单片机开发,我们早已习惯了C语言+库函数的方式,偶尔在需要的地方加入几句汇编。然而我们还不知足,大部分编译器已经支持汇编、C语言和C++编译了,这次让我们体验一下用C++开发。当然,前提是牺牲那么一点效率。
在这里我们先介绍一下作者使用的开发环境(发一点小广告):单片机是ELMOS公司的E703.15,内核类似于MSP430(兼容MSP430指令),仿真器为MAZ JTAG,集成开发环境为IAR for MSP430 6.4,PC采用Windows7 32位旗舰版。接下来主要介绍用C++实现2个串口,并利用C++的封装、集成和多态的特性,复用代码。
1.1串口类设计分析
当然,用上了C++,我们先用封装特性,把串口的数据和操作封装为类(class)。
设计前我们分析一下,E703.15有2个串口,2个串口有相同的操作,但是有不同的硬件寄存器如引脚等。设计串口类的时候,我们采用基类和派生类的方式设计。
✦ 基类:封装串口变量并定义串口的操作;
✦ 派生类:根据串口硬件特性重载硬件相关操作。
1.2串口基类设计
✦ 数据:串口号;
✦ 操作:串口初始化(不同串口不同,虚函数);
✦ 操作:串口发送一个字节;
✦ 操作:串口接收一个字节;
✦ 操作:串口发送字符串。
class CUartBase {
public:
CUartBase(uart_num_t eUart);
~CUartBase(void);
public:
void uartByteSend(uint8_t ucData);
uint8_t uartByteRecv(void);
void uartStrWrite(char *pcStr);
public:
virtual void uartInit(void) = 0;
protected:
uart_num_t eUartNum;
};
1.2.1串口基类定义
在介绍定义之前,先说明一下,具体的实现是调用了ELMOS提供的E703.15的外设库,如uart_transmit_byte函数。由于操作都比较简单,所以不进行详细介绍。
CUartBase::CUartBase(uart_num_t eUart)
{
eUartNum = eUart;
}
CUartBase::~CUartBase(void)
{
}
void CUartBase::uartByteSend(uint8_t ucData)
{
uart_transmit_byte( eUartNum, ucData, true );
}
uint8_t CUartBase::uartByteRecv(void)
{
uint8_t ucData;
uart_receive_byte( eUartNum, &ucData, true );
return ucData;
}
void CUartBase::uartStrWrite(char *pcStr)
{
while ( '\0' != *pcStr ) {
uartByteSend( *pcStr++ );
}
}
1.3串口0派生类
定义了基类之后,我们用上C++继承的特性,派生出串口0和串口1,由于串口0和串口1除了硬件初始化不同之外,其他操作相同,所以只介绍串口0派生类。同样先介绍原型,再介绍定义。更多学习交流可以加Q3472880374,嵌入式实训就来信盈达,单片机,LINUX,免费试听。
1.3.1串口0原型
由于已经设计了基类,代码复用程度很高,所以派生类设计非常方便,只需重载硬件初始化虚函数即可(uartInit函数)。需要注意:构造函数使用了默认参数UART0。
class CUart0 : public CUartBase {
public:
CUart0(uart_num_t eUart = UART0);
~CUart0(void);
public:
void uartInit(void);
};
1.3.2串口0定义
只要重载硬件初始化函数即可,其他操作集成自基类,具体定义如下。uartInit函数在派生类实现(基类定义为虚函数),即利用C++的多态。
CUart0::CUart0(uart_num_t eUart) : CUartBase(eUart)
{
uartInit();
}
CUart0::~CUart0(void)
{
}
void CUart0::uartInit(void)
{
sys_state_module_enable( SYS_STATE_MODULE_UART0, false ); /* 禁用串口 */
sys_state_module_enable( SYS_STATE_MODULE_UART0, true ); /* 使能串口 */
uart_init( eUartNum, UART_SPEED_115200, UART_FRAC_115200, UART_DATA_LEN_8, UART_PARITY_EVEN, UART_ONE_STOP );
uart_fifo_clear( eUartNum, true, true );
sys_state_module_enable( SYS_STATE_MODULE_IOMUX_CTRL, true ); /* 使能串口 */
iomux_ctrl_select( IOMUX_IO_0, IOMUX_FUNC_2ND ); /* 使能发送引脚 */
}
1.4主函数测试
定义了串口基类和派生类之后,在主函数new出2个串口进行测试,测试代码如下(定义基类指针,用来存放派生类,可以利用多态的特性,为了简化,这里并没有体现出多态)。
#include "uart0.h"
#include "uart1.h"
int main (void)
{
CUartBase *phUart0 = new CUart0();
CUartBase *phUart1 = new CUart1();
phUart0->uartStrWrite( "Uart0: Hello world\r\n" );
phUart1->uartStrWrite( "Uart1 Hello world\r\n" );
while(1);
}
1.5温馨提示
虽然IAR for MSP430 6.4支持C++开发,但是并不完全支持C++的所有特性,大致支持特性和不支持特性如下,具体可参考编译器帮助文档。
✦ 类(class);
✦ 多态(Polymorphism);
✦ 重载(Overloading);
✦ new和delete;
✦ 模板(Templates);
✦ 名字空间(namespace)。
✦ 异常(Exception);
✦ 运行时类型识别(RTTI)。
1.6 结束语
根据以上介绍,是否发现用C++开发单片机,利用封装、集成和多态特性,可以增加代码的复用率,提高系统的稳定性呢。有兴趣的童鞋可以在自己的开发环境中试一下C++开发,换个角度看待单片机。