赞
踩
现单片机已经白菜价了,可用的资源也不断丰富起来.
有一天我突发奇想,用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++);
- }
- }
未完待续....
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。