STM32實戰三 C++ IO.cpp

這一章開始編寫代碼,主要是兩個方面,一是C++,二是進行簡單的IO封裝。其它教程一般是用C語言,從按鍵或LED燈開始,比較直觀,容易上手,但與實際應用有一定的區別,這裏要做的是實用控制程序,開始就比較正規,C++是發展趨勢,所以就從這裏開始。

說是C++,實際是C和C++的混合程序,系統提供的都是C,新寫的代碼是C++,先從簡單的IO開始,添加兩個文件IO.cpp和IO.h代碼如下:

IO.h

#ifndef __IO__
#define __IO__

extern "C" {	// 按C語言編譯,Keil5中的包含文件已經加入了C++兼容,不用再加這一段
#pragma diag_remark 368		//消除 warning: #368-D: class "<unnamed>" defines no constructor to initialize the following:

#include "stm32f10x.h"

#pragma diag_default 368	// 恢復368號警告
}

// 通用IO
class IO
{
// Construction
public:
	IO(GPIO_TypeDef* GPIOx, u16 nPin, GPIOMode_TypeDef GPIO_Mode, u16 nLevel);	// 輸出時設置初始電平,0低,1高,其它不設置
		
// Properties
public:
  GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_TypeDef* m_GPIOx;
	u16 m_nPin;

private:

// Methods
public:
		
// Overwrite
public:
};

#endif

IO.cpp

/**
  ******************************************************************************
  * @file			IO.cpp
  * @author		Mr. Hu
  * @version	V1.0.0 STM32F103VET6
  * @date			05/19/2019
  * @brief		通用端口初始化
	*					
  ******************************************************************************
  * @remarks
  *
  */ 
	
extern "C" {	// 兼容C,按C語言編譯,Keil5中的包含文件已經加入了C++兼容,不用再加這一段
#pragma diag_remark 368			//消除 warning:  #368-D: class "<unnamed>" defines no constructor to initialize the following:

#include "stm32f10x_tim.h"

#pragma diag_default 368	// 恢復368號警告
}

#include "IO.h"

/**
  * @date		05/19/2019
  * @brief  初始化端口.
  * @param	GPIOx: where x can be (A..G) to select the GPIO peripheral.
  * @param	nPin_x: specifies the port bits to be written.
  *   This parameter can be any combination of nPin_x where 
  *   x can be (0..15).
  * @param	GPIO_Mode: 輸入輸出模式.
  * @param	nLevel: 輸出時初始電平0低,1高,其它無效,初始化端口之前設置,避免開機跳動.
  * @retval None
  */
IO::IO(GPIO_TypeDef* GPIOx, u16 nPin_x,	GPIOMode_TypeDef GPIO_Mode, u16 nLevel)
	: m_GPIOx( GPIOx )
	, m_nPin( nPin_x )
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(nPin_x));

	u32 RCC_APB2Periph_GPIOx =	// 獲取對應的RCC參數
		GPIOx != GPIOA ? GPIOx != GPIOB ? GPIOx != GPIOC ? GPIOx != GPIOD ? GPIOx != GPIOE
		? 0 : RCC_APB2Periph_GPIOE : RCC_APB2Periph_GPIOD : RCC_APB2Periph_GPIOC : RCC_APB2Periph_GPIOB : RCC_APB2Periph_GPIOA;

	// 使能端口, 開啓按鍵端口時鐘
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
	
	// 先設置輸出狀態,避免開機時跳動。
	if(nLevel == 0)
		GPIO_ResetBits(GPIOx, nPin_x);	// 設置低電平
	else if(nLevel == 1)
		GPIO_SetBits(GPIOx, nPin_x);		// 設置高電平
	// 輸入狀態不設置
	
	// 配置端口,用最低的採樣頻率,過濾高頻干擾,延長壽命,需要高頻時在外部重設
  GPIO_InitStructure.GPIO_Pin = nPin_x;	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode;       
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;	// 用最低的採樣頻率
  GPIO_Init(GPIOx, &GPIO_InitStructure);  					// 初始化端口
}

所有與C語言有關的代碼用extern "C" { ... ... } 包括起來,告訴編譯器是C語言,只能從C++中調用C語言,不能從C中調用C++。 

還有一個要改動的地方,stm32f10x.h 中240行,原語句是 typedef enum {FALSE = 0, TRUE = !FALSE} bool; 修改成:

// C++ 編譯時出現錯誤:..\CMSIS\stm32f10x.h(240): error:  #65: expected a ";"
// 增加C++兼容代碼,如果是C++用BOOL,否則用原來的bool
#ifdef __cplusplus
	typedef enum {FALSE = 0, TRUE = !FALSE} BOOL;
#else
	typedef enum {FALSE = 0, TRUE = !FALSE} bool;
#endif

需要說明的是,上面的封裝不太完善,勉強能用,以後再修改。

STM32實戰系列源碼,按鍵/定時器/PWM/ADC/DAC/DMA/濾波
STM32實戰一 初識單片機
STM32實戰二 新建工程
STM32實戰三 C++ IO.cpp
STM32實戰四 定時器和按鍵
STM32實戰五 板載LED顯示數據
STM32實戰六 PWM加移相正交
STM32實戰七 數字濾波
STM32實戰八 DAC/ADC
STM32實戰九 編碼器
STM32開發過程的常見問題

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章