STM32實戰五 板載LED顯示數據

寫到第五章,終於有可以看見的結果了。不過磨刀不誤砍柴功。正因爲前面的基礎,纔有今天的成果,而且有一定的實用價值。封裝一個BoardLED類,主要功能是利用板載LED顯示數據,類似於 Morse code 電報碼,以點亮時間的長短表示二進制數據的0和1,最多4位二進制,十進制15,可以擴展到更多。下面的程序顯示主循環週期時間,單位1us,實際上可以用來顯示設置運行狀態。購買或開發不同的開發板,LED對應的腳號不同,修改程序對應的IO號即可。

 BoardLED.h 代碼中用到了前幾章的封裝類,需要前面的原程序,全部做完以後做一個總的封包,上傳到資源庫中。

#ifndef __BOARDLED__
#define __BOARDLED__

extern "C" {	// 兼容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號警告
}

#include "GeneralTimer.h"
#include "IO.h"

class BoardLED : public IO
{
// Construction
public:
	BoardLED(GeneralTimer * pTimer);

// Properties
public:
	GeneralTimer * m_pTimer;	// 定時器
	u16 m_nNum;		// 要顯示的數
	u16 m_nCurrent;	// 當前顯示的位

private:

// Methods
public:
	void showNumber(void);	// 四位二進制形式顯示m_nNum
	void showLED(u16 nPin, u8 nOn);	// 開關LED
		
// Overwrite
public:
};

#endif

 BoardLED.cpp

/**
  ******************************************************************************
  * @file		BoardLED.cpp
  * @author		Mr. Hu
  * @version	V1.0.0 STM32F103VET6
  * @date		05/20/2019
  * @brief		板載LED
  * @IO
  *		PB13	板載LED2,不同的開發板,端口不同,做相應調整
  *		PE14	板載LED3
  *		m_t[0]	定時器m_pTimer中的計數1
  ******************************************************************************
  * @remarks
  *		從IO類繼承,初始化對應端口
  * 	LED2長短編碼形式顯示二進制數據,短是0,長是1
  * 	只顯示m_nNum的低四位
  */ 

/* Includes ------------------------------------------------------------------*/
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 "GeneralTimer.h"	// 通用定時器
#include "BoardLED.h"

/**
  * @date	05/20/2019
  * @brief  板載LED類
: *		IO(GPIOB, GPIO_Pin_13 | GPIO_Pin_14, GPIO_Mode_Out_PP, 1)
  *		初始化板載LED對應端口,不同的開發板,端口不同,做相應調整,
  *		最後一個參數1表示初始化爲上拉
  * @param	pTimer,指向通用定時器類對象
  * @retval None
  */
BoardLED::BoardLED(GeneralTimer * pTimer)
: IO(GPIOB, GPIO_Pin_13 | GPIO_Pin_14, GPIO_Mode_Out_PP, 1)	// 初始化板載LED對應端口,不同的開發板,端口不同,做相應調整,最後一個參數1表示初始化爲上拉
, m_pTimer(pTimer)	// 保存定時器
, m_nNum(0)			// 要顯示的數,0-15
, m_nCurrent(0x8)	// 當前顯示的位,最多4位
{
}

/**
  * @date	05/20/2019
  * @brief  以二進制形式顯示m_nNum指定的數據
: *		LED2點亮時間的長短表示二進制位,短是0,長是1,最大二進制數1111,十進制15。
  * @param	None
  * @retval None
  */
void BoardLED::showNumber(void)
{
	u32 & tim = m_pTimer->m_t[0];	// 定時時間
	if(tim)
		return;	// 只有計數到0才顯示
	
	u8 level = GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_13);
	if(level)	// 當前是高電平,LED不亮
	{
		GPIO_ResetBits(GPIOB, GPIO_Pin_13);	// 設置高電平,點亮
		tim = (m_nCurrent & m_nNum) ? 500 : 5;	// 當前二進制位是1,顯示500ms,如果二進制位是0顯示200ms秒
		m_nCurrent >>= 1; // 移到下一位			
	}
	else	// 當前是低電平,LED亮
	{
		GPIO_SetBits(GPIOB, GPIO_Pin_13);	// 設置高電平,熄滅
		if(!m_nCurrent)	// 數據顯示完畢,暗1.5秒
		{
			tim = 1500;			// 延時1500ms
			m_nCurrent = 0x8;	// 初始化當前位到最高位
		}
		else	// 二個二進制位中間,暗500ms
			tim = 500;
	}	
}

/**
  * @date	05/20/2019
  * @brief  板載LED點亮和熄滅
  * @param	nPin,端口號,PB13 和/或 PB14
  * @param	nOn,0滅,1亮
  * @retval None
  */
void BoardLED::showLED(u16 nPin, u8 nOn)
{
	if( nOn )
		GPIO_ResetBits(GPIOB, nPin);	// 點亮
	else
		GPIO_SetBits(GPIOB, nPin);		// 熄滅
}

Main.h 文件中還沒有實際內容


