STM32
直播中

凌章致

7年用户 875经验值
私信 关注
[问答]

如何利用89C51和STM32F1实现2.4G无线射频智能家居?

如何利用89C51和STM32F1实现2.4G无线射频智能家居?

回帖(1)

李葛葛

2021-12-20 11:02:57
  前段时间学51单片机的时候做了一个简单的智能家居,实现了三个传感器采集数据,于OLED显示。当时并没有深入的去研究,仅仅是51采集数据显示:单片机==简易智能家居OLED。这次扩展了一下这个项目。


项目需求:
  采集房间的温度、湿度、光照、烟雾等信息,51采集完数据在OLED上显示,采用2.4G射频模块NRF24L01,将51采集的数据发送给STM32,STM32接收完数据在TFT屏中显示一下。当温度、湿度、烟雾过高时,启动蜂鸣器报警电路。


项目过程:
  首先这个项目已经在普中开发板上运行过了,详细信息请到前文博客查看::单片机==简易智能家居OLED
  第一步,制作单片机电路原理图和PCB图:
原理图:




















PCB图:








绘制原理图和PCB图是最基础的一步,PCB绘制成功后便开始了PCB板子的制作。本项目采用的是单层板,首先将PCB图用激光打印机打印至热转印纸上,然后将热转印纸和单层铜板贴合,放至热转印机中来回5-6次,取出撕掉热转印纸,将铜板放至腐蚀液中半小时左右,取出,打孔。PCB板便做成功了。
注意:在制作PCB板时,一开始没有采用镜像打印,导致了后期电路不好焊,又重新做了一个。打印时一点要添加镜像。


总结:此次PCB图绘制时没有考虑到布局的影响,导致了最终很多器件挤在一起,这是本次的一个大失误。


成品:
















 
51制作完毕后,限于实验条件的影响,STM32的PCB板子不好制作,所以STM32直接在淘宝上买了一个最小系统板使用。


  STM32移植了UCOS-III系统,使用TFT屏显示无线接收的数据,按照原计划我本来是想移植STEMWin的GUI来显示,奈何买的STM32最小系统板没有带外部SRAM,所以导致GUI的空间分配不够,最终无奈放弃了。


  这里我就分享一下24L01的收发代码吧,其他传感器的程序在上次的博客中说过,就不在讲了。




/********************STC89C51发送数据****************************/
#ifndef _24L01_H_
#define _24L01_H_

***it  MISO = P1^3;
***it  MOSI = P1 ^ 4;
***it  SCLK1  = P1^5;
***it  CE   = P1^7;
***it  CSN  = P1^6;

unsigned char code RxAddr[]={'m','n','m','n','i'};
unsigned char code TxAddr[]={'m','n','m','n','i'};

unsigned char bdata sta;   

***it RX_DR=sta^6;
***it TX_DS=sta^5;
***it MAX_RT=sta^4;
#define TX_ADDR_WITDH 5       
#define RX_ADDR_WITDH 5
#define TX_DATA_WITDH 32
#define RX_DATA_WITDH 32
#define  R_REGISTER      0x00
#define  W_REGISTER      0x20
#define  R_RX_PAYLOAD          0x61
#define  W_TX_PAYLOAD         0xa0
#define  FLUSH_TX                 0xe1
#define  FLUSH_RX                 0xe2
#define  REUSE_TX_PL     0xe3
#define  NOP             0xff
#define  CONFIG          0x00
#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
#define  RX_ADDR_P1      0x0b
#define  RX_ADDR_P2      0x0c
#define  RX_ADDR_P3      0x0d
#define  RX_ADDR_P4      0x0e
#define  RX_ADDR_P5      0x0f
#define  TX_ADDR         0x10
#define  RX_PW_P0        0x11
#define  RX_PW_P1        0x12
#define  RX_PW_P2        0x13
#define  RX_PW_P3        0x14
#define  RX_PW_P4        0x15
#define  RX_PW_P5        0x16
#define  FIFO_STATUS     0x17

/**************************************************
函数:NRFSPI()
描述:
    根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01
        读出一字节
/**************************************************/
unsigned char NRFSPI(unsigned char date)
{
    unsigned char i;
           for(i=0;i<8;i++)         
           {
          if(date&0x80)
            MOSI=1;
          else
            MOSI=0;   
             date<<=1;            
             SCLK1=1;
          if(MISO)               
               date|=0x01;              
             SCLK1=0;                   
           }
    return(date);           
}

/**************************************************
函数:NRFReadReg()
描述:
    从reg寄存器读一字节
/**************************************************/
unsigned char NRFReadReg(unsigned char RegAddr)
{
   unsigned char BackDate;
   CSN=0;
   NRFSPI(RegAddr);
   BackDate=NRFSPI(0x00);
   CSN=1;
   return(BackDate);
}

/**************************************************
函数:NRFWriteReg()
描述:
    写数据value到reg寄存器
/**************************************************/
unsigned char NRFWriteReg(unsigned char RegAddr,unsigned char date)
{
   unsigned char BackDate;
   CSN=0;
   BackDate=NRFSPI(RegAddr);
   NRFSPI(date);
   CSN=1;
   return(BackDate);
}

/**************************************************
函数:NRFWriteTxDate()
描述:
    把pBuf缓存中的数据写入到nRF24L01,通常用来写入发
        射通道数据或接收/发送地址
/**************************************************/
unsigned char NRFWriteTxDate(unsigned char RegAddr,unsigned char *TxDate,unsigned char DateLen)
{
   unsigned char BackDate,i;
   CSN=0;
   BackDate=NRFSPI(RegAddr);
   for(i=0;i      {
            NRFSPI(*TxDate++);
         }   
   CSN=1;
   return(BackDate);
}

/**************************************************
函数:NRFReadRxDate()
描述:
    从reg寄存器读出bytes个字节,通常用来读取接收通道
        数据或接收/发送地址
/**************************************************/
unsigned char NRFReadRxDate(unsigned char RegAddr,unsigned char *RxDate,unsigned char DateLen)
{
    unsigned char BackDate,i;
        CSN=0;
        BackDate=NRFSPI(RegAddr);
        for(i=0;i           {
             RxDate=NRFSPI(0);
          }
    CSN=1;
   return(BackDate);
}

/**************************************************
函数: NRF24L01Int()
描述:
    初始化IO
/**************************************************/
void NRF24L01Int()
{
        CE=0;   
        CSN=1;  
        SCLK1=0;
        delay_ms(2);
}

/**************************************************
函数:NRFSetTxMode()
描述:
    这个函数设置nRF24L01为发送模式,(CE=1持续至少10us),
        130us后启动发射,数据发送结束后,发送模块自动转入接收
        模式等待应答信号。
/**************************************************/
void NRFSetTxMode()
{
        CE=0;
    NRFWriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_ADDR_WITDH);
        NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);
        NRFWriteReg(W_REGISTER+EN_AA,0x01);
        NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);
        NRFWriteReg(W_REGISTER+SETUP_RETR,0x1a);
        NRFWriteReg(W_REGISTER+RF_CH,40);
        NRFWriteReg(W_REGISTER+RF_SETUP,0x0f);
        NRFWriteReg(W_REGISTER+CONFIG,0x0e);      
        CE=1;
        delay_ms(1);
}


unsigned char NRF_TxData(unsigned char *TxDate)
{
        unsigned char sta;
  CE=0;
  NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WITDH);
        CE=1;
        delay_ms(1);
        sta = NRFReadReg(STATUS);
        NRFWriteReg(W_REGISTER+STATUS,sta);
        if(sta&0x10)
        {
                NRFWriteReg(FLUSH_TX,0xff);
                return 1;
        }
        if(sta&0x20)
                return 0;
        else
            return 0xff;
}

/**************************************************
函数:NRFSetRXMode()
描述:
    这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包
/**************************************************/
void NRFSetRXMode()
{
  CE=0;
  NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);
        NRFWriteReg(W_REGISTER+EN_AA,0x01);
        NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);
        NRFWriteReg(W_REGISTER+RF_CH,40);
        NRFWriteReg(W_REGISTER+RX_PW_P0,RX_DATA_WITDH);
        NRFWriteReg(W_REGISTER+RF_SETUP,0x0f);
        NRFWriteReg(W_REGISTER+CONFIG,0x0f);      
        CE=1;
        delay_ms(0);
}

extern unsigned char ty;

void GetDate(unsigned char *rec_buf)                                 
{
    sta=NRFReadReg(R_REGISTER+STATUS);
          RX_DR=(sta&0x40);
          ty=RX_DR;
          NRFWriteReg(W_REGISTER+STATUS,sta);
    if(RX_DR)                               
    {
                        CE=0;
                        NRFReadRxDate(R_RX_PAYLOAD,rec_buf,RX_DATA_WITDH);
                        NRFWriteReg(FLUSH_RX,0xff);
                  CSN=0;
                  NRFSPI(FLUSH_RX);
                  CSN=1;               
                }                       
}
#endif


/**********************STM32F103ZET6接收数据******************************/
#ifndef _24L01_H_
#define _24L01_H_

#include  
#include "delay.h"
#define  MISOIN    GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)


#define  SCK_1     GPIO_SetBits(GPIOA,GPIO_Pin_5)
#define  SCK_0     GPIO_ResetBits(GPIOA,GPIO_Pin_5)

#define  MOSI_1    GPIO_SetBits(GPIOA,GPIO_Pin_7)
#define  MOSI_0    GPIO_ResetBits(GPIOA,GPIO_Pin_7)

#define  CSN_1     GPIO_SetBits(GPIOC,GPIO_Pin_4)
#define  CSN_0     GPIO_ResetBits(GPIOC,GPIO_Pin_4)

#define  CE_1      GPIO_SetBits(GPIOA,GPIO_Pin_4)
#define  CE_0      GPIO_ResetBits(GPIOA,GPIO_Pin_4)



unsigned char  RxAddr[]={'m','n','m','n','i'};
unsigned char  TxAddr[]={'m','n','m','n','i'};

unsigned char  sta;   

u8 RX_DR;
#define TX_DS  sta&(1<<5)
#define MAX_RT sta&(1<<4)

#define TX_ADDR_WITDH 5       
#define RX_ADDR_WITDH 5
#define TX_DATA_WITDH 32
#define RX_DATA_WITDH 32
#define  R_REGISTER      0x00
#define  W_REGISTER      0x20
#define  R_RX_PAYLOAD          0x61
#define  W_TX_PAYLOAD         0xa0
#define  FLUSH_TX                 0xe1
#define  FLUSH_RX                 0xe2
#define  REUSE_TX_PL     0xe3
#define  NOP             0xff
#define  CONFIG          0x00
#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
#define  RX_ADDR_P1      0x0b
#define  RX_ADDR_P2      0x0c
#define  RX_ADDR_P3      0x0d
#define  RX_ADDR_P4      0x0e
#define  RX_ADDR_P5      0x0f
#define  TX_ADDR         0x10
#define  RX_PW_P0        0x11
#define  RX_PW_P1        0x12
#define  RX_PW_P2        0x13
#define  RX_PW_P3        0x14
#define  RX_PW_P4        0x15
#define  RX_PW_P5        0x16
#define  FIFO_STATUS     0x17
void _NOP_()
{
        int i;
        i++;i--;
}
void NRF24L01Int(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7|GPIO_Pin_11;//ce  pb13   csn  pb12   sck   pb10    mosi  pb11   miso  pb9
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
       
        CE_0;   
        CSN_1;  
        SCK_0;
        delay_ms(2);
}
unsigned char NRFSPI(unsigned char date)
{
    unsigned char i;
           for(i=0;i<8;i++)         
           {
                        _NOP_();
                        if(date&0x80)
                                MOSI_1;
                        else
                                MOSI_0;                 
                                date<<=1;
      _NOP_();                       
                                SCK_1;
      _NOP_();                               
                        if(MISOIN)               
                                        date|=0x01;              
                                SCK_0;                 
           }
    return(date);           
}

unsigned char NRFReadReg(unsigned char RegAddr)
{
   unsigned char BackDate;
   CSN_0;
   NRFSPI(RegAddr);
   BackDate=NRFSPI(0x00);
   CSN_1;
   return(BackDate);
}

unsigned char NRFWriteReg(unsigned char RegAddr,unsigned char date)
{
   unsigned char BackDate;
   CSN_0;
   BackDate=NRFSPI(RegAddr);
   NRFSPI(date);
   CSN_1;
   return(BackDate);
}
unsigned char NRFWriteTxDate(unsigned char RegAddr,unsigned char *TxDate,unsigned char DateLen)
{
   unsigned char BackDate,i;
   CSN_0;
   BackDate=NRFSPI(RegAddr);
   for(i=0;i      {
            NRFSPI(*TxDate++);
         }   
   CSN_1;
   return(BackDate);
}
unsigned char NRFReadRxDate(unsigned char RegAddr,unsigned char *RxDate,unsigned char DateLen)
{  
  unsigned char BackDate,i;
  CSN_0;
  BackDate=NRFSPI(RegAddr);
  for(i=0;i   {
    RxDate=NRFSPI(0);
  }
   CSN_1;
   return(BackDate);
}
u8 NRFGetDate(unsigned char *rec_buf)                                 
{
        sta=NRFReadReg(R_REGISTER+STATUS);
        RX_DR=(sta&0x40);
        NRFWriteReg(W_REGISTER+STATUS,sta);
        delay_ms(100);
        if(RX_DR)                               
        {
                CE_0;
                NRFReadRxDate(R_RX_PAYLOAD,rec_buf,RX_DATA_WITDH);
                NRFWriteReg(FLUSH_RX,0xff);
                CSN_0;
                NRFSPI(FLUSH_RX);
                CSN_1;       
                return 1;       
         }
        return 0;
}
void NRFSetRXMode(void)
{
  CE_0;
  NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);
        NRFWriteReg(W_REGISTER+EN_AA,0x01);
        NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);
        NRFWriteReg(W_REGISTER+RF_CH,40);
        NRFWriteReg(W_REGISTER+RX_PW_P0,RX_DATA_WITDH);
        NRFWriteReg(W_REGISTER+RF_SETUP,0x0f);
        NRFWriteReg(W_REGISTER+CONFIG,0x0f);      
        CE_1;
        delay_us(50);
}

#endif



效果图:













举报

更多回帖

×
20
完善资料,
赚取积分