您的位置:首页 > 其它

51单片机加NRF24L01做的无线温度采集

2018-01-02 00:20 330 查看
/****************************************************

                        接收机(下位机)

        功能 :自动接收上位机DS18B20实时读取的温度,用1602显示

                        温度值

        单片机:STC12C5a60s2

        晶振 :11.0592M

        作者  :苏义江改编自网络

        时间  :2016.4.19

        注释 :用多功能实验板发射,接收成功

**************************************************/

#include <reg52.h> 

#include <intrins.h>  

#define uchar unsigned char  

uchar code digit[11]={"0123456789-"};     //定义字符数组显示数字 

uchar code Str[]={"RICHMCU DS18B20"};    //说明显示的是温度 

uchar code Temp[]={"WENDU:"};        //说明显示的是温度 

uchar code Cent[]={"Cent"};          //温度单位 

uchar  tm[2]; //温度值存储数组

uchar flg=0;      //负温度标志 和临时暂存变量 

uchar tltemp; 

#define TX_ADR_WIDTH   5  

#define RX_ADDR_WITDH  5//接收地址宽度设置为5个字节  

#define TX_PLOAD_WIDTH 20  

#define RX_DATA_WITDH  20//接收数据宽度8字节  

uchar const TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x55,0x10,0x10,0x01};

uchar const RX_ADDRESS[TX_ADR_WIDTH]={0x34,0x55,0x10,0x10,0x01};   

uchar rx_buf[TX_PLOAD_WIDTH]; 

uchar tx_buf[TX_PLOAD_WIDTH]; 

uchar flag;//标志   

int cout;  

///STC12C5A60S2NRF24L01端口定义

sbit CE  =P1^6;  //发射高电平大于10MS 接收高电平  

sbit CSN =P2^4;  //低电平ISP使能 

sbit SCK =P2^3;   //下降沿 

sbit MOSI=P2^2;  //MCU出

sbit MISO=P2^1;  //MCU入 

sbit IRQ =P2^0;  //中断 

#define dats P0

sbit RS =P2^7;           //寄存器选择位,将RS位定义为P2.0引脚 

sbit RW =P2^6;           //读写选择位,将RW位定义为P2.1引脚 

sbit E  =P2^5;            //使能信号位,将E位定义为P2.2引脚 

sbit BF =P0^7;           //忙碌标志位,,将BF位定义为P0.7引脚 

//STC12C5608AD NRF24L01端口定义

/*sbit CE  =P1^3;  //发射高电平大于10MS 接收高电平  

sbit CSN =P1^2;  //低电平ISP使能 

sbit SCK =P1^5;   //下降沿 

sbit MOSI=P1^4;  //MCU出

sbit MISO=P1^7;  //MCU入 

sbit IRQ =P1^6;  //中断 

#define dats P2

sbit RS =P3^4;           

//寄存器选择位,将RS位定义为P3.0引脚 

sbit RW =P3^6;           

//读写选择位,将RW位引脚接地 

sbit E  =P3^5;            

//使能信号位,将E位定义为P3.1引脚 

sbit BF =P0^7;           

//忙碌标志位,,将BF位定义为P0.7引脚 

*/

uchar  bdata sta;  

sbit RX_DR =sta^6;   //接收数据准备就绪 

sbit TX_DS =sta^5;   //已发送数据 

sbit MAX_RT =sta^4;

#define READ_REG        0x00   // 读寄存器指令 

#define WRITE_REG       0x20  // 写寄存器指令 

#define RD_RX_PLOAD     0x61   // 读取接收数据指令 

#define WR_TX_PLOAD     0xA0   // 写待发数据指令 

#define FLUSH_TX        0xE1  // 冲洗发送 FIFO指令 

#define FLUSH_RX        0xE2   // 冲洗接收 FIFO指令 

#define REUSE_TX_PL     0xE3   // 定义重复装载数据指令 

#define NOP             0xFF   // 保留

#define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式 

#define EN_AA           0x01  // 自动应答功能设置 

#define EN_RXADDR       0x02  // 可用信道设置 

#define SETUP_AW        0x03  // 收发地址宽度设置 

#define SETUP_RETR      0x04  // 自动重发功能设置 

#define RF_CH           0x05  // 工作频率设置  

#define RF_SETUP        0x06  // 发射速率、功耗功能设置

 #define STATUS          0x07  // 状态寄存器 

#define OBSERVE_TX      0x08  // 发送监测功能  

#define CD              0x09  // 地址检测           

 #define RX_ADDR_P0      0x0A  // 频道0接收数据地址 

#define RX_ADDR_P1      0x0B  // 频道1接收数据地址 

#define RX_ADDR_P2      0x0C  // 频道2接收数据地址 

#define RX_ADDR_P3      0x0D  // 频道3接收数据地址 

#define RX_ADDR_P4      0x0E  // 频道4接收数据地址 

#define RX_ADDR_P5      0x0F  // 频道5接收数据地址 

#define TX_ADDR         0x10  // 发送地址寄存器  

#define RX_PW_P0        0x11  // 接收频道0接收数据长度 

#define RX_PW_P1        0x12  // 接收频道0接收数据长度 

#define RX_PW_P2        0x13  // 接收频道0接收数据长度 

#define RX_PW_P3        0x14  // 接收频道0接收数据长度

#define RX_PW_P4        0x15  // 接收频道0接收数据长度 

#define RX_PW_P5        0x16  // 接收频道0接收数据长度 

#define FIFO_STATUS     0x17  // FIFO栈入栈出状态寄存器设置

void delay1ms() 

{     

        uchar i,j;    

        for(i=0;i<4;i++)    

        for(j=0;j<33;j++)     ;     

}

void delaynms(uchar n)  

{     

        uchar i;  

        for(i=0;i<n;i++)     

        delay1ms();  

}

bit BusyTest(void)   

{      

        bit result;  

        RS=0;       //根据规定,RS为低电平,RW为高电平时,可以读状态     

        RW=1;      

        E=1;        //E=1,才允许读写     

        _nop_();   //空操作     

        _nop_();_nop_();

        _nop_();   //空操作四个机器周期,给硬件反应时间      

        result=BF;  //将忙碌标志电平赋给result    

        E=0;         //将E恢复低电平    

        return result;   



void WriteInstruction (uchar dictate) 

{        

         while(BusyTest()==1);   //如果忙就等待

        RS=0;                  //根据规定,RS和R/W同时为低电平时,可以写入指令   

        RW=0;      

        E=0;            //E置低电平(根据表8-6,写指令时,E为高脉冲, 

    _nop_();                            // 就是让E从0到1发生正跳变,所以应先置"0"  

         _nop_();        //空操作4个机器周期,给硬件反应时间 

        _nop_();                            // 就是让E从0到1发生正跳变,所以应先置"0"  

        _nop_();  

        dats=dictate;     //将数据送入P0口,即写入指令或地址 

        _nop_();                            // 就是让E从0到1发生正跳变,所以应先置"0"  

        _nop_();  

        _nop_();_nop_();

        _nop_();_nop_();  //空操作6个机器周期,给硬件反应时间   

        E=1;                   //E置高电平   

        delaynms(50) ;               //空操作四个机器周期,给硬件反应时间   

        E=0;                  //当E由高电平跳变成低电平时,液晶模块开始执行命令  



void WriteAddress(uchar x)  

{       

        WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x" 

}

void WriteData(uchar y)  

{      

        while(BusyTest()==1);      

        RS=1;    //RS为高电平,RW为低电平时,可以写入数据    

        RW=0;    

        E=0;      //E置低电平(根据表8-6,写指令时,E为高脉冲,                      // 就是让E从0到1发生正跳变,所以应先置"0"    

        dats=y;    //将数据送入P0口,即将数据写入液晶模块   

         _nop_();_nop_();

        _nop_();_nop_();//空操作四个机器周期,给硬件反应时间   

         E=1;  //E置高电平   

        delaynms(50) ;        //空操作四个机器周期,给硬件反应时间   

        E=0;            //当E由高电平跳变成低电平时,液晶模块开始执行命令 

}

void LcdInitiate(void) 

{     

         delaynms(50);               //延时15ms,首次写指令时应给LCD一段较长的反应时间      

        WriteInstruction(0x38);     //显示模式设置:16×2显示,5×7点阵,8位数据接口

          delaynms(5);                //延时5ms ,给硬件一点反应时间     

        WriteInstruction(0x38); 

         delaynms(5);               //延时5ms ,给硬件一点反应时间  

        WriteInstruction(0x38);     //连续三次,确保初始化成功  d

        delaynms(5);               //延时5ms ,给硬件一点反应时间  

        WriteInstruction(0x0c);     //显示模式设置:显示开,无光标,光标不闪烁  

        delaynms(5);               //延时5ms ,给硬件一点反应时间 

         WriteInstruction(0x06);     //显示模式设置:光标右移,字符不移  

        delaynms(5);                //延时5ms ,给硬件一点反应时间 

         WriteInstruction(0x01);     //清屏幕指令,将以前的显示内容清除  

        delaynms(5);             //延时5ms ,给硬件一点反应时间

  

}

void display_explain(void)  

{         

        uchar i;        

         WriteAddress(0x00);    //写显示地址,将在第1行第1列开始显示      

         i = 0;                //从第一个字符开始显示     

        while(Str[i] != '\0')  //只要没有写到结束标志,就继续写     

        {            

                WriteData(Str[i]);   //将字符常量写入LCD      

                i++;                 //指向下一个字符      

                delaynms(100);        //延时100ms较长时间,以看清关于显示的说明  

   

        }  

}

void display_symbol(void)  

{         

        uchar i;        

         WriteAddress(0x40);    //写显示地址,将在第2行第1列开始显示       

        i = 0;                //从第一个字符开始显示     

        while(Temp[i] != '\0')  //只要没有写到结束标志,就继续写     

        {            

                WriteData(Temp[i]);   //将字符常量写入LCD     

                 i++;                 //指向下一个字符      

                delaynms(50);        //延时1ms给硬件一点反应时间     

        }  

}

void  display_dot(void) 

{           

         WriteAddress(0x49);   //写显示地址,将在第2行第10列开始显示        

        WriteData('.');      //将小数点的字符常量写入LCD   

        delaynms(50);         //延时1ms给硬件一点反应时间   

}

void  display_cent(void) 

{             

        unsigned char i;             

        WriteAddress(0x4c);  //写显示地址,将在第2行第13列开始显示       

        i = 0;                 //从第一个字符开始显示      

        while(Cent[i] != '\0')  //只要没有写到结束标志,就继续写     

        {           

                WriteData(Cent[i]);    //将字符常量写入LCD      

                i++;                 //指向下一个字符     

                 delaynms(50);        //延时1ms给硬件一点反应时间     

        }  



void display_temp1(uchar x) 

{

        uchar j,k,l;     //j,k,l分别储存温度的百位、十位和个位  

        j=x/100;              //取百位  

        k=(x%100)/10;    //取十位  

        l=x%10;             //取个位    

        WriteAddress(0x46);    //写显示地址,将在第2行第7列开始显示  

        if(flg==1)   

        {  

                WriteData(digit[10]);    //将百位数字的字符常量写入LCD 

        }                                                                                                 

        else

        {  

                WriteData(digit[j]);    //将十位数字的字符常量写入LCD  

        }  

        WriteData(digit[k]);    //将十位数字的字符常量写入LCD  

        WriteData(digit[l]);    //将个位数字的字符常量写入LCD  

        delaynms(5);         //延时1ms给硬件一点反应时间       

}

void display_temp2(uchar x) 

{    

        WriteAddress(0x4a);      //写显示地址,将在第2行第11列开始显示  

        WriteData(digit[x]);     //将小数部分的第一位数字字符常量写入LCD  

        delaynms(5);          //延时1ms给硬件一点反应时间 

}

void init_io(void) 

{  

        CE=0;     

        CSN=1;      

        SCK=0;     

}  

void delay_ms(unsigned int x)

{      

        unsigned int i,j;     

        for(i=0;i<x;i++)     

        {        

                 j=108;        

                while(j--);     

        } 

}

uchar SPI_RW(uchar byte) 

{  

        uchar bit_ctr;     

         for(bit_ctr=0;bit_ctr<8;bit_ctr++)        

        {      

                MOSI = (byte&0x80);               

                byte = (byte<<1);                 

                SCK = 1;                          

                byte|=MISO;                 

                SCK=0;                   

        }      

        return(byte);               

}

uchar SPI_RW_Reg(uchar reg, uchar value) 

{  

        uchar status;     

        CSN = 0;                       

        status = SPI_RW(reg);         

        SPI_RW(value);                 

        CSN = 1;                       

        return(status);             



uchar SPI_Read(uchar reg) 

{  

        uchar reg_val;     

        CSN = 0;                    

        SPI_RW(reg);                

        reg_val = SPI_RW(0);        

        CSN = 1;                    

        return(reg_val);         

}

uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes) 

{  

        uchar status,byte_ctr;     

        CSN = 0;                          

        status = SPI_RW(reg);             

        for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)      

        pBuf[byte_ctr] = SPI_RW(0);        

        CSN = 1;                               

        return(status);                     

}

uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes) 

{  

        uchar status,byte_ctr;     

        CSN = 0;

        status = SPI_RW(reg);         

        for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)       

        SPI_RW(*pBuf++);    

        CSN = 1;                    

        return(status);          



void RX_Mode(void) 

{  

        CE=0;     

        SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); 

  

//        SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, TX_ADDRESS, TX_ADR_WIDTH); 

// 接收频道0 接收数据长度设置

        SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);

 // 接收频道1 接收数据长度设置 

//        SPI_RW_Reg(WRITE_REG + RX_PW_P1, TX_PLOAD_WIDTH);

   

        SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);  //数据通道0应答允许         

        SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);//接收数据通道0允许   

//        SPI_RW_Reg(WRITE_REG + EN_AA, 0x02);  //数据通道1应答允许         

//        SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x02);//接收数据通道1允许  

    

        SPI_RW_Reg(WRITE_REG + RF_CH, 40);            

             

        SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);   //数据传输率1Mbps ,发射功率0dBm     

        SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);  //配置寄存器       

        CE = 1; 

        delay_ms(200);

}

void checkflag() 

{      

        sta=SPI_Read(STATUS);     

        if(RX_DR)           

        {

                SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);      

                flag=1;           

        }      

        if(MAX_RT)        

        {

                SPI_RW_Reg(FLUSH_TX,0);           

        }   

        SPI_RW_Reg(WRITE_REG+STATUS,sta);   

}

void yejinchu(void)  

{       

        LcdInitiate();         //将液晶初始化     

        delaynms(5);        //延时5ms给硬件一点反应时间       

        display_explain();      

        display_symbol();    //显示温度说明        

        display_dot();       //显示温度的小数点      

         display_cent();      //显示温度的单位

}

void xianshi(void) 

{      

        uchar TL;     //储存暂存器的温度低位      

        uchar  TH;    //储存暂存器的温度高位      

        uchar  TN;      //储存温度的整数部分    

        uchar  TD;       //储存温度的小数部分   

        TH=tm[0] ;  

        TL=tm[1];

        if((TH&0xf8)!=0x00)//判断高五位 得到温度正负标志   

        {   

                flg=1;   

                TL=~TL;  //取反   

                TH=~TH;   //取反   

                tltemp=TL+1; //低位加1   

                TL=tltemp;   

                if(tltemp>255) 

                TH++;  //如果低8位大于255,向高8位进1     

                TN=TH*16+TL/16;      //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16                       

//这样得出的是温度的整数部分,小数部分被丢弃了     

                TD=(TL%16)*10/16;    

//计算温度的小数部分,将余数乘以10再除以16取整,   

        }   

        TN=TH*16+TL/16;      

//实际温度值=(TH*256+TL)/16,即:TH*16+TL/16                       

//这样得出的是温度的整数部分,小数部分被丢弃了     

        TD=(TL%16)*10/16;    

//计算温度的小数部分,将余数乘以10再除以16取整,                      

//这样得到的是温度小数部分的第一位数字(保留1位小数)     

        display_temp1(TN);    //显示温度的整数部分     

        display_temp2(TD);    //显示温度的小数部分       

        delaynms(5); 

}

void main(void) 

{  

        uchar xx;   

        yejinchu();  

        init_io();            

        RX_Mode();    

        while(1)  

        {

                RX_Mode(); 

                checkflag();   

                if(flag)    

                {       

                        flag=0;    

                        for(xx=0;xx<2;xx++)     

                         {

                                tm[xx]=rx_buf[xx];               

                                delay_ms(1);    

                        }         

                        xianshi();     

                }   

        }  

}/***********************************************

                        发射机(上位机)

        功能 :自动或通过按键发射DS18B20实时读取的温度,下位机用1602显示

                        温度值

        单片机:STC12C2052AD

        晶振 :11.0592M

        作者  :苏义江改编自网络

        时间  :2016.4.19

        注释 :用多功能实验板发射,接收成功

********************************************/

#include <reg52.h> 

#include <intrins.h>

#define uchar unsigned char  

#define uint unsigned int  

#define TX_ADR_WIDTH   5  // 发射地址的字节个数 

#define RX_ADDR_WITDH  5  //接收地址宽度设置为5个字节 

#define TX_PLOAD_WIDTH 20  //发射字节

#define RX_DATA_WITDH  20 //接收数据宽度20字节

#define dats P2

uchar const TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x55,0x10,0x10,0x01};

uchar const RX_ADDRESS[TX_ADR_WIDTH]={0x34,0x55,0x10,0x10,0x01};  

uchar rx_buf[TX_PLOAD_WIDTH]; 

uchar tx_buf[TX_PLOAD_WIDTH]; 

uchar distance_data[2]; 

uchar code digit[11]={"0123456789-"};     //定义字符数组显示数字 

uchar code Str[]={"RICHMCU DS18B20"};    //说明显示的是温度 

uchar code Temp[]={"WENDU:"};             //说明显示的是温度 

uchar code Cent[]={"Cent"};              //温度单位 

uchar  tm[2]; 

uchar flg=0;      //负温度标志 和临时暂存变量 

uchar tltemp; 

uchar flag;//标志

//移动采集模块端口

/*sbit CE  =P1^7;  //发射高电平大于10MS 接收高电平  

sbit CSN =P1^2;  //低电平ISP使能 

sbit SCK =P1^6;   //下降沿 

sbit MOSI=P1^3;  //MCU出 

sbit MISO=P1^5;  //MCU入 

sbit IRQ =P1^4;  //中断 

sbit DQ  =P2^0;

sbit led=P2^0;//STC12C5608指示灯(移动采集)*/

sbit CE  =P1^3;  //发射高电平大于10MS 接收高电平  

sbit CSN =P1^2;  //低电平ISP使能 

sbit SCK =P1^5;   //下降沿 

sbit MOSI=P1^4;  //MCU出 

sbit MISO=P1^7;  //MCU入 

sbit IRQ =P1^6;  //中断 

sbit DQ     =P3^3; 

sbit led=P3^7;//带1602显示STC12C5608指示灯

//sbit led=P3^5;//STC12C2052指示灯

//sbit led=P2^6;//STC12C5608指示灯

sbit RS =P3^4;           

//寄存器选择位,将RS位定义为P3.0引脚 

sbit RW =P3^6;           

//读写选择位,将RW位引脚接地 

sbit E  =P3^5;            

//使能信号位,将E位定义为P3.1引脚 

sbit BF =P0^7;           

//忙碌标志位,,将BF位定义为P0.7引脚 

sbit key=P3^2;

uchar  bdata sta;  

sbit RX_DR  =sta^6;   //接收数据准备就绪 

sbit TX_DS  =sta^5;   //已发送数据 

sbit MAX_RT =sta^4; //中断溢出

 

#define READ_REG      0x00   // 读寄存器指令 

#define WRITE_REG     0x20  // 写寄存器指令 

#define RD_RX_PLOAD   0x61   // 读取接收数据指令 

#define WR_TX_PLOAD   0xA0   // 写待发数据指令 

#define FLUSH_TX      0xE1  // 冲洗发送 FIFO指令 

#define FLUSH_RX      0xE2   // 冲洗接收 FIFO指令 

#define REUSE_TX_PL   0xE3   // 定义重复装载数据指令 

#define NOP           0xFF   // 保留

#define CONFIG        0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式 

#define EN_AA         0x01  // 自动应答功能设置 

#define EN_RXADDR     0x02  // 可用信道设置 

#define SETUP_AW      0x03  // 收发地址宽度设置 

#define SETUP_RETR    0x04  // 自动重发功能设置 

#define RF_CH         0x05  // 工作频率设置  

#define RF_SETUP      0x06  // 发射速率、功耗功能设置

 #define STATUS       0x07  // 状态寄存器 

#define OBSERVE_TX    0x08  // 发送监测功能  

#define CD            0x09  // 地址检测           

 #define RX_ADDR_P0   0x0A  // 频道0接收数据地址 

#define RX_ADDR_P1    0x0B  // 频道1接收数据地址 

#define RX_ADDR_P2    0x0C  // 频道2接收数据地址 

#define RX_ADDR_P3    0x0D  // 频道3接收数据地址 

#define RX_ADDR_P4    0x0E  // 频道4接收数据地址 

#define RX_ADDR_P5    0x0F  // 频道5接收数据地址 

#define TX_ADDR       0x10  // 发送地址寄存器  

#define RX_PW_P0      0x11  // 接收频道0接收数据长度 

#define RX_PW_P1      0x12  // 接收频道0接收数据长度 

#define RX_PW_P2      0x13  // 接收频道0接收数据长度 

#define RX_PW_P3      0x14  // 接收频道0接收数据长度

#define RX_PW_P4      0x15  // 接收频道0接收数据长度 

#define RX_PW_P5      0x16  // 接收频道0接收数据长度 

#define FIFO_STATUS   0x17  // FIFO栈入栈出状态寄存器设置

void delay1ms() 

{     

        uchar i,j;    

        for(i=0;i<4;i++)    

        for(j=0;j<33;j++)     ;     

}

void delaynms(uchar n)  

{     

        uchar i;  

        for(i=0;i<n;i++)     

        delay1ms();  

}

/*bit BusyTest(void)   

{      

        bit result;  

        RS=0;       //根据规定,RS为低电平,RW为高电平时,可以读状态     

        RW=1;      

        E=1;        //E=1,才允许读写     

        _nop_();   //空操作     

        _nop_();_nop_();

        _nop_();   //空操作四个机器周期,给硬件反应时间      

        result=BF;  //将忙碌标志电平赋给result    

        E=0;         //将E恢复低电平    

        return result;   

} */

void WriteInstruction (uchar dictate) 

{        

        RS=0;                  //根据规定,RS和R/W同时为低电平时,可以写入指令   

        RW=0;      

        E=0;            //E置低电平(根据表8-6,写指令时,E为高脉冲, 

    _nop_();                            // 就是让E从0到1发生正跳变,所以应先置"0"  

         _nop_();        //空操作4个机器周期,给硬件反应时间 

        _nop_();                            // 就是让E从0到1发生正跳变,所以应先置"0"  

        _nop_();  

        dats=dictate;     //将数据送入P0口,即写入指令或地址 

        _nop_();                            // 就是让E从0到1发生正跳变,所以应先置"0"  

        _nop_();  

        _nop_();_nop_();

        _nop_();_nop_();  //空操作6个机器周期,给硬件反应时间   

        E=1;                   //E置高电平   

        delaynms(50) ;               //空操作四个机器周期,给硬件反应时间   

        E=0;                  //当E由高电平跳变成低电平时,液晶模块开始执行命令  



void WriteAddress(uchar x)  

{       

        WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x" 

}

void WriteData(uchar y)  

{      

//        while(BusyTest()==1);      

        RS=1;    //RS为高电平,RW为低电平时,可以写入数据    

        RW=0;    

        E=0;      //E置低电平(根据表8-6,写指令时,E为高脉冲,                      // 就是让E从0到1发生正跳变,所以应先置"0"    

        dats=y;    //将数据送入P0口,即将数据写入液晶模块   

         _nop_();_nop_();

        _nop_();_nop_();//空操作四个机器周期,给硬件反应时间   

         E=1;  //E置高电平   

        delaynms(50) ;        //空操作四个机器周期,给硬件反应时间   

        E=0;            //当E由高电平跳变成低电平时,液晶模块开始执行命令 

}

void LcdInitiate(void) 

{     

         delaynms(50);               //延时15ms,首次写指令时应给LCD一段较长的反应时间      

        WriteInstruction(0x38);     //显示模式设置:16×2显示,5×7点阵,8位数据接口

          delaynms(5);                //延时5ms ,给硬件一点反应时间     

        WriteInstruction(0x38); 

         delaynms(5);               //延时5ms ,给硬件一点反应时间  

        WriteInstruction(0x38);     //连续三次,确保初始化成功  d

        delaynms(5);               //延时5ms ,给硬件一点反应时间  

        WriteInstruction(0x0c);     //显示模式设置:显示开,无光标,光标不闪烁  

        delaynms(5);               //延时5ms ,给硬件一点反应时间 

         WriteInstruction(0x06);     //显示模式设置:光标右移,字符不移  

        delaynms(5);                //延时5ms ,给硬件一点反应时间 

         WriteInstruction(0x01);     //清屏幕指令,将以前的显示内容清除  

        delaynms(5);             //延时5ms ,给硬件一点反应时间

  

}

void display_explain(void)  

{         

        uchar i;        

         WriteAddress(0x00);    //写显示地址,将在第1行第1列开始显示      

         i = 0;                //从第一个字符开始显示     

        while(Str[i] != '\0')  //只要没有写到结束标志,就继续写     

        {            

                WriteData(Str[i]);   //将字符常量写入LCD      

                i++;                 //指向下一个字符      

                delaynms(100);        //延时100ms较长时间,以看清关于显示的说明  

   

        }  

}

void display_symbol(void)  

{         

        uchar i;        

         WriteAddress(0x40);    //写显示地址,将在第2行第1列开始显示       

        i = 0;                //从第一个字符开始显示     

        while(Temp[i] != '\0')  //只要没有写到结束标志,就继续写     

        {            

                WriteData(Temp[i]);   //将字符常量写入LCD     

                 i++;                 //指向下一个字符      

                delaynms(50);        //延时1ms给硬件一点反应时间     

        }  

}

void  display_dot(void) 

{           

         WriteAddress(0x49);   //写显示地址,将在第2行第10列开始显示        

        WriteData('.');      //将小数点的字符常量写入LCD   

        delaynms(50);         //延时1ms给硬件一点反应时间   

}

void  display_cent(void) 

{             

        unsigned char i;             

        WriteAddress(0x4c);  //写显示地址,将在第2行第13列开始显示       

        i = 0;                 //从第一个字符开始显示      

        while(Cent[i] != '\0')  //只要没有写到结束标志,就继续写     

        {           

                WriteData(Cent[i]);    //将字符常量写入LCD      

                i++;                 //指向下一个字符     

                 delaynms(50);        //延时1ms给硬件一点反应时间     

        }  



/*void display_temp1(uchar x) 

{

        uchar j,k,l;     //j,k,l分别储存温度的百位、十位和个位  

        j=x/100;              //取百位  

        k=(x%100)/10;    //取十位  

        l=x%10;             //取个位    

        WriteAddress(0x46);    //写显示地址,将在第2行第7列开始显示  

        if(flg==1)   

        {  

                WriteData(digit[10]);    //将百位数字的字符常量写入LCD 

        }                                                                                                 

        else

        {  

                WriteData(digit[j]);    //将十位数字的字符常量写入LCD  

        }  

        WriteData(digit[k]);    //将十位数字的字符常量写入LCD  

        WriteData(digit[l]);    //将个位数字的字符常量写入LCD  

        delaynms(5);         //延时1ms给硬件一点反应时间       

}

void display_temp2(uchar x) 

{    

        WriteAddress(0x4a);      //写显示地址,将在第2行第11列开始显示  

        WriteData(digit[x]);     //将小数部分的第一位数字字符常量写入LCD  

        delaynms(5);          //延时1ms给硬件一点反应时间 

}

*/

void yejinchu(void)  

{       

        LcdInitiate();         //将液晶初始化     

        delaynms(5);        //延时5ms给硬件一点反应时间       

        display_explain();      

        display_symbol();    //显示温度说明        

        display_dot();       //显示温度的小数点      

         display_cent();      //显示温度的单位

}

/*void xianshi(void) 

{      

        uchar TL;     //储存暂存器的温度低位      

        uchar  TH;    //储存暂存器的温度高位      

        uchar  TN;      //储存温度的整数部分    

        uchar  TD;       //储存温度的小数部分   

        TH=tm[0] ;  

        TL=tm[1];

        if((TH&0xf8)!=0x00)//判断高五位 得到温度正负标志   

        {   

                flg=1;   

                TL=~TL;  //取反   

                TH=~TH;   //取反   

                tltemp=TL+1; //低位加1   

                TL=tltemp;   

                if(tltemp>255) 

                TH++;  //如果低8位大于255,向高8位进1     

                TN=TH*16+TL/16;      //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16                       

//这样得出的是温度的整数部分,小数部分被丢弃了     

                TD=(TL%16)*10/16;    

//计算温度的小数部分,将余数乘以10再除以16取整,   

        }   

        TN=TH*16+TL/16;      

//实际温度值=(TH*256+TL)/16,即:TH*16+TL/16                       

//这样得出的是温度的整数部分,小数部分被丢弃了     

        TD=(TL%16)*10/16;    

//计算温度的小数部分,将余数乘以10再除以16取整,                      

//这样得到的是温度小数部分的第一位数字(保留1位小数)     

        display_temp1(TN);    //显示温度的整数部分     

        display_temp2(TD);    //显示温度的小数部分       

        delaynms(5); 

}*/

void init_io(void) 

{  

        CE=0;    

        CSN=1;    

         SCK=0;   

}  

void delay_ms(unsigned int x)

{      

        unsigned int i,j;    

         for(i=0;i<x;i++)    

         {

                j=108;        

                while(j--);     

        } 

}

uchar SPI_RW(uchar byte) 

{  

        uchar bit_ctr;     

         for(bit_ctr=0;bit_ctr<8;bit_ctr++)        

        {      

                MOSI = (byte&0x80);               

                byte = (byte<<1);                 

                SCK = 1;                          

                byte|=MISO;                 

                SCK=0;                   

        }      

        return(byte);               

}

uchar SPI_RW_Reg(uchar reg, uchar value) 

{  

        uchar status;     

        CSN = 0;                       

        status = SPI_RW(reg);         

        SPI_RW(value);                 

        CSN = 1;                       

        return(status);             



uchar SPI_Read(uchar reg) 

{  

        uchar reg_val;     

        CSN = 0;                    

        SPI_RW(reg);//写指令                

        reg_val = SPI_RW(0);//读reg的内容        

        CSN = 1;                    

        return(reg_val);         

}

/*检测应答信号*/

uchar Check_Ack(void)

{

    sta=SPI_Read(READ_REG +STATUS);/*读取寄存状态*/

    if(TX_DS||MAX_RT)/*如果TX_DS或MAX_RT为1,则清除中断和清除TX_FIFO寄存器的值*/

    {

        SPI_RW_Reg(WRITE_REG+STATUS,0xff);

        CSN=0;

        SPI_RW(FLUSH_TX);/*如果没有这一句只能发一次数据,大家要注意*/

        CSN=1;

        return 0;

    }

    else

        return 1;

}

uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes) 

{  

        uchar status,byte_ctr;     

        CSN = 0;                          

        status = SPI_RW(reg);             

        for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)      

        pBuf[byte_ctr] = SPI_RW(0);        

        CSN = 1;                               

        return(status);                     

}

uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes) 

{  

        uchar status,byte_ctr;     

        CSN = 0;

        status = SPI_RW(reg);         

        for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)       

        SPI_RW(*pBuf++);    

        CSN = 1;                    

        return(status);          

}

void TX_Mode(void) 

{  

        CE=0;     

        SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS/*接收模块的地址*/, 

        TX_ADR_WIDTH/*地址宽度5*/);         

        SPI_Write_Buf(WRITE_REG + RX_ADDR_P0/*通道0 接收数据地址*/, 

        RX_ADDRESS, TX_ADR_WIDTH);  

//        SPI_Write_Buf(WRITE_REG + RX_ADDR_P1/*通道1 接收数据地址*/, 

//        RX_ADDRESS, TX_ADR_WIDTH);    

        SPI_Write_Buf(WR_TX_PLOAD,/*写待发数据指令a0*/ 

        tx_buf, TX_PLOAD_WIDTH/*20*/);      

        SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);  //数据通道0应答允许        

        SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //接收数据通道0允许   

//        SPI_RW_Reg(WRITE_REG + EN_AA, 0x02);  //数据通道0应答允许        

//        SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x02); //接收数据通道0允许

   

        SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a);//等待 500+86us 自动重发10次    

        SPI_RW_Reg(WRITE_REG + RF_CH,40);             

        SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);   //数据传输率1Mbps ,发射功率0dBm    

        SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);     //配置寄存器  

        CE=1; 

        delay_ms(5);



void checkflag()  //判断接收成功

{    

        sta=SPI_Read(STATUS);//读状态寄存器  

         if(RX_DR)           

         {    //读取接收数据指令 数组[20]  20

                SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH); 

                 //  

                flag=1;        

        }      

        if(MAX_RT)        

        {     

                

                /*冲洗发送FIFO指令*/ 

                SPI_RW_Reg(FLUSH_TX,0); 

          

        }           

        SPI_RW_Reg(WRITE_REG+STATUS,sta);//清除中断 

 

}

/*void nRF24L01_TxPacket(uchar * tx_buf)

{

        CE=0; //StandBy I模式

        SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址

        SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据

        SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送

        CE=1; //置高CE,激发数据发送

        delay_ms(5);

}

//以下是DS18B20的操作程序

 */

void  delay_b20(uint n)//STC12C5A单片机定时1us

{  

  while(n--)

  {

  _nop_();

  }

  

}

bit Init_DS18B20(void)  

