433MHz无线通信

 

  • 基本概念

工作频率:433.92MHz

调制方式:ASK/OOK,FSK,GFSK

现有遥控与接收器方案中,多数使用ASK/OOK调试方式。ASK即“幅移键控”又称为“振幅键控”,也有称为“开关键控”(通断键控)的,所以又记作OOK(On-Off keyed)信号。ASK是一种相对简单的调制方式。幅移键控(ASK)相当于模拟信号中的调幅,不同的是与载频信号相乘的是二进制数码。幅移就是把频率、相位作为常量,而把振幅作为变量,信息比特是通过载波的幅度来传递的。如下图所示,ASK调制方式的典型时域波形,虚线部分表示二进制的0和1,红色实线部分表示调制信号。

 

  • 国家标准

标准可参考“信部无[2005]423号 关于发布《微功率(短距离)无线电设备的技术要求》的通知”,要求如下:

(十一)各类民用设备的无线控制装置

不得用于无线控制玩具、模型等。

1.使用频率:314-316MHz,430-432MHz,433.00-434.79MHz

  发射功率限值:10mW(e.r.p)

  占用带宽:不大于400kHz

  • 编码与解码

以遥控器为例,在明确调制方式后,需要为遥控器编码方式进行约定。一组遥控编码通常需要包含“引导码/起始码”、“用户码”、“数据码”、“结束码”、“重复码”,格式如下:

 

确定编码组成后需要明确“逻辑0”、“逻辑1”的表示方法,可以遵循标准的编码方案,也可以进行自定义。标准编码方案可以使用“曼彻斯特编码”等方案,在自定义编码方案时可以参考下图所示的编码规则,主要是电平顺序与电平长度的组合。

 

以遥控的编码为例进行分析,得到如下编码波形:

 

假设:

高电平长码 + 低电平短码表示逻辑1

高电平短码 + 低电平长码表示逻辑0

可以得到该组数据为“0x88 0x03 0xBD 0xB6”。

 

解码过程是对编码过程的逆向,解码程序需要根据编码方案进行设计。遥控器的解码方案请参考“参考示例”。

  • 参考示例

根据测得的遥控器编码波形可知,433MHz接收端输出的信号中,电平维持时间有20ms、9ms、1.6ms、700us这几种。使用1.6ms高电平 + 700us低电平表示逻辑1,700us高电平 + 1.6ms低电平表示逻辑0,9ms高电平表示引导/起始码,700us高电平 + 20ms低电平表示结束码,同时也表示“重复码“”的起始。

程序设计中,对700us的电平进行检测并计数,要保证做够的容错能力,需要将定时器中断做到100us以下,甚至更小,显然使用定时器中断处理时不合理的。在本示例中,采用外部中断 + 定时器计数的方式进行电平长度采样。外部中断采用上升沿和下降沿触发,在中断中根据当前电平切换边沿触发方式。定时器使用系统时钟(16.6MHz)的64分频作为时钟源,具有足够的分辨率,可提高接收机的容错能力。

数据采样逻辑中,下降沿时判断当前高电平表示的逻辑值,上升沿是对上一步中产生的逻辑值进行确认,若逻辑值合法则对该逻辑值进行记录,若不合法,这舍弃该逻辑值,并初始化接收机,等待下一次数据。程序流程图如下:

 

示例代码:

代码基于中颖电子SH79F3212书写。

外部中断初始化为上升沿触发,当前电平INT45Level默认为低。

使用定时器3作为计数器

/*---------------定时器时钟使用系统频率64分频------------------*/
//1ms计数260
//实测引导码高电平长度为9.7ms,低电平长度为2ms
#define HeadCont_H 2540      //9.7ms
#define HeadCont_L 500       //2ms

//实测逻辑1为高电平1.7ms+低电平0.6ms
#define OneCode_H 450        //1.7ms
#define OneCode_L 160        //0.6ms

//假设0码为高电平0.6ms+低电平1.7ms
#define Zero_H 160  
#define Zero_L 450  

//容错范围
#define FaultTolerant 50

寄存器定义
uint16 T3Counter;
bit INT45Level = 0;

bit ZeroCode;           //接收到逻辑0
bit OneCode;            //接收到逻辑1
bit MaybeRemoteStart;   //疑似接收到起始码
bit RemoteStart;        //开始接收遥控数据
bit ReadOver;           //接收完成

