历史上的今天
返回首页

历史上的今天

今天是:2026年01月30日(星期五)

正在发生

2023年01月30日 | 51单片机与蜂鸣器实现摩斯电码转换

2023-01-30 来源:zhihu

具体功能实现

当我们按下矩阵按键中不同的按键时,在LCD1602显示相应的内容,同时一个按键按下多次可以切换不同的字母或数字,并且LED灯会闪烁。最后当我们按下确认时,蜂鸣器会发出不同频率的声音。

器件

蜂鸣器,AT89C51,若干按键,LCD1602,两支LED灯,排阻

仿真展示图

仿真前


仿真后


知识介绍

矩阵按键控制原理

如果使用独立按键与单片机连接, 每一个按键都需要单片机的一个 I/O 口, 若某单片机系统需较多按键, 用独立按键便会占用过多的 I/O 口资源。 单片机系统中 I/O 口资源往往比较宝贵, 当用到多个按键时为了减少 I/O 口引脚, 引入了矩阵按键。

矩阵按键检测原理

按键检测一般通过扫描来实现,先使某一列变为低电平,其余几列为高电平,后检测每行是否出现低电平。若没有出现,则某行按键没有被按下,若出现则说明按键被按下,即可锁定位置。

矩阵按键控制方法

①行列式法:

上图将第一列全部置0,其余位置均为1

将第一行全部置0,其余位全部置1。

因此我们可以得出按键按下的正是第一行第一列的

②线翻转法:

首先使所有行置为0,然后检测列是否含有低电平,如果有,则记录列的位置;之后再翻转,使所有列置为0,检测行是否有低电平,如果有,则记录行的位置(本文采用的是线翻转法)

主函数代码(C语言)KEIL5实现

#include

#include

void delay(unsigned char ms);

void delay2(int i);

void lcd_wcmd(unsigned char cmd);

void lcd_pos(unsigned char pos);

void lcd_wdat(unsigned char dat);

void lcd_init();

void xianshi();

void KeyDown();

void la_ba();


sbit rs= P2^6;

sbit rw = P2^5;

sbit ep = P2^7;

sbit d=P3^0;

sbit d1=P3^1;

sbit lb=P3^2;

int b,c,s=0,q=0,w=0;

#define GPIO_KEY P1

unsigned char dis1[32];

unsigned char dis2[9]={',','A','D','G','J','M','P','T','W'};

unsigned char dis3[9]={'1','2','3','4','5','6','7','8','9'};

unsigned int code laba[36][5]={

1,2,3,3,3,//A

2,1,1,1,3,//B

2,1,2,1,3,//C

2,1,1,3,3,//D

1,3,3,3,3,//E

1,1,2,1,3,//F

2,2,1,3,3,//G

1,1,1,1,3,//H

1,1,3,3,3,//I

1,2,2,2,3,//J

2,1,2,3,3,//K

1,2,1,1,3,//L

2,2,3,3,3,//M

2,1,3,3,3,//N

2,2,2,3,3,//0

1,2,2,1,3,//P

2,2,1,2,3,//Q

1,2,1,3,3,//R

1,1,1,3,3,//S

2,3,3,3,3,//T

1,1,2,3,3,//U

1,1,1,2,3,//V

1,2,2,3,3,//W

2,1,1,2,3,//X

2,1,2,2,3,//Y

2,2,1,1,3,//Z

2,2,2,2,2,//0

1,2,2,2,2,//1

1,1,2,2,2,//2

1,1,1,2,2,//3

1,1,1,1,2,//4

1,1,1,1,1,//5

2,1,1,1,1,//6

2,2,1,1,1,//7

2,2,2,1,1,//8

2,2,2,2,1,//9

};

// LCD1602代码开始

bit lcd_bz()

{

bit result;

rs = 0;

rw = 1;

ep = 1;

_nop_();

_nop_();

_nop_();

_nop_();

result = (bit)(P0 & 0x80);

ep = 0;

return result;

}

void lcd_wcmd(unsigned char cmd)

{

while(lcd_bz());//判断LCD是否忙碌

rs = 0;

rw = 0;

ep = 0;

_nop_();

_nop_();

P0 = cmd;

_nop_();

_nop_();

_nop_();

_nop_();

ep = 1;

_nop_();

_nop_();

_nop_();

_nop_();

ep = 0;

}

void lcd_pos(unsigned char pos)

{

lcd_wcmd(pos | 0x80);

}

void lcd_wdat(unsigned char dat)

{

while(lcd_bz());//判断LCD是否忙碌

rs = 1;

rw = 0;

ep = 0;

P0 = dat;

_nop_();

_nop_();

_nop_();

_nop_();

ep = 1;

_nop_();

_nop_();

_nop_();

_nop_();

ep = 0;

}

void lcd_init()

{

lcd_wcmd(0x38);

delay(1);

lcd_wcmd(0x0c);

delay(1);

lcd_wcmd(0x06);

delay(1);

lcd_wcmd(0x01);

delay(1);

}

