GPIO应用之蜂鸣器驱动

蜂鸣器主要有电磁式和电压式两种, 而且都有无源蜂鸣器和有源蜂鸣器两类。开发板使用的是电磁式无源蜂鸣器, 而有源和无源的区别是有源蜂鸣器内部自带振荡器,给个电压就能发声, 但频率是固定的,只能发出一种声音,而无源蜂鸣器频率可控,给个方波才可以发声, 并且根据不同频率发出不同的声音效果

驱动设计:

这里接着介绍下安富莱的有源蜂鸣器,但无源和有源蜂鸣器的核心思想都是一样的。

大部分情况下可以配置鸣叫次数、 鸣叫的时间和停止的时间。 本驱动设计就是基于这种应用方式实现,基本可以满足大部分应用情况。

设计这个软件驱动的关键之处是如何避免采用阻塞式的实现方式, 比如要实现鸣叫 1 秒,停止 1 秒,循环 5 次,如果是阻塞方式等待 1 秒执行完毕,那就时间太长了。 鉴于这种情况,程序里面实现了一种非阻塞的方式,通过滴答定时器中断每 10ms 调用一次蜂鸣器处理函数来实现鸣叫次数、 鸣叫的时间和停止的时间的更新。

蜂鸣器驱动的实现

一,定义结构体:

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;		/* 1表示静音 */	
}BEEP_T;
BEEP_T g_tBeep;		/* 定义蜂鸣器全局结构体变量 */

成员 ucEnalbe: 用于使能或者禁止蜂鸣器。

成员 ucState: 状态变量,用于蜂鸣器鸣叫和停止的区分。

成员 usBeepTime: 鸣叫时间,单位 10ms。

 成员 usStopTime: 停止鸣叫时间,单位 10ms。

成员 usCycle:鸣叫和停止的循环次数。

成员 usCount: 用于鸣叫和停止时的计数。

成员 usCycleCount: 用于循环次数计数。

二,启动蜂鸣器:

void BEEP_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();			/* 开始发声 */
}

第 1 个参数_usBeepTime 用于设置蜂鸣时间,单位 10ms,配置为 0 表示不鸣叫。

第 2 个参数_usStopTime 用于设置蜂鸣时间,单位 10ms,配置为 0 表示不鸣叫。

第 3 个参数_ _usCycle 用于鸣叫次数, 配置为 0 表示持续鸣叫。

三,被检测蜂鸣器状态:

void BEEP_Pro(void)   //(5,2,2)
{
	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。

本来想具体给大家分析以下的,问了下GPT,这玩意写的真牛逼,贴在这了,清晰明了

声控制。
GPT-3.5
void BEEP_Pro(void)   //(5,2,2)
{
	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();			/* 开始发声 */
		}
	}
} 解释一下这段代码

2024-03-07 00:39:55
GPT-3.5
这段代码是一个蜂鸣器控制函数。下面是对代码的解释:

函数名称是 BEEP_Pro,表示蜂鸣器处理函数。

该函数首先进行一系列条件判断,判断蜂鸣器是否允许发声。如果满足以下条件之一,则不进行后续操作,直接返回:

g_tBeep.ucEnable 等于 0,表示蜂鸣器被禁用;
g_tBeep.usStopTime 等于 0,表示停止时间为0,即不发声;
g_tBeep.ucMute 等于 1,表示蜂鸣器被静音。
接下来,根据蜂鸣器的当前状态进行处理:

如果 g_tBeep.ucState 等于 0,表示蜂鸣器当前处于准备开始发声的状态。在这种情况下,代码会根据以下逻辑进行处理:

如果蜂鸣器是间断发声模式(g_tBeep.usStopTime > 0),则判断发声计数器是否达到了设定的发声时间(g_tBeep.usBeepTime)。如果计数器达到了发声时间,则停止发声,设置状态为 1,重置计数器。
如果蜂鸣器是连续发声模式(g_tBeep.usStopTime 等于 0),则不进行任何处理。
如果 g_tBeep.ucState 等于 1,表示蜂鸣器准备要停止发声。在这种情况下,代码会根据以下逻辑进行处理:

判断停止发声计数器是否达到了设定的停止时间(g_tBeep.usStopTime)。如果计数器达到了停止时间,则执行以下操作:
如果蜂鸣器需要循环发声(g_tBeep.usCycle > 0),则判断循环计数器是否达到了设定的循环次数(g_tBeep.usCycle)。如果循环计数器达到了循环次数,则将 g_tBeep.ucEnable 设置为 0,即停止发声。
如果蜂鸣器已经停止发声,则将 g_tBeep.usStopTime 设置为 0,以便在下一次调用时清零,并直接返回。
重置计数器,将状态设置为 0,然后开始发声。
该段代码主要用于控制蜂鸣器的发声和停止发声过程,根据不同的模式(间断发声或连续发声),在合适的时间进行相应的操作。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值