基于单片机DHT11温湿度NRF2401无线通信控制系统

一、系统方案

本设计采用STC89C5单片机作为主控制器,从机采用DHT11传感器采集温湿度、按键设置报警阀值,液晶1602显示,蜂鸣器报警,无线NRF2401模块。

二、硬件设计

原理图如下:

三、单片机软件设计

1、首先是系统初始化:

init_io(); // 初始化IO

RX_Mode(); // 设置为接收模式

LCD_Initial(); //液晶初始化

2、液晶显示程序

//1602程序

//内部等待函数*************************************************************

unsigned char LCD_Wait(void)

{

RS=0;

RW=1; nop ();

E=1; nop ();

E=0;

return DBPort;

}

//向LCD写入命令或数据********************************************************

#define LCD_COMMAND 0 // Command

#define LCD_DATA 1 // Data

#define LCD_CLEAR_SCREEN 0x01 // 清屏

#define LCD_HOMING 0x02 // 光标返回原点

void LCD_Write(bit style, unsigned char input)

{

E=0;

RS=style;

RW=0; nop ();

DBPort=input; nop ();//注意顺序

E=1; nop ();//注意顺序

E=0; nop ();

LCD_Wait();

}

//设置显示模式************************************************************

#define LCD_SHOW 0x04 //显示开

#define LCD_HIDE 0x00 //显示关

#define LCD_CURSOR 0x02 //显示光标

#define LCD_NO_CURSOR 0x00 //无光标

#define LCD_FLASH 0x01 //光标闪动

#define LCD_NO_FLASH 0x00 //光标不闪动

void LCD_SetDisplay(unsigned char DisplayMode)

{

LCD_Write(LCD_COMMAND, 0x08|DisplayMode);

}

//设置输入模式************************************************************

#define LCD_AC_UP 0x02

#define LCD_AC_DOWN 0x00 // default

#define LCD_MOVE 0x01 // 画面可平移

#define LCD_NO_MOVE 0x00 //default

void LCD_SetInput(unsigned char InputMode)

{

LCD_Write(LCD_COMMAND, 0x04|InputMode);

}

//初始化LCD************************************************************

void LCD_Initial()

{

E=0;

LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵

LCD_Write(LCD_COMMAND,0x38);

LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标

LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏

LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动

}

//液晶字符输入的位置************************

void GotoXY(unsigned char x, unsigned char y)

{

if(y0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y1)

LCD_Write(LCD_COMMAND,0x80|(x-0x40));

}

//将字符输出到液晶显示

void Print(unsigned char *str)

{

while(*str!='\0')

{

LCD_Write(LCD_DATA,*str);

str++;

}

}

3、按键检测程序

void key()

{

if (k10) //调整按键检测
{
delay(10);
if (k10)

{

presskeynum++;

if(presskeynum5)
presskeynum=0;
while(k10);

LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏

}

}

if(presskeynum1)//温度上限设置
{
if(k20)// 加

{

delay(10);

temp_high++;

if (temp_high>99)

temp_high=0;

if (temp_high<0)

temp_high=99;

while(k20); //加上此句必须松按键才处理
}
if(k30)//减

{

delay(10);

temp_high--;

if (temp_high>99)

temp_high=0;

if (temp_high<0)

temp_high=99;

while(k30); //加上此句必须松按键才处理
}
}
if(presskeynum2)//温度下限设置

{

if(k20)// 加
{
delay(10);
temp_low++;
if (temp_low>99)
temp_low=0;
if (temp_low<0)
temp_low=99;
while(k20);

}

if(k30)
{
delay(10);
temp_low--;
if (temp_low>99)
temp_low=0;
if (temp_low<0)
temp_low=99;
while(k30);

}

}

if(presskeynum3)//湿度上限设置
{
if(k20)// 加

{

delay(10);

humi_high++;

if (humi_high>99)

humi_high=0;

if (humi_high<0)

humi_high=99;

while(k20);
}
if(k30)

{

delay(10);

humi_high--;

if (humi_high>99)

humi_high=0;

if (humi_high<0)

humi_high=99;

while(k30);
}
}
if(presskeynum4)//湿度下限设置

{

if(k20)//加
{
delay(10);
humi_low++;
if (humi_low>99)
humi_low=0;
if (humi_low<0)
humi_low=99;
while(k20);

}

if(k30)// 减
{
delay(10);
humi_low--;
if (humi_low>99)
humi_low=0;
if (humi_low<0)
humi_low=99;
while(k30);

}

}

if(k40)// 退出键
{
delay(10);
if(k40)

{

while(k4==0);

presskeynum=0;

复制代码
      LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   			//清屏
   }

}

}

4、核心算法程序

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

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

*函数名: SPI_RW

*函数功能: 读写一个字节

*输入: 无

*输出: 无

