首页 > 代码库 > 疯狂单片机--用C++写STM32程序

疯狂单片机--用C++写STM32程序

现单片机已经白菜价了,可用的资源也不断丰富起来.

有一天我突发奇想,用C++写单片机不是更方便.(相信很多人有类似的想法,不过在网上找到的参考资料也太少了)

话说很多编译器本身是支持C++,大部分人认为C++效率C低,我想说的是当年Android刚出来的时候,也受到了很多人的抵触...

手上正好有块STM32开发板,就拿它开刀了:

一.把库中的.C文件改成.CPP


二.定义一个GPIO的类

单片机的helloworld,那就是流水灯.

要是能够简化定义成这样子就好理解了

STM32PIN DS1_N(PF,6);
STM32PIN DS2_N(PF,7);
STM32PIN DS3_N(PF,8);
STM32PIN DS4_N(PF,9);

于是我定义了下面这么一个类

//stm32pin.h
#pragma once
typedef struct   tagGPIO_PIN
{
	uint32_t		periph;//eg:RCC_APB2Periph_GPIOF
	GPIO_TypeDef*   	port;	 //eg:GPIOF
	uint16_t 		pin;	 //eg:GPIO_Pin_10
	GPIOMode_TypeDef  	mode;	 //eg.GPIO_Mode_IN_FLOATING;
	GPIOSpeed_TypeDef  	speed; 	 //eg.GPIO_Speed_50MHz
}GPIO_PIN;

enum STM32_PORT_INDEX
{
	PA=0,PB,PC,PD,PE,PF,PG 
};
struct 
{
		uint32_t		p_periph;
		GPIO_TypeDef*		p_port;
}PERIPH_PORT[]=
{
	RCC_APB2Periph_GPIOA,GPIOA,
	RCC_APB2Periph_GPIOB,GPIOB,
	RCC_APB2Periph_GPIOC,GPIOC,
	RCC_APB2Periph_GPIOD,GPIOD,
	RCC_APB2Periph_GPIOE,GPIOE,
	RCC_APB2Periph_GPIOF,GPIOF,
	RCC_APB2Periph_GPIOG,GPIOG,
};
//简化书写 
#define			GM_AIN		        GPIO_Mode_AIN            //模拟输入模式    
#define			GM_IN_FLOATING		GPIO_Mode_IN_FLOATING   //浮空输入模式    
#define			GM_IPD			GPIO_Mode_IPD         //下拉输入模式    
#define			GM_IPU 			GPIO_Mode_IPU          //上拉输入模式    
#define			GM_OUT_OD 		GPIO_Mode_Out_OD       //开漏输出模式    
#define			GM_OUT_PP 		GPIO_Mode_Out_PP       //通用推挽输出模式    
#define			GM_AFOD 		GPIO_Mode_AF_OD        //复用功能开漏输出    
#define			GM_AFPP 		GPIO_Mode_AF_PP          //复用功能推挽输出   



/*--------------------如何定义STM32PIN--------------------------------------*/
// //eg:
//  STM32PIN  key1(RCC_APB2Periph_GPIOC,GPIOC,GPIO_Pin_1,GM_IN_FLOATING);
//  STM32PIN  pins(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,GPIOC,GPIO_Pin_1|GPIO_Pin_10);
//  STM32PIN  EnTk(PA,0);

 
 
class STM32PIN
{
private:
	 GPIO_PIN m_gpio;
public:
	 ~STM32PIN()
	 {

	 }
	 STM32PIN()
	 {

	 }
 STM32PIN(                              STM32_PORT_INDEX 	indexPort,
					uint16_t 		        indexPin, //只能取0~15对应GPIO_Pin_0~GPIO_Pin_15
					GPIOMode_TypeDef		p_mode=GM_OUT_PP,
					GPIOSpeed_TypeDef		p_speed=GPIO_Speed_50MHz )	//对于输入Speed应为0
{	   	 
		reset(PERIPH_PORT[indexPort].p_periph,
					PERIPH_PORT[indexPort].p_port,
					(uint16_t)1<<indexPin,//根据GPIO_Pin_x对应规则
					p_mode,
					p_speed );
}
	 
	  STM32PIN(             uint32_t		        p_periph,
				GPIO_TypeDef*		        p_port,
				uint16_t			p_pins,    //可以或上多引脚
				GPIOMode_TypeDef		p_mode=GPIO_Mode_Out_PP,
				GPIOSpeed_TypeDef		p_speed=GPIO_Speed_50MHz )	//对于输入Speed应为0
	 {
	   	 reset(	 p_periph,
							 p_port,
							 p_pins,    //可以或上多引脚
							 p_mode,
							 p_speed );
	 }
	   void reset( GPIOMode_TypeDef   p_mode=GPIO_Mode_Out_PP )
	   {
	   		if(m_gpio.mode==p_mode)return;
				reset( 	m_gpio.periph,
					m_gpio.port,
					m_gpio.pin,    //可以或上多引脚
					p_mode,
					m_gpio.speed );
				        m_gpio.mode=p_mode;
	   }
	 void reset( 	uint32_t    		p_periph,
			GPIO_TypeDef*    	p_port,
			uint16_t    		p_pins,    //可以或上多引脚,如片外RAM扩展的定义
			GPIOMode_TypeDef   		p_mode=GPIO_Mode_Out_PP,
			GPIOSpeed_TypeDef  		p_speed=GPIO_Speed_50MHz )
	 {
		  m_gpio.periph = p_periph;
		  m_gpio.port = p_port;
		  m_gpio.pin = p_pins;
		  m_gpio.mode=p_mode;
		  m_gpio.speed=p_speed;

		  GPIO_InitTypeDef tmp_InitType;//临时产生
		  tmp_InitType.GPIO_Pin= m_gpio.pin ;
		  tmp_InitType.GPIO_Mode=m_gpio.mode;
		  tmp_InitType.GPIO_Speed=m_gpio.speed;

		  RCC_APB2PeriphClockCmd( m_gpio.periph, ENABLE );

		  GPIO_Init( m_gpio.port ,&tmp_InitType);
	 }

	  inline  bool get(void)
	  {
		    if( ishigh() )
		    {
		        return true;
		    }
		    else
		    {
		       return false;
		    }
	  }
	 inline void set(bool bs)
	 {
		  if(bs)
		  {
		   	high();//GPIO_SetBits(m_gpio.port, m_gpio.pin);
		  }
		  else
		  {
		   	low();//GPIO_ResetBits(m_gpio.port, m_gpio.pin);
		  }
	  }
	 inline void invert(void)
	 {
	 	  if ( ishigh() )
		  {
		  	low();//GPIO_ResetBits(m_gpio.port, m_gpio.pin);
		  }
		  else
		  {
  		   	high();//GPIO_SetBits(m_gpio.port, m_gpio.pin);
		  }
	 }

 	 inline void high(void)
	 {		
		 //GPIO_SetBits(m_gpio.port, m_gpio.pin);
			m_gpio.port->BSRR = m_gpio.pin;
	 }

	 inline void low(void)
	 {		
			//GPIO_ResetBits(m_gpio.port, m_gpio.pin);
			m_gpio.port->BRR = m_gpio.pin;
	 }
	 inline bool ishigh()
	 {	
		 // if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)	GPIO_ReadInputDataBit(m_gpio.port, m_gpio.pin)==Bit_SET
		  if( m_gpio.port->IDR & m_gpio.pin)
		  {
		      return true;
		  }
		  else
		  {
		     return false;
		  }
	 }
	inline bool islow()
	 {		  
	    // if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)	GPIO_ReadInputDataBit(m_gpio.port, m_gpio.pin)==Bit_SET
		  if( m_gpio.port->IDR & m_gpio.pin)
		  {
		      return false; 
		  }
		  else
		  {
					return true;
		  }
	 }

	 void toggle(uint32_t t=1000,bool bLoop=true) 
	 {
				while(bLoop)
				{
					high();
					for(int i=0;i<t;i++);
					low();
					for(int i=0;i<t;i++);
				}
	 }

};
从上面的类,可以看到,让GPIO拉高使用high(),拉使用low(),
为了能产生高效的代码,其中大部分函数使用内联,
将 GPIO_SetBits() GPIO_ResetBits()函数调用改写成寄存器方式
 //GPIO_SetBits(m_gpio.port, m_gpio.pin);
  inline void high(void)
{
m_gpio.port->BSRR = m_gpio.pin;
}
//GPIO_ResetBits(m_gpio.port, m_gpio.pin);
 inline void low(void)

{

        m_gpio.port->BRR = m_gpio.pin;
 }

于是流水灯的程序就可以写这样子:



//main.cpp
#include "stm32pin.h"
int main(void)
{
		STM32PIN DS1_N(PF,6);
		STM32PIN DS2_N(PF,7);
		STM32PIN DS3_N(PF,8);
		STM32PIN DS4_N(PF,9);

		uint8_t i=0;
		while(true)
		 {
			 i++;
			 i & 0x01 ? DS1_N.low():DS1_N.high();
			 i & 0x02 ? DS2_N.low():DS2_N.high();
			 i & 0x04 ? DS3_N.low():DS3_N.high();
			 i & 0x08 ? DS4_N.low():DS4_N.high();
			 for(uint32_t i=0;i<10000000;i++);
		 }
}


接着让USER2键按下,流水灯反过来计数,只要这样定义

STM32PIN USER2(PD,3,GM_IN_FLOATING);

使用的时候这样写

if( USER2.islow() ) 

{

//要执行的动作

}


#include "stm32pin.h"
int main(void)
{

		STM32PIN DS1_N(PF,6);
		STM32PIN DS2_N(PF,7);
		STM32PIN DS3_N(PF,8);
		STM32PIN DS4_N(PF,9);
		STM32PIN USER2(PD,3,GM_IN_FLOATING);
		uint8_t i=0;
		while(true)
		 {
			 i++;
			 if( USER2.islow() )
			 {
					 i & 0x08 ? DS1_N.low():DS1_N.high();
					 i & 0x04 ? DS2_N.low():DS2_N.high();
					 i & 0x02 ? DS3_N.low():DS3_N.high();
					 i & 0x01 ? DS4_N.low():DS4_N.high();
			 }
				else
				{
					 i & 0x01 ? DS1_N.low():DS1_N.high();
					 i & 0x02 ? DS2_N.low():DS2_N.high();
					 i & 0x04 ? DS3_N.low():DS3_N.high();
					 i & 0x08 ? DS4_N.low():DS4_N.high();
				}
			 for(uint32_t i=0;i<10000000;i++);
		 }
}

未完待续....