瘋狂微控制器--用C++寫STM32程式-STM32PIN
阿新 • • 發佈:2019-02-09
現微控制器已經白菜價了,可用的資源也不斷豐富起來.
STM32PIN DS2_N(PF,7);
STM32PIN DS3_N(PF,8);
STM32PIN DS4_N(PF,9);
為了能產生高效的程式碼,其中大部分函式使用內聯,
將 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)
未完待續....
有一天我突發奇想,用C++寫微控制器不是更方便.(相信很多人有類似的想法,不過在網上找到的參考資料也太少了)
話說很多編譯器本身是支援C++,大部分人認為C++效率C低,我想說的是當年Android剛出來的時候,也受到了很多人的抵觸...
手上正好有塊STM32開發板,就拿它開刀了:
一.把庫中的.C檔案改成.CPP二.定義一個GPIO的類
微控制器的helloworld,那就是流水燈.
要是能夠簡化定義成這樣子就好理解了
STM32PIN DS2_N(PF,7);
STM32PIN DS3_N(PF,8);
STM32PIN DS4_N(PF,9);
於是我定義了下面這麼一個類
從上面的類,可以看到,讓GPIO拉高使用high(),拉使用low(),//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_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++);
}
}
未完待續....