您的位置:首页 > 编程语言 > C语言/C++

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

2014-05-18 12:26 441 查看
现单片机已经白菜价了,可用的资源也不断丰富起来.

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


未完待续....
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: