C51用GY39光强检测通过串口通信CT连RXD,DR连TXD,用LCD1602显示
时间: 2024-05-29 14:03:10 浏览: 127
首先,需要确保GY39光强检测模块能够正常工作,可以使用单片机的串口助手工具来进行测试和调试。接下来,需要将GY39模块的CT引脚连接到单片机的RXD引脚,DR引脚连接到单片机的TXD引脚。
在单片机程序中,需要使用UART通信协议来进行串口通信,并且需要配置串口的波特率、数据位、停止位和校验位等参数。可以使用标准的C语言库函数或者单片机厂家提供的专门的库函数来实现串口通信。
接下来,需要将LCD1602模块连接到单片机的相应引脚上,并且需要编写LCD1602的驱动程序来控制LCD显示屏的显示内容。可以参考LCD1602的应用手册或者单片机厂家提供的相关资料来编写LCD1602的驱动程序。
最后,需要将GY39模块读取到的光强数据通过串口发送给单片机,并且将数据转换为可读的格式并显示在LCD1602屏幕上。可以使用标准的C语言库函数或者单片机厂家提供的专门的库函数来实现数据转换和LCD1602的显示操作。
相关问题
编写代码实现:1) 用 51 单片机做控制芯片,用 GY39 模块(引脚为vcc,ct,dr,gnd)来实现光强的检测; 2) 湿度值通过计算后,要能够准确的显示在 LCD1602 上面; 3) 当光照值过低时自动的打开 LED 灯; 4) 当光照值过高时步进电机开始动作。
以下是基于 Keil C51 编译器的代码实现:
```
#include <reg52.h>
#include <stdio.h>
#include <lcd.h>
sbit LED = P1^0; //LED 灯连接在 P1.0
sbit STEPPER_PUL = P2^0; //步进电机脉冲信号连接在 P2.0
sbit STEPPER_DIR = P2^1; //步进电机方向信号连接在 P2.1
sbit GY39_VCC = P3^7; //GY39 VCC 引脚连接在 P3.7
sbit GY39_CT = P3^6; //GY39 CT 引脚连接在 P3.6
sbit GY39_DR = P3^5; //GY39 DR 引脚连接在 P3.5
sbit GY39_GND = P3^4; //GY39 GND 引脚连接在 P3.4
void delay_ms(unsigned int ms) //延时函数
{
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 1000; j++);
}
void stepper_motor_rotate(int steps, int direction) //步进电机转动函数
{
int i;
STEPPER_DIR = direction; //设置方向
for(i = 0; i < steps; i++)
{
STEPPER_PUL = 1; //脉冲信号置高
delay_ms(1); //延时
STEPPER_PUL = 0; //脉冲信号置低
delay_ms(1); //延时
}
}
void main()
{
unsigned char hum_str[10]; //湿度字符串缓冲区
unsigned char lcd_str[16]; //LCD 显示字符串缓冲区
unsigned int light_intensity; //光强值
float humidity; //湿度值
GY39_VCC = 1; //GY39 模块供电
delay_ms(100); //等待模块初始化完成
lcd_init(); //LCD 初始化
while(1)
{
GY39_CT = 1; //触发测量
delay_ms(10); //等待测量完成
light_intensity = (GY39_DR << 8) | P0; //读取光强值
humidity = (float)((P0 << 8) | GY39_DR) / 10.0; //计算湿度值
sprintf(hum_str, "%.1f", humidity); //格式化湿度值字符串
lcd_clear(); //清屏
sprintf(lcd_str, "Humidity: %s%%", hum_str); //格式化 LCD 显示字符串
lcd_puts(lcd_str); //显示湿度值
if(light_intensity < 100) //光强过低
LED = 1; //打开 LED 灯
else
LED = 0; //关闭 LED 灯
if(light_intensity > 500) //光强过高
stepper_motor_rotate(100, 0); //步进电机顺时针转动 100 步
delay_ms(1000); //等待 1 秒
}
}
```
注意:以上代码仅供参考,需要根据具体的硬件环境进行修改和调试。
代码实现1) 用 51 单片机做控制芯片,用 GY39 模块(ct、dr端)来实现光强和湿度的检测; 2) 光照值和湿度值通过计算后,要能够准确的显示在 LCD1602 上面; 3) 当光照值过低时自动的打开 LED 灯; 4) 当光照值过高时蜂鸣器报警 5) 适当创新
以下是基于51单片机和GY39模块的代码实现,实现了光强和湿度的检测并在LCD1602上显示,当光照值过低时自动打开LED灯,当光照值过高时蜂鸣器报警,同时添加了人体红外感应模块,当检测到人体时关闭LED灯和蜂鸣器。
```c
#include <reg52.h> // 51单片机头文件
#include <intrins.h> // 延时函数头文件
#define uint unsigned int
#define uchar unsigned char
sbit RS = P2^0; // LCD1602的RS引脚
sbit RW = P2^1; // LCD1602的RW引脚
sbit EN = P2^2; // LCD1602的EN引脚
sbit LED = P1^0; // LED灯引脚
sbit BEEP = P1^1; // 蜂鸣器引脚
sbit PIR = P3^2; // 人体红外感应模块引脚
uchar code table[] = "0123456789"; // 数字显示表
void delay(uint x) // 延时函数
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
void write_com(uchar com) // 写入指令函数
{
RS = 0;
RW = 0;
P0 = com;
EN = 1;
delay(5);
EN = 0;
}
void write_data(uchar date) // 写入数据函数
{
RS = 1;
RW = 0;
P0 = date;
EN = 1;
delay(5);
EN = 0;
}
void init() // LCD1602初始化函数
{
write_com(0x38); // 初始化
write_com(0x0c); // 打开显示,关闭光标
write_com(0x06); // 光标右移,字符不移动
write_com(0x01); // 清屏
}
void display(uchar *p, uchar addr) // 显示数据函数
{
write_com(addr);
while(*p)
{
write_data(*p++);
}
}
uchar read_data() // 读取GY39模块数据函数
{
uchar date;
while(RI == 0);
date = SBUF;
RI = 0;
return date;
}
void main()
{
uchar hum_h, hum_l, temp_h, temp_l, light_h, light_l; // 存储读取的数值
float hum, temp, light; // 存储计算后的数值
uchar str[20]; // 存储要显示的字符串
init(); // LCD1602初始化
write_com(0x80); // 光标移到第一行第一列
display("Temp: ", 0x80); // 显示温度标题
display("Hum : ", 0xc0); // 显示湿度标题
while(1)
{
SCON = 0x50; // 串口工作方式1
TMOD = 0x20; // 定时器工作方式2
TH1 = 0xfd; // 波特率9600
TL1 = 0xfd;
TR1 = 1; // 启动定时器
ES = 1; // 打开串口中断
EA = 1; // 打开总中断
// 读取湿度值
SBUF = 0xff;
while(TI == 0);
TI = 0;
hum_h = read_data();
SBUF = 0xe1;
while(TI == 0);
TI = 0;
hum_l = read_data();
hum = (hum_h * 256 + hum_l) * 0.01;
sprintf(str, "%.2f%%", hum); // 将湿度值转换为字符串
display(str, 0xc5); // 在LCD1602上显示湿度值
// 读取温度值
SBUF = 0xff;
while(TI == 0);
TI = 0;
temp_h = read_data();
SBUF = 0xe3;
while(TI == 0);
TI = 0;
temp_l = read_data();
temp = (temp_h * 256 + temp_l) * 0.01;
sprintf(str, "%.2fC", temp); // 将温度值转换为字符串
display(str, 0x86); // 在LCD1602上显示温度值
// 读取光照值
SBUF = 0xff;
while(TI == 0);
TI = 0;
light_h = read_data();
SBUF = 0xe5;
while(TI == 0);
TI = 0;
light_l = read_data();
light = (light_h * 256 + light_l) * 0.25;
sprintf(str, "%.2fLx", light); // 将光照值转换为字符串
display(str, 0xcf); // 在LCD1602上显示光照值
// 根据光照值控制LED灯和蜂鸣器
if (light < 1000)
{
LED = 1;
}
else if (light > 2000)
{
BEEP = 1;
}
// 根据人体红外感应模块控制LED灯和蜂鸣器
if (PIR == 1)
{
LED = 0;
BEEP = 0;
}
}
}
void ser() interrupt 4 // 串口中断函数
{
RI = 0;
}
```
需要注意的是,以上代码只是一个简单的示例,实际使用时还需要根据具体情况进行修改和优化。
阅读全文