现单片机已经白菜价了,可用的资源也不断丰富起来.
有一天我突发奇想,用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<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
从上面的类,可以看到,让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++);
}
}
未完待续....