首页 > 其他分享 >嵌入式开发学习之--用蜂鸣器来传递摩斯码

嵌入式开发学习之--用蜂鸣器来传递摩斯码

时间:2023-02-22 22:31:37浏览次数:36  
标签:蜂鸣器 morse -- Morse 嵌入式 BEEP GPIO define

本篇文章致力于从开发的角度思考问题,而不是搞学术的东西。

文章目录


前言

  在点亮led灯之后,接连写了两篇理论,更多的是力求自己学习旅程的完整吧,总觉得没多大意义。从今天开始,结合开发板开始搞实验,毕竟实战是检验一切的标准。一起学习的小伙伴如果有什么好的想法,可以留言,我们一起来完成。


一、项目概况

1.1、项目需求

  根据输入的情报,让蜂鸣器按照摩斯码的加密方式发出声音,用户通过蜂鸣器发出的声音能准确的写出输入的情报,就算成功。

1.2、项目来源

  作者脑洞。

1.3、项目开发环境

  软件:keil5;   硬件:野火挑战者开发板。

1.4、项目意义

  为情报人员传递信息,可以在影视剧,密室逃脱等场景中作为道具使用。

二、开发步骤

2.1、什么是摩斯码

  作为嵌入式开发,首先你要了解的是你开发的东西是个什么,我们既然要做摩斯码传递,那么就要了解什么是摩斯码。

  通过百度可以知道摩尔斯电码(Morse code)也被称作摩斯密码,是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母、数字和标点符号。它发明于1837年,是一种早期的数字化通信形式。不同于现代化的数字通讯,摩尔斯电码只使用零和一两种状态的二进制代码,它的代码包括五种:短促的点信号“・”,保持一定时间的长信号“—”,表示点和划之间的停顿、每个词之间中等的停顿,以及句子之间长的停顿。划一般是三个点的长度;点划之间的间隔是一个点的长度;字元之间的间隔就是三个点的长度;而单词之间的间隔是七个点的长度。

在这里插入图片描述

也就是说,我们需要通过蜂鸣器模拟出这几种情况。

2.2、构建项目流程图

  这个就比较考验个人了,也是我一直想实战的原因,不同的人都会有不同的思路,这里分享一下我的思路,算是抛砖引玉吧。

  首先从项目需求来看,要有一个输入情报,接着根据摩斯电码表,将输入的情报拆解成电码表的样式,然后再通过蜂鸣器进行输出。

flowchat
st=>start: 开始
e=>end: 结束
op=>operation: 输入情报
o1=>operation: 情报解析成摩斯码
o2=>operation: 摩斯码解析成蜂鸣器信号
o3=>operation: 蜂鸣器输出 

st->op->o1->o2->o3->e

2.3、找到合适的模板

  这里我们就用野火的工程模板,找到打开后简单编译一下。0错误,说明可以用。 在这里插入图片描述

2.4、增加文件

  根据项目接着新添加几个文件:   1.上层应用,主要是用来定义、存储上层应用所用到的函数变量。   2.底层硬件,主要根据所应用到的硬件资源创建。

  创建文件时可以县创建记事本,然后修改尾缀和名字。 在这里插入图片描述

  创建了4个文件,app.c、app.h、beep.c、beep.h。 在这里插入图片描述

  添加进工程:

在这里插入图片描述

  基本的工程框架已经建好,下一步就是写代码。

2.5、添加代码

  我们把代码分为三部分,蜂鸣器,摩斯码,main函数。

  首先我们先初始化需要用到的硬件蜂鸣器。

  按照之前我们处理led灯的思路,首先我们要看电路图,找到蜂鸣器。

在这里插入图片描述

  通过电路图我们可以看出,开发板的蜂鸣器是通过PI11引脚的高低控制是否有电。也就是我们要像配置led灯一样配置蜂鸣器。

蜂鸣器代码如下(示例):

  beep.c

#include "stm32f4xx.h"
#include "beep.h"


void BEEP_GPIO_Config(void)
{		
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd( BEEP_GPIO_CLK, ENABLE);   														   
	GPIO_InitStructure.GPIO_Pin = BEEP_GPIO_PIN;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   	
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_Init(BEEP_GPIO_PORT, &GPIO_InitStructure);			   
	GPIO_ResetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);	 
}

  beep.h

#ifndef __BEEP_H
#define __BEEP_H

#include "stm32f4xx.h"


#define BEEP_GPIO_PORT    	GPIOI			             
#define BEEP_GPIO_CLK 	    RCC_AHB1Periph_GPIOI	
#define BEEP_GPIO_PIN		  	GPIO_Pin_11			     

