[OpenHarmony轻量系统]润和3861实现TCP电子琴③ 原创 精华

离北况归
发布于 2023-7-31 22:26
浏览
1收藏

通过本文您将了解:
1、HiHopePegasus 3861 开发环境选择
2、HiHopePegasus 3861 连接wifi
3、HiHopePegasus 3861 TCP 连接
4、HiHopePegasus 3861 环境监测板上蜂鸣器的控制

目录


1. TCP电子琴样例运行效果

  • 3861开发板作为TCP服务端与TCP客户端(自己的设备)连接。
  • TCP客户端发送12345678,控制开发板上环境拓展板上的蜂鸣器发出duō lái mī fā suō lā xī duō 8种音调。

2. 样例运行步骤

  • 2.1 下载 https://gitee.com/from-north-to-north/open-armony-north/tree/master/润和3861轻量系统TCP电子琴 ,将源文件文件放置在命名为TCP_keyboard_demo的文件夹下,将其放置在OpenHarmony轻量系统源码 applications\sample\wifi-iot\app目录下。

  • 2.1 修改net_params.h文件的相关代码:

    • PARAM_HOTSPOT_SSID 设置为要连接的热点名称
    • PARAM_HOTSPOT_PSK 设置为要连接的热点秘码;
    • PARAM_SERVER_ADDR 设置为要连接的作为 TCP客户端的设备IP地址
    • PARAM_SERVER_PORT 设置 3861开发板(作为TCP服务端) TCP socket端口号
  • 2.2 在源码 applications\sample\wifi-iot\app\BUILD.gn文件features 字段下添加"TCP_keyboard_demo:TCP_keyboard_demo",使样例demo加入编译。

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

[OpenHarmony轻量系统]润和3861实现TCP电子琴③ -鸿蒙开发者社区

3. 环境监测板上蜂鸣器与主控芯片(Pegasus)引脚的对应关系

  • GPIO9/PWM0

4. 源码分析

4.1 文件说明

文件名 说明
BUILD.gn 构建脚本
demo_entry_cmsis.c wifi和tcp连接的部分
net_common.h 系统网络接口头文件
net_demo.h demo脚手架头文件
net_params.h 网络参数,包括WiFi热点信息,tcp 客户端的ip 、tcp连接的端口号
tcp_server_test.c 3861开发板作为TCP服务端收发数据、电子琴的实现代码
wifi_connecter.c WiFi STA模式API的封装实现文件
wifi_connecter.h WiFi STA模式API的封装头文件

4.2 tcp_server_test.c文件解析

#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <unistd.h>

//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("_______________________________________\r\n");
        printf("bind failed, %ld!\r\n", retval);
        
        //关闭socket
        printf("do_cleanup...\r\n");
        close(sockfd);
    }else{
    printf("_______________________________________\r\n");
    printf("bind to port %hu success!\r\n", port);
    }

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

    retval = listen(sockfd, backlog); // 开始监听
    if (retval < 0) {
        printf("_______________________________________\r\n");
        printf("listen failed!\r\n");
        
        //关闭socket
        printf("do_cleanup...\r\n");
        close(sockfd);
    }else{
    printf("_______________________________________\r\n");
    printf("listen with %d backlog success!\r\n", 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\r\n", connfd, errno);

        //关闭socket
        printf("do_cleanup...\r\n");
        close(sockfd);
    }else{
    printf("_______________________________________\r\n");
    printf("accept success, connfd = %d!\r\n", connfd);
    printf("client addr info: host = %s, port = %hu\r\n", 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("_______________________________________\r\n");
           printf("recv request failed, %ld!\r\n", retval);

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

        //发送数据到客户端
        retval = send(connfd, request, strlen(request), 0);
        if (retval <= 0) {
           printf("_______________________________________\r\n");
           printf("send response failed, %ld!\r\n", retval);
           
           //关闭与客户端的连接
           printf("do_disconnect...\r\n");
           sleep(DELAY_1S);
           close(connfd);
           sleep(DELAY_1S); // for debug
        }else{
           printf("The data responsed to the client is %s\r\n", 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\n" );

        /**
          * 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\n");
          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\n");
          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\n");
          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\n");
          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\n");
          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\n");
          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\n");
          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);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
已于2023-7-31 22:26:55修改
3
收藏 1
回复
举报
3
3
1
3条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

样例demo下载链接访问受限的情况请问如何解决

回复
2023-8-1 10:18:36
hmyxd
hmyxd

注释很详细,好评

回复
2023-8-1 18:20:23
诺舒华吃西瓜
诺舒华吃西瓜

可以考虑放个歌什么的了

回复
2023-8-2 16:27:39


回复
    相关推荐