void xianshi()

{

int i=0,j=1,n=0;

while(dis1[i] != '')

{

lcd_pos(0x00);//设置显示位置

while(j!=0&&dis1[i] != '')

{

lcd_wdat(dis1[i]);//显示字符

i++;

j=i%16;

}

lcd_pos(0x40);// 设置显示位置

j=1;

while(j!=0&&dis1[i] != '')

{

lcd_wdat(dis1[i]);// 显示字符

i++;

j=i%16;

}

j=1;

if(dis1[i] != '')

i-=16;

}

i=0;

}

//LCD1602代码结束

void delay(unsigned char ms)

{

unsigned char i;

while(ms--)

{

for(i = 0; i< 250; i++)

{

_nop_();

_nop_();

_nop_();

_nop_();

}

}

}

void delay2(int i)

{

while(i--);

}

//按下按键

void KeyDown()

{

int KeyValue=0;

GPIO_KEY=0x0f;

if(GPIO_KEY!=0x0f)

{

delay(5);  //消抖

if(GPIO_KEY!=0x0f)

{

GPIO_KEY=0X0F;

switch(GPIO_KEY)

{

case(0X07): KeyValue=0;break;

case(0X0b): KeyValue=1;break;

case(0X0d): KeyValue=2;break;

case(0X0e): KeyValue=12;break;

}

}

GPIO_KEY=0XF0;

switch(GPIO_KEY)

{

case(0X70): KeyValue=KeyValue;break;

case(0Xb0): KeyValue=KeyValue+3;break;

case(0Xd0): KeyValue=KeyValue+6;break;

case(0Xe0): KeyValue=KeyValue+9;break;

}

while(GPIO_KEY!=0xf0);

if(KeyValue!=c&&dis1[w]!='')

{b=0;w++;}

if(KeyValue<=8&&s==0)

{

if(c==12||c==15)w--;

dis1[w]=dis2[KeyValue]+b;

d=0;delay(25);d=1;delay(25);

}

else if(KeyValue<=8&&s==1)

{

if(c==12||c==15)w--;

dis1[w]=dis3[KeyValue];

d=0;delay(25);d=1;delay(25);

}

else if(KeyValue==12)

{

//当按键为12时,删除一位(退格)

if(w>0)

{

w--;

dis1[w]=' ';

}

else

{

dis1[w]=' ';

}

d1=0;delay(25);d1=1;delay(25);

}

else if(KeyValue==15)

{

//当按下15时,添加一个空格

while(w!=0)

{

w--;

dis1[w]=' ';

}

}

else if(KeyValue==9)

{

//显示数字7

q++;

s=q%2;

if(c==12||c==15)w-=2;

}

else if(KeyValue==10)

{

//显示数字8

if(s==0)

dis1[w]=' ';

else

dis1[w]='0';

}

else if(KeyValue==11)

{

//显示数字9

dis1[w]=' ';

}

else if(KeyValue==18)

{

dis1[w]=' ';

w--;

}

else if(KeyValue==21)

{

la_ba();

}

b++;

if(b==3)b=0;

c=KeyValue;

}

}

//蜂鸣器

void la_ba()

{

int i,j,t;

for(i=0;dis1[i]!='';i++)

{

if(dis1[i]>=65&&dis1[i]<=90)

{

d1=0;delay(25);d1=1;delay(25);

for(j=0;laba[dis1[i]-65][j]!=3;j++)

{

if(laba[dis1[i]-65][j]==1)

{

t=100;

while(t--)

{

lb=~lb;

delay2(70);

}

delay(50);

}

if(laba[dis1[i]-65][j]==2)

{

t=300;

while(t--)

{

lb=~lb;

delay2(70);

}

delay(50);

}

if(laba[dis1[i]-65][j+1]==3)

{

delay(100);

}

}

}

if(dis1[i]>=48&&dis1[i]<=57)

{

d=0;delay(25);d=1;delay(25);

for(j=0;j<5;j++)

{

if(laba[dis1[i]-22][j]==1)

{

t=100;

while(t--)

{

lb=~lb;

delay2(70);

}

delay(50);

}

if(laba[dis1[i]-22][j]==2)

{

t=300;

while(t--)

{

lb=~lb;

delay2(70);

}

delay(50);

}

if(j==4)

{

delay(100);

}

}

}

}

}

void main()

{

lcd_init();// 初始化LCD

delay(10);

while(1)

{

KeyDown();

xianshi();

}

}


推荐阅读

史海拾趣

深圳杜因特(DOINGTER)公司的发展小趣事

作为一家快速发展的电子企业,杜因特深知人才是公司最宝贵的财富。因此,公司始终将团队建设和人才培养放在重要位置。通过引进优秀人才、加强内部培训等方式,杜因特打造了一支高效协作、专业精湛的团队。同时,公司还为员工提供了良好的工作环境和福利待遇,让员工能够在一个如家般的团队中做具有革新性的工作。

