| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2012 人关注过本帖
标题:用C语言编写 DS18B20与NRF24L01的程序,用于无线传输体温计获取的数据
只看楼主 加入收藏
小章_1
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2012-3-19
结帖率:0
收藏
已结贴  问题点数:20 回复次数:1 
用C语言编写 DS18B20与NRF24L01的程序,用于无线传输体温计获取的数据
#include <reg52.h>
#include <stdio.h>
#include <Allhead.h>
#define uint unsigned int
#define uchar unsigned char

sbit DQ=P1^6;  //数据端
sbit CE=P1^5;  //RX/TX模式选择端
sbit IRQ=P1^2; //可屏蔽中断端
sbit CSN=P1^7; //SPI片选端//就是SS
sbit MOSI=P3^7;    //SPI主机输出从机输入端
sbit MISO=P1^3;    //SPI主机输出从机输出端
sbit SCK=P1^4;    //SPI时钟端

#define TX_ADDR_WIDTH    5    // 5 uints TX address width
#define RX_ADDR_WIDTH    5    // 5 uints RX address width
#define TX_DATA_WIDTH    16   // 16 uints TX data width
#define RX_DATA_WIDTH    16   // 16 uints RX data width

uchar TX_ADDRESS[TX_ADDR_WIDTH]= {0x34,0x43,0x10,0x10,0x07}; //发送地址0x34,0x43,0x10,0x10,0x07

/*****************状态标志*****************************************/
uchar bdata sta;   //状态标志
sbit RX_DR=sta^6;  //接收数据中断
sbit TX_DS=sta^5;  //数据发送完成中断
sbit MAX_RT=sta^4; //达到最多次重发中断

/***************************延时函数****************/
void Delay(uint t)
{
  uint x,y;
  for(x=t;x>0;x--)
   for(y=110;y>0;y--);
}
/**********************************************
   DS18B20专用延时子函数
**********************************************/
void DDelay(uint t)
{
    uint n;
    n=0;
    while(n<t)
    {
      n++;
    }
}

void Init_Com(void)//串口初始化函数
{
     TMOD=0x20;      //设置定时器1为工作方式2(0010 0000),工作方式2为8位初值自动重装的8位定时器/计数器
     PCON=0x00;      //电源管理寄存器PCON处于正常工作状态,波特率正常
     SCON=0x50;      //串行口控制寄存器SCON处于工作方式1,10位异步收发(8位数据),允许串行口接收数据
     TH1=0xFd;      //波特率为9600
     TL1=0xFd;
     EA=1;
     ES=1;
     TR1=1;         //启动定时器1
}


/*********************************************************
    DS18B20复位函数
**********************************************************/
void Reset()
{   
    DQ=1;
    DDelay(8);
    DQ=0;
    DDelay(85);
    DQ=1;
    DDelay(14);

}     

/****************************************************
     DS18B20读一个字节函数
****************************************************/
uint ReadChar()
{            
    uchar i,dat=0;
    for (i=8;i>0;i--)
    {
        DQ=1;
        DDelay(1);
        DQ=0;  
        dat>>=1;
        DQ=1;
        if(DQ)
        dat=dat|0x80;
        DDelay(4);
     }
return(dat);
}

/***********************************************************
    DS18B20写一个字节函数
*********************************************************/
void WriteChar(uchar dat)
{
      uint i;
      for(i=8;i>0;i--)
      {
        DQ=0;   
        DQ=dat&0x01;
        DDelay(5);
        DQ=1;
        dat>>=1;
       }
     DDelay(4);
}


/***************************************************
    DS18B20读温度程序
****************************************************/
uint ReadTemperature()
{
  uint temperature,tempL,tempH;
    Reset();
    WriteChar(0xcc);        //写跳过读ROM指令
    WriteChar(0x44);        //写温度转换指令
    DDelay(125);
    Reset();
    WriteChar(0xcc);
    WriteChar(0xbe);      //读取寄存器中存储的温度数据
    tempL=ReadChar();  //读低8位
    tempH=ReadChar();  //读高8位
    temperature=((tempH*256)+tempL)*0.0625*10;      //温度在寄存器中为12位,分辨率为0.0625,乘以10表示小数点后面只取1位
    DDelay(200);
    return(temperature); //返回的是0123格式
}

/**********************NRF24L01初始化函数*******************************/
void NRF24L01_Init(void)
{
    Delay(2);//让系统什么都不干
    CE=0; //待机模式1   
    CSN=1;  
    SCK=0;
    IRQ=1;     
}

/*****************SPI时序函数******************************************/
uchar NRF24L01_SPI(uchar date)
{
    uchar i;
       for(i=0;i<8;i++)          // 循环8次
       {
      if(date&0x80)
        MOSI=1;
      else
        MOSI=0;   // byte最高位输出到MOSI
         date<<=1;             // 低一位移位到最高位
         SCK=1;
      if(MISO)               // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据
           date|=0x01;           // 读MISO到byte最低位
         SCK=0;                // SCK置低
       }
    return(date);               // 返回读出的一字节
}

/*****************SPI写寄存器一字节函数*********************************/
uchar NRFWriteReg(uchar RegAddr,uchar date)
{
   uchar BackDate;
   CSN=0;//启动时序
   BackDate=NRF24L01_SPI(RegAddr);//写入地址
   NRF24L01_SPI(date);//写入值
   CSN=1;
   return(BackDate);
}


/*****************SPI读寄存器一字节函数*********************************/
uchar NRFReadReg(uchar RegAddr)
{
   uchar BackDate;
   CSN=0;//启动时序
   NRF24L01_SPI(RegAddr);//写寄存器地址
   BackDate=NRF24L01_SPI(0x00);//写入读寄存器指令  
   CSN=1;
   return(BackDate); //返回状态
}


