本文是本人51单片机和物联网的期末课程设计,没学过打板焊接,只用面包板和公母线实现。
安卓和esp8266控灯主要参考Android Studio设计APP实现与51单片机通过WIFI模块(ESP8266-01S)通讯控制LED灯亮灭的设计源码【详解】_手机app通过wifi控制单片机_"殇影的博客-CSDN博客
光敏电阻使用参考(也可以去b站看别人实物介绍,我也从b站看的)
51单片机光敏电阻控制led亮_番茄蛋汤485的博客-CSDN博客
lcd1602使用参考
LCD1602驱动(51单片机)_lcd1602驱动程序_Linux冰岛的博客-CSDN博客
1、系统功能:lcd屏幕显示wifi密码账号,IP,端口号、通过光敏电阻实现光敏控灯、通过esp8266模块和手机app实现控灯。
2、材料:光敏电阻、r52单片机芯片、最小单片机系统、lcd1602模块、小按钮和公母线、esp8266模块、烧写器、电阻(lcd1602模块要接电阻才能显示)。(成本大概四十多?)
3、系统功能实现
网络连接助手实现通信
主要是在同一个局域网内通过tcp/ip与esp8266模块路由连接,esp8266又通过收发的双工通信口与STC89C52RC芯片进行通信。App收发数据主要是通过线程进行。
光敏电阻实现控灯
光敏电阻控制四盏led灯,是通过检测与光敏电阻DO连接的P2^0口输出的电平判断周围光线是否超过阈值,来控制led灯的亮灭。即光线强度高于阈值时,DO输出低电平,亮两盏灯;否则DO口输出高电平,亮四盏灯。
LCD1602液晶屏幕显示实现
Lcd1602会先显示hello wifi lsh,大概3s后显示wifi名称和密码以及ip和端口号。LCD1602可以显示16字*2行字符,每个显示位置都有对应地址,第一行首地址为00H,第二行首地址为40H。但是LCD1602有个特点就是写入显示地址时要求最高位 D7 恒定为高电平,所以该地址需要与80H做位或运算才能真正在该地址写入数
esp8266模块实现局域网通信
Esp8266可以通过AT指令设置wifi名称密码,tcp的ip地址和端口号等,进行初始化,在主函数中调用初始化wifi模块,已经设置中断使能,若产生tcp连接请求,则进入串口中断实现实现连接通信,而串口中断是51单片机通过特殊功能寄存器SBUF对串行接收或串行发送寄存器进行访问。
4、实物结果
app+esp8266+51单片机+光敏电阻+lcd1602
5、整合上面三个文章代码实现的c代码
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit lcd_1602_RS=P2^6; //区分命令和数据
sbit lcd_1602_R_W=P2^5; //读写区分
sbit lcd_1602_E=P2^7; //使能信号
#define lcd_1602_data_cmd P0 //发送接收数据和命令
#define u8 unsigned char
code u8 str1[]="hello wifi"; //字符串结尾 '\0'
code u8 str2[]="lsh"; //字符串结尾 '\0'
code u8 str3[]="lsh 12345678"; //字符串结尾 '\0'
code u8 str4[]="192.168.4.2 8080"; //字符串结尾 '\0'
sbit SW1=P1^0; //S1按键
sbit LED1=P1^1;
sbit LED2=P1^2;
sbit LED3=P1^3;
sbit LED4=P1^4;
sbit key=P2^0; //光敏DO口检测端口
sbit sw2=P2^1; //S2按键
//ESP8266 EN、vcc脚接 vcc 3.3 GND 接地,必须和51共地
//ESP8266 TX 接P3^0, RX 接P3^1
bit flag=0;
int count;
uchar SendBuf[9]="LED1 ON! ";
uchar RecBuf[15];
uchar RecNum=0;
void delay_10us(uint us); //延时
void delay(uint n); //延时
void UART_Init();
void UART_SendByte(uchar dat);
void ESP8266_SendCmd(uchar *pbuf);
void ESP8266_SendData(uchar *pbuf);
void ESP8266_ModeInit(void); //WIFI模块初始化
void UART_Irq( ); // 接收信号
void delay_10us(uint us)
{
while(us--);
}
void delay(uint ms)
{
int x,y;
for(x= ms;x>0;x--)
for(y=110;y>0;y--);
}
//1602写命令
void LCD1602_WriteCmd(unsigned char cmd)
{
lcd_1602_RS=0;
lcd_1602_R_W=0;
lcd_1602_data_cmd=cmd;
lcd_1602_E=1;
delay(5);
lcd_1602_E=0;
}
//1602的初始化函数
void LCD1602_Init()
{
LCD1602_WriteCmd(0x38); //设置显示模式
LCD1602_WriteCmd(0x06); //设置数据指针自增
LCD1602_WriteCmd(0x0C); //设置光标显示关闭,开启显示
LCD1602_WriteCmd(0x01); //清屏
}
//1602写数据
void LCD1602_WriteData(unsigned char dat)
{
lcd_1602_RS=1;//表示写数据
lcd_1602_R_W=0;//表示写操作
lcd_1602_data_cmd=dat;//写入的数据
lcd_1602_E=1;//高脉冲
delay(5);
lcd_1602_E=0;
}
/*
设置光标地址
x : 显示的位置
y :显示的行数 0表示1行显示 1表示第2行显示
*/
void LCD1602_SetCursorAddr(unsigned char x,unsigned char y)
{
unsigned char addr=0;
if(y==1) //表示设置在第2行显示
{
addr=x+0x40; //第二行地址
}
else
{
addr=x+0x00; //第一行地址
}
LCD1602_WriteCmd(0x80|addr); //加上0x80表示设置地址,将最高位赋值为1
}
/*
设置显示的数据
*dat :表示要显示的数据
len :显示数据的长度
*/
void LCD1602_DisplayData(unsigned char *dat,unsigned char len)
{
while(len--)
{
LCD1602_WriteData(*dat++);
}
}
void displayLCD(){
LCD1602_Init(); //1602初始化
delay(50);
LCD1602_SetCursorAddr(0x3,0x0); //设置光标地址
LCD1602_DisplayData(str1,strlen(str1)); //在1602上显示数据
LCD1602_SetCursorAddr(0x6,0x1); //设置光标地址
LCD1602_DisplayData(str2,strlen(str2)); //在1602上显示数据
delay(3000);
LCD1602_Init(); //1602初始化
delay(50);
LCD1602_SetCursorAddr(0x0,0x0); //设置光标地址
LCD1602_DisplayData(str3,strlen(str3)); //在1602上显示数据
LCD1602_SetCursorAddr(0x0,0x1); //设置光标地址
LCD1602_DisplayData(str4,strlen(str4)); //在1602上显示数据
}
void light() //光敏电阻控制函数
{ sw2=0;
while(1){
if(key==0)
{ LED1=LED2=LED3=LED4=1;
LED1=0;
LED2=0;
if(sw2)
{
count=1 ;
if(count==1)
{
break;
}
}
}
else
{ LED1=LED2=LED3=LED4=1;
LED1=0;
LED2=0;
LED3=0;
LED4=0;
if(sw2)
{
count=1 ;
if(count==1)
{
break;
}
}
}
}
}
void UART_Init()
{
SCON=0X50; //串口:工作方式1
TMOD=0X20; //定时器:工作方式2
TH1=0xFD; //波特率:9600
TL1=0xFD;
ES=0; //禁止串口中断
EA=1; //使能总中断
TR1=1; //启动计数器
}
void UART_SendByte(uchar dat)
{
ES=0; //禁止串口中断
SBUF=dat; //串口发送
while(TI==0); //等待发送结束
TI=0; //发送标志位清零
ES=1; //使能串口中断
}
void ESP8266_SendCmd(uchar *pbuf)
{
while(*pbuf!='\0') //遇到空格跳出循环
{
UART_SendByte(*pbuf);
delay_10us(5);
pbuf++;
}
delay_10us(5);
UART_SendByte('\r'); //回车
delay_10us(5);
UART_SendByte('\n'); //换行
delay(1000);
}
void ESP8266_SendData(uchar *pbuf)
{
uchar i=0;
ESP8266_SendCmd("AT+CIPSEND=0,9"); //发送数据:AT+CIPSEND=,
for(i=0;i<=8;i++)
{
UART_SendByte(*pbuf);
delay_10us(5);
pbuf++;
}
}
void ESP8266_ModeInit(void) //WIFI模块初始化
{
ESP8266_SendCmd("AT+CWMODE=3"); //设置路由器模式 1:Station,,2:AP,3:Station+AP
ESP8266_SendCmd("AT+CWSAP=\"lsh\",\"12345678\",11,3"); //设置WIFI热点名称及密码
ESP8266_SendCmd("AT+CIPAP=\"192.168.4.2\""); //设置AP的IP地址
ESP8266_SendCmd("AT+RST"); //重新启动wifi模块
ESP8266_SendCmd("AT+CIPMUX=1"); //开启多连接模式
ESP8266_SendCmd("AT+CIPSERVER=1,8080"); //启动TCP/IP 端口为8080
}
void main()
{
displayLCD();
light:
light();
P1=0x01; //光敏电阻函数
while(SW1); //等待S1键按下
LED1=LED2=LED3=LED4=1;
UART_Init(); //串口初始化
ESP8266_ModeInit();
ES=1; //允许串口中断
while(1)
{
if(sw2)
{
count=2 ;
if(count==2)
{
goto light;
}
}
if(flag==1)
{
flag = 0;
ESP8266_SendData(SendBuf);
}
delay(10);
}
}
void UART_Irq( ) interrupt 4 // 接收信号
{
if(RI)
{
RI=0;
RecBuf[RecNum]=SBUF; //接收到网络数据:+IPD,0,1<数据长度>:F<接收的数据>
if(RecBuf[0]=='+')
RecNum++;
else
RecNum=0;
if(RecNum==10)
{
RecNum=0;
if(RecBuf[0]=='+'&&RecBuf[1]=='I'&&RecBuf[2]=='P'&&RecBuf[3]=='D')
{
switch(RecBuf[9])
{
case '1': LED1=0;break;
case '2': LED2=0;break;
case '3': LED3=0;break;
case '4': LED4=0;break;
case '5': LED1=1;break;
case '6': LED2=1;break;
case '7': LED3=1;break;
case '8': LED4=1;break;
case '9': LED1=1;LED2=1;LED3=1;LED4=1;break;
default:P1 = 0xe0;
}
SendBuf[3] = RecBuf[9];
if(sw2)
{
count=3 ;
if(count==3)
{
ES=0;
}
}
flag = 1;
}
}
}
}
6、ad图?第一次画这个,平时都用仿真软件proteus8.7,这次课设都是直接拿实物试的,应该有问题,不过大概接线差不多是这样(也是第一次搞实物,线太乱了,都是参考别人的修修改改做的):