{   

        bit flag;         //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在   

        DQ = 1;           //先将数据线拉高   

        delay_b20(1); //略微延时约6微秒      ;  

         DQ = 0;           //再将数据线从高拉低,要求保持480~960us  

        delay_b20(500); //略微延时约600微秒       ;         

//以向DS18B20发出一持续480~960us的低电平复位脉冲   

        DQ = 1;           //释放数据线(将数据线拉高)    

        delay_b20(60);   //延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)  

        flag=DQ;          //让单片机检测是否输出了存在脉冲(DQ=0表示存在)        

        delay_b20(500); //延时足够长时间,等待存在脉冲输出完毕       ;   

        return flag;    //返回检测成功标志 

}

uchar ReadOneChar(void)  

{   

        unsigned char i=0;   

         unsigned char dat;  //储存读出的一个字节数据   

        for (i=0;i<8;i++)    

        {           

                 DQ =1;       // 先将数据线拉高      

                delay_b20(1);     //等待一个机器周期        

                DQ = 0;      //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序      

                delay_b20(1);     //等待一个机器周期          

                DQ = 1;     //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备     

                 delay_b20(1);               ;      //延时约6us,使主机在15us内采样      

                dat>>=1;      

                if(DQ==1)         

                dat|=0x80;  //如果读到的数据是1,则将1存入dat    

                else     

                dat|=0x00;//如果读到的数据是0,则将0存入dat        //将单片机检测到的电平信号DQ存入r[i]       

                delay_b20(60);         ;              //延时3us,两个读时序之间必须有大于1us的恢复期      

         }                        

        return(dat);    //返回读出的十六进制数据 

}

void WriteOneChar(uchar dat) 

{  

        uchar i=0;  

        for (i=0; i<8; i++)    

        {     

                DQ =1;         // 先将数据线拉高     

                delay_b20(1);      //等待一个机器周期      

                 DQ=0;          //将数据线从高拉低时即启动写时序           

                 DQ=dat&0x01;   //利用与运算取出要写的某位二进制数据,      

                  //并将其送到数据线上等待DS18B20采样     

                delay_b20(60);         ;

//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样     

                DQ=1;          //释放数据线           

                delay_b20(60);

                dat>>=1;       //将dat中的各二进制位数据右移1位    

        }    

        delay_b20(1);

}

void ReadyReadTemp(void) 

{        

        Init_DS18B20();     //将DS18B20初始化   

        WriteOneChar(0xCC); // 跳过读序号列号的操作  

         WriteOneChar(0x44); // 启动温度转换          

         delay_b20(200); //转换一次需要延时一段时间      

        Init_DS18B20();     //将DS18B20初始化   

        WriteOneChar(0xCC); //跳过读序号列号的操作   

        WriteOneChar(0xBE); //读取温度寄存器,前两个分别是温度的低位和高位  



void wendu()

{

        uchar TL,TH;

        TL=ReadOneChar();

        TH=ReadOneChar();

        tm[0]=TH;

        tm[1]=TL;

}

uchar doe[4];

uint wendu_duzhuanhuan()

{

        uint a,b,t;

        Init_DS18B20();     //将DS18B20初始化   

        WriteOneChar(0xCC); // 跳过读序号列号的操作  

         WriteOneChar(0x44); // 启动温度转换          

         delay_b20(200); //转换一次需要延时一段时间      

        Init_DS18B20();     //将DS18B20初始化   

        WriteOneChar(0xCC); //跳过读序号列号的操作   

        WriteOneChar(0xBE); //读取温度寄存器,前两个?

        a=ReadOneChar();

        b=ReadOneChar();

        t=b;

        t<<=8;

        t=t|a;

        t=t*0.6250+0.5;

        return t;

}

void display()

{

        uint tp;

        tp=wendu_duzhuanhuan();

        doe[0]=tp/1000+0x30;

        doe[1]=tp%1000/100+0x30;

        doe[2]=tp%100/10+0x30;

        doe[3]=tp%10+0x30;

         WriteInstruction(0x80+0x46);

         WriteData(doe[0]);

        WriteInstruction(0x80+0x47);

         WriteData(doe[1]);

        WriteInstruction(0x80+0x48);

         WriteData(doe[2]);

        WriteInstruction(0x80+0x49);

         WriteData('.');

        WriteInstruction(0x80+0x4a);

         WriteData(doe[3]);

}

void main(void) 

{  

        uchar xx;  

        init_io(); //NRF24L01初始化

        LcdInitiate() ;//LCD初始化        

        yejinchu() ;//显示字符

        led=1;    

        while(1)  

        { 

                                     

                TX_Mode();//必须启动发送模块 

                while(Check_Ack());

                led=0;

                delay_ms(200);

                led=1;

                ReadyReadTemp();//温度转换

                wendu();//读取温度值

        //        if(key==0)

        //        {

        //                delay_ms(15);

        //                if(key==0)

        //                {

                                 

                                checkflag(); //判断接收成功 

                        

                                for(xx=0;xx<2;xx++)   

                                {   //发数据之前必须把要发送的数据装入它           

                                        tx_buf[xx]=tm[xx];

                                } 

                                

        //                } 

        //                while(!key);

        //        }

                SPI_RW_Reg(WRITE_REG+STATUS,0XFF);

                TX_Mode();//必须启动发送模块     

                

                delay_ms(1500); 

                display();//本地显示温度

         } 

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: