为什么用C++开发单片机程序
在以微处理器为核心的嵌入式系统中,大部分采用C语言来进行程序设计,但是随着系统规模的增大,程序越来越复杂,维护也越发困难。而使用C++进行开发有以下好处(前提是编译器必须支持C++,否则都是空谈):
- 减少了参数传递。在C++中可以将用到的数据作为数据成员,这样可以避免函数的参数传递过程,能够提高执行速度和效率。
- 更加安全。C++对数据和方法进行了封装,这样可以隐藏类实现的细节,避免内部数据结构暴露。
- 可以减少命名的冲突。C语言没有命名空间的概念,这样容易导致名字冲突。
当然在C语言中也可以通过在结构体中定义函数指针的方式达到与C++封装类似的效果。但是这种方式比较麻烦,而且在C语言中没有访问权限控制 ,结构体内的所有成员全部是可以直接访问的,这样不利于隐藏实现的细节,而且如果调用者对结构体不熟悉,访问了不该访问的成员,那后果是灾难性的。
这里我以stm32l151c8t6
为例,和大家交流如何使用C++进行单片机开发,编译器使用的是MDK,使用的固件库为STM32L1xx_StdPeriph_Lib_V1.3.1
从流水灯看面向对象程序风格
下面是面向过程和面向对象两种程序风格的示例:
面向过程的程序风格:
int main(){
BSP_Init();
while(1){
delay(2000);
GPIO_SetBits(LED1);
delay(2000);
GPIO_ResetBits(LED1);
}
return 0;
}
面向对象的程序风格:
int main(){
CBsp bsp;
bsp.Init();
CLed led1(LED1);
while(1){
bsp.delay_ms(2000);
led1.isOn()?led1.Off():led1.On();
}
return 0;
}
从中可以看出面向对象的程序风格思路更加清晰,对于while(1)中的业务代码,如果底层IO变化了,面向过程的程序修改涉及了业务代码的修改,而对于面向对象的程序,仅仅只要修改相关的类就行了,无需修改业务代码,这大大降低了复杂程序的维护成本。
而且由于将相关函数和数据封装到相关类中去了,程序有了较好的分类和层次性。下面我来介绍一下我们的第一个类CBsp
。
第一个C++类------CBsp
CBsp的职能:
-
初始化系统相关的资源:比如中断向量属性的设置,调试串口的初始化。
-
为用户提供延时操作。
这是CBsp类:
class CBsp{
public:
void Init(void);
void delay_us(uint32_t n_ms);
void delay_ms(uint16_t n_ms);
private:
void sys_debug_Init(void);
void SysTick_Init(void);
};
具体实现:
#include "Bsp.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar (int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
#endif
extern "C"
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
USART_SendData(USART2, (uint8_t) ch);
/* Loop until transmit data register is empty */
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
{}
return ch;
}
static uint8_t fac_us=0; //us延时倍乘数
static uint16_t fac_ms=0; //ms延时倍乘数
void CBsp::Init(void){
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
sys_debug_Init();
SysTick_Init();
}
/*
*配置systick仅作为一般的延时用途 24Bit向下计数器
*CPU主频 = 32MHz
*/
void CBsp::SysTick_Init(void)
{
//uint32_t reload = 0;
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;//systick_clk = 4MHz
fac_us = 4;//1us需要4个systick时钟
fac_ms = (uint16_t)fac_us*1000;
}
/*
最大4194304us
*/
void CBsp::delay_us(uint32_t n_us)
{
uint32_t temp;
SysTick->LOAD=n_us*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
/*
最大4194ms
*/
void CBsp::delay_ms(uint16_t n_ms)
{
uint32_t temp;
SysTick->LOAD=(uint32_t)n_ms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void CBsp::sys_debug_Init(void)
{
GPIO_InitTypeDef uart_gpio;
USART_InitTypeDef debug_uart;
/*
config for usart2
*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
/* Connect PXx to USARTx_Tx */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
/* Connect PXx to USARTx_Rx */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
/* Configure USART Tx as alternate function push-pull */
uart_gpio.GPIO_Pin = GPIO_Pin_2;
uart_gpio.GPIO_Mode = GPIO_Mode_AF;
uart_gpio.GPIO_Speed = GPIO_Speed_40MHz;
uart_gpio.GPIO_OType = GPIO_OType_PP;
uart_gpio.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &uart_gpio);
/* Configure USART Rx as alternate function push-pull */
uart_gpio.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA, &uart_gpio);
debug_uart.USART_BaudRate = 115200;
debug_uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
debug_uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
debug_uart.USART_Parity = USART_Parity_No;
debug_uart.USART_StopBits = USART_StopBits_1;
debug_uart.USART_WordLength = USART_WordLength_8b;
/* USART configuration */
USART_Init(USART2, &debug_uart);
USART_Cmd(USART2,ENABLE);
USART_ClearFlag(USART2, USART_FLAG_TC);
USART_ClearITPendingBit(USART2,USART_IT_RXNE);
USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);
}
调用示例:
int main(void){
CBsp bsp;
bsp.Init();
bsp.delay_ms(1000);
while (1);
return 0;
}
参考文献
- cortex-m3之stm32嵌入式系统设计
- CBsp类代码:http://download.csdn.net/detail/winsbb/9869686