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

来源:互联网 发布:剑网三捏脸正太数据 编辑:程序博客网 时间:2024/05/24 05:21
现单片机已经白菜价了,可用的资源也不断丰富起来.

有一天我突发奇想,用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 oncetypedef struct   tagGPIO_PIN{uint32_tperiph;//eg:RCC_APB2Periph_GPIOFGPIO_TypeDef*   port; //eg:GPIOFuint16_t pin; //eg:GPIO_Pin_10GPIOMode_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_tp_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,};//简化书写 #defineGM_AIN        GPIO_Mode_AIN            //模拟输入模式    #defineGM_IN_FLOATINGGPIO_Mode_IN_FLOATING   //浮空输入模式    #defineGM_IPDGPIO_Mode_IPD         //下拉输入模式    #defineGM_IPU GPIO_Mode_IPU          //上拉输入模式    #defineGM_OUT_OD GPIO_Mode_Out_OD       //开漏输出模式    #defineGM_OUT_PP GPIO_Mode_Out_PP       //通用推挽输出模式    #defineGM_AFOD GPIO_Mode_AF_OD        //复用功能开漏输出    #defineGM_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_15GPIOMode_TypeDefp_mode=GM_OUT_PP,GPIOSpeed_TypeDefp_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_tp_pins,    //可以或上多引脚GPIOMode_TypeDefp_mode=GPIO_Mode_Out_PP,GPIOSpeed_TypeDefp_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++); }}

未完待续....

0 0