本文是本人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 <reg52.h>
#include <stdio.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned intsbit 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^1bit 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; //串口:工作方式1TMOD=0X20; //定时器:工作方式2TH1=0xFD; //波特率:9600TL1=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=<id>,<length>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+APESP8266_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<id>,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,这次课设都是直接拿实物试的,应该有问题,不过大概接线差不多是这样(也是第一次搞实物,线太乱了,都是参考别人的修修改改做的):