#define DefRemoteDataBufLen 10  //默认遥控数据长度
idata uint8 RemoteDataBuffer[DefRemoteDataBufLen];  //接收缓冲区
idata uint8 ReadTab[DefRemoteDataBufLen];   //已接收,待处理数据
idata uint8 ReadBitCont;  //读取Bit计数
idata uint8 ReadBuffer;   //数据缓存区
idata uint8 ReadByteCont; //读取字节计数

外部中断服务程序
void INT45_interrupt() interrupt 9
{
    u8 backtemp;
    backtemp = INSCON;
    INSCON = 0x00;
    
   if((EXF1&0x20) == 0x20)
    {
        //读取T3计数器
        INSCON |= 0x40;
        T3CON = 0x00;
        T3Counter = 0x0000|(TH3 << 8);
        T3Counter |= TL3;
        
        TL3 = 0x00;
        TH3 = 0x00;
        T3CON = 0x24;           //系统分频1/64,启动定时器
        INSCON &= ~0x40;
        
        if(INT45Level)      //处理下降沿
        {
            if((T3Counter > (HeadCont_H - FaultTolerant))&&(T3Counter < (HeadCont_H + FaultTolerant)))
            {
                MaybeRemoteStart = 1;       //疑似遥控数据头
            }
            else
            {
                if((T3Counter> (OneCode_H - FaultTolerant))&&(T3Counter < (OneCode_H + FaultTolerant)))
                {
                    OneCode = 1;
                    ZeroCode = 0;
                }
                else
                {
                    if((T3Counter > (Zero_H - FaultTolerant))&&(T3Counter < (Zero_H + FaultTolerant)))
                    {
                        ZeroCode = 1;
                        OneCode = 0;
                    }
                    else
                    {
                        ZeroCode = 0;
                        OneCode = 0;
                    }
                }
            }
            INT45Level = 0;     //当前电平为低
            EXF0 = 0x80;        //设置为上升沿触发
        }
        else        //处理上升沿
        {
            if(RemoteStart)
            {
                if((T3Counter >(OneCode_L - FaultTolerant))&&(T3Counter < (OneCode_L + FaultTolerant)))
                {
                    if(OneCode)
                    {
                        //接收到一个bit 为1
                        GetOneByte();
                    }
                    else
                    {
                        //数据出错,丢弃
                        RemoteStart = 0;
                        OneCode = 0;
                        ZeroCode = 0;
                        ReadOver = 0;
                    }
                }
                else
                {
                    if((T3Counter > (Zero_L - FaultTolerant))&&(T3Counter < (Zero_L + FaultTolerant)))
                    {
                        if(ZeroCode)
                        {
                            //接收到一个bit 为0
                            GetOneByte();
                        }
                        else
                        {
                            //数据出错,丢弃
                            RemoteStart = 0;
                            OneCode = 0;
                            ZeroCode = 0;
                            ReadOver = 0;
                        }
                    }
                    else
                    {
                        if(ZeroCode && (T3Counter > 4000)) //结束码,同时也是重复码的起始
                        {
                            ReadOver = 1;
                            OneCode = 0;
                            ZeroCode = 0;
                            RemoteStart = 0;
                            GetOneByte();
                        }
                        else
                        {
                            //干扰数据,接收器初始化
                            RemoteStart = 0;
                            OneCode = 0;
                            ZeroCode = 0;
                            ReadOver = 0;
                        }
                    }
                }
            }
            else
            {
                if(MaybeRemoteStart)
                {
                    if((T3Counter > (HeadCont_L - 20))&&(T3Counter < (HeadCont_L + 20)))
                    {
                        RemoteStart = 1;  //遥控数据开始发送
                        ReadBitCont = 0;  //读取Bit计数
                        ReadBuffer = 0;   //数据缓存区
                        ReadByteCont = 0; //读取字节计数
                        ReadOver = 0;
                        MaybeRemoteStart = 0;
                    }
                }
            }
            INT45Level = 1;     //当前电平为高
            EXF0 = 0x40;        //设置为下降沿触发
        }
    }
	
	EXF1 = 0x00;
 	INSCON = backtemp;   
}