//
uchar SPI_RW(uchar byte)
{
uchar i;
for(i=0; i<8; i++) // 循环8次
{
MOSI = (byte & 0x80); // byte最高位输出到MOSI
byte <<= 1; // 低一位移位到最高位
SCK = 1; // 拉高SCK,nRF24L01从MOSI读取1位数据,同时从MISO输出1位数据
byte |= MISO; // 读MISO到byte最低位
SCK = 0; // SCK置低
}
return(byte); // 返回读取一个字节
}
/
/

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

*函数名: SPI_RW_Reg

*函数功能: 写数据到reg

*输入: 无

*输出: 无

//
uchar SPI_RW_Reg(uchar reg, uchar value)
{
uchar status;
CSN = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
SPI_RW(value); // 写数据到寄存器
CSN = 1; // CSN拉高,结束数据传输
return(status); // 返回状态寄存器
}
/
/

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

*函数名: SPI_Read

*函数功能: 从reg寄存器读字节

*输入: 无

*输出: 无

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

uchar SPI_Read(uchar reg)

{

复制代码
uchar reg_val;

CSN = 0;                    // CSN置低,开始传输数据
  SPI_RW(reg);                // 选择寄存器
  reg_val = SPI_RW(0);        // 然后从该寄存器读数据

  CSN = 1;                    // CSN拉高,结束数据传输
  return(reg_val);            // 返回寄存器数据

}

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

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

*函数名: SPI_Read_Buf

*函数功能: 从reg寄存器读数据

*输入: 无

*输出: 无

//
uchar SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes)
{
uchar status, i;
CSN = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
for(i=0; i<bytes; i++)
pBuf[i] = SPI_RW(0); // 逐个字节从nRF24L01读出
CSN = 1; // CSN拉高,结束数据传输
return(status); // 返回状态寄存器
}
/
/

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

*函数名: SPI_Write_Buf

*函数功能: 把缓存的数据写入NRF

*输入: 无

*输出: 无

//
uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)
{
uchar status, i;
CSN = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
for(i=0; i<bytes; i++)
SPI_RW(pBuf[i]); // 逐个字节写入nRF24L01
CSN = 1; // CSN拉高,结束数据传输
return(status); // 返回状态寄存器
}
/
/

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

*函数名: RX_Mode

*函数功能: 将nrf设置为接收模式

*输入: 无

*输出: 无

//
void RX_Mode(void)
{
CE = 0;
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 接收设备接收通道0使用和发送设备相同的发送地址
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0选择和发送通道相同有效数据宽度
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式
delay_ms(150);
CE = 1; // 拉高CE启动接收设备
}
/
/

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

*函数名: TX_Mode

*函数功能: 将nrf设置为发送模式

*输入: 无

*输出: 无

//
void TX_Mode(uchar * BUF)
{
CE = 0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 应答接收设备,接收通道0地址和发送地址相同
SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // 写数据包到TX FIFO
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a); // 自动重发延时等待250us+86us,自动重发
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电
delay_ms(150);
CE = 1;
}
/
/

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

*函数名: Check_ACK

*函数功能: 检查接收设备有无数据包,设定没有应答信号重发

*输入: 无

*输出: 无

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

uchar Check_ACK(bit clear)

{

while(IRQ);

sta = SPI_RW(NOP); // 返回状态寄存器

if(TX_DS)

{

//blink(3);

}

//blink(5);

if(MAX_RT)

if(clear) // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发

SPI_RW(FLUSH_TX);

SPI_RW_Reg(WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中断标志

IRQ = 1;

if(TX_DS)

return(0x00);

else

return(0xff);

}

相关推荐
芯动力小子3 小时前
MCU开发学习记录17* - RTC学习与实践(HAL库) - 日历、闹钟、RTC备份寄存器 -STM32CubeMX
单片机·学习·实时音视频
广药门徒12 小时前
STM32简易计算机设计
stm32·单片机·嵌入式硬件
Ronin-Lotus13 小时前
嵌入式硬件篇---拓展板
嵌入式硬件
天天爱吃肉821814 小时前
【低成本STM32的T-BOX开发实战:高可靠的车联网解决方案】
stm32·单片机·嵌入式硬件·云原生
不脱发的程序猿16 小时前
在超频单片机时,需要注意哪些稳定性问题?
单片机·嵌入式硬件
sword devil90017 小时前
STM32项目实战:ADC采集
stm32·单片机·嵌入式硬件
-liming-17 小时前
单片机设计_停车场车位管理系统(AT89C52、LCD1602)
单片机·嵌入式硬件·51单片机
不脱发的程序猿18 小时前
单片机超频怎么搞?
单片机·嵌入式硬件·单片机超频
hahaha601618 小时前
uart16550详细说明
stm32·单片机·嵌入式硬件
Invinciblenuonuo19 小时前
STM32八股【9】-----volatile关键字
stm32·单片机·嵌入式硬件