[OpenHarmony轻量系统]润和3861实现TCP电子琴③ 原创 精华
-
本文实现了用润和HiHope Pegasus 3861开发板 实现TCP电子琴,样例demo下载链接:https://gitee.com/from-north-to-north/open-armony-north/tree/master/润和3861轻量系统TCP电子琴
-
样例运行的OpenHarmony源码环境下载:https://gitee.com/HiSpark/hi3861_hdu_iot_application
通过本文您将了解:
1、HiHopePegasus 3861 开发环境选择
2、HiHopePegasus 3861 连接wifi
3、HiHopePegasus 3861 TCP 连接
4、HiHopePegasus 3861 环境监测板上蜂鸣器的控制
@toc
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开发板。
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);
样例demo下载链接访问受限的情况请问如何解决
注释很详细,好评
可以考虑放个歌什么的了