鸿蒙开发板上实现TCP电子琴

描述

本文实现了用润和 HiHope Pegasus 3861 开发板实现 TCP 电子琴。

开发板

样例运行的 OpenHarmony 源码环境下载:

https://gitee.com/HiSpark/hi3861_hdu_iot_application
通过本文您将了解:

 

HiHopePegasus 3861 开发环境选择

HiHopePegasus 3861 连接 wifi

HiHopePegasus 3861 TCP 连接

HiHopePegasus 3861 环境监测板上蜂鸣器的控制

TCP电子琴样例运行效果

3861 开发板作为 TCP 服务端与 TCP 客户端(自己的设备)连接。

TCP 客户端发送 12345678,控制开发板上环境拓展板上的蜂鸣器发出 duō lái mī fā suō lā xī duō 8 种音调。

样例运行步骤

①下载源文件

 

https://gitee.com/from-north-to-north/open-armony-north/tree/master/润和3861轻量系统TCP电子琴 

 

将源文件文件放置在命名为 TCP_keyboard_demo 的文件夹下,将其放置在 OpenHarmony 轻量系统源码 applicationssamplewifi-iotapp 目录下。

②修改 net_params.h 文件的相关代码

如下:

PARAM_HOTSPOT_SSID 设置为要连接的热点名称

PARAM_HOTSPOT_PSK 设置为要连接的热点秘码

PARAM_SERVER_ADDR 设置为要连接的作为 TCP 客户端的设备 IP 地址

PARAM_SERVER_PORT 设置 3861开发板(作为 TCP 服务端) TCP socket端口号

③在源码 applicationssamplewifi-iotappBUILD.gn 文件 features 字段下添加"TCP_keyboard_demo:TCP_keyboard_demo",使样例 demo 加入编译。

④根据 3861 开发板的 ip(串口打印出来的)和 net_params.h 中填写的 TCP socket 端口号创建客户端,连接 3861 开发板。

开发板

主控芯片对应关系

环境监测板上蜂鸣器与主控芯片(Pegasus)引脚的对应关系:GPIO9/PWM0。

源码分析

    文件说明:

开发板

tcp_server_test.c 文件解析:

 

#include 
#include 
#include 

#include 

//TCP连接的部分
#include "net_demo.h"
#include "net_common.h"

/********************环境监测板上蜂鸣器的部分*********************************/
#include "iot_gpio.h"
#include "iot_pwm.h"
#include "hi_pwm.h"
#include "hi_io.h"
#define BEEP_PIN_NAME 9
#define BEEP_PIN_FUNCTION 5
#define WIFI_IOT_PWM_PORT_PWM0 0
#define BEEP_PWM_DUTY 50

/*********************************************************************/

#define DELAY_1S  (1)

void TcpServerTest(unsigned short port)
{

/********************环境监测板上蜂鸣器的部分*********************************/
    // 初始化蜂鸣器
    // 蜂鸣器:GPIO9/PWM0
    // 环境监测板上蜂鸣器与主控芯片(Pegasus)引脚的对应关系 GPIO9/PWM0
    // IoTGpioInit用于初始化 GPIO 设备
    IoTGpioInit(BEEP_PIN_NAME);
    // hi_io_set_func 用于 配置某个IO的复用功能
    hi_io_set_func(BEEP_PIN_NAME, BEEP_PIN_FUNCTION);
    // IoTGpioSetDir 用于 设置 GPIO 引脚的方向
    IoTGpioSetDir(BEEP_PIN_NAME, IOT_GPIO_DIR_OUT);
    // IoTPwmInit 用于 初始化 PWM 设备
    IoTPwmInit(WIFI_IOT_PWM_PORT_PWM0);

/***************************************************************************************/ 

    ssize_t retval = 0;
    int backlog = 1;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
    int connfd = -1;

    struct sockaddr_in clientAddr = {0};
    socklen_t clientAddrLen = sizeof(clientAddr);
    struct sockaddr_in serverAddr = {0};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);  // 端口号,从主机字节序转为网络字节序
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 允许任意主机接入, 0.0.0.0

