1. 程式人生 > >瘋狂微控制器--用C++寫STM32程式-STM32PIN

瘋狂微控制器--用C++寫STM32程式-STM32PIN

現微控制器已經白菜價了,可用的資源也不斷豐富起來.

有一天我突發奇想,用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++);
		 }
}

未完待續....