WT588F02使用中断实现一线制串口

本文章是使用stm32使用LL库实现中断一线制串口

首先看WT588F02BP-14S的通信协议

WT588F02BP-14S的通信是有点类似串口的,但是又不是标准串口不能使用硬件,官方的案例里都是使用堵塞去发送,堵塞整体代码,这里我是用中断去模拟发送

一线制串口发送

思路是去单独开一个较高优先级的中断,快进快出去按每个bit置为io口,尽量不堵塞主程序,发送完成后将中断断闭

代码如下

配置一个100ns的中断,将voice();放进去,要播报就voice_write(uint8_t data);

voice.h

#ifndef _VOICE_H_
#define _VOICE_H_

#include "main.h"

#define VOICE_START 500//最快能连续播放时间重复发送
#define VOICE_LEN 20//声音队列长度
#define HIGH_TICK 2000//紧急播放的间隔时间
#define VOICEL_GPIN GPIOC
#define VOICE_PIN LL_GPIO_PIN_3
#define VOICE_TIM TIM7 //定时器
//接口函数
uint8_t find_voice(uint8_t num);//判断队列是否有该语音,没有就装填并打开播放,重复填充无效,从尾部填充,适合在正常情况下播放
void voice_interrupt(uint8_t num);//紧急播报,会打断正在播放的语音,但不影响后面播报的语音
//测试函数
void voice_write(uint8_t data);//马上写一个字节,并可以马上播放音乐,可打断上面音乐队列
//调度函数

void voice(void);//放入100us的中断里面
void phonic_alarming(void);//放10ms中断,根据队列放声音






#endif

voice.c 


volatile uint8_t voice_data,start_tick,stop_tick,bit,bit_tick=0;//这些变量描述在voice_write里
static uint8_t voice_queue[VOICE_LEN];//语音队列
static uint8_t voice_flag=0;//是否播放声音
static uint8_t queue_head=0;//队列头
static uint32_t tick_start=0;//等待播放
static uint32_t High_tick=0;//紧急标志位
/**
* @brief 播放音乐和设置,每次间隔必须在20ms以上,同时连续使用可能会打断上一条语音
* @param 0-223音乐列表,e0-ef设置声音大小
* @retval 无
*
* @example
voice_write(0);
*/
void voice_write(uint8_t data)
{
  start_tick=25; //5ms低电平
  voice_data=data;//数据
  stop_tick=10; //2m高电平
  bit=8;
  //一个字节8位,用来判断第几位
  bit_tick=0; //因为电平要分为2:6来区别高低电平,用来判断高低电平
  LL_TIM_EnableCounter (VOICE_TIM); //使能计数
  LL_TIM_EnableIT_UPDATE (VOICE_TIM); //使能更新中断
}
/**
* @brief 音乐调度, 必须放在一个100um的中断, 这里是借用定时器7, 这里面只有判断和拉高拉低电平
* @param 无
* @retval 无
* @example
-*/


void voice()
{
	if (start_tick)//开始低电平5ms
	{
		LL_GPIO_ResetOutputPin(VOICEL_GPIN,VOICE_PIN);
		start_tick--;
	}
	else if(bit>0)//一个字节8个bit,一个bit内要进中断8次
	{
		if(voice_data & 0X01)//高电平
		{
				if(bit_tick<6)
				{
					LL_GPIO_SetOutputPin(VOICEL_GPIN,VOICE_PIN);
				}else
				{
					LL_GPIO_ResetOutputPin(VOICEL_GPIN,VOICE_PIN);
				}
		}
			
		else//低电平
		{
				if(bit_tick<2)
				{
					LL_GPIO_SetOutputPin(VOICEL_GPIN,VOICE_PIN);
					
				}
				else
				{
					LL_GPIO_ResetOutputPin(VOICEL_GPIN,VOICE_PIN);
				}	
		}
		
		bit_tick++;
		
		if(bit_tick>=8)//发送下一个bit
			{
				bit_tick=0;
				bit--;
				voice_data=voice_data>>1;
			}
	}
	else if(stop_tick--)//结束高电平2ms
	{
		LL_GPIO_SetOutputPin(VOICEL_GPIN,VOICE_PIN);
	}
	else//关闭中断
	{
		LL_TIM_DisableCounter(VOICE_TIM);
		LL_TIM_DisableIT_UPDATE(VOICE_TIM);
	}
}

同时WT588F02BP-14S能检测是否在播报音乐,可添加一个IO检测和队列连续发送

本身芯片自身是可以连续发送的,但是他不能检测多条同样的语音连续发送,不方便就没用

队列发送语音

/**
  * @brief  判断队列是否有该语音,没有就装填并打开播放,重复填充无效,从尾部填充,
	* @param 语音地址
  * @retval 返回0正常,返回1代表要么语音在队列了,要么队列满了
	* @example 
find_voice(0x1)
								
	*/
uint8_t find_voice(uint8_t num)
{
for(int i=0;i<queue_head;i++)
	{
		if(voice_queue[i]==num)//判断队列是否有这条语音了
		{
			return 2;//存在语音
		}

	}
	if(queue_head<VOICE_LEN)//没超过限幅的情况下存进去
	{
	voice_queue[queue_head++]=num;
	voice_flag=1;//开启播报
	return 0;
	}
	return 1;//超出队列
}

/**
  * @brief  紧急播报,会打断正在播放的语音
	* @param 语音地址
	* @example 
voice_interrupt(0x1)
								
	*/
void voice_interrupt(uint8_t num)
{
	if(uwTick-High_tick>HIGH_TICK)
	{
voice_write(num);
		tick_start=uwTick;
	voice_flag=1;
	High_tick=uwTick;
	}
	
}
/**
  * @brief  根据队列播放语音,放1ms或者空闲中断
	* @param 
  * @retval 
	* @example 
computer(0x1)
								
	*/
void phonic_alarming()
{
	
//detection(VOICE_BUSY)==0是本人封装读io口的,你可自定义
	if(uwTick-tick_start>=VOICE_START&&voice_flag==1&&detection(VOICE_BUSY)==0)//防止连续播报(距离上次发送一秒后&&队列有语音&&没语音在发声)
	{
		tick_start=uwTick;
		if(queue_head!=0)//队列里面有语音
		{
		voice_write(voice_queue[0]);//播放第一条
		for(int i=0;i<queue_head-1;i++)//对队列进行递推
			{
				voice_queue[i]=voice_queue[i+1];
			}
			queue_head--;
		}
		else//播放完毕
		{
			voice_flag=0;
		}

	}

}

一线制串口接收

本项目是没用,但提供个思路

可以使用上升或下降沿中断来启动定时器中断,中断每次进去采样多少次后关闭中断来实现软件串口,在波特率不高和项目不大的时候可以使用,或者面试回答问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值