/*************************************绑定端口****************************************************/
    retval = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); 
    if (retval < 0) {
        printf("_______________________________________
");
        printf("bind failed, %ld!
", retval);

        //关闭socket
        printf("do_cleanup...
");
        close(sockfd);
    }else{
    printf("_______________________________________
");
    printf("bind to port %hu success!
", port);
    }

/***********************************************************************************************/

    retval = listen(sockfd, backlog); // 开始监听
    if (retval < 0) {
        printf("_______________________________________
");
        printf("listen failed!
");

        //关闭socket
        printf("do_cleanup...
");
        close(sockfd);
    }else{
    printf("_______________________________________
");
    printf("listen with %d backlog success!
", backlog);
    }

/**************************************接受客户端连接*********************************************************/

    // 接受客户端连接,成功会返回一个表示连接的 socket , clientAddr 参数将会携带客户端主机和端口信息 ;失败返回 -1
    // 此后的 收、发 都在 表示连接的 socket 上进行;之后 sockfd 依然可以继续接受其他客户端的连接,
    //  UNIX系统上经典的并发模型是“每个连接一个进程”——创建子进程处理连接,父进程继续接受其他客户端的连接
    //  鸿蒙liteos-a内核之上,可以使用UNIX的“每个连接一个进程”的并发模型
    //     liteos-m内核之上,可以使用“每个连接一个线程”的并发模型
    connfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen);
    if (connfd < 0) {
        printf("accept failed, %d, %d
", connfd, errno);

        //关闭socket
        printf("do_cleanup...
");
        close(sockfd);
    }else{
    printf("_______________________________________
");
    printf("accept success, connfd = %d!
", connfd);
    printf("client addr info: host = %s, port = %hu
", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
    }

/***********************************socket收、发的部分************************************************************/

  // 后续 收、发 都在 表示连接的 socket 上进行;
    while (1) {
       char request[128] = "";
       //接收客户端发送过来的数据
       retval = recv(connfd, request, sizeof(request), 0);
       if (retval < 0) {
           printf("_______________________________________
");
           printf("recv request failed, %ld!
", retval);

           //关闭与客户端的连接
           printf("do_disconnect...
");
           sleep(DELAY_1S);
           close(connfd);
           sleep(DELAY_1S); // for debug
        }else{
           printf("_______________________________________
");
           printf("The data received from the client is %s 
", request);
        }

        //发送数据到客户端
        retval = send(connfd, request, strlen(request), 0);
        if (retval <= 0) {
           printf("_______________________________________
");
           printf("send response failed, %ld!
", retval);

           //关闭与客户端的连接
           printf("do_disconnect...
");
           sleep(DELAY_1S);
           close(connfd);
           sleep(DELAY_1S); // for debug
        }else{
           printf("The data responsed to the client is %s
", request);
        }

/************************tcp 客户端发送12345678控制不同的音调****************************/
      int i=atoi(request); // 将字符串request转换成int类型
      hi_pwm_set_clock(PWM_CLK_XTAL); // 设置时钟源为晶体时钟(40MHz,默认时钟源160MHz)
        switch (i)
        {
         case 1:
          printf("Tone is 1
" );

        /**
          * IoTPwmStart 根据给定的输出频率和占空比启动指定端口的 PWM 信号输出。
          * - port 指示 PWM 设备的端口号
          * - 占空比 表示 PWM 信号输出的占空比。值范围为 1 到 99。
          * - 频率 指示 PWM 信号输出的频率。
        **/
          IoTPwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, 2500);  //通过调节PWM 信号输出的频率控制蜂鸣器声调(调到2000听不到蜂鸣器声音)
          usleep(500000);//音长
          IoTPwmStop(WIFI_IOT_PWM_PORT_PWM0);
          break;  

         case 2:
          printf("Tone is 2
");
          IoTPwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, 3000);
          usleep(500000);//音长
          IoTPwmStop(WIFI_IOT_PWM_PORT_PWM0);
          break;    

         case 3:

          printf("Tone is 3
");
          IoTPwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, 3500);
          usleep(500000);//音长
          IoTPwmStop(WIFI_IOT_PWM_PORT_PWM0);
          break;

         case 4:
          printf("Tone is 3
");
          IoTPwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, 4000);
          usleep(500000);//音长
          IoTPwmStop(WIFI_IOT_PWM_PORT_PWM0);
          break;

         case 5:
          printf("Tone is 5
");
          IoTPwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, 4500);
          usleep(500000);//音长
          IoTPwmStop(WIFI_IOT_PWM_PORT_PWM0);
          break;

         case 6:
          printf("Tone is 6
");
          IoTPwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, 5000);
          usleep(500000);//音长
          IoTPwmStop(WIFI_IOT_PWM_PORT_PWM0);
          break;

         case 7:
          printf("Tone is 7
");
          IoTPwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, 5500);
          usleep(500000);//音长
          IoTPwmStop(WIFI_IOT_PWM_PORT_PWM0);
          break;

       case 8:
          printf("Tone is 8
");
          IoTPwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, 6000);
          usleep(500000);//音长
          IoTPwmStop(WIFI_IOT_PWM_PORT_PWM0);
          break;

         default:break;
        }
/***********************************************************************************************/

       usleep(10);
    }

/***********************************************************************************************/

}

SERVER_TEST_DEMO(TcpServerTest);

 

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分