stm32无源蜂鸣器定时器_【STM32H7教程】第20章 STM32H7的GPIO应用之无源蜂鸣器...
第20章?????? STM32H7的GPIO應(yīng)用之無源蜂鳴器
本章教程為大家介紹STM32H7的GPIO應(yīng)用之無源蜂鳴器,蜂鳴器也是GPIO控制的經(jīng)典測試例程,可以讓大家對STM32H7應(yīng)用有個簡單的整體認識。
20.1 初學(xué)者重要提示
20.2 蜂鳴器硬件設(shè)計
20.3 蜂鳴器軟件驅(qū)動設(shè)計
20.4 蜂鳴器板級支持包(bsp_beep.c)
20.5 蜂鳴器驅(qū)動移植和使用(裸機版)
20.6 使用例程設(shè)計框架
20.7 實驗例程說明(MDK)
20.8 實驗例程說明(IAR)
20.9 總結(jié)
20.1 初學(xué)者重要提示
學(xué)習(xí)本章節(jié)前,務(wù)必保證已經(jīng)學(xué)習(xí)了第13,14和15章。
注意有源蜂鳴器和無源蜂鳴器的區(qū)別,本章教程的17.2.1小節(jié)有專門說明。
開發(fā)板是采用的有源蜂鳴器,需要PWM驅(qū)動,而截至本章節(jié)還沒有講到PWM,會在34章節(jié)專門為大家講解,程序中是通過一個宏定義控制使能和關(guān)閉,所以對于初學(xué)者來說,當前階段僅需了解到使能和關(guān)閉方法即可,后面學(xué)習(xí)到PWM章節(jié)了,再深入了解。
無源蜂鳴器的控制采用的非阻塞方式,實際項目中比較實用。
20.2 蜂鳴器硬件設(shè)計
蜂鳴器的硬件設(shè)計如下:
通過這個硬件設(shè)計,有如下兩點需要學(xué)習(xí):
20.2.1 蜂鳴器分類
蜂鳴器主要有電磁式和電壓式兩種,而且都有無源蜂鳴器和有源蜂鳴器兩類。開發(fā)板使用的是電磁式有源蜂鳴器,而有源和無源的區(qū)別是有源蜂鳴器內(nèi)部自帶振蕩器,給個電壓就能發(fā)聲,但頻率是固定的,只能發(fā)出一種聲音,而無源蜂鳴器頻率可控,給個方波才可以發(fā)聲,并且根據(jù)不同頻率發(fā)出不同的聲音效果。
拓展知識
關(guān)于有源蜂鳴器和無源蜂鳴器區(qū)別:
20.2.2 硬件設(shè)計
關(guān)于硬件驅(qū)動,這里主要有三點需要大家認識到:
S8050TL1是NPN型三極管,這里是當開關(guān)使用,PA8輸出高電平的時候三極管導(dǎo)通,輸出低電平,三極管關(guān)閉。
電阻R70起到限流的作用。
電阻R47在這里有特別的作用,首先要普及一個知識點,這里使用的是電磁式蜂鳴器,屬于感性負載,切斷這種負載必須要注意,如果電流消失,電感兩端的電壓將急劇上升,這種感應(yīng)沖擊足以損壞邏輯門電路或者其它形式的負載驅(qū)動電路,為了保護這個電路,可以用一個二極管或者電阻吸收感應(yīng)沖擊。
拓展知識
STM32H7的GPIO控制三極管驅(qū)動各種負載的安全措施和注意事項:
20.3 蜂鳴器軟件驅(qū)動設(shè)計
軟件驅(qū)動對有源蜂鳴器和無源蜂鳴器都做了支持,默認情況下用的是有源蜂鳴器。我們使用蜂鳴器的話,大部分情況下可以配置鳴叫次數(shù)、鳴叫的時間和停止的時間。本驅(qū)動設(shè)計就是基于這種應(yīng)用方式實現(xiàn),基本可以滿足大部分應(yīng)用情況。
設(shè)計這個軟件驅(qū)動的關(guān)鍵之處是如何避免采用阻塞式的實現(xiàn)方式,比如要實現(xiàn)鳴叫1秒,停止1秒,循環(huán)5次,如果是阻塞方式等待1秒執(zhí)行完畢,那就時間太長了。鑒于這種情況,程序里面實現(xiàn)了一種非阻塞的方式,通過滴答定時器中斷每10ms調(diào)用一次蜂鳴器處理函數(shù)來實現(xiàn)鳴叫次數(shù)、鳴叫的時間和停止的時間的更新。
20.4 蜂鳴器板級支持包(bsp_beep.c)
蜂鳴器驅(qū)動文件bsp_beep.c主要實現(xiàn)了如下幾個API:
BEEP_InitHard
BEEP_Start
BEEP_Stop
BEEP_Pause
BEEP_Resume
BEEP_KeyTone
BEEP_Pro
這里我們重點講解函數(shù)BEEP_InitHard、BEEP_Sart和BEEP_Pro。
函數(shù)BEEP_Stop、BEEP_Pause和BEEP_Resume測試效果不夠好,推薦直接使用BEEP_Sart即可,設(shè)置鳴叫時間、停止鳴叫時間和循環(huán)次數(shù)。而BEEP_KeyTone是基于BEEP_Start實現(xiàn)的,直接調(diào)用的BEEP_Start(5, 1, 1);?????? /* 鳴叫50ms,停10ms, 1次 */
20.4.1 宏定義設(shè)置
此文件的開頭有一個宏定義選擇,用戶可以選擇使用有源蜂鳴器或者無源蜂鳴器。
//#define BEEP_HAVE_POWER /* 定義此行表示有源蜂鳴器,直接通過GPIO驅(qū)動, 無需PWM */
#ifdef BEEP_HAVE_POWER/*有源蜂鳴器*/
/*PA8*/
#define GPIO_RCC_BEEP RCC_AHB1Periph_GPIOA
#define GPIO_PORT_BEEP GPIOA
#define GPIO_PIN_BEEP GPIO_Pin_8
#define BEEP_ENABLE() GPIO_PORT_BEEP->BSRRL = GPIO_PIN_BEEP /* 使能蜂鳴器鳴叫 */
#define BEEP_DISABLE() GPIO_PORT_BEEP->BSRRH = GPIO_PIN_BEEP /* 禁止蜂鳴器鳴叫 */
#else /* 無源蜂鳴器 */
/*PA8 ---> TIM1_CH1*/
/*1500表示頻率1.5KHz,5000表示50.00%的占空比*/
#define BEEP_ENABLE() bsp_SetTIMOutPWM(GPIOA, GPIO_Pin_8, TIM1, 1, 1500, 5000);
/*禁止蜂鳴器鳴叫*/
#define BEEP_DISABLE() bsp_SetTIMOutPWM(GPIOA, GPIO_Pin_8, TIM1, 1, 1500, 0);
#endif
使能了宏定義BEEP_HAVE_POWER就可以選擇使用有源蜂鳴器,默認是無源的。
使用無源蜂鳴器時,需要用到定時器的PWM功能,這個功能會在34章節(jié)專門講解,這里僅需只知道配置了一個PWM來驅(qū)動蜂鳴器即可。
20.4.2 蜂鳴器結(jié)構(gòu)體變量
為了方便蜂鳴器的控制,專門封裝了一個結(jié)構(gòu)體變量:
typedef struct_BEEP_T
{
uint8_t ucEnalbe;
uint8_t ucState;
uint16_t usBeepTime;
uint16_t usStopTime;
uint16_t usCycle;
uint16_t usCount;
uint16_t usCycleCount;
uint8_t ucMute;
}BEEP_T;
成員ucEnalbe:用于使能或者禁止蜂鳴器。
成員ucState:狀態(tài)變量,用于蜂鳴器鳴叫和停止的區(qū)分。
成員usBeepTime:鳴叫時間,單位10ms。
成員usStopTime:停止鳴叫時間,單位10ms。
成員usCycle:鳴叫和停止的循環(huán)次數(shù)。
成員usCount:用于鳴叫和停止時的計數(shù)。
成員usCycleCount:用于循環(huán)次數(shù)計數(shù)。
成員ucMute:用于靜音。
20.4.3 函數(shù)BEEP_InitHard
函數(shù)原型:
/**********************************************************************************************************
* 函 數(shù) 名: BEEP_InitHard
* 功能說明: 初始化蜂鳴器硬件
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
void BEEP_InitHard(void)
{
#ifdef BEEP_HAVE_POWER/*有源蜂鳴器*/GPIO_InitTypeDef GPIO_InitStructure;/*打開GPIOF的時鐘*/RCC_AHB1PeriphClockCmd(GPIO_RCC_BEEP, ENABLE);
BEEP_DISABLE();
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT; /*設(shè)為輸出口*/GPIO_InitStructure.GPIO_OType= GPIO_OType_PP; /*設(shè)為推挽模式*/GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_NOPULL; /*上下拉電阻不使能*/GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; /*IO口最大速度*/GPIO_InitStructure.GPIO_Pin=GPIO_PIN_BEEP;
GPIO_Init(GPIO_PORT_BEEP,&GPIO_InitStructure);#endifg_tBeep.ucMute= 0; /*關(guān)閉靜音*/}
函數(shù)描述:
此函數(shù)主要用于蜂鳴器的初始化,代碼比較好理解。條件編譯實現(xiàn)了一個無源蜂鳴器的初始化,配置引腳為推挽輸出模式。由于V7開發(fā)板使用的無源蜂鳴器,所有沒有開啟宏定義BEEP_HAVE_POWER。
使用舉例:
底層驅(qū)動初始化直接在bsp.c文件的函數(shù)bsp_Init里面調(diào)用即可。
20.4.4 函數(shù)BEEP_Start
函數(shù)原型:
/**********************************************************************************************************
* 函 數(shù) 名: BEEP_Start
* 功能說明: 啟動蜂鳴音。
* 形 參: _usBeepTime : 蜂鳴時間,單位10ms; 0 表示不鳴叫
* _usStopTime : 停止時間,單位10ms; 0 表示持續(xù)鳴叫
* _usCycle : 鳴叫次數(shù), 0 表示持續(xù)鳴叫
* 返 回 值: 無
**********************************************************************************************************/
voidBEEP_Start(uint16_t _usBeepTime, uint16_t _usStopTime, uint16_t _usCycle)
{if (_usBeepTime == 0 || g_tBeep.ucMute == 1)
{return;
}
g_tBeep.usBeepTime=_usBeepTime;
g_tBeep.usStopTime=_usStopTime;
g_tBeep.usCycle=_usCycle;
g_tBeep.usCount= 0;
g_tBeep.usCycleCount= 0;
g_tBeep.ucState= 0;
g_tBeep.ucEnalbe= 1; /*設(shè)置完全局參數(shù)后再使能發(fā)聲標志*/BEEP_ENABLE();/*開始發(fā)聲*/}
函數(shù)描述:
此函數(shù)主要用于蜂鳴器的初始化,代碼比較好理解。條件編譯實現(xiàn)了一個無源蜂鳴器的初始化,配置引腳為推挽輸出模式。由于V7開發(fā)板使用的無源蜂鳴器,所有沒有開啟宏定義BEEP_HAVE_POWER。
函數(shù)參數(shù):
第1個參數(shù)_usBeepTime用于設(shè)置蜂鳴時間,單位10ms,配置為0 表示不鳴叫。
第2個參數(shù)_usStopTime用于設(shè)置蜂鳴時間,單位10ms,配置為0 表示不鳴叫。
第3個參數(shù)_ _usCycle用于鳴叫次數(shù),配置為0 表示持續(xù)鳴叫。
使用舉例:
調(diào)用此函數(shù)前,務(wù)必優(yōu)先調(diào)用函數(shù)BEEP_InitHard進行初始化。比如要實現(xiàn)鳴叫50ms,停10ms, 1次,就是BEEP_Start(5, 1, 1);
20.4.5 函數(shù)BEEP_Pro
函數(shù)原型:
/**********************************************************************************************************
* 函 數(shù) 名: BEEP_Pro
* 功能說明: 每隔10ms調(diào)用1次該函數(shù),用于控制蜂鳴器發(fā)聲。該函數(shù)在 bsp_timer.c 中被調(diào)用。
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
void BEEP_Pro(void)
{if ((g_tBeep.ucEnalbe == 0) || (g_tBeep.usStopTime == 0) || (g_tBeep.ucMute == 1))
{return;
}if (g_tBeep.ucState == 0)
{if (g_tBeep.usStopTime > 0) /*間斷發(fā)聲*/{if (++g_tBeep.usCount >=g_tBeep.usBeepTime)
{
BEEP_DISABLE();/*停止發(fā)聲*/g_tBeep.usCount= 0;
g_tBeep.ucState= 1;
}
}else{
;/*不做任何處理,連續(xù)發(fā)聲*/}
}else if (g_tBeep.ucState == 1)
{if (++g_tBeep.usCount >=g_tBeep.usStopTime)
{/*連續(xù)發(fā)聲時,直到調(diào)用stop停止為止*/
if (g_tBeep.usCycle > 0)
{if (++g_tBeep.usCycleCount >=g_tBeep.usCycle)
{/*循環(huán)次數(shù)到,停止發(fā)聲*/g_tBeep.ucEnalbe= 0;
}if (g_tBeep.ucEnalbe == 0)
{
g_tBeep.usStopTime= 0;return;
}
}
g_tBeep.usCount= 0;
g_tBeep.ucState= 0;
BEEP_ENABLE();/*開始發(fā)聲*/}
}
}
函數(shù)描述:
此函數(shù)是蜂鳴器的主處理函數(shù),用于實現(xiàn)鳴叫時間、停止鳴叫時間和循環(huán)次數(shù)的處理。
使用舉例:
調(diào)用此函數(shù)前,務(wù)必優(yōu)先調(diào)用函數(shù)BEEP_InitHard進行初始化。
另外,此函數(shù)需要周期性調(diào)用,每10ms調(diào)用一次。
如果是裸機使用,將此函數(shù)放在bsp.c文件的bsp_RunPer10ms函數(shù)里面即可,這個函數(shù)是由滴答定時器調(diào)用的,也就是說,大家要使用蜂鳴器,定時器的初始化函數(shù)bsp_InitTimer一定要調(diào)用。
如果是RTOS使用,需要開啟一個10ms為周期的任務(wù)調(diào)用函數(shù)BEEP_Pro。
20.5 蜂鳴器驅(qū)動移植和使用
按鍵移植步驟如下:
第1步:復(fù)制bsp_beep.c,bsp_beep.h,bsp_tim_pwm.c和bsp_tim_pwm.h到自己的工程目錄,并添加到工程里面。
第2步:根據(jù)自己使用的蜂鳴器驅(qū)動引腳和頻率,修改下面的宏定義即可
#ifdef BEEP_HAVE_POWER /*有源蜂鳴器*/
/*PA8*/
#define GPIO_RCC_BEEP RCC_AHB1Periph_GPIOA
#define GPIO_PORT_BEEP GPIOA
#define GPIO_PIN_BEEP GPIO_PIN_8
#define BEEP_ENABLE() GPIO_PORT_BEEP->BSRRL = GPIO_PIN_BEEP /* 使能蜂鳴器鳴叫 */
#define BEEP_DISABLE() GPIO_PORT_BEEP->BSRRH = GPIO_PIN_BEEP /* 禁止蜂鳴器鳴叫 */
#else /* 無源蜂鳴器 */
/*PA0 ---> TIM5_CH1*/
/*1500表示頻率1.5KHz,5000表示50.00%的占空比*/
#define BEEP_ENABLE() bsp_SetTIMOutPWM(GPIOA, GPIO_PIN_0, TIM5, 1, 1500, 5000);
/*禁止蜂鳴器鳴叫*/
#define BEEP_DISABLE() bsp_SetTIMOutPWM(GPIOA, GPIO_PIN_0, TIM5, 1, 1500, 0);
#endif
第3步:這幾個驅(qū)動文件主要用到HAL庫的GPIO和TIM驅(qū)動文件,簡單省事些可以添加所有HAL庫.C源文件進來。
第4步,應(yīng)用方法看本章節(jié)配套例子即可。
特別注意,別忘了每10ms調(diào)用一次按鍵檢測函數(shù)BEEP_Pro()。
20.6 實驗例程設(shè)計框架
通過程序設(shè)計框架,讓大家先對配套例程有一個全面的認識,然后再理解細節(jié),本次實驗例程的設(shè)計框架如下:
1、 第1階段,上電啟動階段:
這部分在第14章進行了詳細說明。
2、 第2階段,進入main函數(shù):
第1部分,硬件初始化,主要是MPU,Cache,HAL庫,系統(tǒng)時鐘,滴答定時器,蜂鳴器等。
第2部分,應(yīng)用程序設(shè)計部分,實現(xiàn)了一個蜂鳴器應(yīng)用。
第3部分,蜂鳴器程序每10ms在滴答定時中斷執(zhí)行一次。
20.7 實驗例程說明(MDK)
配套例子:
V7-003_無源蜂鳴器
實驗?zāi)康?#xff1a;
學(xué)習(xí)無源蜂鳴器的控制實現(xiàn)。
實驗內(nèi)容:
啟動一個自動重裝軟件定時器,每100ms翻轉(zhuǎn)一次LED2。
實驗操作:
K1鍵按下,按鍵提示音(固定頻率1.5KHz)。
K2鍵按下,急促鳴叫10次。
K3鍵按下,長鳴3次。
上電后串口打印的信息:
波特率 115200,數(shù)據(jù)位 8,奇偶校驗位無,停止位 1
程序設(shè)計:
系統(tǒng)棧大小分配:
RAM空間用的DTCM:
硬件外設(shè)初始化
硬件外設(shè)的初始化是在 bsp.c 文件實現(xiàn):
/**********************************************************************************************************
* 函 數(shù) 名: bsp_Init
* 功能說明: 初始化所有的硬件設(shè)備。該函數(shù)配置CPU寄存器和外設(shè)的寄存器并初始化一些全局變量。只需要調(diào)用一次
* 形 參:無
* 返 回 值: 無
**********************************************************************************************************/
void bsp_Init(void)
{/*配置MPU*/MPU_Config();/*使能L1 Cache*/CPU_CACHE_Enable();/*STM32H7xx HAL 庫初始化,此時系統(tǒng)用的還是H7自帶的64MHz,HSI時鐘:
- 調(diào)用函數(shù)HAL_InitTick,初始化滴答時鐘中斷1ms。
- 設(shè)置NVIV優(yōu)先級分組為4。*/HAL_Init();/*配置系統(tǒng)時鐘到400MHz
- 切換使用HSE。
- 此函數(shù)會更新全局變量SystemCoreClock,并重新配置HAL_InitTick。*/SystemClock_Config();/*Event Recorder:
- 可用于代碼執(zhí)行時間測量,MDK5.25及其以上版本才支持,IAR不支持。
- 默認不開啟,如果要使能此選項,務(wù)必看V7開發(fā)板用戶手冊第xx章*/
#if Enable_EventRecorder == 1
/*初始化EventRecorder并開啟*/EventRecorderInitialize(EventRecordAll,1U);
EventRecorderStart();#endifbsp_InitKey();/*按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描*/bsp_InitTimer();/*初始化滴答定時器*/bsp_InitUart();/*初始化串口*/bsp_InitExtIO();/*初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執(zhí)行*/bsp_InitLed();/*初始化LED*/BEEP_InitHard();/*初始化蜂鳴器*/}
MPU配置和Cache配置:
數(shù)據(jù)Cache和指令Cache都開啟。配置了AXI SRAM區(qū)(本例子未用到AXI SRAM)和FMC的擴展IO區(qū)。
/**********************************************************************************************************
* 函 數(shù) 名: MPU_Config
* 功能說明: 配置MPU
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
static void MPU_Config( void)
{
MPU_Region_InitTypeDef MPU_InitStruct;/*禁止 MPU*/HAL_MPU_Disable();/*配置AXI SRAM的MPU屬性為Write back, Read allocate,Write allocate*/MPU_InitStruct.Enable=MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress= 0x24000000;
MPU_InitStruct.Size=MPU_REGION_SIZE_512KB;
MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable=MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable=MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number=MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable= 0x00;
MPU_InitStruct.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);/*配置FMC擴展IO的MPU屬性為Device或者Strongly Ordered*/MPU_InitStruct.Enable=MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress= 0x60000000;
MPU_InitStruct.Size=ARM_MPU_REGION_SIZE_64KB;
MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable=MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable=MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number=MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable= 0x00;
MPU_InitStruct.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);/*使能 MPU*/HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}/**********************************************************************************************************
* 函 數(shù) 名: CPU_CACHE_Enable
* 功能說明: 使能L1 Cache
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
static void CPU_CACHE_Enable(void)
{/*使能 I-Cache*/SCB_EnableICache();/*使能 D-Cache*/SCB_EnableDCache();
}
每10ms調(diào)用一次蜂鳴器處理:
蜂鳴器處理是在滴答定時器中斷里面實現(xiàn),每10ms執(zhí)行一次檢測。
/**********************************************************************************************************
* 函 數(shù) 名: bsp_RunPer10ms
* 功能說明: 該函數(shù)每隔10ms被Systick中斷調(diào)用1次。詳見 bsp_timer.c的定時中斷服務(wù)程序。一些處理時間要求
* 不嚴格的任務(wù)可以放在此函數(shù)。比如:按鍵掃描、蜂鳴器鳴叫控制等。
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
void bsp_RunPer10ms(void)
{
bsp_KeyScan10ms();
BEEP_Pro();
}
主功能:
主功能的實現(xiàn)主要分為兩部分:
啟動一個自動重裝軟件定時器,每100ms翻轉(zhuǎn)一次LED2。
通過按鍵做蜂鳴器演示。
/**********************************************************************************************************
* 函 數(shù) 名: main
* 功能說明: c程序入口
* 形 參: 無
* 返 回 值: 錯誤代碼(無需處理)
**********************************************************************************************************/
int main(void)
{
uint8_t ucKeyCode;
uint32_t freq= 1500;
bsp_Init();/*硬件初始化*/PrintfLogo();/*打印例程名稱和版本等信息*/PrintfHelp();/*打印操作提示*/bsp_StartAutoTimer(0, 100); /*啟動1個100ms的自動重裝的定時器*/printf("蜂鳴器頻率 = %dHz\r\n", freq);/*主程序大循環(huán)*/
while (1)
{
bsp_Idle();/*CPU空閑時執(zhí)行的函數(shù),在 bsp.c*/
/*判斷定時器超時時間*/
if (bsp_CheckTimer(0))
{/*每隔100ms 進來一次*/bsp_LedToggle(2);
}/*處理按鍵事件*/ucKeyCode=bsp_GetKey();if (ucKeyCode > 0)
{/*有鍵按下*/
switch(ucKeyCode)
{case KEY_DOWN_K1: /*K1按鍵按下,提示音*/BEEP_KeyTone();
printf("1按鍵按下,提示音(固定頻率1.5KHz)\r\n");break;case KEY_DOWN_K2: /*K2按鍵按下,急促鳴叫10次*/BEEP_Start(5, 5, 10); /*鳴叫50ms,停止50ms,10次*/printf("K2按鍵按下,急促鳴叫10次\r\n");break;case KEY_DOWN_K3: /*K3按鍵按下,長鳴3次*/BEEP_Start(50, 50, 3); /*鳴叫500ms,停止500ms,3次*/printf("K3按鍵按下,長鳴3次\r\n");break;default:break;
}
}
}
}
20.8 實驗例程說明(IAR)
配套例子:
V7-003_無源蜂鳴器
實驗?zāi)康?#xff1a;
學(xué)習(xí)無源蜂鳴器的控制實現(xiàn)。
實驗內(nèi)容:
啟動一個自動重裝軟件定時器,每100ms翻轉(zhuǎn)一次LED2。
實驗操作:
K1鍵按下,按鍵提示音(固定頻率1.5KHz)。
K2鍵按下,急促鳴叫10次。
K3鍵按下,長鳴3次。
上電后串口打印的信息:
波特率 115200,數(shù)據(jù)位 8,奇偶校驗位無,停止位 1
程序設(shè)計:
系統(tǒng)棧大小分配:
RAM空間用的DTCM:
硬件外設(shè)初始化
硬件外設(shè)的初始化是在 bsp.c 文件實現(xiàn):
/**********************************************************************************************************
* 函 數(shù) 名: bsp_Init
* 功能說明: 初始化所有的硬件設(shè)備。該函數(shù)配置CPU寄存器和外設(shè)的寄存器并初始化一些全局變量。只需要調(diào)用一次
* 形 參:無
* 返 回 值: 無
**********************************************************************************************************/
void bsp_Init(void)
{/*配置MPU*/MPU_Config();/*使能L1 Cache*/CPU_CACHE_Enable();/*STM32H7xx HAL 庫初始化,此時系統(tǒng)用的還是H7自帶的64MHz,HSI時鐘:
- 調(diào)用函數(shù)HAL_InitTick,初始化滴答時鐘中斷1ms。
- 設(shè)置NVIV優(yōu)先級分組為4。*/HAL_Init();/*配置系統(tǒng)時鐘到400MHz
- 切換使用HSE。
- 此函數(shù)會更新全局變量SystemCoreClock,并重新配置HAL_InitTick。*/SystemClock_Config();/*Event Recorder:
- 可用于代碼執(zhí)行時間測量,MDK5.25及其以上版本才支持,IAR不支持。
- 默認不開啟,如果要使能此選項,務(wù)必看V7開發(fā)板用戶手冊第xx章*/
#if Enable_EventRecorder == 1
/*初始化EventRecorder并開啟*/EventRecorderInitialize(EventRecordAll,1U);
EventRecorderStart();#endifbsp_InitKey();/*按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描*/bsp_InitTimer();/*初始化滴答定時器*/bsp_InitUart();/*初始化串口*/bsp_InitExtIO();/*初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執(zhí)行*/bsp_InitLed();/*初始化LED*/BEEP_InitHard();/*初始化蜂鳴器*/}
MPU配置和Cache配置:
數(shù)據(jù)Cache和指令Cache都開啟。配置了AXI SRAM區(qū)(本例子未用到AXI SRAM)和FMC的擴展IO區(qū)。
/**********************************************************************************************************
* 函 數(shù) 名: MPU_Config
* 功能說明: 配置MPU
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
static void MPU_Config( void)
{
MPU_Region_InitTypeDef MPU_InitStruct;/*禁止 MPU*/HAL_MPU_Disable();/*配置AXI SRAM的MPU屬性為Write back, Read allocate,Write allocate*/MPU_InitStruct.Enable=MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress= 0x24000000;
MPU_InitStruct.Size=MPU_REGION_SIZE_512KB;
MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable=MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable=MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number=MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable= 0x00;
MPU_InitStruct.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);/*配置FMC擴展IO的MPU屬性為Device或者Strongly Ordered*/MPU_InitStruct.Enable=MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress= 0x60000000;
MPU_InitStruct.Size=ARM_MPU_REGION_SIZE_64KB;
MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable=MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable=MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number=MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable= 0x00;
MPU_InitStruct.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);/*使能 MPU*/HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}/**********************************************************************************************************
* 函 數(shù) 名: CPU_CACHE_Enable
* 功能說明: 使能L1 Cache
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
static void CPU_CACHE_Enable(void)
{/*使能 I-Cache*/SCB_EnableICache();/*使能 D-Cache*/SCB_EnableDCache();
}
每10ms調(diào)用一次蜂鳴器處理:
蜂鳴器處理是在滴答定時器中斷里面實現(xiàn),每10ms執(zhí)行一次檢測。
/**********************************************************************************************************
* 函 數(shù) 名: bsp_RunPer10ms
* 功能說明: 該函數(shù)每隔10ms被Systick中斷調(diào)用1次。詳見 bsp_timer.c的定時中斷服務(wù)程序。一些處理時間要求
* 不嚴格的任務(wù)可以放在此函數(shù)。比如:按鍵掃描、蜂鳴器鳴叫控制等。
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
void bsp_RunPer10ms(void)
{
bsp_KeyScan10ms();
BEEP_Pro();
}
主功能:
主功能的實現(xiàn)主要分為兩部分:
啟動一個自動重裝軟件定時器,每100ms翻轉(zhuǎn)一次LED2。
通過按鍵做蜂鳴器演示。
/**********************************************************************************************************
* 函 數(shù) 名: main
* 功能說明: c程序入口
* 形 參: 無
* 返 回 值: 錯誤代碼(無需處理)
**********************************************************************************************************/
int main(void)
{
uint8_t ucKeyCode;
uint32_t freq= 1500;
bsp_Init();/*硬件初始化*/PrintfLogo();/*打印例程名稱和版本等信息*/PrintfHelp();/*打印操作提示*/bsp_StartAutoTimer(0, 100); /*啟動1個100ms的自動重裝的定時器*/printf("蜂鳴器頻率 = %dHz\r\n", freq);/*主程序大循環(huán)*/
while (1)
{
bsp_Idle();/*CPU空閑時執(zhí)行的函數(shù),在 bsp.c*/
/*判斷定時器超時時間*/
if (bsp_CheckTimer(0))
{/*每隔100ms 進來一次*/bsp_LedToggle(2);
}/*處理按鍵事件*/ucKeyCode=bsp_GetKey();if (ucKeyCode > 0)
{/*有鍵按下*/
switch(ucKeyCode)
{case KEY_DOWN_K1: /*K1按鍵按下,提示音*/BEEP_KeyTone();
printf("1按鍵按下,提示音(固定頻率1.5KHz)\r\n");break;case KEY_DOWN_K2: /*K2按鍵按下,急促鳴叫10次*/BEEP_Start(5, 5, 10); /*鳴叫50ms,停止50ms,10次*/printf("K2按鍵按下,急促鳴叫10次\r\n");break;case KEY_DOWN_K3: /*K3按鍵按下,長鳴3次*/BEEP_Start(50, 50, 3); /*鳴叫500ms,停止500ms,3次*/printf("K3按鍵按下,長鳴3次\r\n");break;default:break;
}
}
}
}
20.9 總結(jié)
本章節(jié)為大家介紹的無源蜂鳴器方案還是比較實用的,采用的非阻塞方式,實際項目中可以放心使用。
總結(jié)
以上是生活随笔為你收集整理的stm32无源蜂鸣器定时器_【STM32H7教程】第20章 STM32H7的GPIO应用之无源蜂鸣器...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 后端技术:Spring Boot 项目优
- 下一篇: java注解 interface_jav