从手机信号格到核心网手把手教你用Python脚本计算EARFCN和频点当手机屏幕右上角的信号格从1格跳到满格时背后是一场精密的频率交响乐。每个运营商都在特定的无线电频段上演奏着自己的乐章而EARFCN就是这场音乐会的五线谱编号。作为技术人员我们常常需要在这些数字与频率之间来回转换——可能是为了分析路测数据可能是为了优化基站配置亦或是单纯想揭开移动通信背后的数学面纱。今天我们将用Python构建一个频点计算瑞士军刀它能处理三大运营商4G/5G频段自动识别频率与EARFCN双向换算带宽配置建议生成3GPP标准参数查询1. 通信频率的数学本质无线电波在空中以不同频率振动就像钢琴上从低音到高音的琴键。在LTE/NR中这些琴键被标准化为概念类比示例Band钢琴的八度范围Band 3 (1800MHz附近)EARFCN具体琴键编号1650 (对应1830MHz)Channel BW同时按下的键宽范围20MHz (100个RB)关键公式藏在3GPP 36.101规范中def freq_to_earfcn(freq, band): # 从3GPP表格获取基准参数 band_info { 3: {F_low: 1805, N_offs: 1575}, 40: {F_low: 2300, N_offs: 38650} } N_earfcn band_info[band][N_offs] 10*(freq - band_info[band][F_low]) return round(N_earfcn)注意实际应用需要补全所有频段参数此处仅示例Band 3和402. 构建频点计算器的核心功能2.1 频率与EARFCN互转完整的转换器需要处理三大场景已知频率求EARFCNdef get_earfcn(freq_mhz, band, uplinkFalse): params BAND_PARAMS[band] base_freq params[ul_freq_low] if uplink else params[dl_freq_low] offset params[ul_offset] if uplink else params[dl_offset] return offset 10 * (freq_mhz - base_freq)已知EARFCN求频率def get_freq(earfcn, band, uplinkFalse): params BAND_PARAMS[band] base_freq params[ul_freq_low] if uplink else params[dl_freq_low] offset params[ul_offset] if uplink else params[dl_offset] return base_freq (earfcn - offset) / 10自动频段检测def auto_detect_band(freq): for band, params in BAND_PARAMS.items(): if params[dl_freq_low] freq params[dl_freq_high]: return band raise ValueError(Frequency out of known bands)2.2 运营商频段数据库中国运营商常用频段运营商4G频段5G频段典型EARFCN范围移动B3/B8/B39n41/n791650-1899联通B1/B3/B8n78150-599电信B1/B3/B5n78/n11825-1869建议用JSON文件存储这些数据{ band3: { dl_freq_low: 1805, dl_freq_high: 1880, ul_freq_low: 1710, ul_freq_high: 1785, dl_offset: 1575, ul_offset: 18000, valid_bw: [5, 10, 15, 20] } }3. 开发命令行实用工具用Click库构建用户友好的CLIimport click click.command() click.option(--freq, typefloat, helpFrequency in MHz) click.option(--earfcn, typeint, helpEARFCN number) click.option(--band, typeint, helpBand number) def convert(freq, earfcn, band): if freq and band: result get_earfcn(freq, band) click.echo(fEARFCN: {result}) elif earfcn and band: result get_freq(earfcn, band) click.echo(fFrequency: {result} MHz) if __name__ __main__: convert()典型使用场景# 计算中国移动B3频段1830MHz对应的EARFCN python freq_tool.py --freq 1830 --band 3 # 查询EARFCN 1650对应的实际频率 python freq_tool.py --earfcn 1650 --band 34. 进阶功能实现4.1 带宽配置建议根据频段自动推荐可用带宽def suggest_bandwidth(band): bw_options BAND_PARAMS[band][valid_bw] return sorted(bw_options, reverseTrue) # 示例输出对于Band 40返回 [20, 15, 10, 5]4.2 邻频干扰检查判断两个EARFCN是否会产生干扰def check_interference(earfcn1, earfcn2, bw110, bw210): freq1 get_freq(earfcn1) freq2 get_freq(earfcn2) return abs(freq1 - freq2) (bw1 bw2)/24.3 可视化频率分布用Matplotlib生成频谱图import matplotlib.pyplot as plt def plot_band(band): params BAND_PARAMS[band] plt.figure(figsize(10, 2)) plt.barh(0, params[dl_freq_high]-params[dl_freq_low], leftparams[dl_freq_low], height0.5) plt.title(fBand {band} Frequency Range) plt.xlabel(Frequency (MHz)) plt.yticks([]) plt.show()5. 工程实践中的坑与技巧单位一致性陷阱公式中的频率单位必须是MHz5G NR的频点计算使用kHz单位频段特殊规则Band 41的EARFCN计算有额外偏移量某些频段上下行间隔不固定性能优化技巧# 使用LRU缓存频繁查询的频段参数 from functools import lru_cache lru_cache(maxsize32) def get_band_params(band): return load_band_data()[str(band)]测试用例设计def test_band3_conversion(): assert get_earfcn(1830, 3) 1650 assert abs(get_freq(1650, 3) - 1830) 0.01把玩这些频率数字时我发现最实用的功能其实是自动识别运营商频段。当现场测试时看到信号强度-85dBm但下载速度只有2Mbps快速查询所在频段的合理带宽能立即判断是否是配置问题。有一次正是通过脚本发现某基站错误配置了5MHz带宽实际应配20MHz节省了半天的排查时间。
从手机信号格到核心网:手把手教你用Python脚本计算EARFCN和频点
从手机信号格到核心网手把手教你用Python脚本计算EARFCN和频点当手机屏幕右上角的信号格从1格跳到满格时背后是一场精密的频率交响乐。每个运营商都在特定的无线电频段上演奏着自己的乐章而EARFCN就是这场音乐会的五线谱编号。作为技术人员我们常常需要在这些数字与频率之间来回转换——可能是为了分析路测数据可能是为了优化基站配置亦或是单纯想揭开移动通信背后的数学面纱。今天我们将用Python构建一个频点计算瑞士军刀它能处理三大运营商4G/5G频段自动识别频率与EARFCN双向换算带宽配置建议生成3GPP标准参数查询1. 通信频率的数学本质无线电波在空中以不同频率振动就像钢琴上从低音到高音的琴键。在LTE/NR中这些琴键被标准化为概念类比示例Band钢琴的八度范围Band 3 (1800MHz附近)EARFCN具体琴键编号1650 (对应1830MHz)Channel BW同时按下的键宽范围20MHz (100个RB)关键公式藏在3GPP 36.101规范中def freq_to_earfcn(freq, band): # 从3GPP表格获取基准参数 band_info { 3: {F_low: 1805, N_offs: 1575}, 40: {F_low: 2300, N_offs: 38650} } N_earfcn band_info[band][N_offs] 10*(freq - band_info[band][F_low]) return round(N_earfcn)注意实际应用需要补全所有频段参数此处仅示例Band 3和402. 构建频点计算器的核心功能2.1 频率与EARFCN互转完整的转换器需要处理三大场景已知频率求EARFCNdef get_earfcn(freq_mhz, band, uplinkFalse): params BAND_PARAMS[band] base_freq params[ul_freq_low] if uplink else params[dl_freq_low] offset params[ul_offset] if uplink else params[dl_offset] return offset 10 * (freq_mhz - base_freq)已知EARFCN求频率def get_freq(earfcn, band, uplinkFalse): params BAND_PARAMS[band] base_freq params[ul_freq_low] if uplink else params[dl_freq_low] offset params[ul_offset] if uplink else params[dl_offset] return base_freq (earfcn - offset) / 10自动频段检测def auto_detect_band(freq): for band, params in BAND_PARAMS.items(): if params[dl_freq_low] freq params[dl_freq_high]: return band raise ValueError(Frequency out of known bands)2.2 运营商频段数据库中国运营商常用频段运营商4G频段5G频段典型EARFCN范围移动B3/B8/B39n41/n791650-1899联通B1/B3/B8n78150-599电信B1/B3/B5n78/n11825-1869建议用JSON文件存储这些数据{ band3: { dl_freq_low: 1805, dl_freq_high: 1880, ul_freq_low: 1710, ul_freq_high: 1785, dl_offset: 1575, ul_offset: 18000, valid_bw: [5, 10, 15, 20] } }3. 开发命令行实用工具用Click库构建用户友好的CLIimport click click.command() click.option(--freq, typefloat, helpFrequency in MHz) click.option(--earfcn, typeint, helpEARFCN number) click.option(--band, typeint, helpBand number) def convert(freq, earfcn, band): if freq and band: result get_earfcn(freq, band) click.echo(fEARFCN: {result}) elif earfcn and band: result get_freq(earfcn, band) click.echo(fFrequency: {result} MHz) if __name__ __main__: convert()典型使用场景# 计算中国移动B3频段1830MHz对应的EARFCN python freq_tool.py --freq 1830 --band 3 # 查询EARFCN 1650对应的实际频率 python freq_tool.py --earfcn 1650 --band 34. 进阶功能实现4.1 带宽配置建议根据频段自动推荐可用带宽def suggest_bandwidth(band): bw_options BAND_PARAMS[band][valid_bw] return sorted(bw_options, reverseTrue) # 示例输出对于Band 40返回 [20, 15, 10, 5]4.2 邻频干扰检查判断两个EARFCN是否会产生干扰def check_interference(earfcn1, earfcn2, bw110, bw210): freq1 get_freq(earfcn1) freq2 get_freq(earfcn2) return abs(freq1 - freq2) (bw1 bw2)/24.3 可视化频率分布用Matplotlib生成频谱图import matplotlib.pyplot as plt def plot_band(band): params BAND_PARAMS[band] plt.figure(figsize(10, 2)) plt.barh(0, params[dl_freq_high]-params[dl_freq_low], leftparams[dl_freq_low], height0.5) plt.title(fBand {band} Frequency Range) plt.xlabel(Frequency (MHz)) plt.yticks([]) plt.show()5. 工程实践中的坑与技巧单位一致性陷阱公式中的频率单位必须是MHz5G NR的频点计算使用kHz单位频段特殊规则Band 41的EARFCN计算有额外偏移量某些频段上下行间隔不固定性能优化技巧# 使用LRU缓存频繁查询的频段参数 from functools import lru_cache lru_cache(maxsize32) def get_band_params(band): return load_band_data()[str(band)]测试用例设计def test_band3_conversion(): assert get_earfcn(1830, 3) 1650 assert abs(get_freq(1650, 3) - 1830) 0.01把玩这些频率数字时我发现最实用的功能其实是自动识别运营商频段。当现场测试时看到信号强度-85dBm但下载速度只有2Mbps快速查询所在频段的合理带宽能立即判断是否是配置问题。有一次正是通过脚本发现某基站错误配置了5MHz带宽实际应配20MHz节省了半天的排查时间。