以上五个故事仅是基于已知信息对深圳杜因特公司发展起来的相关事实的概括性描述,具体细节可能因实际情况而有所不同。

Bias Power公司的发展小趣事

在竞争激烈的电子行业中,Bias Power公司始终坚持质量至上的原则。公司建立了严格的质量控制体系,从原材料采购到生产加工、产品测试等各个环节都进行严格把关。此外,公司还引入了先进的生产设备和技术,确保产品的稳定性和可靠性。

由于公司对产品质量的严格把控,Bias Power公司的产品在市场上享有很高的声誉。许多知名企业都选择与其合作,将其产品应用于关键领域和重要项目中。这种信赖和认可为Bias Power公司的发展提供了有力支持。

BOPLA公司的发展小趣事

近年来,随着环保意识的提高和政府对塑料污染治理的关注,BOPLA积极响应国家号召,开始研发和推广生物基可降解材料。经过多年的努力,公司成功推出了BOPLA生物基膜材,实现了产品的绿色转型。这一创新不仅有助于减少塑料污染,还为公司赢得了更多的环保意识和绿色消费市场的青睐。

BETA Transformer Technology Corp公司的发展小趣事

随着全球环保意识的不断提高,BETA Transformer Technology Corp公司积极响应国家绿色发展的号召,将环保理念贯穿于产品研发、生产和销售的全过程。公司推出了一系列节能环保的变压器产品,深受客户好评。同时,BETA公司还加强了对生产废弃物的处理和回收利用,实现了资源的循环利用和减少环境污染。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。

成都振芯/国腾(CORPRO)公司的发展小趣事

2003年,成都国腾微电子有限公司(后更名为成都振芯科技股份有限公司)正式成立,标志着CORPRO的起点。公司由成都国腾电子集团投资设立,创始人团队汇聚了来自中国物资储运集团、电子科技大学等单位的精英。在成立之初,CORPRO就致力于集成电路、微波组件及相关电子器件的设计、开发与销售,奠定了其在电子行业的基础。

富信半导体(FOSAN)公司的发展小趣事

在北斗卫星导航系统的发展过程中,CORPRO始终扮演着重要角色。作为北斗终端的最大供应商之一,CORPRO通过不懈的技术研发和产品迭代,成功实现了北斗设备零部件的国产化。同时,公司还构建了“元器件-终端-系统及运营”的完整产业链,在高性能集成电路板块取得了显著成就。此外,CORPRO还是首批承担“核高基”核心电子器件项目企业中唯一的一家民营企业,体现了其在电子行业的领先地位和创新能力。

问答坊 | AI 解惑

基于VB 的台达PLC 与监控计算机的串行通信实现

Implementation of Serial Communication Between MonitoringComputer and Delta PLC Based on Visual Basic…

查看全部问答>

是同是测两个电压。可以显示一个出来

#include<reg52.h>unsigned char code dispbitcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsigned char dispbuf[4];unsigned int i;unsigned int j;unsigned char getdata,getdata1;unsigned int temp;unsigned int temp1;u ...…

查看全部问答>

写了个2440下的wince SPI驱动,请高手看下有什么问题

#include #include #include #include #include #include #include #include #include //#include #include #include #include #include \"s2440.h\" //#include \"SPI.h\" HANDLE g_hInstance; volatile IOPreg * ...…

查看全部问答>

关于MOBILE 5 SDK的发短信sample问题

Example This sample shows how to send an SMS message to a mobile phone.             public void SmsMessageSend()             {      ...…

查看全部问答>

【低功耗】Xilinx 功耗估算器 (XPE) 演示

太大了,给个外链吧 http://www.21ic.com/video/jishujiangzuo/201011/70721.htm…

查看全部问答>

Lwip中接收回调函数是中断

遇到问题如下: 单独用网络接收或者发送数据都正常。 然后在网络接收回调函数中,收到一个特定的数据后写EEPROM,I2C的中断一直无法结束。 有木有人遇到过这种情况。帮忙解答下。…

查看全部问答>

富士通工业控制DIY板部分程序整合

LED、按键、遥信、AD、温度、蜂鸣器、1602液晶目前已经整合。 1602使用参照“富士通工业测控DIY板硬件说明”    https://bbs.eeworld.com.cn/thread-339498-1-1.html 富士通工业控制DIY板部分模块整合程序见4楼  https://bbs ...…

查看全部问答>

【玩转C2000 LaunchPad】点阵LCD作波形显示

这是做示波器的前奏。 本LCD使用的驱动芯片是0724,在显示方法上,没有特长,对CPU的资源的浪费还是比较大的。 但作为示波器使用时,显示并不使用实时方法,所以,还是可以接受的。 先上个图: …

查看全部问答>

正弦波转换成方波

怎样才能将正弦波转换成方波,而且方波幅值的变化还要随正弦波峰峰值的变化而变化?也就是说我要实时的对正弦信号进行变换,没想明白该怎样设计这样一个硬件电路。…

查看全部问答>