stm32无源蜂鸣器定时器_【STM32H7教程】第20章 STM32H7的GPIO应用之无源蜂鸣器...
第20章?????? STM32H7的GPIO應用之無源蜂鳴器
本章教程為大家介紹STM32H7的GPIO應用之無源蜂鳴器,蜂鳴器也是GPIO控制的經典測試例程,可以讓大家對STM32H7應用有個簡單的整體認識。
20.1 初學者重要提示
20.2 蜂鳴器硬件設計
20.3 蜂鳴器軟件驅動設計
20.4 蜂鳴器板級支持包(bsp_beep.c)
20.5 蜂鳴器驅動移植和使用(裸機版)
20.6 使用例程設計框架
20.7 實驗例程說明(MDK)
20.8 實驗例程說明(IAR)
20.9 總結
20.1 初學者重要提示
學習本章節前,務必保證已經學習了第13,14和15章。
注意有源蜂鳴器和無源蜂鳴器的區別,本章教程的17.2.1小節有專門說明。
開發板是采用的有源蜂鳴器,需要PWM驅動,而截至本章節還沒有講到PWM,會在34章節專門為大家講解,程序中是通過一個宏定義控制使能和關閉,所以對于初學者來說,當前階段僅需了解到使能和關閉方法即可,后面學習到PWM章節了,再深入了解。
無源蜂鳴器的控制采用的非阻塞方式,實際項目中比較實用。
20.2 蜂鳴器硬件設計
蜂鳴器的硬件設計如下:
通過這個硬件設計,有如下兩點需要學習:
20.2.1 蜂鳴器分類
蜂鳴器主要有電磁式和電壓式兩種,而且都有無源蜂鳴器和有源蜂鳴器兩類。開發板使用的是電磁式有源蜂鳴器,而有源和無源的區別是有源蜂鳴器內部自帶振蕩器,給個電壓就能發聲,但頻率是固定的,只能發出一種聲音,而無源蜂鳴器頻率可控,給個方波才可以發聲,并且根據不同頻率發出不同的聲音效果。
拓展知識
關于有源蜂鳴器和無源蜂鳴器區別:
20.2.2 硬件設計
關于硬件驅動,這里主要有三點需要大家認識到:
S8050TL1是NPN型三極管,這里是當開關使用,PA8輸出高電平的時候三極管導通,輸出低電平,三極管關閉。
電阻R70起到限流的作用。
電阻R47在這里有特別的作用,首先要普及一個知識點,這里使用的是電磁式蜂鳴器,屬于感性負載,切斷這種負載必須要注意,如果電流消失,電感兩端的電壓將急劇上升,這種感應沖擊足以損壞邏輯門電路或者其它形式的負載驅動電路,為了保護這個電路,可以用一個二極管或者電阻吸收感應沖擊。
拓展知識
STM32H7的GPIO控制三極管驅動各種負載的安全措施和注意事項:
20.3 蜂鳴器軟件驅動設計
軟件驅動對有源蜂鳴器和無源蜂鳴器都做了支持,默認情況下用的是有源蜂鳴器。我們使用蜂鳴器的話,大部分情況下可以配置鳴叫次數、鳴叫的時間和停止的時間。本驅動設計就是基于這種應用方式實現,基本可以滿足大部分應用情況。
設計這個軟件驅動的關鍵之處是如何避免采用阻塞式的實現方式,比如要實現鳴叫1秒,停止1秒,循環5次,如果是阻塞方式等待1秒執行完畢,那就時間太長了。鑒于這種情況,程序里面實現了一種非阻塞的方式,通過滴答定時器中斷每10ms調用一次蜂鳴器處理函數來實現鳴叫次數、鳴叫的時間和停止的時間的更新。
20.4 蜂鳴器板級支持包(bsp_beep.c)
蜂鳴器驅動文件bsp_beep.c主要實現了如下幾個API:
BEEP_InitHard
BEEP_Start
BEEP_Stop
BEEP_Pause
BEEP_Resume
BEEP_KeyTone
BEEP_Pro
這里我們重點講解函數BEEP_InitHard、BEEP_Sart和BEEP_Pro。
函數BEEP_Stop、BEEP_Pause和BEEP_Resume測試效果不夠好,推薦直接使用BEEP_Sart即可,設置鳴叫時間、停止鳴叫時間和循環次數。而BEEP_KeyTone是基于BEEP_Start實現的,直接調用的BEEP_Start(5, 1, 1);?????? /* 鳴叫50ms,停10ms, 1次 */
20.4.1 宏定義設置
此文件的開頭有一個宏定義選擇,用戶可以選擇使用有源蜂鳴器或者無源蜂鳴器。
//#define BEEP_HAVE_POWER /* 定義此行表示有源蜂鳴器,直接通過GPIO驅動, 無需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章節專門講解,這里僅需只知道配置了一個PWM來驅動蜂鳴器即可。
20.4.2 蜂鳴器結構體變量
為了方便蜂鳴器的控制,專門封裝了一個結構體變量:
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:狀態變量,用于蜂鳴器鳴叫和停止的區分。
成員usBeepTime:鳴叫時間,單位10ms。
成員usStopTime:停止鳴叫時間,單位10ms。
成員usCycle:鳴叫和停止的循環次數。
成員usCount:用于鳴叫和停止時的計數。
成員usCycleCount:用于循環次數計數。
成員ucMute:用于靜音。
20.4.3 函數BEEP_InitHard
函數原型:
/**********************************************************************************************************
* 函 數 名: 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; /*設為輸出口*/GPIO_InitStructure.GPIO_OType= GPIO_OType_PP; /*設為推挽模式*/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; /*關閉靜音*/}
函數描述:
此函數主要用于蜂鳴器的初始化,代碼比較好理解。條件編譯實現了一個無源蜂鳴器的初始化,配置引腳為推挽輸出模式。由于V7開發板使用的無源蜂鳴器,所有沒有開啟宏定義BEEP_HAVE_POWER。
使用舉例:
底層驅動初始化直接在bsp.c文件的函數bsp_Init里面調用即可。
20.4.4 函數BEEP_Start
函數原型:
/**********************************************************************************************************
* 函 數 名: BEEP_Start
* 功能說明: 啟動蜂鳴音。
* 形 參: _usBeepTime : 蜂鳴時間,單位10ms; 0 表示不鳴叫
* _usStopTime : 停止時間,單位10ms; 0 表示持續鳴叫
* _usCycle : 鳴叫次數, 0 表示持續鳴叫
* 返 回 值: 無
**********************************************************************************************************/
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; /*設置完全局參數后再使能發聲標志*/BEEP_ENABLE();/*開始發聲*/}
函數描述:
此函數主要用于蜂鳴器的初始化,代碼比較好理解。條件編譯實現了一個無源蜂鳴器的初始化,配置引腳為推挽輸出模式。由于V7開發板使用的無源蜂鳴器,所有沒有開啟宏定義BEEP_HAVE_POWER。
函數參數:
第1個參數_usBeepTime用于設置蜂鳴時間,單位10ms,配置為0 表示不鳴叫。
第2個參數_usStopTime用于設置蜂鳴時間,單位10ms,配置為0 表示不鳴叫。
第3個參數_ _usCycle用于鳴叫次數,配置為0 表示持續鳴叫。
使用舉例:
調用此函數前,務必優先調用函數BEEP_InitHard進行初始化。比如要實現鳴叫50ms,停10ms, 1次,就是BEEP_Start(5, 1, 1);
20.4.5 函數BEEP_Pro
函數原型:
/**********************************************************************************************************
* 函 數 名: BEEP_Pro
* 功能說明: 每隔10ms調用1次該函數,用于控制蜂鳴器發聲。該函數在 bsp_timer.c 中被調用。
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
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) /*間斷發聲*/{if (++g_tBeep.usCount >=g_tBeep.usBeepTime)
{
BEEP_DISABLE();/*停止發聲*/g_tBeep.usCount= 0;
g_tBeep.ucState= 1;
}
}else{
;/*不做任何處理,連續發聲*/}
}else if (g_tBeep.ucState == 1)
{if (++g_tBeep.usCount >=g_tBeep.usStopTime)
{/*連續發聲時,直到調用stop停止為止*/
if (g_tBeep.usCycle > 0)
{if (++g_tBeep.usCycleCount >=g_tBeep.usCycle)
{/*循環次數到,停止發聲*/g_tBeep.ucEnalbe= 0;
}if (g_tBeep.ucEnalbe == 0)
{
g_tBeep.usStopTime= 0;return;
}
}
g_tBeep.usCount= 0;
g_tBeep.ucState= 0;
BEEP_ENABLE();/*開始發聲*/}
}
}
函數描述:
此函數是蜂鳴器的主處理函數,用于實現鳴叫時間、停止鳴叫時間和循環次數的處理。
使用舉例:
調用此函數前,務必優先調用函數BEEP_InitHard進行初始化。
另外,此函數需要周期性調用,每10ms調用一次。
如果是裸機使用,將此函數放在bsp.c文件的bsp_RunPer10ms函數里面即可,這個函數是由滴答定時器調用的,也就是說,大家要使用蜂鳴器,定時器的初始化函數bsp_InitTimer一定要調用。
如果是RTOS使用,需要開啟一個10ms為周期的任務調用函數BEEP_Pro。
20.5 蜂鳴器驅動移植和使用
按鍵移植步驟如下:
第1步:復制bsp_beep.c,bsp_beep.h,bsp_tim_pwm.c和bsp_tim_pwm.h到自己的工程目錄,并添加到工程里面。
第2步:根據自己使用的蜂鳴器驅動引腳和頻率,修改下面的宏定義即可
#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步:這幾個驅動文件主要用到HAL庫的GPIO和TIM驅動文件,簡單省事些可以添加所有HAL庫.C源文件進來。
第4步,應用方法看本章節配套例子即可。
特別注意,別忘了每10ms調用一次按鍵檢測函數BEEP_Pro()。
20.6 實驗例程設計框架
通過程序設計框架,讓大家先對配套例程有一個全面的認識,然后再理解細節,本次實驗例程的設計框架如下:
1、 第1階段,上電啟動階段:
這部分在第14章進行了詳細說明。
2、 第2階段,進入main函數:
第1部分,硬件初始化,主要是MPU,Cache,HAL庫,系統時鐘,滴答定時器,蜂鳴器等。
第2部分,應用程序設計部分,實現了一個蜂鳴器應用。
第3部分,蜂鳴器程序每10ms在滴答定時中斷執行一次。
20.7 實驗例程說明(MDK)
配套例子:
V7-003_無源蜂鳴器
實驗目的:
學習無源蜂鳴器的控制實現。
實驗內容:
啟動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
實驗操作:
K1鍵按下,按鍵提示音(固定頻率1.5KHz)。
K2鍵按下,急促鳴叫10次。
K3鍵按下,長鳴3次。
上電后串口打印的信息:
波特率 115200,數據位 8,奇偶校驗位無,停止位 1
程序設計:
系統棧大小分配:
RAM空間用的DTCM:
硬件外設初始化
硬件外設的初始化是在 bsp.c 文件實現:
/**********************************************************************************************************
* 函 數 名: bsp_Init
* 功能說明: 初始化所有的硬件設備。該函數配置CPU寄存器和外設的寄存器并初始化一些全局變量。只需要調用一次
* 形 參:無
* 返 回 值: 無
**********************************************************************************************************/
void bsp_Init(void)
{/*配置MPU*/MPU_Config();/*使能L1 Cache*/CPU_CACHE_Enable();/*STM32H7xx HAL 庫初始化,此時系統用的還是H7自帶的64MHz,HSI時鐘:
- 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。
- 設置NVIV優先級分組為4。*/HAL_Init();/*配置系統時鐘到400MHz
- 切換使用HSE。
- 此函數會更新全局變量SystemCoreClock,并重新配置HAL_InitTick。*/SystemClock_Config();/*Event Recorder:
- 可用于代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。
- 默認不開啟,如果要使能此選項,務必看V7開發板用戶手冊第xx章*/
#if Enable_EventRecorder == 1
/*初始化EventRecorder并開啟*/EventRecorderInitialize(EventRecordAll,1U);
EventRecorderStart();#endifbsp_InitKey();/*按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描*/bsp_InitTimer();/*初始化滴答定時器*/bsp_InitUart();/*初始化串口*/bsp_InitExtIO();/*初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行*/bsp_InitLed();/*初始化LED*/BEEP_InitHard();/*初始化蜂鳴器*/}
MPU配置和Cache配置:
數據Cache和指令Cache都開啟。配置了AXI SRAM區(本例子未用到AXI SRAM)和FMC的擴展IO區。
/**********************************************************************************************************
* 函 數 名: 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);
}/**********************************************************************************************************
* 函 數 名: CPU_CACHE_Enable
* 功能說明: 使能L1 Cache
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
static void CPU_CACHE_Enable(void)
{/*使能 I-Cache*/SCB_EnableICache();/*使能 D-Cache*/SCB_EnableDCache();
}
每10ms調用一次蜂鳴器處理:
蜂鳴器處理是在滴答定時器中斷里面實現,每10ms執行一次檢測。
/**********************************************************************************************************
* 函 數 名: bsp_RunPer10ms
* 功能說明: 該函數每隔10ms被Systick中斷調用1次。詳見 bsp_timer.c的定時中斷服務程序。一些處理時間要求
* 不嚴格的任務可以放在此函數。比如:按鍵掃描、蜂鳴器鳴叫控制等。
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
void bsp_RunPer10ms(void)
{
bsp_KeyScan10ms();
BEEP_Pro();
}
主功能:
主功能的實現主要分為兩部分:
啟動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
通過按鍵做蜂鳴器演示。
/**********************************************************************************************************
* 函 數 名: 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);/*主程序大循環*/
while (1)
{
bsp_Idle();/*CPU空閑時執行的函數,在 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_無源蜂鳴器
實驗目的:
學習無源蜂鳴器的控制實現。
實驗內容:
啟動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
實驗操作:
K1鍵按下,按鍵提示音(固定頻率1.5KHz)。
K2鍵按下,急促鳴叫10次。
K3鍵按下,長鳴3次。
上電后串口打印的信息:
波特率 115200,數據位 8,奇偶校驗位無,停止位 1
程序設計:
系統棧大小分配:
RAM空間用的DTCM:
硬件外設初始化
硬件外設的初始化是在 bsp.c 文件實現:
/**********************************************************************************************************
* 函 數 名: bsp_Init
* 功能說明: 初始化所有的硬件設備。該函數配置CPU寄存器和外設的寄存器并初始化一些全局變量。只需要調用一次
* 形 參:無
* 返 回 值: 無
**********************************************************************************************************/
void bsp_Init(void)
{/*配置MPU*/MPU_Config();/*使能L1 Cache*/CPU_CACHE_Enable();/*STM32H7xx HAL 庫初始化,此時系統用的還是H7自帶的64MHz,HSI時鐘:
- 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。
- 設置NVIV優先級分組為4。*/HAL_Init();/*配置系統時鐘到400MHz
- 切換使用HSE。
- 此函數會更新全局變量SystemCoreClock,并重新配置HAL_InitTick。*/SystemClock_Config();/*Event Recorder:
- 可用于代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。
- 默認不開啟,如果要使能此選項,務必看V7開發板用戶手冊第xx章*/
#if Enable_EventRecorder == 1
/*初始化EventRecorder并開啟*/EventRecorderInitialize(EventRecordAll,1U);
EventRecorderStart();#endifbsp_InitKey();/*按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描*/bsp_InitTimer();/*初始化滴答定時器*/bsp_InitUart();/*初始化串口*/bsp_InitExtIO();/*初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行*/bsp_InitLed();/*初始化LED*/BEEP_InitHard();/*初始化蜂鳴器*/}
MPU配置和Cache配置:
數據Cache和指令Cache都開啟。配置了AXI SRAM區(本例子未用到AXI SRAM)和FMC的擴展IO區。
/**********************************************************************************************************
* 函 數 名: 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);
}/**********************************************************************************************************
* 函 數 名: CPU_CACHE_Enable
* 功能說明: 使能L1 Cache
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
static void CPU_CACHE_Enable(void)
{/*使能 I-Cache*/SCB_EnableICache();/*使能 D-Cache*/SCB_EnableDCache();
}
每10ms調用一次蜂鳴器處理:
蜂鳴器處理是在滴答定時器中斷里面實現,每10ms執行一次檢測。
/**********************************************************************************************************
* 函 數 名: bsp_RunPer10ms
* 功能說明: 該函數每隔10ms被Systick中斷調用1次。詳見 bsp_timer.c的定時中斷服務程序。一些處理時間要求
* 不嚴格的任務可以放在此函數。比如:按鍵掃描、蜂鳴器鳴叫控制等。
* 形 參: 無
* 返 回 值: 無
**********************************************************************************************************/
void bsp_RunPer10ms(void)
{
bsp_KeyScan10ms();
BEEP_Pro();
}
主功能:
主功能的實現主要分為兩部分:
啟動一個自動重裝軟件定時器,每100ms翻轉一次LED2。
通過按鍵做蜂鳴器演示。
/**********************************************************************************************************
* 函 數 名: 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);/*主程序大循環*/
while (1)
{
bsp_Idle();/*CPU空閑時執行的函數,在 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 總結
本章節為大家介紹的無源蜂鳴器方案還是比較實用的,采用的非阻塞方式,實際項目中可以放心使用。
總結
以上是生活随笔為你收集整理的stm32无源蜂鸣器定时器_【STM32H7教程】第20章 STM32H7的GPIO应用之无源蜂鸣器...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 后端技术:Spring Boot 项目优
- 下一篇: java注解 interface_jav