树老大 发表于 2014-1-2 17:45:44

51单片机+315M无线射频模块接受程序


用的就是那种最普通的 最便宜的 大约几块钱 的315兆的无线模块接受发射,不带解码的,433m的程序也是一样的不用修改





压缩包中的内容:






上位机以及完整程序在文件夹中,大家可自己下载
地址是:http://www.51hei.com/bbs/dpj-19033-1.html
下面是接受端的源代码:
#include <AT89X52.H>
#include "string.h"
//液晶块
#define LCM_RW P3_6 //定义引脚
#define LCM_RS P3_5
#define LCM_E P3_7
#define LCM_Data P1
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
typedef int byte;
typedef unsigned intword;
void Read_Temp(void);
void mychar(char,char);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void delay(word useconds)
{
for(;useconds>0;useconds--);
}
void mychar(char xx,char yy)
{
DisplayOneChar(0,0,0x54);
DisplayOneChar(1,0,0x65);
DisplayOneChar(2,0,0x6D);
DisplayOneChar(3,0,0x70);
DisplayOneChar(4,0,0x65);
DisplayOneChar(5,0,0x72);
DisplayOneChar(6,0,0x61);
DisplayOneChar(7,0,0x74);
DisplayOneChar(8,0,0x75);
DisplayOneChar(9,0,0x72);
DisplayOneChar(10,0,0x65);
DisplayOneChar(11,0,0x3A);
///////////////////////自定义字符
WriteCommandLCM(0x48, 0); //第一行
WriteDataLCM(0x06);
WriteCommandLCM(0x49, 0); //第2行
WriteDataLCM(0x09);
WriteCommandLCM(0x4a, 0); //第3
WriteDataLCM(0x09);
WriteCommandLCM(0x4b, 0); //第4
WriteDataLCM(0x06);
WriteCommandLCM(0x4c, 0); //第5
WriteDataLCM(0x00);
WriteCommandLCM(0x4d, 0); //第6
WriteDataLCM(0x00);
WriteCommandLCM(0x4e, 0); //第7
WriteDataLCM(0x00);
WriteCommandLCM(0x4f, 0); //第8
WriteDataLCM(0x00);
DisplayOneChar(xx,yy,0x01);
DisplayOneChar(xx+1,yy,0x43);
}
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高可以在这后加小的延时
LCM_E = 0; //延时
LCM_E = 1;
}
//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCM(); //根据需要检测忙
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}
//读状态
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //检测忙信号
return(LCM_Data);
}
void LCMInit(void) //LCM初始化
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置
}
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);
}
//按指定位置显示一串字符***原来的遇到空格0x20就不显示***
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength,j;
ListLength = strlen(DData);
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
      if (X <= 0xF) //X坐标应小于0xF
      {
      for(j=0;j<ListLength;j++)
      {
             DisplayOneChar(X, Y, DData); //显示单个字符
             X++;
            }
      }
}

//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}







sbit W_IN = P2^1;
sbit W_OUT = P2^0;
unsigned char w_data;//接收时用于存储两次上升沿之间的时长,发送时存储前半周
unsigned char send_busy = 0;//存储发送时后半周
unsigned char recv_timer = 0;
bit w_stat, last_w_stat;
unsigned char jiffies=0;
void clock_timer(void) interrupt 1 using 1{
if (send_busy){
if(w_data){
   w_data--;
   w_stat = 0;
}else{
   send_busy--;
   w_stat = 1;
}
W_OUT = w_stat;
}else{
w_stat = W_IN;
if (w_stat != last_w_stat){
   last_w_stat = w_stat;
   if (w_stat){
    w_data = recv_timer;
    recv_timer = 0;
   }
}
if (~recv_timer)//if(recv_busy != 0xff)
   recv_timer++;
}
jiffies++;
}
void clock_init(void){
jiffies = 0;
TMOD=0x02;
TH0=TL0=0x0ce;//12M,50us
// TH0=TL0=0x7a;//16M
// TH0=TL0=0x75;//16.59M
// TH0=TL0=0x72;//17M
// TH0=TL0=0x37;//24M
// TH0=TL0=0x47;//22.1844M, 100us
// TH0=TL0=0xa3;//22.1844M, 50us
EA=1;
ET0=1;
TR0=1;
}
void init_serialcomm(void)
{
    SCON= 0x50;       //SCON: serail mode 1, 8-bit UART, enable ucvr
    TMOD |= 0x20;       //TMOD: timer 1, mode 2, 8-bit reload
    PCON |= 0x80;       //SMOD=1;
    TH1   = 0x0e6;       //Baud:2400fosc=11.0592MHz:f4
TL1   = 0x0e6;
    //IE   |= 0x90;       //Enable Serial Interrupt
    TR1   = 1;          // timer 1 run
RI=0;
TI=1;
}
void serial_out(unsigned char d){
while(!TI);
TI=0;
SBUF=(d);
}

void send_string_com(unsigned char *str,int strlen)//串口程序
{   unsigned char sum;
    unsigned char k=0;
    //serial_out(02);
    do
    {   //sum^=*(str+k);
      serial_out(*(str + k));
//serial_out('a');
      k++;
    } while(k < strlen);
//serial_out(sum);
//serial_out('e');
}
//等待指定长度的串行数据到达,超时值为每两个字节之间的间隔时间而非等待整个串的时间.
//超时单位为time_out * 100uS
bit wait_serial(unsigned char *p, unsigned char len, unsigned char time_out){
unsigned int time=jiffies;
unsigned char n=0;
do{
if (RI){
   p=SBUF;
   RI=0;
   if(n==len)
    return 0;
   time=jiffies;
}
}while(jiffies-time < time_out);
return 1;
}
sys_init(){
clock_init();
init_serialcomm();
}


//=============================================================
//发送程序 开始
//=============================================================
#define PULS_0_WIDTH 8   //低电平脉宽
#define PULS_1_WIDTH 16   //高电平脉宽
#define PULS_HEAD_WIDTH 8//前导信号脉宽
#define PULS_START_WIDTH 24//引导信号脉宽
#define PULS_STOP_WIDTH 8//结束码脉宽
#define PULS_HEAD_COUNTS 16//前导信号长度

unsigned char send_buf;
#define send_byts send_buf //剩余字节数,发送完后为0
unsigned char sending_byte;//当前正在发送的字节
unsigned char send_byte_p;//已发送字节数(含正在发送的字节)
unsigned char send_bit_p;//当前正在发送的字节已发送位数(含正在发送的位)
#define SEND_PROGRESSING 0x41
#define SEND_FAILED 0x21
#define SEND_SUCCESS 0x31
unsigned char send_stat = 0; //发送程序当前状态,为0时正常
unsigned char head_counts; //前导信号计数器(包括引导信号)
void start_send(){
send_byte_p = 0;
send_bit_p = 0;
send_stat = SEND_PROGRESSING;
head_counts = 16;
}
#define START_SEND(byts) send_buf=byts;send_byts=byts;start_send()
//发送前应清除send_byte_p,send_bit_p,send_stat,并设置send_byts
//发送过程中可根据send_byts的值得到剩余字节数,根据send_byte_p的值得到已发送字节数.注意,将正在发送的字节当作已发送完毕.
//发送过程中可根据send_stat的值得到发送状态.
//发送完成后,send_byts和send_bit_p的值都为0.
#define SEND_PULS(x) w_data=send_busy=(x>>1)
void send(){
//下面两行在wirless()中已经执行过了,所以无需写上
// if (send_stat != SEND_PROGRESSING)
//return;
if (!send_busy){
if(send_byts || send_bit_p){
   if (head_counts){
    head_counts--;
    if(head_counts)
   SEND_PULS(PULS_HEAD_WIDTH);
    else
   SEND_PULS(PULS_START_WIDTH);
   }else{
    if (send_bit_p == 0){
   sending_byte = send_buf;
   send_byte_p++;
   send_byts--;
   send_bit_p = 8;
    }

    if(sending_byte & 0x80){
   SEND_PULS(PULS_1_WIDTH);
    }else{
   SEND_PULS(PULS_0_WIDTH);
    }

    sending_byte <<= 1;
    send_bit_p--;
   }
}else{
   SEND_PULS(PULS_STOP_WIDTH);
   send_stat = SEND_SUCCESS;
}
}
return;
}
//=============================================================
//发送程序 结束
//=============================================================
//=============================================================
//接收程序 开始
//=============================================================
unsigned char recv_buf;
#define recv_byts recv_buf//应收到字节数,由每个包的第一个字节指定
unsigned char recving_byte;   //当前正在接收的字节
unsigned char recv_byte_p;   //已收到字节数(不含正在接收的字节)
unsigned char recv_bit_p;   //当前正在接收的字节等待接收位数(不含正在接收的位)
#define RECV_FAILED 0x31
#define RECV_SUCCESS 0x41
unsigned char recv_stat = 0;//接收程序当前状态,为0时正常
unsigned char recv_step = 0;//引导脉冲标志,为0时等待引导,为1时等待数据
#define TEST_PULS(puls_in, puls_type) (puls_in > puls_type - PULS_0_WIDTH / 2 && puls_in < puls_type + PULS_0_WIDTH / 2)
#define HEAD_NEED_RECIVED 8
void recv(){
unsigned puls_width;
if ((recv_stat == RECV_SUCCESS) || !w_data)
return;
puls_width = w_data;
w_data = 0;
#if 0 //输出脉宽
serial_out(puls_width);
// printhex(puls_width);
#endif
if (recv_step < HEAD_NEED_RECIVED){
if(TEST_PULS(puls_width, PULS_HEAD_WIDTH)){
   recv_step++;
}else{
   recv_step = 0;
}
}else if (recv_step == HEAD_NEED_RECIVED){
if(TEST_PULS(puls_width, PULS_START_WIDTH)){
   serial_out(0xbb);
   recv_byte_p = 0;
   recv_bit_p = 8;
   recv_stat = 0;
   recv_step++;
}else{
   if(!TEST_PULS(puls_width, PULS_HEAD_WIDTH)){
    recv_step = 0;
   }
}
}else{
//serial_out(puls_width);
recving_byte <<= 1;
if(TEST_PULS(puls_width, PULS_0_WIDTH)){
   recving_byte &= 0xfe;
}else if(TEST_PULS(puls_width, PULS_1_WIDTH)){
   recving_byte |= 1;
}else{
   serial_out(puls_width);
   recv_step = 0;
   serial_out(0xaa);
   return;
}
recv_bit_p--;
if(recv_bit_p == 0){ //接收完一字节
   recv_bit_p = 8;
//   serial_out(recving_byte); //输出接收到的字符
   recv_buf = recving_byte;
   recv_byte_p++;
   if(recv_byte_p == recv_byts){
    recv_step = 0;
    recv_stat = RECV_SUCCESS;
   }
}
}
}
//=============================================================
//接收程序 结束
//=============================================================
#define SEND_DELAY_TIME 20//防碰撞延迟(单位:毫秒)
unsigned char send_delay = SEND_DELAY_TIME;
#define VALID_PULS_COUNT 10
unsigned char valid_puls_counts = VALID_PULS_COUNT;
//碰撞检测在该函数中实现.由于无线模块本身的限制,碰撞检测为非完全检测,只能在发送前
//检测是否有其它单元在使用信道,在发送过程中受到的碰撞干扰是无法检测到的.经测试,效果还行
void wirless(){
if (send_stat == SEND_PROGRESSING && send_delay == 0){
send();
if (send_stat == SEND_SUCCESS)
   send_delay = SEND_DELAY_TIME;
}else{
recv();
if (recv_step > HEAD_NEED_RECIVED) //如果检测到当前有其它单元正在发送,继续等待
   send_delay = SEND_DELAY_TIME;
else{
   if(TEST_PULS(w_data, PULS_0_WIDTH) //如果检测到当前有其它单元正在发送,继续等待
    || TEST_PULS(w_data, PULS_1_WIDTH)
    //|| TEST_PULS(w_data, PULS_HEAD_WIDTH)
    || TEST_PULS(w_data, PULS_START_WIDTH)
    //|| TEST_PULS(w_data, PULS_STOP_WIDTH)
    ){
   if (valid_puls_counts)
      valid_puls_counts--;
   else
      send_delay = SEND_DELAY_TIME;
    }else{
   valid_puls_counts = VALID_PULS_COUNT;
    }
}
}
}

void Display_T()
{
DisplayOneChar(9,1,recv_buf);
DisplayOneChar(8,1,recv_buf);
DisplayOneChar(7,1,recv_buf);
DisplayOneChar(6,1,recv_buf);
DisplayOneChar(5,1,recv_buf);
DisplayOneChar(0,0,0x54);
}
#define SCMD_SET_PORT 0x51
#define SCMD_GET_PORT 0x52
#define SCMD_RESET 0x61
#define SCMD_LCD_OUTSTR 0x71
#define SCMD_LCD_RESET 0x72
#define SCMD_LCD_SETXY 0x73
#define SCMD_LCD_SETLINE 0x74
#define SCMD_LCD_CLEAR 0x75

#define SRESP_GET_PORT_ERROR 0x41
#define SRESP_SET_PORT_ERROR 0x42
#define HEART_BEAT_INTERVAL 200//心跳间隔 X / 1000   秒
unsigned int heart_beat_timer = HEART_BEAT_INTERVAL;
unsigned int last_jiffies=0;


void main(){
    Delay400Ms(); //启动等待,等LCM讲入工作状态
    LCMInit(); //LCM初始化
    Delay5Ms(); //延时片刻(可不要)
mychar(10,1); //显示 自定义字符
init_serialcomm();
P0=0x0ff;
P2=0x00;
sys_init();

//send_string_com("ok",2);
//lcd_reset();
//lcd_power_on();
//lcd_self_test();
while(1){
if (jiffies - last_jiffies >= 20){//每次中断为50us,所以要20次才为1ms
   last_jiffies = jiffies;
   heart_beat_timer--;
   if (send_delay)
    send_delay--;
}
            
if (heart_beat_timer == 0){
   heart_beat_timer = HEART_BEAT_INTERVAL;

   while(1) {recv();if (recv_stat == RECV_SUCCESS)
      {
      P0_0=~P0_0;
   send_string_com(recv_buf,strlen(recv_buf));
   Display_T();
   recv_stat = 0;break;}
   recv_stat = 0;   
    }
}
/*#if 0
if (send_stat == 0){
   //碰撞测试
   START_SEND(8);
   send_buf='T';
   send_buf='e';
   send_buf='s';
   send_buf='t';
   send_buf='O';
   send_buf='k';
   send_buf='!';
   
   lcd_out_string("sending:");
   //send_string_com(send_buf,strlen(send_buf));
   printhex(send_buf);
   printhex(send_buf);
}
#endif
*/
wirless();
if (send_stat == SEND_FAILED){

   send_stat = 0;
}else if (send_stat == SEND_SUCCESS){
   send_stat = 0;
   P2_3=~P2_3;
}
   //recv();
       //send_string_com("start",5);
/*while(1) {recv();if (recv_stat == RECV_SUCCESS)
      {
      P0_0=~P0_0;
   send_string_com(recv_buf,strlen(recv_buf));} }*/
/* if (recv_stat == RECV_SUCCESS){
//send_string_com("test1",5);
#if 1
   //unsigned int i;
   //for(i=0; i<recv_byts; i++)
   // serial_out(recv_buf); //输出接收到的字符
   P0_0=~P0_0;
   send_string_com(recv_buf,strlen(recv_buf));
#else
   //if (recv_buf=='o')
   //P0=0x00;
   //lcd_out_string("data recived:");
   //printhex(recv_buf);
   //printhex(recv_buf);
   //OutChar('\n');
   //send_string_com("test3",5);
#endif
   recv_stat = 0;
}
*/
#if 0
if (RI){
   unsigned char scmd;
   heart_beat_timer = HEART_BEAT_INTERVAL;
   wait_serial(scmd, 1, 0);
   switch(scmd){
    case SCMD_RESET:
   ((void (code *) (void))0x0000) ();//软件复位
    case SCMD_SET_PORT:
   if (wait_serial(scmd, 2, 200))
      break;
   switch(scmd){
      case 0:
       P0 = scmd;
       break;
      case 1:
       P1 = scmd;
       break;
      case 2:
       P2 = scmd;
       break;
      case 3:
       P3 = scmd;
       break;
   }
   break;
    case SCMD_GET_PORT:
   if (wait_serial(scmd, 1, 200))
      break;
   switch(scmd){
      case 0:
       serial_out(P0);
       break;
      case 1:
       serial_out(P1);
       break;
      case 2:
       serial_out(P2);
       break;
      case 3:
       serial_out(P3);
       break;
   }
   break;
    case SCMD_LCD_OUTSTR:
   if (wait_serial(scmd, 1, 200))
      break;
   scmd] = 0;
   if (wait_serial(scmd, scmd, 200))
      break;
   lcd_out_string(scmd);
   break;
    case SCMD_LCD_RESET:
   lcd_reset();
   break;
    case SCMD_LCD_CLEAR:
   lcd_clear();
   break;
    case SCMD_LCD_SETXY:
   if (wait_serial(scmd, 2, 200))
      break;
   SetXY(scmd, scmd);
   break;
    case SCMD_LCD_SETLINE:
   if (wait_serial(scmd, 1, 200))
      break;
   SetLine(scmd);
   break;
    default:
   break;
   }
}
#endif
}
}


kpnew9 发表于 2014-2-4 09:43:39

学习一下!!
页: [1]
查看完整版本: 51单片机+315M无线射频模块接受程序