要让 51 单片机实现上网功能,需要借助通信模块(如 ESP8266、SIM800C 等)作为 “翻译官”,因为 51 单片机本身无法直接连接网络。下面以 ESP8266 WiFi 模块为例,用 “三步法” 解释这个过程:

第一步:硬件连接

  • 51 单片机 → ESP8266 模块:用 4 根线连起来(就像打电话的两头接上线):
    • TXD(51 的发送) → RXD(ESP 的接收):让 51 能 “说话” 给 ESP 听。
    • RXD(51 的接收) → TXD(ESP 的发送):让 ESP 能 “回答” 51。
    • VCC/GND:接电源(一般 ESP 用 3.3V,别接 5V 会烧!)。
    • EN:有些 ESP 模块需要接高电平(比如接 3.3V)才能开机。

第二步:教 ESP8266 “听话”(配置 AT 指令)

ESP8266 默认是 “聋哑人”,得先用 AT 指令教它 “说话” 和 “听话”。这个过程就像教小朋友背口诀:

  1. 开机测试:51 单片机给 ESP 发AT(后面加个回车键),ESP 如果回OK,说明它 “醒了”。
  2. 连 WiFi:发AT+CWJAP="WiFi名","密码",比如AT+CWJAP="奶奶家","123456",ESP 就会去连 WiFi。
  3. 设置上网模式:发AT+CIPMUX=0(让 ESP 一次只干一件事)。
  4. 连服务器:发AT+CIPSTART="TCP","服务器地址",80(比如连百度:AT+CIPSTART="TCP","www.baidu.com",80)。

第三步:让 51 单片机 “指挥” ESP 干活

51 单片机就像 “指挥官”,通过 AT 指令让 ESP8266 去上网、发数据:

  1. 发数据

    • 先发AT+CIPSEND=5(告诉 ESP:我要发 5 个字符)。
    • 等 ESP 回>后,再发Hello(实际项目里可能是温度、湿度数据)。
    • ESP 会把数据打包成 “上网包裹” 发给服务器。
  2. 收数据

    • 服务器回的数据会先到 ESP,ESP 再把数据 “翻译” 成 AT 指令格式发给 51 单片机。
    • 比如 ESP 收到+IPD,5:World,51 单片机读到后就知道服务器回了 “World”。

关键注意事项

  1. 波特率要一致:51 单片机和 ESP8266 “说话” 的速度要一样(比如都设为 115200bps)。
  2. 电源要稳:ESP8266 上网时耗电比较大,电源不稳会断网(就像电灯电压不稳会闪)。
  3. 指令后加回车:AT 指令结尾要加\r\n(就像说话要带句号)。

代码

#include "reg52.h"
#include "intrins.h"
#include "string.h"
sfr AUXR = 0x8E;
sbit D5=P3^7;
sbit D6=P3^6;
char cmd[12];
char MS[]="AT+CWMODE_CUR=1\r\n";
code char JR_lyq[] = "AT+CWJAP=\"WiFi名\",\"密码\"\r\n";
code char JR_fwq[] = "AT+CIPSTART=\"TCP\",\"电脑IP地址\",8880\r\n";
     char TC[] = "AT+CIPMODE=1\r\n";
     char SR[] = "AT+CIPSEND\r\n";
int i=0;
int AT_ok=0;//输入指令后返回语句,为OK则为1,否则为0

void chushihua()
{
    SCON=0x50;//选择每次传输的有效数据位数 这里是8位
    AUXR=0x01;//减少辐射
    TMOD &= 0x0F;//选择模式
    TMOD |= 0x20;
    TH1=0xFD;//开始计数的初始高位
    TH0=0xFD;    
    TR1=1;
    EA=1;
    ES=1;
}

void Delay1000ms()        //延续1s
{
    unsigned char i, j, k;
    _nop_();
    i = 8;
    j = 1;
    k = 243;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}

void shuchu(char *p)
{
    while(*p!='\0')//从字符串起始位直到\0 一位一位的发送给SBUF
    {        
        SBUF=*p;
        
        while(!TI);
        TI=0;//输入一个数据,给一个间隔时间,这样不卡壳 
        
        p++;        
    }
}

void main()
{
    D5 = D6 = 1;
    chushihua();
    Delay1000ms();

        shuchu(MS);
        while(!AT_ok);
        AT_ok=0;
        D5=0;//选择模式,检测是否连接成功,连接成功D5灯亮
    
        shuchu(JR_lyq);
        while(!AT_ok);
        AT_ok=0;    
        D6=0;    //连接网络,连接成功D6灯亮
    
        shuchu(JR_fwq);
        while(!AT_ok);
        AT_ok=0;    //连接服务器,连接成功D5灯灭
        D5=1;
    
        shuchu(TC);
        while(!AT_ok);
        AT_ok=0;//发送透传指令,发送成功D6灯灭
        D6=1;
        
        shuchu(SR);
        while(!AT_ok);
        AT_ok=0;        //发送无限制输入指令
            
    while(1)//循环 每隔1S 输入 xintiaobao
    {
        //shuchu("zhanghan shuai \r\n");
        //shuru(cmd);
        shuchu("xintiaobao\r\n");//心跳包
        Delay1000ms();
  }
}

void UART_Routine()   interrupt 4
{
    static int i=0;
    char tmp;
    if(RI)
        {
            RI=0;
            tmp=SBUF;
            if(tmp=='O' || tmp=='L')//如果检测到O或L强制将i=0
                i=0;
            cmd[i++]=SBUF;
            
            if(cmd[0]=='O' && cmd[1]=='K')//检测如果返回值为OK则改变AT_ok值,并且清空字符串
            {
                memset(cmd, 0, sizeof(cmd)); // 清空字符串
                i=0;
                AT_ok=1;
            }
            
            if(cmd[0]=='L' && cmd[2]=='1')//检测如果输入值为L*1,则亮D5
            {
                memset(cmd, 0, sizeof(cmd));
                i=0;
                D5=0;
            }
            
            if(cmd[0]=='L' && cmd[2]=='0')////检测如果输入值为L*0,则亮D6
            {
                memset(cmd, 0, sizeof(cmd));
                i=0;
                D5=1;
            }
                
            if(i==sizeof(cmd))//数组满了,下标回0,清空数组 
            {
                memset(cmd, 0, sizeof(cmd));
                i=0;
            }
    }        
}


 

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