#ifndef __MAIN__
#define __MAIN__

extern "C" {	// 兼容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號警告
}


#endif

Main.cpp 主入口程序,所列端口有些是以後用的。程序實現兩個功能,一是計算主循環週期,二是設置兩個板載按鍵,按下時LED3點亮,並具有防抖動和抗干擾功能。

/**
  ******************************************************************************
  * @file  Main.cpp
  * @author  Mr. Hu
  * @version  V1.0.0 STM32F103VET6
  * @date  05/18/2019
  * @brief  程序入口
	*	@io
	*		TIM3	PWM
	*		TIM4	Encode
	*		TIM7	通用定時器
	*		ADC1	ADC
	*		DAC1
	*		DAC2
	*
	*		PA0-PA3 ADC
	*		PA4	DAC1輸出
	*		PA5	DAC2輸出
	*		PA6 	PWM1
	*		PA7 	PWM2
	*		PA9 	板載串口
	*		PA10 	板載串口
	*		PA13	板載JLINK佔用
	*		PA14	板載JLINK佔用
	*		PA15	板載JLINK佔用
	*
	*		PB1	板載SW2
	*		PB3	板載JLINK佔用
	*		PB4	板載JLINK佔用,部分映像的通道1不能用,所以用了沒有得映像
	*		PB5	PWM
	*		PB6	編碼器 A
	*		PB7	編碼器 B
	*		PB8	板載CAN
	*		PB9	板載CAN
	*		PB10	板載RS485
	*		PB11	板載RS485
	*		PB13	板載LED2
	*		PB14	板載LED3
	*		PB15	板載SW3
	*
	*		PC4	板載RS485
	*		PC5	板載RS485
	******************************************************************************
  * @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"
#include "stm32f10x_dac.h"

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

#include "stm32f10x_adc.h"
#include "IO.h"
#include "Timer.h"
#include "GeneralTimer.h"
#include "BoardLED.h"
#include "Main.h" 

/**
  * @date   05/18/2019
  * @brief  主入口,主循環
  *	    如果不正常運行,可能是棧設置不夠 startup_stm32f10x_hd.s Stack_Size EQU 0x600
  * @param  None
  * @retval None
*/
int main(void)
{
	SystemInit();	// 配置系統時鐘爲72M

	GeneralTimer tim(TIM2);		// 通用定時器,實際用TIM7,不佔用IO,但軟件仿真只有1-4,所以選2
	BoardLED boardLED( &tim );	// 板載LED
	
	// 板載按鍵,PB1 SW2, PB2 SW3,不同的板子不一樣。
	IO key(GPIOB, GPIO_Pin_1 | GPIO_Pin_15, GPIO_Mode_IPU, 2);	// GPIOx, nPin, GPIO_Mode_IPU 上拉, 2 輸入時無效
	
	// 使能按鍵濾波
	//tim.inb[1].level = 1;		// SW2 PB1 上拉
	tim.inb[1].enable = 1;		// SW2 PB1 使能
	//tim.inb[15].level = 1;	// SW3 PB15 上拉
	tim.inb[15].enable = 1;		// SW3 PB15
	
	u32 loopCount = 0;	// 主循環計數
	
	while(1)
	{
		tim.loop();	// 必須放在主循環的第一行,按鍵濾波和上下沿微分。
		
		// LED
		// 測試時間
		loopCount++;
		if( !tim.m_t[2] )	// 定時器2
		{
			tim.m_t[2] = 1000;		// 延時1000ms
			boardLED.m_nNum = 1000 * 1000 / loopCount;	// 計算循環週期,1000*1000對應週期單位是1us,100*1000是10us,以此類推。
			if( boardLED.m_nNum > 0xf )
				boardLED.m_nNum = 0xf;		// 大於15時,顯示15
			loopCount = 0;
		}
		boardLED.showNumber();	// 顯示四位二進制boardLED.m_nNum,用了m_t[0]

		// 開關LED
		if( tim.inb[1].down | tim.inb[15].down ) 	// 兩個板載開關的下降沿
		{
			boardLED.showLED(GPIO_Pin_14, 1);	// 點亮LED3
		}
		else if( tim.inb[1].up | tim.inb[15].up )	// 兩個板載開關的上升沿
		{
			boardLED.showLED(GPIO_Pin_14, 0);	// 熄滅LED3
		}
	}
}

把實戰三、四、五的源程序加在一起,編譯下載到單片機中,會看到LED【長短長短】有節奏的顯示二進制1010,說明主循環週期是6us,軟件仿真示波器顯示如下,低電平是點亮。

不同的開發板,數據會不同,如果全部是0或全部是1表示溢出,修改Main.cpp中的量程,【1000*1000對應週期單位是1us,100*1000是10us,以此類推。】,如果都是0,這個數加大,否則減小。這種顯示方式還有一個更好的用途就是顯示錯誤代碼,0表示正常,1-15表示各種異常,當然還可以用作其它用途。

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

 

 

 

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