昨天我在51论坛发布了基于89C51单片机摩尔斯电码收发系统仿真,附完整代码和仿真,还有视频演示,帖子:http://www.51hei.com/bbs/dpj-213679-1.html 。由于接收部分没有完善,所以主程序没有上传,现给予补上。
别看程序比较短,缺费了我好几天时间编写调试修改,所以请大家给予多多鼓励,评论,以利我进一步提高。
单片机源程序如下:
- /*----------------------------------------------------------------
- * 【实验平台】: 89C51单片机开发板
- * 【外部晶振】: 11.0592mhz
- * 【主控芯片】: STC89C52
- * 【编译环境】: Keil μVisio4
- * 【程序编写】: wzqwxx 水上人家
- 名称:摩尔斯电码接收
- 内容:仅供交流学习,其他用途请注明编者,不保证功能正常
- 本程序仅实现了短电报自动接收功能
- 编制程序过程本身就很有趣和充满挑战,如果能制作成品,
- 练习发报也十分有趣,这也是对古老的电讯一种纪念,致敬
- 充满智慧的先辈们。
- 播发摩尔斯电码的一般要求是:以一个“点”的长度为一个时间
- 单位,“划”是三个点的时间长度;点划之间的间隔是一个点的长度;
- 字符之间的间隔是三个点的长度;单词之间的间隔是七个点的长度。
- 这样才能被收报人识别。
- ------------------------------------------------------------------*/
- //MRSJS.c文件
- #include<regx52.h>
- //#include <stdio.h>
- #include "1602.h"
- #define L 33 //显存数组元素个数
- sbit MRSIN = P3^3; //摩尔斯接口
- sbit beep = P2^3; //蜂鸣器接口
- unsigned char MRScode;//暂存接收码值
- unsigned char MRStime_L = 0,MRStime_H = 0; //接收摩尔斯码计数延时
- unsigned char idata i,strbuf[L];//显示缓冲
-
- //摩尔斯码字库 A~Z 0~9共36个 ? , . ! @ : - 共7个,总共43个字节
- unsigned char code MRSZK[] = { 0x61,0X28,0X2a,0x44,0x80,0x22,
- 0x46,0x20,0x60,0x27,0x45,0x24,0x63,0x62,0x47,0x26,0x2d,0x42,
- 0x40,0x81,0x41,0x21,0x43,0x29,0x2b,0x2c,/*A~Z*/0xbf,0xaf,0xa7,0xa3,
- 0xa1,0xa0,0xb0,0xb8,0xbc,0xbe,/*0~9*/0xcc,0xf3,0xd5,0xeb,0xda,0xf8,0xe1};
- unsigned char code ASCIIZK[] = "?,.!@:-"; //符号库,可扩展
- /*******************信号接收解码*********************/
- void EX1MRS (void) interrupt 2 //外部中断1服务函数
- {
- static unsigned char num,blag; //num为接收摩尔斯码点划的个数
- unsigned char j;
- /*******************处理低电平*********************/
- TR0 = 1; //启动time0计数产生中断
- if(blag == 1) //从第二个下降沿开始处理
- {
- //按点平均时长89ms,划时长约270ms,空格约640ms计算的范围
- if(MRStime_L > 2 && MRStime_L < 120 ) //处理点和划
- {
- MRScode <<= 1; //发送端从高位开始的
- if(MRStime_L > 43 ) //点时长计数上限22,划时长计数上限68
- {
- MRScode |= 0x01;
- Lcdwritechar(0,6+num,'_');
- }
- else
- {
- Lcdwritechar(0,6+num,'.');
- }
- num++;
- MRStime_L=0;
- /*******************处理高电平*********************/
- if(MRStime_H > 43 )//处理可见字符;字元之间时长计数是68
- {
- if(num<5 && num >0) //处理字母
- {
- num = (8-3-num) << 5; //得到字母前三位识别码值
- for(j = 0; j <= 25;j++)//字母字库地址0~25;
- {
- if( MRSZK[j] == (MRScode | num) )
- {
- strbuf[i] = j+0x41;
- i++;
- //printf("%bc",j+0x41) ;//发送到串口文本模式显示
- break;
- }
- }
- num = 0;
- }
- else if(num>5) //处理符号
- {
- num = 0;
- for(j = 36; j <= 42;j++)//符号字库地址36~42;
- {
- if((MRSZK[j]&0x3F) == MRScode ) //清零高两位
- {
- strbuf[i] = ASCIIZK[j-36];
- i++;
- // printf("%bc",ASCIIZK[j-36]) ;//发送到串口显示
- break;
- }
- }
- }
- else //处理数字
- {
- num = 0;
- for(j = 26; j <= 35;j++)//数字地址26~35;
- {
- if((MRSZK[j]&0x1F) == MRScode ) //清零高三位
- {
- strbuf[i] = j+0x16;
- i++;
- // printf("%bc",j+0x16) ;//发送到串口文本模式显示
- break;
- }
- }
- }
- if(MRStime_H > 110) //处理空格;
- {
- strbuf[i] = ' ';
- i++;
- // printf(" ") ;
- }
- if(MRStime_H > 190) //结束处理;
- {
- // printf("\n") ;//这里有时执行不到 ?
- blag = 0;
- TR0 = 0;
- }
- MRScode = 0;
- write_com(0x01);// 清屏
- Lcdwritestring(1,0,strbuf);//x行,Y列写字符串
- num = 0;
- }
- MRStime_H=0;
- }
- }
- else
- {
- write_com(0x01);// 清屏
- for(i = 0; i < L ;i++){strbuf[i] = 0;}; //清空显存
- i = 0;
- num = 0;
- blag = 1;
- MRStime_H = 0;
- MRStime_L = 0;
- }
- }
- void time0_MRS (void) interrupt 1 //STC89C52 4毫秒@11.0592MHz
- {
- TL0 = 0x9A; //设置定时初值 我这是按点平均时长90ms,划时长270ms设置的
- TH0 = 0xF1; //设置定时初值 在接收人工发送的要设计智能调整适应
- if(MRSIN)
- ++MRStime_H; //高电平延时计数
- if(!MRSIN)
- ++MRStime_L; //低电平延时计数
- if(MRStime_H > 250) //这是为接收最后一个字符自己产生一个下降沿触发中断
- {
- MRSIN = 1;
- MRSIN = 0;
- MRSIN = 1;
- }
- }
- //void UART_init()
- //{
- // TMOD |= 0x20; //T1工作模式2 8位自动重装
- // TH1 = 0xfd;
- // TL1 = 0xfd; //比特率9600 时钟频率11.0592MHZ
- // TR1 = 1; //启动T1定时器
- // SM0 = 0;
- // SM1 = 1; //串口工作方式1 10位异步
- // REN = 1; //串口允许接收
- // TI = 1;
- //}
- //
- void Timer0Init(void) //4毫秒@11.0592MHz
- {
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0x9A; //设置定时初值
- TH0 = 0xF1; //设置定时初值
- TF0 = 0; //清除TF0标志
- ET0 = 1;
- TR0 = 0; //定时器0开始设为0,由外中断启动计时
- }
- void EX1init(void)
- {
- IT1 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)
- EX1 = 1; //使能外部中断
- PX1 = 1;
- EA = 1; //开总中断
- }
- void main(void)
- {
- Timer0Init();//初始化定时器
- // UART_init(); //初始化串口
- EX1init(); //初始化外部中断
- lcd_init();//初始化液晶屏
- while(1)//主循环
- {
- beep = MRSIN; //单手键发送功能
- }
- }
-
-
复制代码
仿真截图
接收源码:
摩斯码电报接收.zip
(38.24 KB, 下载次数: 39)
|