GetOneByte()子函数,接收完整字节并处理
void GetOneByte()
{
    int i;
    if(ReadBitCont<=7)
    {
        ReadBuffer <<= 1;
        if(OneCode)
        {
            ReadBuffer |= 0x01;
        }
    }
    ReadBitCont ++;
    if(ReadBitCont >= 8)
    {
        RemoteDataBuffer[ReadByteCont++] = ReadBuffer;		//每接收1byte,写入缓存
        ReadBuffer = 0;
        ReadBitCont = 0;
    }
    if(ReadOver)							//全部接收完后
    {
        for(i=0;i<ReadByteCont;i++)
        {
            ReadTab[i]=RemoteDataBuffer[i];	
        }
        ReadByteCont = 0;
    }
}

 

<think>好的,用户想用pip安装numpy和matplotlib库。我需要先回忆一下相关的安装步骤,并参考提供的引用内容。 首先,用户可能已经安装了Python和pip,但不确定。根据引用[1],第一步是检查pip是否安装。打开命令提示符,输入pip,如果出现帮助信息,说明已经安装。如果提示错误,可能需要先安装pip,不过用户的问题里没提到这个,可能已经安装好了。 接下来,引用[1]提到升级pip可以避免安装过程中的版本问题。所以应该建议用户先升级pip,使用命令python -m pip install --upgrade pip。这能确保pip是最新版本,减少安装库时的兼容性问题。 然后是安装numpy和matplotlib。根据引用[1]和[2],有两种方法:普通安装和使用镜像源。普通安装直接运行python -m pip install numpy和python -m pip install matplotlib。但有时候下载速度慢,用户可能遇到网络问题,这时候可以用清华的镜像源,如引用[2]中的命令:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy,同样适用于matplotlib。 另外,引用[3]提到另一种方法,把easy_install和pip添加到环境变量中,但用户的问题似乎已经知道用pip,所以可能不需要这部分。不过可以提到如果遇到路径问题,可能需要检查环境变量设置。 用户还可能遇到安装后的验证问题,比如如何确认库是否安装成功。应该建议用户使用pip list或在Python中导入库来检查是否报错。 另外,考虑到不同操作系统,用户可能是在Windows下操作,因为引用中提到了Win+R输入cmd。如果是其他系统,命令可能略有不同,但主要步骤相似。 需要确保用户按照步骤操作时不会遗漏任何步骤,比如升级pip后再安装,或者使用镜像源的正确命令格式。同时,注意可能的错误情况,比如权限问题,可能需要以管理员身份运行cmd,或者使用虚拟环境。 总结下来,回答应该分步骤,先检查pip,升级pip,安装库(普通和镜像两种方法),最后验证安装。同时提供常见问题解决方法,如镜像使用和权限问题。</think>### 分步安装指南 #### 步骤1:检查pip是否已安装 打开命令行工具(Windows按`Win+R`输入`cmd`,Mac/Linux打开终端),输入以下命令: ```bash pip --version ``` - 若显示pip版本信息(如`pip 23.3.1`),则已安装[^1]。 - 若提示“找不到命令”,需先[安装pip](https://pip.pypa.io/en/stable/installation/)。 --- #### 步骤2:升级pip(推荐) 在命令行中执行: ```bash python -m pip install --upgrade pip ``` 升级后可运行`pip show pip`确认版本[^1]。 --- #### 步骤3:安装numpy和matplotlib **方法1:默认源安装** ```bash python -m pip install numpy python -m pip install matplotlib ``` **方法2:使用清华镜像加速(适合国内用户)** ```bash pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy pip install -i https://pypi.tuna.tsinghua.edu.cn/simple matplotlib ``` 镜像源可大幅提升下载速度[^2]。 --- #### 步骤4:验证安装 1. 查看已安装库: ```bash pip list ``` 检查输出是否包含`numpy`和`matplotlib`。 2. 在Python中测试导入: ```python import numpy as np import matplotlib.pyplot as plt ``` 若无报错则安装成功。 --- ### 常见问题解决 1. **权限不足**:在命令前加`sudo`(Mac/Linux)或以管理员身份运行CMD(Windows)。 2. **安装超时**:延长超时限制: ```bash pip --default-timeout=1000 install numpy ``` 3. **依赖冲突**:使用虚拟环境隔离项目依赖。 --- ### 相关问题 1. 如何解决`pip`安装时的SSL证书错误? 2. 如何通过Anaconda安装科学计算库? 3. 如何卸载已安装的Python库? --- 通过以上步骤,您可以顺利完成安装。若遇到网络问题,优先推荐使用清华镜像源[^2]。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

沧海孤叶

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值