#define ON  1
#define OFF 0


#define BEEP(a)	if (a)	\
					GPIO_SetBits(BEEP_GPIO_PORT,BEEP_GPIO_PIN);\
					else		\
					GPIO_ResetBits(BEEP_GPIO_PIN)
					
#define	digitalHi(p,i)			{p->BSRRL=i;}			 		
#define digitalLo(p,i)			{p->BSRRH=i;}				
#define digitalToggle(p,i)	{p->ODR ^=i;}			


#define BEEP_TOGGLE		digitalToggle(BEEP_GPIO_PORT,BEEP_GPIO_PIN)
#define BEEP_OFF			digitalLo(BEEP_GPIO_PORT,BEEP_GPIO_PIN)
#define BEEP_ON				digitalHi(BEEP_GPIO_PORT,BEEP_GPIO_PIN)

void BEEP_GPIO_Config(void);

#endif

  简单解读一下,通过BEEP_GPIO_Config这个函数对蜂鸣器控制引脚PI11进行配置,然后将参数定义成宏定义,这样后期想换也十分方便;就将关闭和打开蜂鸣器的函数分别定义成BEEP_OFF和BEEP_ON,这样使用时十分方便。

  接着处理莫斯码函数,应该单独定义出摩斯码相关文件更合适,这里直接写在app文件里了。

  app.c

代码如下(示例):

#include "stm32f4xx.h"
#include "app.h"

_morse_code morse_code;

uint8_t morse_table_1[Ms_Table_num][Ms_Table_long]={" 0000000","A102","B2010101","C2010201","D20101","E1","F1010201","G20201", \
															 "H1010101","I101","J1020202","K20102","L1020101","M202","N201",\
															 "O20202","P1020201","Q2020102","R10201","S10101","T2",\
															 "U10102","V1010102","W10202","X2010102","Y2010202","Z2020101"};


															 
void delay_ms(uint32_t time)
{	
	int i;
	for(i=0;i<(SYS_FRE/1000)*time;i++){
		
	}
}														 
//³õʼ»¯app
int app_init()
{

}
uint8_t infor_translate_morse(uint8_t infor,uint8_t morse,uint32_t size)
{

	return morse;
	
}

uint8_t morse_translate_beep(uint8_t_morse)
{
	return 0;
}

app.h

代码如下(示例):

#ifndef __APP_H
#define __APP_H

#include "stm32f4xx.h"

#define Ms    morse_code
#define Ms_T  morse_table_1


#define Ms_Table_num 50
#define Ms_Table_long 20

#define Ms_Pause "0"
#define Ms_Short "1"
#define Ms_Long  "2"

#define Morse_Dalay_Time                 50   
#define Morse_Pause_Time                 Morse_Dalay_Time*1
#define Morse_Pause_OF_Letter_Time       Morse_Dalay_Time*3
#define Morse_Pause_OF_Word_Time       Morse_Dalay_Time*1
#define Morse_Short_Time                 Morse_Dalay_Time*1 
#define Morse_Long_Time                  Morse_Dalay_Time*3

#define SYS_FRE   72000000
typedef struct MORSE_CODE{

uint8_t* morse_table[50];
uint8_t* morse_in;
uint8_t* morse_out;	

}_morse_code;

extern _morse_code morse_code;
extern uint8_t morse_table_1[Ms_Table_num][Ms_Table_long];
extern void delay_ms(uint32_t time);

#endif

  简单解读一下,我的思路将摩斯码转换成字符串,然后对字符串进行操作,间隔是0,点是1,划是2,然后通过2维数组来定义摩斯码,定义的方式字符串首字符是发送字符,后面是其对应的摩斯码,这样进行首字符对比,找到对应字符以后,再对其后面的字符串进行读取并执行相关操作即可。定义时,依旧记得尽量采取宏定义的方式。这里还定义了一个延时函数,延时方式就是通过数数,我们的单片机频率是72M的,也就是1秒中可以数执行72M的操作,那么1ms可以数72000。如果未来更换频率是其它的单片机,这个记得要改。

  最后是main函数,我把最终执行函数写在了一起,其实不是很满意,耦合性太强了,可以划分的更合理。

  main.c

  代码如下(示例):


#include "stm32f4xx.h"
#include "beep.h"
#include "app.h"
#include <string.h>

int beep_out_morse_data(uint8_t* data,int size)
{
 uint32_t i;
 uint32_t j;

 uint8_t* p;
 uint8_t* q;			
 p=data;														
	for(i=0;i<size;i++){									
		for(j=0;j<Ms_Table_num;j++){	      
			q=Ms_T[j];
			if(*p==*q){										
				break;	
			}					
		}
		
		if(j>=Ms_Table_num){
						
		}
		
		while(*q!='\0'){
			q++;
			if(*q=='0'){
				BEEP_OFF;	
				delay_ms(Morse_Pause_Time);
			}else if(*q=='1'){
				BEEP_ON;	
				delay_ms(Morse_Short_Time);				
			}else if(*q=='2'){
				BEEP_ON;	
				delay_ms(Morse_Long_Time);						
			}else if(*q=='3'){
			
			}else{
			
			}			
		}
		
		BEEP_OFF;	
		delay_ms(Morse_Pause_OF_Letter_Time);		
		
		j=0;
		p++;		
		}
	
	
}


int main(void)
{
	uint8_t information[]= "I LOVE YOU";	
	BEEP_GPIO_Config();	
	morse_code.morse_in=information;	
	
	while(1){
		beep_out_morse_data(morse_code.morse_in,strlen((const char *)morse_code.morse_in));	
	}
	
}

总结

  1.蜂鸣器的配置和led灯思路完全一致,就是一个普通I/O口的配置操作。可以自己写一写复习一下。   2.注意代码架构,不仅要考虑当前的任务,也要考虑之后的维护,移植,扩展等等。我做的也不是很好,在写这个的时候脑子里多了很多想法,越想越复杂,最后按照自己思路去先做出来再说,后期可以在这个基础上继续补充。   3.实践是检验真理的唯一标准,多动手写一写,多跑跑代码,将理论转化为实际。

标签:蜂鸣器,morse,--,Morse,嵌入式,BEEP,GPIO,define
From: https://blog.51cto.com/u_15941409/6079466

相关文章

  • 【五期李伟平】CCF-C(Applied Intelligence'16)Outlier-eliminated k-means clustering
    Luo,etal."Outlier-eliminatedk-meansclusteringalgorithmbasedondifferentialprivacypreservation."AppliedIntelligencetheInternationalJournalofAr......
  • 【Spring AOP】【八】Spring AOP源码解析-拦截器/通知器链的执行顺序
    1 前言上节我们看过了代理对象执行方法的大致过程,我们留着通知器链的具体执行没说,这节我们先讲解一下通知器的执行顺序。通知器或者叫拦截器,叫法不一样,这里我们还是都......
  • 【算法训练营day59】LeetCode503. 下一个更大元素II LeetCode42. 接雨水
    LeetCode503.下一个更大元素II题目链接:503.下一个更大元素II独上高楼,望尽天涯路和昨天的那道题大部分是一个思路,对于循环数组,只需要遍历nums两遍即可。classSolutio......
  • 线程终止
    线程终止的方式:1.主动终止a.线程运行函数中调用returnb.线程中调用pthread_exit函数2.被动终止线程可以被同一进程的其他线程取消,其他线程调用pthrea......
  • tf.keras序列问题
    目录加载Tensorflow的dataset数据文本训练场密集向量创建模型配置模型模型训练查看history中的参数绘制loss变化曲线绘制accuracy变化曲线解决过拟合问题:1:dropout层2:l2,l1......
  • django-drf跨域
    django使用django-cors-headers解决跨域问题1、使用pip安装pipinstalldjango-cors-headers2、添加到setting的app中INSTALLED_APPS=( ... 'corsheaders', ........
  • Vue学习:实现用户没有登陆时,访问后自动跳转登录页面
    设计思路定义路由的时候配置属性,这里使用needLogin标记访问页面是否需要登录设置路由守卫,每个页面在跳转之前都要经过验证,校验用户信息是否存在,不存在跳转到登录页用户......
  • ACM模版202108
    字符串String类的基本用法substring(a,b) 将字符串取出[a,b),组成新的字符串indexOf(ch) 返回字符串ch第一次出现的位置,没有则-1马拉车voidmanacher(){intl......
  • 树和二叉树的转换
    规则:1.把兄弟连起来2.只留下长子3.顺时针旋转45度例如:二叉树转换成树则是这个过程的逆过程......
  • 最新的腾讯云服务器如何获取宝塔面板地址?
    最近购买了一台腾讯云的服务器,登陆进去发现可以聚合宝塔,但是宝塔如何获取呢?步骤如下:1.进入腾讯云后台,选择轻量应用服务器,选择应用管理,复制指定位置的命令sudo/etc/init.......