OOK

AI-摘要
切换
Huggingface
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
OOK
KayerOOK及其应用
1. OOK
1.1 什么是 OOK
“OOK” 全称为 On-Off Keying(开关键控),是一种最简单、最基础的数字调制技术,核心原理是通过 载波信号的 “存在”(On)与 “消失”(Off) 来对应传输二进制数字中的 “1” 和 “0”,广泛应用于低速率、低成本的无线通信场景。
1.2 OOK 的核心原理
数字通信的本质是将二进制数据(0 和 1)转换为可在信道(如空气、电缆)中传输的电 / 电磁波信号。
OOK 的调制逻辑极为直接:
- 当传输二进制 “1” 时:发送端输出 → 有载波信号(比如一个固定频率的正弦波);
- 当传输二进制 “0” 时:发送端停止 → 输出载波(信号幅度为 0,即 “无信号”)。
1.3 OOK 的优缺点
优缺点 | 说明 |
---|---|
优点 | 1. 实现成本极低:发送端只需控制载波的通断,接收端只需检测信号 “有无”,电路简单(无需复杂的相位 / 幅度调节模块); 2. 功耗低:传输 “0” 时无载波输出,可减少设备能耗,适合电池供电的低功耗设备(如遥控器); 3. 技术门槛低:原理直观,易于设计和调试。 |
缺点 | 1. 抗干扰能力差:信道中的噪声(如电磁干扰)可能误将 “无信号”(0)判为 “有信号”(1),或反之,速率越高误码率越高; 2. 频谱效率低:相同带宽下,OOK 传输速率远低于 PSK(相移键控)、QAM(正交振幅调制)等复杂调制技术; 3. 依赖强信号:信号衰减后易丢失,适合短距离通信。 |
1.4 OOK 的典型应用场景
由于其 “低成本、低功耗” 的特点,OOK 主要用于 短距离、低速率、对可靠性要求不极致的场景。
常见例子包括:
- 红外遥控器:如电视、空调、机顶盒的遥控器,通过红外光的 “亮 / 灭” 传输控制指令。
- 无线射频(RF)低速率设备:如汽车遥控钥匙(解锁 / 锁车指令)、无线门铃(触发信号)、低功耗传感器(如温湿度传感器的简单数据上报);
- 早期通信系统:如电报系统(摩尔斯电码),本质是通过电线中电流的 “通 / 断” 实现远距离信息传输,是 OOK 的早期雏形。
1.5 OOK 与其他调制技术的对比
为了更清晰理解 OOK 的定位,可将其与常见的数字调制技术对比:
调制技术 | 核心原理 | 抗干扰能力 | 频谱效率 | 适用场景 |
---|---|---|---|---|
OOK | 载波 “有 / 无” 对应 1/0 | 最差 | 最低 | 短距离、低速率、低成本设备(遥控器、钥匙) |
ASK | 不同幅度载波对应不同符号 | 较差 | 较低 | 中短距离数据传输(如部分 RFID) |
FSK | 不同频率载波对应不同符号 | 较好 | 中等 | 无线数据传输(如蓝牙低功耗、对讲机) |
PSK | 不同相位载波对应不同符号 | 最好 | 较高 | 高速通信(如 WiFi、4G/5G、卫星通信) |
2. 软件模拟OOK
2.1 原理
通过把发送串口(串口也可以换成其他)的Tx引脚发送的串口数据帧用OOK调制,再用接收串口的Rx引脚在经过解调之后接收。
高电平输出正弦波,低电平输出中间电平。
2.2 OOK波形输出
使用DAC+DMA把串口的Tx引脚发送的数据帧进行数模转换,使开发板通过PA4引脚输出带有调制的载波信号。
由于是定时器触发,因此可以通过调节定时器的周期和分频系数来调节正弦波的周期。比如,调节每个bit所输出的正弦波个数。
关键步骤:
- 发送:
定义正弦波数组(不用函数计算),用DMA直接把数组值传输至DAC,更高效。
1
2
3
4
5
6
7
8
9
10
11
12
13const uint16_t SineWave128[128] = {
2047, 2147, 2248, 2347, 2446, 2545, 2641, 2737, 2831, 2922, 3012, 3100, 3185, 3267, 3346, 3422,
3495, 3564, 3630, 3692, 3749, 3803, 3853, 3898, 3939, 3975, 4006, 4033, 4055, 4072, 4085, 4092, 4095,
4092, 4085, 4072, 4055, 4033, 4006, 3975, 3939, 3898, 3853, 3803, 3749, 3692, 3630, 3564, 3495, 3422,
3346, 3267, 3185, 3100, 3012, 2922, 2831, 2737, 2641, 2545, 2446, 2347, 2248, 2147, 2047,
1947, 1846, 1747, 1648, 1549, 1453, 1357, 1263, 1172, 1082, 994, 909, 827, 748, 672, 599, 530, 464,
402, 345, 291, 241, 196, 155, 119, 88, 61, 39, 22, 9, 2, 0,
2, 9, 22, 39, 61, 88, 119, 155, 196, 241, 291, 345, 402, 464, 530, 599, 672,
748, 827, 909, 994, 1082, 1172, 1263, 1357, 1453, 1549, 1648, 1747, 1846, 1947
};把串口的Tx引脚连接至一个GPIO中断引脚,通过检测该引脚的上升沿和下降沿进行判断此时的电平高低,并赋值给标志位。
1 | // 引脚中断回调 |
- 使用DMA半全缓冲模式(把一个缓冲区逻辑上分为前半区和后半区,当DMA把前半区写满时,触发半传输完成中断,此时CPU可以在DMA继续写后半区时,先处理前半区的数据。传输完成中断同理)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// DMA半传输中断
void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef *hdac)
{
if (tx_level_flag)
{
// 高电平,把前半部分数组赋值为正弦波数组
memcpy(&OOK_Buffer[0], &SineWave128[0], BUFFER_SIZE / 2 * sizeof(uint16_t));
}
else
{
// 低电平,把前半部分数组赋值为平电平
memset(&OOK_Buffer[0], 2048, BUFFER_SIZE / 2 * sizeof(uint16_t));
}
}
// DMA全传输中断
void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
{
if (tx_level_flag)
{
// 高电平,把后半部分数组赋值为正弦波数组
memcpy(&OOK_Buffer[BUFFER_SIZE / 2], &SineWave128[BUFFER_SIZE / 2], BUFFER_SIZE / 2 * sizeof(uint16_t));
}
else
{
// 低电平,把后半部分数组赋值为平电平
memset(&OOK_Buffer[BUFFER_SIZE / 2], 2048, BUFFER_SIZE / 2 * sizeof(uint16_t));
}
}
- 接收
- 计算采样点信息,用于匹配发送的时序。以下例子的芯片时钟为144MHz
- 计算每一位所占用的时间 $T_{bit} =\frac 1 {BaudRate}$,如波特率9600,1bit时间 ≈ 104.167us。
- 计算每个周期的时间 $T_{period} =\frac {T_{bit}} {n}$,n为每个bit的正弦波数量。比如6个,则每个正弦波周期 ≈ 17.36us。
- 计算每个采样点的时间间隔 $T_{sample} =\frac {T_{period}} {m}$,m为每个周期 ADC 的采样点个数。比如8个,则每个采样点时间间隔 ≈ 2.17us。
- ADC(12bit)总转换时间 $T_{conv} = {采样时间} + {12.5 个周期}$。比如使用13.5个周期为采样时间,则$T_{sample-total} = ({13.5} + {12.5}) \times {55.56ns} ≈ {1.44us}$, (ADC时钟为18MHz,则一个周期 ≈ 55.56ns。
- 条件:ADC 总采样时间 ≤ 采样间隔 → 1.44us < 2.17us。
- 一个正弦波周期时间采样六个点后,触发DMA全传输中断进入回调函数处理。
- 将PA6引脚接入串口的RX引脚,即可读取数据。转换后的波形:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
* 判断一个正弦波周期的六个采样点的峰峰值是否大于阈值
* 如果大于阈值则为正弦波,返回1,代表高电平,反之返回0,代表低电平
*/
static uint8_t decide_bit_from_block(const uint16_t *buf, uint32_t n)
{
uint16_t maxv = 0;
uint16_t minv = 4095;
for (uint32_t i = 0; i < n; i++)
{
if (buf[i] > maxv)
maxv = buf[i];
if (buf[i] < minv)
minv = buf[i];
}
uint16_t p2p = maxv - minv;
return (p2p > p2p_threshold) ? 1 : 0;
}
// DMA传输6个采样点完成
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if (hadc->Instance == ADC1)
{
uint8_t b = decide_bit_from_block(adc_buf, SINGLE_PERIOD_POINTS);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, b ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
}
- 计算采样点信息,用于匹配发送的时序。以下例子的芯片时钟为144MHz
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果