/*****************SPI读取RXFIFO寄存器的值********************************/
uchar NRFReadRxDate(uchar RegAddr,uchar *RxDate,uchar DateLen)
{  //寄存器地址//读取数据存放变量//读取数据长度//用于接收
    uchar BackDate,i;
    CSN=0;//启动时序
    BackDate=NRF24L01_SPI(RegAddr);//写入要读取的寄存器地址
    for(i=0;i<DateLen;i++) //读取数据
      {
         RxDate[i]=NRF24L01_SPI(0);
      }
    CSN=1;
   return(BackDate);
}
/*****************SPI写入TXFIFO寄存器的值**********************************/
uchar NRFWriteTxDate(uchar RegAddr,uchar *TxDate,uchar DateLen)
{ //寄存器地址//写入数据存放变量//读取数据长度//用于发送
   uchar BackDate,i;
   CSN=0;
   BackDate=NRF24L01_SPI(RegAddr);//写入要写入寄存器的地址
   for(i=0;i<DateLen;i++)//写入数据
     {
        NRF24L01_SPI(*TxDate++);
     }   
   CSN=1;
   return(BackDate);
}
/*****************NRF设置为发送模式并发送数据******************************/
void NRFSetTxMode(uchar *TxDate)
{//发送模式
    CE=0;
   NRFWriteTxDate(W_REGISTER+TX_ADDR,TX_ADDRESS,TX_ADDR_WIDTH);//写寄存器指令+接收地址使能指令+接收地址+地址宽度
     NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TX_ADDRESS,TX_ADDR_WIDTH);//为了应答接收设备,接收通道0地址和发送地址相同
    NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WIDTH);//写入数据
    /******下面有关寄存器配置**************/
      NRFWriteReg(W_REGISTER+EN_AA,0x01);       // 使能接收通道0自动应答
      NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);   // 使能接收通道0
      NRFWriteReg(W_REGISTER+SETUP_RETR,0x0a);  // 自动重发延时等待250us+86us,自动重发10次
      NRFWriteReg(W_REGISTER+RF_CH,0x40);         // 选择射频通道0x40
      NRFWriteReg(W_REGISTER+RF_SETUP,0x07);    // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
    NRFWriteReg(W_REGISTER+CONFIG,0x0e);      // CRC使能,16位CRC校验,上电  
    CE=1;
    Delay(5);//保持10us秒以上
}
/*****************NRF设置为接收模式并接收数据******************************/
//主要接收模式
void NRFSetRXMode()
{
    CE=0;  
      NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TX_ADDRESS,TX_ADDR_WIDTH);  // 接收设备接收通道0使用和发送设备相同的发送地址
      NRFWriteReg(W_REGISTER+EN_AA,0x01);               // 使能接收通道0自动应答
      NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);           // 使能接收通道0
      NRFWriteReg(W_REGISTER+RF_CH,0x40);                 // 选择射频通道0x40
      NRFWriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WIDTH);  // 接收通道0选择和发送通道相同有效数据宽度
      NRFWriteReg(W_REGISTER+RF_SETUP,0x07);            // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益*/
      NRFWriteReg(W_REGISTER+CONFIG,0x0f);              // CRC使能,16位CRC校验,上电,接收模式
      CE = 1;
    Delay(5);//保持10us秒以上     
}
/****************************检测应答信号******************************/
uchar CheckACK()
{  //用于发射
    sta=NRFReadReg(R_REGISTER+FIFO_STATUS);                    // 返回状态寄存器
    if(TX_DS||MAX_RT) //发送完毕中断
    {
       NRFWriteReg(W_REGISTER+FIFO_STATUS,0xff);  // 清除TX_DS或MAX_RT中断标志
       CSN=0;
       NRF24L01_SPI(FLUSH_TX);//用于清空FIFO !!关键!!不然会出现意想不到的后果!!!大家记住!!  
       CSN=1;
       return(0);
    }
    else
       return(1);
}
/******************判断是否接收收到数据,接到就从RX取出*********************/
//用于接收模式
uchar NRFRevDate(uchar *RevDate)
{
        uchar RevFlags=0;
     sta=NRFReadReg(R_REGISTER+FIFO_STATUS);//发送数据后读取状态寄存器
     if(RX_DR)                // 判断是否接收到数据
     {
        CE=0;             //SPI使能
        NRFReadRxDate(R_RX_PAYLOAD,RevDate,RX_DATA_WIDTH);// 从RXFIFO读取数据
        RevFlags=1;       //读取数据完成标志
      }
     NRFWriteReg(W_REGISTER+FIFO_STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清除中断标
     return(RevFlags);
}

void main()
{
         uint temperature,ReadTempDate;
             uchar TxDate[4];
         Init_Com();
         NRF24L01_Init();
         temperature=ReadTemperature();
         ReadTempDate=temperature;
         TxDate[0]=ReadTempDate/100+'0';
         TxDate[1]=ReadTempDate%100/10+'0';
         TxDate[2]='.';
         TxDate[3]=ReadTempDate%100%10+'0';   
         NRFSetTxMode(TxDate);//发送温度
         /*SBUF=0xfd;
         while(!TI);
         TI=0;
         while(1)
         {
            SBUF=temperature;
                while(!TI);
                TI=0;
                Delay(4000);
        }*/
        while(CheckACK());    //检测是否发送完毕
}         

我想问一下,我想把这个数据用串口显示出来,主程序部分应该要怎么编程,我不知道哪里错了,总是无法显示,有哪位高手可以帮忙,可以的话,请指点一下!谢谢
搜索更多相关主题的帖子: C语言 include address 数据 
2012-03-19 14:41
zaixuexi
Rank: 12Rank: 12Rank: 12
来 自:上海
等 级:火箭侠
威 望:8
帖 子:858
专家分:3233
注 册:2010-12-1
收藏
得分:20 
示波器先抓下波形了,TX,RX都有,再调,还有,你线连的对伐?TX->RX,RX<-TX

技术问题,请不要以短消息方式提问
2012-03-19 21:14
快速回复:用C语言编写 DS18B20与NRF24L01的程序,用于无线传输体温计获取的数据
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.027687 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved