⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test.c

📁 无线收发系统 无线收发系统 无线收发系统 无线收发系统
💻 C
字号:
#include <AT89X52.H>

#include "string.h"
sbit LED1 = P1^1;
sbit LED2 = P1^2;
sbit W_IN = P2^2;
sbit W_OUT = P2^0;
sbit DQ =P2^1; 
unsigned char Te=0;//温度整数部分
unsigned char Te_D=0;//温度小数部分
unsigned char T0_last;
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 delay(unsigned int i)
{
     while(i--);
    
}
//初始化函数
Init_DS18B20(void)
{
 unsigned char x=0;
 DQ = 1;    //DQ复位
 delay(8);  //稍做延时
 DQ = 0;    //单片机将DQ拉低
 delay(50); //精确延时 大于 480us
 DQ = 1;    //拉高总线
 delay(14);
 x=DQ;      //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
 delay(20);
}
//读一个字节
ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
 {
  DQ = 0; // 给脉冲信号
  dat>>=1;
  DQ = 1; // 给脉冲信号
  if(DQ)
   dat|=0x80;
  delay(4);
 }
 return(dat);
}
//写一个字节
WriteOneChar(unsigned char dat)
{
 unsigned char i=0;
 for (i=8; i>0; i--)
 {
  DQ = 0;
  DQ = dat&0x01;
  delay(5);
  DQ = 1;
  dat>>=1;
 }
delay(4);
}
//读取温度
void ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned char e=0;
//unsigned char t;
unsigned char c,d;

//unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();   //读取温度值低位
b=ReadOneChar();   //读取温度值高位

e=a&0x0f;//小数部分
c=(e*10)/16;
d=((e*10)%16)*10/16;  
Te_D=c*10+d;    
a=a>>4;
Te=b<<4;
Te=Te|a;

}

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++;
	T0_last=TL0;
}

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 clock_init_again(void){
   
	TMOD=0x02;
	TH0=0x0ce;//12M,50us
	TL0=T0_last;
//	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;
    jiffies=0;
	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:2400  fosc=11.0592MHz  :f4
	TL1	  = 0x0e6;
    //IE   |= 0x90;       //Enable Serial Interrupt 
    TR1   = 1;          // timer 1 run
	RI=0;
	TI=1; 
}

void serial_out(char d){
	while(!TI);
	TI=0;
	SBUF=(d);
}



void send_string_com(char *str,int strlen)//串口程序
{   char sum;

    int k=0;
    serial_out(02);
    do
    {   sum^=*(str+k);
        serial_out(*(str + k));
        k++;
    } while(k < strlen);
	serial_out(sum);
	serial_out(03);
}

//等待指定长度的串行数据到达,超时值为每两个字节之间的间隔时间而非等待整个串的时间.
//超时单位为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[n++]=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[16];
#define send_byts send_buf[0]	//剩余字节数,发送完后为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[0]=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_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[16];
#define recv_byts recv_buf[0]		//应收到字节数,由每个包的第一个字节指定
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[recv_byte_p] = 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;
				}
		}
	}
}

#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 100		//心跳间隔 X / 1000   秒
unsigned int heart_beat_timer = HEART_BEAT_INTERVAL;
unsigned int last_jiffies=0;

 void main(){
    
	init_serialcomm();
	//P0=0xff;
	//P2=0x00;                                                                                                                                                                                                 ;
	sys_init();

	LED1 = 0;
	LED2 = 1;
	//send_string_com("ok",2);
	//lcd_reset();
	//lcd_power_on();
 	//lcd_self_test();

	while(1){
          
     	  

		if (jiffies - last_jiffies >= 50){//每次中断为50us,所以要20次才为1ms
			last_jiffies = jiffies;
			heart_beat_timer--;
		    
		    if (send_stat == 0 ){//		碰撞测试
			
            ET0=0;
		    ReadTemperature();
		   
			clock_init_again();
		   
			START_SEND(8);
			send_buf[1]=Te/10+0x30;
			send_buf[2]=Te%10+0x30;
			send_buf[3]='.';
			send_buf[4]=Te_D/10+0x30;
			send_buf[5]=(Te_D%10)+0x30;
            send_buf[6]='D';
			send_buf[7]='\0';
			//wirless();
			
	        
			//send_string_com(send_buf,strlen(send_buf));
				}
		 if (send_delay)
				send_delay--;
		}

       

		if (heart_beat_timer == 0){
			heart_beat_timer = HEART_BEAT_INTERVAL;
			LED1 = ~LED1;
			LED2 = ~LED2;
		}

		wirless();

		if (send_stat == SEND_FAILED){

			send_stat = 0;break;

		}else if (send_stat == SEND_SUCCESS){
			send_stat = 0;
			P2_3=~P2_3;break;
	
		}



	}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -