最近做了一個用USB無線串口模塊,串口轉NRF24L01 數傳通信,通過DS18B20采集外界溫度,并通過傳口助手顯示采集的溫度用到的模塊用到的器材
USB無線串口模塊,串口轉NRF24L01 數傳通信
溫度采集模塊,DS18B20
2塊NRF24L01
51單片機
軟件:串口助手
USB無線串口模塊,串口轉NRF24L01 數傳通信.jpg (154.46 KB, 下載次數: 50)
下載附件
2020-11-18 04:57 上傳
DS18B20.jpg (140.86 KB, 下載次數: 52)
下載附件
2020-11-18 04:57 上傳
測試結果.PNG (156.5 KB, 下載次數: 54)
下載附件
2020-11-18 04:57 上傳
具體程序如下
- #include<reg51.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /********** NRF24L01寄存器操作命令 ***********/
- #define READ_REG 0x00 //讀配置寄存器,低5位為寄存器地址
- #define WRITE_REG 0x20 //寫配置寄存器,低5位為寄存器地址
- #define RD_RX_PLOAD 0x61 //讀RX有效數據,1~32字節
- #define WR_TX_PLOAD 0xA0 //寫TX有效數據,1~32字節
- #define FLUSH_TX 0xE1 //清除TX FIFO寄存器.發射模式下用
- #define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用
- #define REUSE_TX_PL 0xE3 //重新使用上一包數據,CE為高,數據包被不斷發送.
- #define NOP 0xFF //空操作,可以用來讀狀態寄存器
- /********** NRF24L01寄存器地址 *************/
- #define CONFIG 0x00 //配置寄存器地址
- #define EN_AA 0x01 //使能自動應答功能
- #define EN_RXADDR 0x02 //接收地址允許
- #define SETUP_AW 0x03 //設置地址寬度(所有數據通道)
- #define SETUP_RETR 0x04 //建立自動重發
- #define RF_CH 0x05 //RF通道
- #define RF_SETUP 0x06 //RF寄存器
- #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有效數據寬度(1~32字節)
- #define RX_PW_P1 0x12 // 接收數據通道1有效數據寬度(1~32字節)
- #define RX_PW_P2 0x13 // 接收數據通道2有效數據寬度(1~32字節)
- #define RX_PW_P3 0x14 // 接收數據通道3有效數據寬度(1~32字節)
- #define RX_PW_P4 0x15 // 接收數據通道4有效數據寬度(1~32字節)
- #define RX_PW_P5 0x16 // 接收數據通道5有效數據寬度(1~32字節)
- #define FIFO_STATUS 0x17 // FIFO狀態寄存器
- /*————————————————————————————————————————————————————————————————————*/
- /****** STATUS寄存器bit位定義 *******/
- #define MAX_TX 0x10 //達到最大發送次數中斷
- #define TX_OK 0x20 //TX發送完成中斷
- #define RX_OK 0x40 //接收到數據中斷
- /*——————————————————————————————————————————————————*/
- /********* 24L01發送接收數據寬度定義 ***********/
- #define TX_ADR_WIDTH 5 //5字節地址寬度
- #define RX_ADR_WIDTH 5 //5字節地址寬度
- #define TX_PLOAD_WIDTH 32 //32字節有效數據寬度
- #define RX_PLOAD_WIDTH 32 //32字節有效數據寬度
- const uchar TX_ADDRESS[TX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //發送地址
- const uchar RX_ADDRESS[RX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //發送地址
- sbit NRF_CE = P0^7;
- sbit NRF_CSN = P0^6;
- sbit NRF_MISO = P0^3;
- sbit NRF_MOSI = P0^4;
- sbit NRF_SCK = P0^5;
- sbit NRF_IRQ = P0^2;
- sbit LED=P1^0;
- sbit DQ=P3^7; //ds18b20 與單片機連接口
- //sbit S1=P3^0;
- //sbit S2=P3^1;
- //sbit S3=P3^2;
- uchar rece_buf[32];
- uchar data disdata[6];// 百、十、個、小數位1、小數位2、 小數位3、
- uint tvalue; // 溫度值
- uchar tflag; // 溫度正負標志
- void delay_us(uchar num)
- {
- uchar i;
- for(i=0;i>num;i++)
- _nop_();
- }
- void delay_150us()
- {
- uint i;
- for(i=0;i>150;i++);
- }
- void delay(uint t)
- {
- uchar k;
- while(t--)
- for(k=0;k<200;k++);
- }
- /***************************************************************/
- /*******************************************************************/
- uchar SPI_RW(uchar byte)
- {
- uchar bit_ctr;
- for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 輸出8位
- {
- NRF_MOSI=(byte&0x80); // MSB TO MOSI
- byte=(byte<<1); // shift next bit to MSB
- NRF_SCK=1;
- byte|=NRF_MISO; // capture current MISO bit
- NRF_SCK=0;
- }
- return byte;
- }
- /*********************************************/
- /* 函數功能:給24L01的寄存器寫值(一個字節) */
- /* 入口參數:reg 要寫的寄存器地址 */
- /* value 給寄存器寫的值 */
- /* 出口參數:status 狀態值 */
- /*********************************************/
- uchar NRF24L01_Write_Reg(uchar reg,uchar value)
- {
- uchar status;
- NRF_CSN=0; //CSN=0;
- status = SPI_RW(reg); //發送寄存器地址,并讀取狀態值
- SPI_RW(value);
- NRF_CSN=1; //CSN=1;
- return status;
- }
- /*************************************************/
- /* 函數功能:讀24L01的寄存器值 (一個字節) */
- /* 入口參數:reg 要讀的寄存器地址 */
- /* 出口參數:value 讀出寄存器的值 */
- /*************************************************/
- uchar NRF24L01_Read_Reg(uchar reg)
- {
- uchar value;
- NRF_CSN=0; //CSN=0;
- SPI_RW(reg); //發送寄存器值(位置),并讀取狀態值
- value = SPI_RW(NOP);
- NRF_CSN=1; //CSN=1;
- return value;
- }
- /*********************************************/
- /* 函數功能:讀24L01的寄存器值(多個字節) */
- /* 入口參數:reg 寄存器地址 */
- /* *pBuf 讀出寄存器值的存放數組 */
- /* len 數組字節長度 */
- /* 出口參數:status 狀態值 */
- /*********************************************/
- uchar NRF24L01_Read_Buf(uchar reg,uchar *pBuf,uchar len)
- {
- uchar status,u8_ctr;
- NRF_CSN=0; //CSN=0
- status=SPI_RW(reg); //發送寄存器地址,并讀取狀態值
- for(u8_ctr=0;u8_ctr<len;u8_ctr++)
- pBuf[u8_ctr]=SPI_RW(0XFF); //讀出數據
- NRF_CSN=1; //CSN=1
- return status; //返回讀到的狀態值
- }
- /**********************************************/
- /* 函數功能:給24L01的寄存器寫值(多個字節) */
- /* 入口參數:reg 要寫的寄存器地址 */
- /* *pBuf 值的存放數組 */
- /* len 數組字節長度 */
- /**********************************************/
- uchar NRF24L01_Write_Buf(uchar reg, uchar *pBuf, uchar len)
- {
- uchar status,u8_ctr;
- NRF_CSN=0;
- status = SPI_RW(reg); //發送寄存器值(位置),并讀取狀態值
- for(u8_ctr=0; u8_ctr<len; u8_ctr++)
- SPI_RW(*pBuf++); //寫入數據
- NRF_CSN=1;
- return status; //返回讀到的狀態值
- }
- /*********************************************/
- /* 函數功能:24L01接收數據 */
- /* 入口參數:rxbuf 接收數據數組 */
- /* 返回值: 0 成功收到數據 */
- /* 1 沒有收到數據 */
- /*********************************************/
- uchar NRF24L01_RxPacket(uchar *rxbuf)
- {
- uchar state;
-
- state=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值
- NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標志
- if(state&RX_OK) //接收到數據
- {
- NRF_CE = 0;
- NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據
- NRF24L01_Write_Reg(FLUSH_RX,0xff); //清除RX FIFO寄存器
- NRF_CE = 1;
- delay_150us();
- return 0;
- }
- return 1;//沒收到任何數據
- }
- /**********************************************/
- /* 函數功能:設置24L01為發送模式 */
- /* 入口參數:txbuf 發送數據數組 */
- /* 返回值; 0x10 達到最大重發次數,發送失敗*/
- /* 0x20 成功發送完成 */
- /* 0xff 發送失敗 */
- /**********************************************/
- uchar NRF24L01_TxPacket(uchar *txbuf)
- {
- uchar state;
-
- NRF_CE=0; //CE拉低,使能24L01配置
- NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); //寫數據到TX BUF 32個字節
- NRF_CE=1; //CE置高,使能發送
- while(NRF_IRQ==1); //等待發送完成
- state=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值
- NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標志
- if(state&MAX_TX) //達到最大重發次數
- {
- NRF24L01_Write_Reg(FLUSH_TX,0xff); //清除TX FIFO寄存器
- return MAX_TX;
- }
- if(state&TX_OK) //發送完成
- {
- return TX_OK;
- }
- return 0xff; //發送失敗
- }
- /********************************************/
- /* 函數功能:檢測24L01是否存在 */
- /* 返回值; 0 存在 */
- /* 1 不存在 */
- /********************************************/
- uchar NRF24L01_Check(void)
- {
- uchar check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
- uchar check_out_buf[5]={0x00};
- NRF_SCK=0;
- NRF_CSN=1;
- NRF_CE=0;
- NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);
- NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);
- if((check_out_buf[0] == 0x11)&&\
- (check_out_buf[1] == 0x22)&&\
- (check_out_buf[2] == 0x33)&&\
- (check_out_buf[3] == 0x44)&&\
- (check_out_buf[4] == 0x55))return 0;
- else return 1;
- }
- void NRF24L01_RT_Init(void)
- {
- NRF_CE=0;
- NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度
- NRF24L01_Write_Reg(FLUSH_RX,0xff); //清除RX FIFO寄存器
- NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(uchar*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址
- NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADR_WIDTH); //設置TX節點地址,主要為了使能ACK
- NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01); //使能通道0的自動應答
- NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
- NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次
- NRF24L01_Write_Reg(WRITE_REG+RF_CH,0); //設置RF通道為2.400GHz 頻率=2.4+0GHz
- NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0F); //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟
- NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f); //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
- NRF_CE=1; //CE置高,使能發送
- }
- void SEND_BUF(uchar *buf)
- {
- NRF_CE=0;
- NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e);
- NRF_CE=1;
- delay_us(15);
- NRF24L01_TxPacket(buf);
- NRF_CE=0;
- NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f);
- NRF_CE=1;
- }
- /******************************ds18b20 程序 ******************************************************************/
- void delay_18b20(uint i) // 延時 1 微秒
- {
- while(i--);
- }
- void ds18b20rst() //ds18b20 初始化子函數
- // 要求"數據線拉高 - 延時 - 數據線拉低 - 延時大于 480 微妙 -數據線拉高 - 延時等待 "
- {
- uchar x=0;
- DQ = 1; // 信號線 DQ復位
- delay_18b20(4); // 延時
- DQ = 0; //DQ 拉低
- delay_18b20(100); // 精確延時大于 480us
- DQ = 1; // 拉高
- delay_18b20(40);
- }
- void ds18b20wr(uchar wdata) /* 寫數據子函數 , 無返回值,含參數 */
- {
- uchar i=0;
- for (i=8; i>0; i--)// 要寫完一個字節,故需要重復 8 次以下操作
- {
- DQ = 0; // 數據線拉低
- DQ = wdata&0x01;//wdata 是一個形參,將其與 0000 0001 進行按位與
- // 按從低到高的順序發送數據(一次發送一位 )
- delay_18b20(10);
- DQ = 1; // 最后將數據線拉高
- wdata>>=1; // 將 wdata 右移 1 位
- }
- }
- uchar ds18b20rd() // 讀數據子函數 , 是有返回值 dat
- {
- uchar i=0;
- uchar dat = 0;
- for (i=8;i>0;i--)// 要讀完一個字節,故需要重復 8 次以下操作
- {
- DQ = 0; // 給脈沖信號
- dat>>=1;
- DQ = 1; // 給脈沖信號
- if(DQ)
- dat|=0x80;
- delay_18b20(10);
- }
- return(dat); // 返回 dat
- }
- read_temp() // 讀取溫度值并轉換的子函數,有返回值溫度值 tvalue
- {
- uchar a,b;
- ds18b20rst(); // 調用 ds18b20 初始化子函數
- ds18b20wr(0xcc);// 調用寫數據子函數,向 ds18b20 寫命令 0xcc
- //ccH 表示跳過 ROM讀序列號,適用于單機工作,直接向 18b20 發送溫度變換命令
- ds18b20wr(0x44);// 調用寫數據子函數,向 ds18b20 寫命令 0x44
- //44H 表示啟動 ds18b20 溫度轉換 , 結果自行存入 9 字節的 RAM中
- ds18b20rst(); // 調用 ds18b20 初始化子函數
- ds18b20wr(0xcc);// 同上
- ds18b20wr(0xbe);// 調用寫數據子函數,向 ds18b20 寫命令 0xbe
- //beH 表示讀取 RAM中 9 字節的溫度數據
- a=ds18b20rd(); // 調用讀數據子函數,并將所得數據給 a
- b=ds18b20rd(); //
- tvalue=b; // 把 b 的值給 tvalue
- tvalue<<=8; //tvalue 左移 8 位
- tvalue=tvalue|a;//tvalue 與 a 進行按位或
- if(tvalue<0x0fff)//
- tflag=0; // 前五位為 0 時,讀取的溫度為正,標志位為 0,此時只要
- // 將測得數值乘以 0.0625 即可得到實際溫度
- else // 前五位為 1 時,讀取的溫度為負,標志位為 1,此時需要
- { // 將測得數值取反后再加 1,再乘以 0.0625 即可得到實際溫度
- tvalue=~tvalue+1;
- tflag=1; // 此時表示負溫度
- }
- tvalue=tvalue*(0.625);// 溫度值擴大 10 倍,精確到 1 位小數
- return(tvalue); // 返回溫度值
- }
- /**********************************************/
- void main()
- {uchar flagdat;
- while(NRF24L01_Check()); // 等待檢測到NRF24L01,程序才會向下執行
- NRF24L01_RT_Init();
- while(1)
- {
- if(NRF_IRQ==0) // 如果無線模塊接收到數據
- {
- if(NRF24L01_RxPacket(rece_buf)==0)
- {
- if( rece_buf[1]=='1') //第1位以后是收到的命令數據,rece_buf[0]是數據位數長度
- LED=0;
- if( rece_buf[1]=='2') //第1位以后是收到的命令數據,rece_buf[0]是數據位數長度
- LED=1;
- }
- }
- read_temp(); // 調用 ds18b20 讀取溫度
-
- rece_buf[1]='T';
- rece_buf[2]='=';
-
- rece_buf[3]='+'; // 百位數;
- rece_buf[4]=tvalue%1000/100+0x30;// 十位數;
- rece_buf[5]=tvalue%100/10+0x30; // 個位數;
- rece_buf[6] ='.';
- rece_buf[7] =tvalue%10+0x30; // 小數位
- rece_buf[8]='C';
- rece_buf[9]=0x0d;
- rece_buf[10]=0x0a;//串口助手換行
- rece_buf[0]=10; //一共要發送10個字節,rece_buf[0]必須是10!!!!!!
- SEND_BUF(rece_buf);
-
- delay(1000);
- }
- }
復制代碼
全部資料51hei下載地址:
DS18B20采集溫度,并通過串口助手顯示采集的溫度.zip
(43.69 KB, 下載次數: 49)
2020-11-17 19:15 上傳
點擊文件名下載附件
工程 下載積分: 黑幣 -5
圖片.zip
(4.84 MB, 下載次數: 25)
2020-11-17 19:15 上傳
點擊文件名下載附件
測試結果 下載積分: 黑幣 -5
|