【业余无线电】Python程序模拟CW电报发报与译码(包含英文和中文,方便练习发报节奏和听音解码)

本文介绍了莫尔斯电码的基本原理和编码表,并展示了如何使用Python编写代码将英文和中文消息转换为莫尔斯电码,同时模拟电报的发送与接收过程。通过Python程序,用户可以体验到CW电报通信的过程,包括英文和中文的编码、解码及声音模拟发报。
摘要由CSDN通过智能技术生成


前言

先展示下程序效果:

python模拟CW通联发报与译码

CW是等幅电报通信(Continuous Wave)的英文字头简称,CW电报通信是业余电台众多通信方式中主要的常用联络方式之一,在业余电台通信联络中通称为CW方式。

由于很多人对CW中使用的电报码还不是很熟悉,更多只是电视剧谍报人员收发报过程中听过到的滴滴答答的声音。

那么电报码到底是什么样的?它的消息发送有什么规律和要求呢?本文将为您一一揭晓。甚至您可以自己编一段消息来体验下发报的过程和声音。当然收报解译需要一个熟练过程。

CW的学习步骤简单的讲只有3个字:“背”“抄”“发”, 那就是背码表,练抄收,练发报的一个过程。

本文将向您展示什么是莫尔斯电码,以及如何使用其发送和接收英文、中文消息。通过Python程序模拟CW电报发报与译码,包括英文和中文,方便练习发报节奏和听音解码。感兴趣的朋友可以试试。代码均已测试OK。

一、什么是莫尔斯电码(也有翻译为摩尔斯)

电报出现于19世纪,是人类最早用电信号传送信息的方式,在19世纪和20世纪也是主要的通信方式之一。进入21世纪后,电报这种通信方式基本不再使用。但在业务无线电里,它依然活跃,而且由于设备的升级,普通人只要考取的业余无线电B类操作证也可以架台和原方的HAM进行CW的通联。这里就有必要解释下电报的工作原理。

1. 电报的工作原理:

发报方将文字转换成特定的编码,然后以电信号把这些编码发送出去;收报方抄收这些编码,然后翻译成文字。双方都有一个相同的代码本,上面记载了文字和编码的对应关系。显然,使用私有的代码本,可避免无关收报方破译电报文本。

电报通常使用国际摩尔斯电码进行收发报。摩尔斯电码使用点(·)和划(-)两种符号的特定组合表示不同的字符,在用声音表示时,其中点(·)为短信号,一个时间单位,读作滴,划(-)为长信号,三个时间单位,读作嗒;两个信号间隔一个时间单位,字符间隔三个时间单位,单词间隔七个时间单位。

2. 莫尔斯电码编码表:

国际莫尔斯电码(字母)

字符代码字符代码字符代码字符代码字符代码字符代码字符代码
A·-B-···C-·-·D-··E·F··-·G–·
H····I··J·—K-·-L·-··MN
OP·–·Q–·-R·-·S···T-U··-
V···-W·–X-··-Y-·–Z–··

国际莫尔斯电码(数字)

字符代码字符代码字符代码字符代码字符代码
1·----2··—3···–4····-5·····
6-····7–···8—··9----·0-----

国际莫尔斯电码(标点)

字符代码字符代码字符代码字符代码字符代码字符代码
.·-·-·-:—···,–··–;-·-·-·?··–··=-···-
·----·/-··-·!-·-·–--····-_··–·-"·-··-·
(-·–·)-·–·-$···-··-&·-···@·–·-·+·-·-·

二、使用Python将英文消息转莫尔斯电码并模拟发报与解码

1. 生成代码字典

# 莫尔斯代码字典
MORSE_CODE_DICT = { 'A':'.-', 'B':'-...', 'C':'-.-.', 'D':'-..', 'E':'.', 'F':'..-.', 'G':'--.', 
                    'H':'....', 'I':'..', 'J':'.---', 'K':'-.-', 'L':'.-..', 'M':'--', 'N':'-.', 
                    'O':'---', 'P':'.--.', 'Q':'--.-', 'R':'.-.', 'S':'...', 'T':'-', 
                    'U':'..-', 'V':'...-', 'W':'.--', 'X':'-..-', 'Y':'-.--', 'Z':'--..', 
                    '1':'.----', '2':'..---', '3':'...--', '4':'....-', '5':'.....', 
                    '6':'-....', '7':'--...', '8':'---..', '9':'----.', '0':'-----', 
                    '.':'·-·-·-', ':':'---···', ',':'--··--', ';':'-·-·-·', '?':'··--··', '=':'-···-',
                    "'":'·----·', '/':'-··-·', '!':'-·-·--', '-':'-····-', '_':'··--·-', '"':'·-··-·',
                    '(':'-·--·', ')':'-·--·-', '$':'···-··-', '&':'·-···', '@':'·--·-·', '+':'·-·-·'} 

由于字典默认使用单引号定义键名,而英文字符单引号也是字符之一,故这里使用双引号,解决的键名定义问题"‘":’·----·’
如果使用双引号定义字符串,那么字符串里如果需要用到双引号,需要使用转移符,修改为:\" 即可。

2. 模拟发报与译码(完整源代码)

# -*- coding: utf-8 -*-

# 莫尔斯代码字典
MORSE_CODE_DICT = { 'A':'.-', 'B':'-...', 'C':'-.-.', 'D':'-..', 'E':'.', 'F':'..-.', 'G':'--.', 
                    'H':'....', 'I':'..', 'J':'.---', 'K':'-.-', 'L':'.-..', 'M':'--', 'N':'-.', 
                    'O':'---', 'P':'.--.', 'Q':'--.-', 'R':'.-.', 'S':'...', 'T':'-', 
                    'U':'..-', 'V':'...-', 'W':'.--', 'X':'-..-', 'Y':'-.--', 'Z':'--..', 
                    '1':'.----', '2':'..---', '3':'...--', '4':'....-', '5':'.....', 
                    '6':'-....', '7':'--...', '8':'---..', '9':'----.', '0':'-----', 
                    '.':'·-·-·-', ':':'---···', ',':'--··--', ';':'-·-·-·', '?':'··--··', '=':'-···-',
                    "'":'·----·', '/':'-··-·', '!':'-·-·--', '-':'-····-', '_':'··--·-', '"':'·-··-·',
                    '(':'-·--·', ')':'-·--·-', '$':'···-··-', '&':'·-···', '@':'·--·-·', '+':'·-·-·'} 

def en2morse(message): 
    # 将字符转为莫尔斯代码字符串
    message = ' '.join(message.split()) # 将多个空格替换为一个,避免程序报错。
    cipher = '' 
    for letter in message: 
        if letter != ' ': 
            cipher += MORSE_CODE_DICT[letter] + ' '
        else: 
            cipher += ' '
    return cipher 

def morse2en(code): 
    # 将莫尔斯代码字符串转为字符
    code = code.strip() # 剔除前后空格,避免程序报错。
    code += ' '
    decipher = '' 
    citext = '' 
    for letter in code: 
        if (letter != ' '): 
            i = 0
            citext += letter
        else: 
            i += 1
            if i == 2 : 
                decipher += ' '
            else: 
                decipher += list(MORSE_CODE_DICT.keys())[list(MORSE_CODE_DICT.values()).index(citext)] 
                citext = '' 
    return decipher

def morse2beep(code):
    # 对莫尔斯字符串转为声音
    import winsound,time,sys
    # 间隔时间:滴=1t,嗒=3t,滴嗒间=1t,字符间=3t,单词间=7t
    di = 80
    da = di*3
    sp = di/1000
    chr_sp = di*3/1000
    word_sp = di*7/1000
    vol = 600
    for i in range(len(code)):
        if code[i] == '.':
            winsound.Beep(vol,di)# 其中vol表示声音大小,di表示发生时长,1000为1秒
        elif code[i] == '-':
            winsound.Beep(vol,da)            
        elif code[i] == ' ':
            if  i < len(code)-1 and code[i+1] == ' ' :
                time.sleep(word_sp)
            else:
                time.sleep(chr_sp)
        else:
            time.sleep(sp)
        print(code[i],end='')
        sys.stdout.flush()
    print()

def msg2beep2msg(msg):
    # 将消息转换为莫尔斯代码并显示,再通过声音模拟发报,最后进行译码。
    print(message)
    ret = en2morse(message.upper()) # 消息转为莫尔斯代码
    print(ret)
    morse2beep(ret)  # 通过声音展示莫尔斯代码,模拟发报
    ret = morse2en(ret)  # 莫尔斯代码转为消息,模拟解码
    print(ret)

if __name__ == '__main__': 
    message = "CQ CQ CQ DE BI9ABG BI9ABG BI9ABG PSE K " # 字符串里使用:”"“,需要修改为:”\"“。
    msg2beep2msg(message)
    

三、使用Python将中文消息转莫尔斯电码并模拟发报

1. 发送中文怎么办?

在电话普及前,已开始使用电报。但要将几千个汉字发成电报貌似比26个英文字母要复杂,于是人们想出对汉字使用4位数字进行编码的方案,也就是汉字电报码。

汉字电报码使用四位数字标识一个汉字,如:我的代码是 2053,西安分别是6007 1344。

既然知道了逻辑,我们把汉字电报码下载下来,使用程序做成字典,调用的时候去查询即可。由于字典太大,我们将汉字电报码保存在hzdbm.txt,和程序放在同一个目录。

当然发报人和收报人需要使用同一个字典,才可以正常译码。这也就是密码本的来由。这也就是电视中破译电报桥段的来由。无线电波信号是公开传递的,但没有密码本,自然收到也无法译码。你也可以自己定义字典,可以定义属于你的专属密码本。不过,作为一般大家都适用通用电码本。下面为大家准备了一个电码字典。

中文电报码-其它文档类资源-CSDN文库 https://download.csdn.net/download/popboy29/87522106

2. 编码与译码

发报时先查字典找到对应汉字的编码,然后对数字使用莫尔斯电码发报;解译的过程和编码的过程相反,先将收到的莫尔斯电码继续下来,4位数字对应一个汉字,然后再按数字查字典找到对应的汉字,就可以看到中文消息内容。

3. 模拟中文发报与译码(完整源代码)

首先将第二部分代码完整保存为morsecode.py,再将以下内容和hzdbm.txt一同保存在同一目录。

from morsecode import *

def hz_morsecode():
    # 将汉字电报码转为dict,方便调用。由于数字唯一,故使用4位数字字符串作为键名。
    import os
    HZ_CODE_DICT = {}
    with open(os.path.dirname(os.path.abspath(__file__))+'\\hzdbm.txt',encoding='utf-8-sig') as file:
        line = file.read()
        line = line.replace('\n', '') # 删除末尾的换行符
        line_list = line.strip().split(" ")
        for i in range(len(line_list)):
            HZ_CODE_DICT[line_list[i][1:5]] = line_list[i][0:1]
    return HZ_CODE_DICT

HZ_CODE_DICT = hz_morsecode()
# print(HZ_CODE_DICT)

def get_keys(d, value):
    # 根据值来查找键
    return [k for k, v in d.items() if v == value]

def get_hz_morsecode(hz_msg):
    # 将字符转为莫尔斯代码字符串
    hz_msg = ''.join(hz_msg.split()) # 将多个空格替换为一个,避免程序报错。
    cipher = '' 
    hz_msg = hz_msg.upper() # 英文需要先全部改为大写
    for hz in hz_msg: 
        if hz in MORSE_CODE_DICT.keys():
            # 如果是英文字符后数字,直接输出
            cipher += en2morse(hz) + ' ' 
        elif hz == ' ':
            cipher += ' '
        else:
            # 如果是汉字字符,转换为4位数字再转莫尔斯码输出
            # print(get_keys(HZ_CODE_DICT, hz))
            for i in get_keys(HZ_CODE_DICT, hz)[0]:
                cipher += en2morse(i) + ' '
    return cipher 

def hz2beep2hz(msg):
    # 将汉字消息逐字转换为4位代码,再将数字转换为莫尔斯代码并显示,再通过声音模拟发报,最后进行译码。
    print(hz_msg)
    ret = get_hz_morsecode(hz_msg)
    print(ret)
    morse2beep(ret)  # 通过声音展示莫尔斯代码,模拟发报
    ret = morse2en(ret)  # 莫尔斯代码转为消息,模拟解码
    print(ret)
    
    # 
    import re
    hz_code_str = ret.replace(' ', '')
    print(hz_code_str)
    hz_code_str = re.findall(r'[0-9]{4}', hz_code_str)
    print(hz_code_str)
    for i in hz_code_str:
        print(HZ_CODE_DICT[i],end='')
    print()

if __name__ == '__main__': 

    hz_msg = "声音传递汉字"
    hz2beep2hz(hz_msg)
    
    

运行结果如下:

声音传递汉字
… .---- .---- -… --… …— ----. ----. ----- …— --… —… -… -… --… --… …-- …-- … …— .---- …-- .---- -…
… .---- .---- -… --… …— ----. ----. ----- …— --… —… -… -… --… --… …-- …-- … …— .---- …-- .---- -…
5 1 1 6 7 2 9 9 0 2 7 8 6 6 7 7 3 3 5 2 1 3 1 6
511672990278667733521316
[‘5116’, ‘7299’, ‘0278’, ‘6677’, ‘3352’, ‘1316’]
声音传递汉字

相比于英文(26个字母+数字+标点符号)莫尔斯码,汉字只需要记住以下0-9数字的莫尔斯码即可(规律很明显,其实很简单),然后就是收到的消息四位数字一分隔,然后去查字典就好。小学生也可以很快掌握。

字符代码字符代码字符代码字符代码字符代码
1·----2··—3···–4····-5·····
6-····7–···8—··9----·0-----

总结

CW,等幅电波,在无线电通信中,特指等幅电报。由于是形如“1、0”的二进制信号,故一般利用摩尔斯电码发送信息。它通过电键控制发信机产生短信号".“(点)和长信号”–"(划),并利用其不同组合表示不同的字符,从而组成单词和句子。与其他无线电通信方式相比,CW优点是所需设备简单、占用频带窄、发射效率高、在同等条件下通信距离更远。但是需要值机员熟练掌握收发报技术。

随着通讯科技的发展,电报已不再是主要的通讯方法。自从电话网络数字化以后,电报通讯变成为数位通讯网络内其中一种以文字通讯的应用,在传真机普及后更被传真所取代。当互联网及行动通讯日渐广泛使用以后,电报更进一步被电子邮件及短信所取代。一般人已不会使用电报通讯。

电报业务虽然已经过时,但是CW通联在业务无线电里依然收到广大HAM的热爱,除了短波CW传输距离远以外,电报这种最早出现的电子信息传递方式依然有其拥趸。也是一种情怀,也许是自由通信的热爱,也许是对古老通信方式的好奇,让我们一起CW通联吧。

注意:使用短波设备CW通联需要首先获得业余无线单B类操作证,并报备后方可设台通联。
(使用Python程序模拟发报、译码先在本地体验一下,这个就不用了。^-^)

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT里的交易员

分享是一种快乐,打赏是一种肯定

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值