一、原理图
实验所用到的 315/433 MHz 超再生模块
发送端原理图
接收端原理图
二、发送端代码
使用 NEC 协议发送数据
#include <reg51.h>
#include <intrins.h>
#define FOSC 6000000L //IRC频率
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;
sbit SEND = P3 ^ 4; //数据发送引脚
sbit btn = P3 ^ 2; //发送按键
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
uchar tx_buff[4]; //发送缓冲区
void Delay9ms() //@6.000MHz
{
unsigned char i, j;
i = 53;
j = 132;
do {
while(--j);
} while(--i);
}
void Delay4ms() //@6.000MHz
{
unsigned char i, j;
i = 24;
j = 85;
do {
while(--j);
} while(--i);
}
void Delay560us() //@6.000MHz
{
unsigned char i, j;
i = 4;
j = 65;
do {
while(--j);
} while(--i);
}
void Delay20us() //@6.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 27;
while(--i);
}
//发送逻辑1,逻辑1为2.25ms,脉冲时间560us
void send_logic_1()
{
SEND = 1;
Delay560us();
SEND = 0;
Delay560us();
Delay560us();
Delay560us();
}
//发送逻辑0,逻辑0为1.12ms,脉冲时间560us
void send_logic_0()
{
SEND = 1;
Delay560us();
SEND = 0;
Delay560us();
}
//发送指定长度的数据
void send(uchar *dat, uint len)
{
uchar i, j, temp;
//引导码
SEND = 1;
Delay9ms(); //9ms高电平
SEND = 0;
Delay4ms(); //4ms低电平
//数据码
for(j = 0; j < len; j++){
temp = *dat;
for(i = 0; i < 8; i++) {
if((temp & 0x01) == 0x01) {
send_logic_1();
} else {
send_logic_0();
}
temp = temp >> 1;
}
dat++;
}
//结束码
SEND = 1;
Delay4ms(); //4ms高电平
SEND = 0;
}
void main()
{
INT0 = 1;
IT0 = 1; //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
EX0 = 1; //使能INT0中断
EA = 1;
P3M1 &= 0xEF; //P3.4推挽输出
P3M0 &= 0xFF;
tx_buff[0] = 0x40;
tx_buff[1] = ~tx_buff[0]; //取反
tx_buff[2] = 0x56;
tx_buff[3] = ~tx_buff[2]; //取反
while(1) {
}
}
//中断服务程序
void ex_int0() interrupt 0 //INT0中断入口
{
if(btn == 0) {
Delay20us();
if(btn == 0) {
Delay20us();
send(tx_buff, 4);
}
while(!btn);//等待 按起
}
}
三、接收端代码
使用 NEC 协议接收数据
#include <reg51.h>
#include <intrins.h>
#ifndef FOSC
#define FOSC 6000000L //IRC频率
#endif
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;
sbit RECEIVE = P3 ^ 2; //数据接收引脚,INT0
bit exint0;
bit flag = 0; //接收标志
sbit LED = P3 ^ 3; //LED
uchar recv[4]; //接收缓冲区
void Delay2ms() //@6.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do {
while(--j);
} while(--i);
}
void Delay200us() //@6.000MHz
{
unsigned char i, j;
i = 2;
j = 39;
do {
while(--j);
} while(--i);
}
void Init_Int0(void)
{
INT0 = 1;
IT0 = 0; //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
EX0 = 1; //使能INT0中断
}
void main()
{
Init_Int0();
EA = 1;
P3M1 &= 0xF7; //P3.3 推挽输出
P3M0 &= 0xFF;
flag = 0;
while(1) {
if(flag) {
flag = 0;
LED = !LED; //接收到数据反转一次IO输出
}
}
}
//中断服务程序
void External_INT0() interrupt 0 //INT0中断入口
{
uchar i, j, N;
uint k;
exint0 = INT0; //保存INT0口的状态, INT0=0(下降沿); INT0=1(上升沿)
EX0 = 0; //关中断
flag = 0;
Delay2ms();
if(RECEIVE == 0) {
EX0 = 1;
flag = 0;
return;
}
k = 100;
//确认RECEIVE信号出现
while(RECEIVE && k) { //等RECEIVE变为低电平,跳过9ms的前导高电平信号。
Delay200us();
k--;
}
k = 100;
while(!RECEIVE && k) { //等 RECEIVE 变为高电平,跳过4ms的前导低电平信号。
Delay200us();
k--;
}
for(i = 0; i < 4; i++) { //4组数据
for(j = 0; j < 8; j++) { //每组数据有8位
k = 100;
while(RECEIVE && k) { //等RECEIVE变为低电平
Delay200us();
k--;
}
k = 100;
N = 0;
while(!RECEIVE && k) { //计算RECEIVE低电平时长
Delay200us();
N++;
k--;
if(N >= 30) {
EX0 = 1;
flag = 0;
return; //0.14ms计数过长自动离开。
}
} //低电平计数完毕
recv[i] = recv[i] >> 1; //数据最高位补“0”
if(N >= 8) {
recv[i] = recv[i] | 0x80; //数据最高位补“1”
}
N = 0;
}
}
if((recv[0] == ~recv[1]) && (recv[2] == ~recv[3])){ //数据校验成功
flag = 1;
}
else{
flag = 0;
}
EX0 = 1; //开中断
}