ch0 CBsp类的实现

本文介绍了在复杂的嵌入式系统中,使用C++代替C语言进行STM32单片机程序开发的好处,包括减少参数传递、增强安全性及避免命名冲突。通过对比面向过程和面向对象的流水灯程序示例,展示了C++的封装特性在降低维护成本和提高代码可读性方面的优势。同时,详细阐述了C++类`CBsp`的实现,用于系统初始化、延迟操作等,并给出了使用示例。
摘要由CSDN通过智能技术生成

为什么用C++开发单片机程序

​ 在以微处理器为核心的嵌入式系统中,大部分采用C语言来进行程序设计,但是随着系统规模的增大,程序越来越复杂,维护也越发困难。而使用C++进行开发有以下好处(前提是编译器必须支持C++,否则都是空谈):

  1. 减少了参数传递。在C++中可以将用到的数据作为数据成员,这样可以避免函数的参数传递过程,能够提高执行速度和效率。
  2. 更加安全。C++对数据和方法进行了封装,这样可以隐藏类实现的细节,避免内部数据结构暴露。
  3. 可以减少命名的冲突。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的职能:

  1. 初始化系统相关的资源:比如中断向量属性的设置,调试串口的初始化。

  2. 为用户提供延时操作。

这是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; 
}

参考文献

  1. cortex-m3之stm32嵌入式系统设计
  2. CBsp类代码:http://download.csdn.net/detail/winsbb/9869686
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值