xshell 6 发送回车_学习ESP8266物联网开发(6)

早期嵌入式开发没有嵌入式操作系统的概念,直接操作裸机,在裸机上写程序,比如51单片机基本就没有操作系统的概念。通常把程序分为两部分,前台系统和后台系统。中断任务就属于前台系统,无线循环的就属于后台系统。RTOS系统:全称Real Time OS,就是实时操作系统,强调的是实时性。又分为硬实时和软实时。我们可以把要实现的功能划分为多个任务,每个任务负责实现其中一部分,每个任务都是一个简单的程序通常是一个死循环。 FreeRTOS是一个可裁剪、可剥夺型的多任务内核,而且没有任务书限制,它提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。 FreeRTOS可以直接去官网下载 http://www.freertos.org

1cf56204fb5308b3a009e66f20127a78.png

学习 FreeRTOS有一定难度,开发时只需要学会怎么调用 FreeRTOS的API函数就可以,由C语言函数实现,对C语言还有一定的要求,需要了解指针、结构体、数据结构体中的链表等,因为 FreeRTOS内核的调用都是通过双链表进行实现的。 FreeRTOS任务: 特性:1、使用简单。2、没有使用限制。3、支持抢占。4、支持优先级。5、每个任务都拥有堆栈导致了RAM使用量增大。6、如果使用抢占的话,必须仔细的考虑重入问题。 状态:运行态、就绪态、阻塞态、挂起态。 优先级:由低到高,空闲任务--->中断任务。《FREERTOS 实时内核实用指南》这本书(资料下载地址 https://share.weiyun.com/5h6TCnn )能够让读者理解如何实现一个任务、如何创建一个或多个任务的实例、如何使用任务函数、如何改变一个亿创建任务的优先级、如何删除任务、 如何实现周期性处理、空闲任务时运行,可以用来干什么。 WIFI UDP Clinet编程:

UDP通讯模型:server端和client端。今天主要学习客户端的编程,主要用到四个函数:socket()、sendto()、recvfrom()、close()。

功能的开发:首先需要在PC端模拟一个UDP Server,指定IP、PORT,等待Client数据,UDP Client向Server发送“I am Client”,Server收到数据后,向Client发送“I am Server”。在user文件夹里新建“udpclient.c”,在include文件夹新建“udpclient.h”。

代码实现:在udpclient.c下,添加udpclient初始化、任务。在udpclient.h下声明。

#include "esp_common.h"#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "lwip/sockets.h"#include "lwip/dns.h"#include "lwip/netdb.h"#include "udpclient.h"#define SERVERADDR "192.168.20.172"#define SERVERPORT 8000/****************************************************************************** * FunctionName : ATaskUdpclient * Description  : ATaskUdpclient任务 * Parameters   : none * Returns      : 描述函数 第一步:判断是否获取到IP地址 第二步:创建socket 第三步:设置接收超时时间 第四步:赋值server信息 第五步:发送数据到server端 第六步:从server端接收数据*******************************************************************************/void ATaskUdpclient( void *pvParameters ){    int iVariableExample = 0;    int fd = -1;    int NetTimeOut = 5000;  //5秒     int ret ;    struct sockaddr_in ServerAddr;    char udpmsg[48];    STATION_STATUS StaStatus;    do    {        StaStatus = wifi_station_get_connect_status();        vTaskDelay(100);        }while(StaStatus != STATION_GOT_IP);        fd = socket(PF_INET ,SOCK_DGRAM,0);    //socket(int domain ,int type, int protocol );    //domain:地址族,type:套接字类型,protocol:参数通常设置为0    if(fd == -1)    {        printf("gey socket  fail !\n");         vTaskDelete( NULL );  //任务删除    }    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &NetTimeOut,sizeof(int));    memset(&ServerAddr,0,sizeof(ServerAddr));    ServerAddr.sin_family = AF_INET;    ServerAddr.sin_addr.s_addr = inet_addr(SERVERADDR);    ServerAddr.sin_port = htons(SERVERPORT);    ServerAddr.sin_len = sizeof(ServerAddr);    /* 任务通常实现在一个死循环中。*/    for( ;; )    {        sendto(fd,"i am udpclient", sizeof("i am udpclient"), \        0,(struct sockaddr *)&ServerAddr , (socklen_t)ServerAddr.sin_len);        do         {           ret = recvfrom(fd,udpmsg, 48, \            0,(struct sockaddr *)&ServerAddr , (socklen_t*)&ServerAddr.sin_len);            if (ret > 0)            {                printf ("udpServer : %s \n",udpmsg);            }            else            {                 printf ("udpServer data is no\n");            }        }while(ret == -1);    }     vTaskDelete( NULL );}/****************************************************************************** * FunctionName : Udpclient_init * Description  : 初始化 * Parameters   : none * Returns      : none*******************************************************************************/void Udpclient_init(void){   xTaskCreate(ATaskUdpclient, "udpclient", 256, NULL, 4, NULL);   }
#ifndef __UDPCLIENT_H__#define __UDPCLIENT_H__#ifdef __cplusplusextern "C" {#endifvoid ATaskUdpclient( void *pvParameters );void Udpclient_init(void);#ifdef __cplusplus}#endif#endif

win+R-->cmd-->ipconfig+回车,可以查看当前以太网配置信息。

WIFI UDP Server编程:
#include "esp_common.h"#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "lwip/sockets.h"#include "lwip/dns.h"#include "lwip/netdb.h"#include "gpio.h"#include "udpserver.h"#define SERVERADDR "192.168.20.186"#define SERVERPORT 8000/****************************************************************************** * FunctionName : ATaskUdpServer * Description  : ATaskUdpServer任务 * Parameters   : none * Returns      : 描述函数 第一步:判断是否获取到IP地址 第二步:创建socket 第三步:Serveraddr信息设置 第四步:设置接收超时时间 第五步:绑定socket 第六步:从client端接收数据 第七步:发送数据到client*******************************************************************************/void ATaskUdpServer( void *pvParameters ){    int iVariableExample = 0;    int fd = -1;    int fdbroad = -1;    int NetTimeOut = 1000;  //1秒     int ret ;    struct sockaddr_in ServerAddr;    struct sockaddr from;    socklen_t  fromlen = sizeof(struct sockaddr);    char udpmsg[48];    STATION_STATUS StaStatus;    struct ip_info info; //用于获取IP地址的信息    char*ipaddr = NULL;    int RecvCode = 0;       do    {        StaStatus = wifi_station_get_connect_status();        vTaskDelay(100);        }while(StaStatus != STATION_GOT_IP);    wifi_get_ip_info(STATION_IF,&info);    ipaddr = inet_ntoa(*(struct in_addr *)&(info.ip));    printf("IP(%s)\n",ipaddr);       fd = socket(PF_INET ,SOCK_DGRAM,0);        //socket(int domain ,int type, int protocol );    //domain:地址族,type:套接字类型,protocol:参数通常设置为0    if(fd == -1)    {        printf("get socket  fail !\n");         vTaskDelete( NULL );  //任务删除         return ;    }    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &NetTimeOut,sizeof(int));    memset(&ServerAddr,0,sizeof(ServerAddr));    ServerAddr.sin_family = AF_INET;    ServerAddr.sin_addr.s_addr = INADDR_ANY;    ServerAddr.sin_port = htons(SERVERPORT);    ServerAddr.sin_len = sizeof(ServerAddr);    if (bind(fd,(struct sockaddr *)&ServerAddr,ServerAddr.sin_len) != 0 )    {        printf("bind socket fail !\n");        vTaskDelete(NULL);        return ;    }    /* 任务通常实现在一个死循环中。*/    for( ;; )    {         do         {           memset(udpmsg,0,48);           ret = recvfrom(fd,udpmsg, 48, 0,&from, &fromlen);            if (ret > 0)            {                printf ("udpclient : %s \n",udpmsg);            }            else            {                 printf ("udpclient data is no\n");            }                }while(ret == -1);        sendto(fd,"i am udpserver", sizeof("i am udpserver"),0,&from, fromlen);      }    vTaskDelete( NULL );}/****************************************************************************** * FunctionName : UdpServer_init * Description  : 初始化 * Parameters   : none * Returns      : none*******************************************************************************/void UdpServer_init(void){   xTaskCreate(ATaskUdpServer, "UdpServer", 256, NULL, 4, NULL);}
#ifndef __UDPSERVER_H__#define __UDPSERVER_H__#ifdef __cplusplusextern "C" {#endifvoid ATaskUdpServer( void *pvParameters );void UdpServer_init(void);#ifdef __cplusplus}#endif#endif

完成一个从client端接收数据给WiFi模块,对比数据信息,符合后输出一个端口控制一盏灯。

在server开发代码中,添加宏定义:

#define OPEN_STATUS "1101" //匹配的字符int G_led_status = 0;

添加控制代码:

/****************************************************************************** * FunctionName :  led_init * Description  : led任务 * Parameters   : none * Returns      : none*******************************************************************************/void led_init(void){    // 配置 MTDI 为 GPIO 模式    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4);}/****************************************************************************** * FunctionName : ATaskLED * Description  : led任务 * Parameters   : none * Returns      : none*******************************************************************************/void ATaskLED( void *pvParameters ){    //printf("ATaskLED   start\n");    /* 任务通常实现在一个死循环中。 */    for( ;; )    {             /* 完成任务功能的代码将放在这里。 */          // printf("ATaskLED   start1\n");        if (G_led_status== 1)        {           GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1);            vTaskDelay(500);           // 配置 MTDI 输出⾼低电平           GPIO_OUTPUT_SET(GPIO_ID_PIN(4),0);            vTaskDelay(100);            G_led_status= 0;        }        vTaskDelay(10);      }    vTaskDelete( NULL );}

在void ATaskUdpServer( void *pvParameters ) 函数中的for循环里面改成以下代码:

    for( ;; )    {         do         {           memset(udpmsg,0,48);           ret = recvfrom(fd,udpmsg, 48, 0,&from, &fromlen);            if (ret > 0)            {                printf ("udpclient : %s \n",udpmsg);                if(strncmp(udpmsg,OPEN_STATUS,4) ==0)                {                    G_led_status= 1;                 }                        }            else            {                 printf ("udpclient data is no\n");            }                }while(ret == -1);
初始化函数改成:
void UdpServer_init(void){   led_init();   xTaskCreate(ATaskLED, "LED", 256, NULL, 2, NULL);   xTaskCreate(ATaskUdpServer, "UdpServer", 256, NULL, 4, NULL);}

在user_main()中,添加#include "udpserver.h",在user_init()函数中,添加UdpServer_init(); 到此,这段代码就已完成。需注意,连接的网路要在同一个网络里面,同一个服务器。

代码保存完成,回去虚拟机里面进行编译,再进行烧录,最后进行测试实现过程。

aa7721c5eae588a898cdb35c0f62b239.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值