赞
踩
点击下载设备演示包,就会下载一个华为云为你写好的SDK
到此,我们需要回头改一些我们匆匆创建好的设备信息,先修改一下设备的密码:
修改完后点确定
修改完密码后我们需要修改一下设备的属性,把它改成我们需要的属性:
命令可以像这样子设置,也可以发送不同的数据类型,笔者是发的bool型数据用于开关灯,如果命令有多种情况,就需要发送别的数据类型。
这个是笔者已经弄好的设备,可以作为对照
好了,到了这一步,我们在云端的工作就已经做好了。
既然我们已经在云端创建了一个设备,也就是一个云设备,并不是真实的设备,我们需要利用华为云给我们提供的SDK,并修改一下代码,然后放到Ubuntu运行,建立与云端的通信,才能激活我们刚刚在华为云创建的设备。首先,我们把文件放到vscode上:
文件总体是这样子的,这里我们主要对AgentLiteDemo.c还有ClientConf.json进行修改:
先改ClientConf.json:
按照自己的设备id,密码修改
把后面的端口号删除,还有那两个冒号,因为如果固定端口的话,可能出现连不上的情况。
网址跟这个一样:
设备ID在这:
然后再修改AgentLiteDemo.c:
#include "stdio.h" #include "signal.h" #if defined(WIN32) || defined(WIN64) #include "windows.h" #endif #include "pthread.h" #include <math.h> #include "hw_type.h" #include "iota_init.h" #include "iota_cfg.h" #include <stdlib.h> #include <stdbool.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <errno.h> #include <pthread.h> #include <semaphore.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include "LogUtil.h" #include "JsonUtil.h" #include "StringUtil.h" #include "iota_login.h" #include "iota_datatrans.h" #include "string.h" #include "cJSON.h" #include "sys/types.h" #include "unistd.h" #include "iota_error_type.h" /* if you want to use syslog,you should do this: * * #include "syslog.h" * #define _SYS_LOG * * */ char* workPath = "."; char* gatewayId = NULL; int alarmValue = 0; char* serverIp_ = ""; int port_ = 1883;//原本是8883,需要把端口改成1883,不然与华为云的tcp会连接失败 char* username_ = "64f82801a266cb7f6e6abfd1_gec6818";//deviceId,这个需要根据自己的情况做修改 char* password_ = "12345678";//这也也需要根据自己的情况做修改 int disconnected_ = 0; char *subDeviceId = "f6cd4bbb1a8ab53acbb595efd0e90199_ABC123456789";//这个一般不用改 int sleepTime = 5000; void timeSleep(int ms) { #if defined(WIN32) || defined(WIN64) Sleep(ms); #else usleep(ms * 1000); #endif }
上面的代码中我已经加入了许多我需要用到的头文件,如果编译出现缺少头文件的情况,需要你加上对应的头文件。
void Test_propertiesReport() { int serviceNum = 1;//此处是上报的服务个数 ST_IOTA_SERVICE_DATA_INFO services[serviceNum]; cJSON *root; root = cJSON_CreateObject(); //设置一个p操作,如果没有资源会在此处阻塞等待 sem_wait(&s); //需要根据自己的设备进行修改,中间的是你的云端设备属性,第三个是值,这里笔者已经用变量代替,原本的只是一个随机数,后面你需要用变量替换 cJSON_AddNumberToObject(root, "led", LED_value); cJSON_AddNumberToObject(root, "adc", ADC_value); cJSON_AddNumberToObject(root, "pwm", BEEP_value); char *payload; payload = cJSON_Print(root); cJSON_Delete(root); services[0].event_time = getEventTimeStamp(); //if event_time is set to NULL, the time will be the iot-platform's time. services[0].service_id = "开发板数据监控系统";//这里是一开始弄的那个产品名称,需要根据自己的情况修改 services[0].properties = payload; int messageId = IOTA_PropertiesReport(services, serviceNum); if(messageId != 0) { printfLog(EN_LOG_LEVEL_ERROR, "AgentLiteDemo: Test_batchPropertiesReport() failed, messageId %d\n", messageId); } free(payload); }
void setConnectConfig(){ FILE *file; long length; char *content; cJSON *json; file=fopen("./ClientConf.json","rb"); fseek(file,0,SEEK_END); length = ftell(file); fseek(file,0,SEEK_SET); content = (char*)malloc(length+1); fread(content,1,length,file); fclose(file); json = cJSON_Parse(content); username_ = JSON_GetStringFromObject(json, "deviceId", NULL); password_ = JSON_GetStringFromObject(json, "secret", NULL); char *url = JSON_GetStringFromObject(json, "serverUri", NULL); deleteSubStr(url,"ssl://"); deleteSubStr(url,":1883");//把这个地方的端口改成1883 serverIp_ = url; }
把上面的端口改一改
如果你需要弄云端下发命令,那么还需要修改一处:
这是原本的代码:
void handleCommandRequest(void* context, int messageId, int code, char *message, char *requestId) { printfLog(EN_LOG_LEVEL_INFO, "AgentLiteDemo: handleCommandRequest(), messageId %d, code %d, messsage %s, requestId %s\n", messageId, code, message, requestId); JSON * root = JSON_Parse(message); //Convert string to JSON char* object_device_id = JSON_GetStringFromObject(root, "object_device_id", "-1"); //get value of object_device_id printfLog(EN_LOG_LEVEL_INFO, "AgentLiteDemo: handleCommandRequest(), object_device_id %s\n", object_device_id); char* service_id = JSON_GetStringFromObject(root, "service_id", "-1"); //get value of service_id printfLog(EN_LOG_LEVEL_INFO, "AgentLiteDemo: handleCommandRequest(), content %s\n", service_id); char* command_name = JSON_GetStringFromObject(root, "command_name", "-1"); //get value of command_name printfLog(EN_LOG_LEVEL_INFO, "AgentLiteDemo: handleCommandRequest(), name %s\n", command_name); JSON* paras = JSON_GetObjectFromObject(root, "paras"); //get value of data printfLog(EN_LOG_LEVEL_INFO, "AgentLiteDemo: handleCommandRequest(), id %s\n", paras); if (paras) { sleepTime = JSON_GetIntFromObject(paras, "value", 1) * 1000; printfLog(EN_LOG_LEVEL_INFO, "AgentLiteDemo: handleCommandRequest(), sleepTime %d\n", sleepTime); } Test_commandResponse(requestId); //command reponse JSON_Delete(root); }
这是笔者根据自己的项目需要进行的修改,仅供参考:
void handleCommandRequest(void* context, int messageId, int code, char *message, char *requestId) { //printfLog(EN_LOG_LEVEL_INFO, "AgentLiteDemo: handleCommandRequest(), messageId %d, code %d, messsage %s, requestId %s\n", messageId, code, message, requestId); //这里的修改需要特别注意,如果需要对两种不同的命令做出判断,需要先提取command_name后,再细分判断,不然会报错 JSON * root = JSON_Parse(message); //Convert string to JSON char* command_name = JSON_GetStringFromObject(root, "command_name", "-1"); if(strstr(command_name,"led")) { JSON* paras = JSON_GetObjectFromObject(root, "paras"); JSON* lled = JSON_GetObjectFromObject(paras, "led"); // memcpy(sendled[0],cJSON_Print(lled),strlen(cJSON_Print(lled))); // printf("%s\n",sendled[0]); if (JSON_GetBoolFromObject(paras, "led状态", NULL) == true ) { strcpy(ledstat, "true"); //设置一个v操作,表示收到云端下发的命令 sem_post(&xf); }else { strcpy(ledstat, "false"); //设置一个v操作,表示收到云端下发的命令 sem_post(&xf); } printf("%s\n", JSON_GetBoolFromObject(paras, "led状态", NULL)?"开灯":"关灯"); } if(strstr(command_name,"beep")) { JSON* paras = JSON_GetObjectFromObject(root, "paras"); JSON* lled = JSON_GetObjectFromObject(paras, "beep"); if (JSON_GetBoolFromObject(paras, "beep状态", NULL) == true ) { strcpy(beepstat, "true"); //设置一个v操作,表示收到云端下发的命令 sem_post(&bp); }else { strcpy(beepstat, "false"); //设置一个v操作,表示收到云端下发的命令 sem_post(&bp); } printf("%s\n", JSON_GetBoolFromObject(paras, "beep状态", NULL)?"开警报":"关警报"); } JSON_Delete(root); }
如此修改完之后,保存后,在编译器直接输入make进行编译,然后给脚本文件start.sh赋予777权限,不然执行的时候会报权限不足的问题,编译好之后,在终端直接输入./start.sh执行这个SDK文件,运行结果会是如此:
可以看到,Ubuntu已经顺利执行华为云提供的SDK,在云端也可以看见设备已经激活,并且已经向云端发送ADC,LED,BEEP的数据,(此时的数据并不是真实设备的数据,只是rand函数随机模拟的数据,如果你想要发送真实设备的数据,还需要接通开发板上的设备),反正不管怎么说,现在已经打通了Ubuntu与云端的通信,下一步就应该想着怎么打通Ubuntu与开发板的联系,就是怎么把开发板的真实设备状态通过tcp或者udp发送到ubuntu,再由ubuntu转发给云端,以达到物联网数据监测的目的。
6、编写设备端代码
这里说的设备端是真实设备,也就是开发板上的蜂鸣器,LED和ADC旋钮,如果你需要将设备的状态简单的显示在开发板上,那还需要用到lcd屏幕,要控制这些硬件,当然需要相应的驱动模块,这里笔者就不给出驱动文件,在这提一嘴笔者踩过的雷,驱动一定要安装正确的版本与之相对应,不然会出现莫名其妙的错误。
这里给出一些常用的驱动命令:
lsmod:列出当前装载的驱动模块
rmmod: 删除指定的驱动模块
insmod: 安装指定驱动模块
还有对应的设备路径:
蜂鸣器:beep/buzzer/pwm
ADC: adc/gec6818_adc
LED: led/Led/gec_led
按键:button/gecBt/key
好了,铺垫了这么久,我们现在开始编写设备端的代码。在编写之前,我们需要考虑,每一个设备都有其对应的控制代码,还有其对应的逻辑控制。也就是每一个设备都有自己的.c文件,每个.c文件都有一个main函数。那么该如何实现,这些设备之间的交互呢,比如ADC到达一定的阈值后会触发警报。那就需要用到我们学过的知识了——进程间的通信。我们可以弄一个管理进程,通过exce函数启动其他设备的进程,例如:
#include "head.h" //蜂鸣器标记位,配合共享内存使用的,可惜没玩明白共享内存,暂时报废 const char *beepmanageron = "true"; //设置一个互斥锁,所有的锁都是为了共享内存准备的,很可惜没玩明白共享内存 pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; int main(int argc, char const *argv[]) { //想用共享内存没有用出来,可惜,所以关于共享内存的代码都是无效的,不用管 int shmid; // 创建或打开一个大小为30的SHM对象,用来存放开关的状态,获取其ID shmid = shmget(key, 40, IPC_CREAT|0666); if(shmid < 0) { perror("创建SHM对象失败"); } //映射共享内存 char *shm_addr = shmat(shmid, NULL, 0); pthread_mutex_lock(&m); //把蜂鸣器的标记位写入共享内存(30-40),共享内存的代码用不着,不用在意 memcpy(shm_addr + 30, beepmanageron, strlen(beepmanageron)); pthread_mutex_unlock(&m); printf("共享内存内容:%s\n", shm_addr); // 1. 准备各个模块所需的IPC mkfifo("/root/fifo", O_CREAT|0666); mkfifo("/root/led", O_CREAT|0666); mkfifo("/root/beep", O_CREAT|0666); mkfifo("/root/ledstat", O_CREAT|0666); mkfifo("/root/beepstat", O_CREAT|0666); mkfifo("/root/setting", O_CREAT|0666); // 2. 依次启动各个模块 if(fork() == 0) { execl("./adc_test", "./adc_test", NULL); } if(fork() == 0) { execl("./buzzer", "./buzzer", NULL); } if(fork() == 0) { execl("./bt_test", "./bt_test" , NULL); } if(fork() == 0) { execl("./led_test", "led_test", NULL); } // 分离共享内存与当前进程,很可惜没弄出来 if (shmdt(shm_addr) == -1) { perror("shmdt"); return 1; } // 删除共享内存对象 if (shmctl(shmid, IPC_RMID, NULL) == -1) { perror("shmctl"); return 1; } pause(); return 0; }
这是笔者的管理程序,笔者通过execl函数启动其他的子线程,使用具名管道进行通信。如果大家觉得很麻烦,那大可以把所有的.c文件都放在一个文件里面,这样就不需要进程间通信,也不需要弄共享内存这些吃力不讨好的东西,但是问题在于一个.c文件集成了所有的设备代码,会显得很臃肿,而且也不能练习我们学过的各种进程间通信的知识。所以笔者不建议都弄到一个文件。
下面展示笔者弄的各设备模块的代码:
adc_test2.c
#include "head.h" #define GEC6818_ADC_IN0 _IOR('A', 1, unsigned long) #define GEC6818_ADC_IN1 _IOR('A', 2, unsigned long) int sockfd; //套接字 int recvfd, sendfd, recvfd1; //这两个数组用来存放灯和凤鸣器的状态 char lednow[6]; char beepnow[6]; //两个信号量,用来让两个更新程序一直等待执行 sem_t lo; sem_t bo; sem_t lf; sem_t bf; //这个是屏幕显示的方法 void showbitmap(bitmap *bm, int x, int y, char *p) { // 直接写指针,不在这里写打开设备,避免重复调用打开 char *q = p + (y*800 + x)*4; for(int j=0;j<bm->height && j < 480 ;j++) { for(int i=0;i<bm->width && i< 800 ;i++) memcpy(q+(800*4*j)+i*4,bm->map+(bm->width*bm->byteperpixel*j)+ bm->byteperpixel*i,bm->byteperpixel); } bzero(bm->map,bm->width*bm->height*bm->byteperpixel); } //这个函数用来一直更新灯的状态 void *updateledon(void *arg) { while (1) { //p操作,如果没有资源就会一直等待 sem_wait(&lo); strcpy(lednow, "on"); } } void *updateledoff(void *arg) { while (1) { //p操作,如果没有资源就会一直等待 sem_wait(&lf); strcpy(lednow, "off"); } } //这个函数用来一直更新蜂鸣器的状态 void *updatebeepon(void *arg) { while (1) { //p操作,如果没有资源就会一直等待 sem_wait(&bo); strcpy(beepnow, "on"); } } void *updatebeepoff(void *arg) { while (1) { //p操作,如果没有资源就会一直等待 sem_wait(&bf); strcpy(beepnow, "off"); } } //用来接收云端发送过来的警报指令 void *recvudp1(void *arg) { //打开led具名管道,把读到的云端命令写到管道里面 int beepfd = open("/root/fifo", O_RDWR); int setting = open("/root/setting", O_RDWR | O_NONBLOCK); if(beepfd == -1 || setting == -1) { perror("打开BEEP和setting具名管道失败!"); exit(0); } //准备好本机的ip struct sockaddr_in addr = {0}; addr.sin_family = AF_INET; //当一个服务器程序需要绑定到本机的某个ip地址上时,可以使用这个 //表示服务器愿意接受来自任何可用网络接口的连接 addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(50003); //绑定上面的地址 if(bind(recvfd1, (struct sockaddr *)&addr, sizeof(addr)) != 0) { perror("102绑定地址失败!"); } //等待对方发来的信息 struct sockaddr_in clientAddr; //用来存放信息 char buf[6]; while (1) { bzero(buf, 6); socklen_t len = sizeof(clientAddr); bzero(&clientAddr, len); //等待udp数据 int n = recvfrom(recvfd1, buf, 6, 0, (struct sockaddr *)&clientAddr, &len); if (buf[0] == 't') { printf("收到来自云端的命令[%s:%hu]:%s\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),"开警报!"); //把开警报信息写入管道 write(setting, "on", 2); usleep(200*1000); write(beepfd, "on", 2); sem_post(&bo); }else if (buf[0] == 'f') { printf("收到来自云端的命令[%s:%hu]:%s\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),"关警报!"); //把关灯信息写入管道 write(beepfd, "off", 3); write(setting, "off", 3); sem_post(&bf); }else{ printf("与云端[%s:%hu]:%s\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),"通信良好!"); } } } //用来接收云端发送过来的灯指令 void *recvudp(void *arg) { //打开led具名管道,把读到的云端命令写到管道里面 int ledfd = open("/root/led", O_RDWR); if(ledfd == -1) { perror("打开LED具名管道失败!"); exit(0); } //准备好本机的ip struct sockaddr_in addr = {0}; addr.sin_family = AF_INET; //当一个服务器程序需要绑定到本机的某个ip地址上时,可以使用这个 //表示服务器愿意接受来自任何可用网络接口的连接 addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(50002); //绑定上面的地址 if(bind(recvfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { perror("154绑定地址失败!"); } //打开显示设备,实现把状态信息显示到屏幕上 //等待对方发来的信息 struct sockaddr_in clientAddr; //用来存放信息 char buf[6]; while (1) { bzero(buf, 6); socklen_t len = sizeof(clientAddr); bzero(&clientAddr, len); //等待udp数据 int n = recvfrom(recvfd, buf, 6, 0, (struct sockaddr *)&clientAddr, &len); if (buf[0] == 't') { printf("收到来自云端的命令[%s:%hu]:%s\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),"开灯!"); //把开灯信息写入管道 write(ledfd, "on", 2); sem_post(&lo); }else if (buf[0] == 'f') { printf("收到来自云端的命令[%s:%hu]:%s\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),"关灯!"); //把关灯信息写入管道 write(ledfd, "off", 3); sem_post(&lf); }else{ printf("与云端[%s:%hu]:%s\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port),"通信良好!"); } } } //设置一个互斥锁, 本来是用来控制读写共享内存的,结果没弄出来,所以不必在意 pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t a = PTHREAD_MUTEX_INITIALIZER; int main(int argc, char **argv) { //打开设备 int lcd = open("/dev/fb0",O_RDWR); if (lcd == -1) { perror("打开屏幕设备错误!"); exit(0); } // 获取屏幕属性 struct fb_var_screeninfo fixinfo; ioctl(lcd,FBIOGET_VSCREENINFO,&fixinfo); unsigned long VWIDTH = fixinfo.xres; //可见区宽度(单位:像素) unsigned long VHEIGHT = fixinfo.yres; //可见区高度(单位:像素) unsigned long BPP = fixinfo.bits_per_pixel; //色深 char *p = mmap(NULL, VWIDTH * VHEIGHT * BPP/8, PROT_WRITE, MAP_SHARED, lcd, 0); bzero(p,VWIDTH*VHEIGHT*BPP/8); //1.初始化字库 font *f1 = fontLoad("simfang.ttf"); // 指定字库文件,比如simfang.ttf font *f2 = fontLoad("simfang.ttf"); font *f3 = fontLoad("simfang.ttf"); font *f4 = fontLoad("simfang.ttf"); //2.设置字体的大小 fontSetSize(f1, 40); fontSetSize(f2, 70); fontSetSize(f3, 60); fontSetSize(f4, 60); //3.设置指针指向分配框区域 bitmap *bm1; bitmap *bm2; bitmap *bm3; bitmap *bm4; //4.给分配框设置不同的大小,因为第三块用来显示通知文本,所以分了200行 bm1 = createBitmapWithInit(800, 50, 4, 0x00000000); bm2 = createBitmapWithInit(800, 200, 4, 0x00000000); bm3 = createBitmapWithInit(800, 100, 4, 0x00000000); bm4 = createBitmapWithInit(800, 100, 4, 0x00000000); int fd=-1; int rt; int i=0; unsigned long adc_vol = 0; //初始化信号量,设置为0 sem_init(&lo, 0, 0); sem_init(&bo,0, 0); sem_init(&lf, 0, 0); sem_init(&bf,0, 0); // 创建SHM对象或者打开 int shmid = shmget(key, 40, IPC_CREAT|0666); if (shmid == -1) { perror("shmget"); return 1; } //映射共享内存 char *shm_addr = shmat(shmid, NULL, 0); //创建一个套接字 sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); recvfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); recvfd1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //sendfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sockfd == -1 ||recvfd == -1 || recvfd1 == -1) { perror("创建套接字失败!"); } //创建两个线程,一个运行发送,一个运行接收 pthread_t t1,t2,t3,t4,t5,t6; pthread_create(&t1, NULL, recvudp, NULL); pthread_create(&t2, NULL, recvudp1, NULL); pthread_create(&t3, NULL, updateledon, NULL); pthread_create(&t4, NULL, updateledoff, NULL); pthread_create(&t5, NULL, updatebeepon, NULL); pthread_create(&t6, NULL, updatebeepoff, NULL); //准备好对端的ip struct sockaddr_in addr; socklen_t len = sizeof(addr); bzero(&addr, len); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("192.168.2.10"); addr.sin_port = htons(50001); //打开adc设备 fd = open("/dev/adc_drv", O_RDWR); if(fd < 0) { perror("open /dev/adc_drv:"); return fd; } //弄一个具名管道,把读到的数据写到管道里面 int fifofd = open("/root/fifo", O_RDWR); //这两个管道用来更新灯和蜂鸣器的状态 int ledstat = open("/root/ledstat", O_RDONLY | O_NONBLOCK); int beepstat = open("/root/beepstat", O_RDONLY | O_NONBLOCK); int setting = open("/root/setting", O_RDONLY | O_NONBLOCK); if(fifofd == -1 || ledstat == -1 || beepstat == -1) { perror("打开具名管道失败!"); exit(0); } unsigned long n = 0; //设置一个字符数组用于存放adc数据 char msg[10]; char led[6]; char beep[6]; char ledmsg[6]; char beepmsg[6]; //这个字符串用来存储ADC数据 char BUF1[100]; bzero(BUF1,100); //这个字符串用来存储灯状态 char BUF2[100]; bzero(BUF2,100); //这个字符串用来存储蜂鸣器的状态 char BUF3[50]; bzero(BUF3,50); //读取共享内存内的灯和蜂鸣器状态 pthread_mutex_lock(&m); memcpy(led, shm_addr + 20, 6); memcpy(beep, shm_addr + 20, 6); pthread_mutex_unlock(&m); while(1) { //显示系统时间 time_t t; //获取系统时间 struct tm *Time; time(&t); char buf[50]; //定义buf缓冲区,用来存放时间数据 bzero(buf,50); Time=localtime(&t); char *wd[7] = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"}; //把要输出的数据保存到缓冲区buf snprintf(buf,50,"%d年%d月%d日 %s %d时%d分%d秒",(1900+Time->tm_year), (1+Time->tm_mon),(Time->tm_mday), wd[Time->tm_wday],(Time->tm_hour), Time->tm_min,Time->tm_sec); //这些数组是暂时用来存放管道里面的数据的 bzero(msg, 10); bzero(ledmsg, 6); bzero(beepmsg, 6); //读取管道内的数据 read(ledstat, ledmsg, 6); read(beepstat, beepmsg, 6); //读取ADC通道0的电压值 rt=ioctl(fd,GEC6818_ADC_IN0,&adc_vol); if(strcmp(ledmsg, "on") == 0) { //让灯更新为开 sem_post(&lo); } if(strcmp(ledmsg, "off") == 0) { //让灯更新为关 sem_post(&lf); } if(strcmp(beepmsg, "on") == 0) { //让蜂鸣器状态更新为开 sem_post(&bo); } if(strcmp(beepmsg, "off") == 0) { //让蜂鸣器状态更新为关 sem_post(&bf); } if(rt != 0) { printf("adc in0 read filed\r\n"); usleep(50*1000); continue; } unsigned long m1 = adc_vol + n; if(m1 >= 3000 && m1 <= 3100) { //把数据写到具名管道 write(fifofd, "on", 2); n = n + 100; } if (m1 > 3500) { n = 0; } if (m1 >800 && m1 <3000) { n = n + 100; } if (m1 > 3100) { n = n + 100; } //把数据写入msg snprintf(msg, sizeof(msg), "%lu", m1); //发送数据 int n = sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr *)&addr, sizeof(addr)); //发送led灯的状态数据 int n1 = sendto(sockfd, lednow, strlen(lednow), 0, (struct sockaddr *)&addr, sizeof(addr)); //发送蜂鸣器的状态数据 int n2 = sendto(sockfd, beepnow, strlen(beepnow), 0, (struct sockaddr *)&addr, sizeof(addr)); if(n == -1) { perror("发送adc数据失败!"); } if(n1 == -1) { perror("发送led数据失败!"); }else { printf("发送成功!"); } if(n2 == -1) { perror("发送beep数据失败!"); } printf("温度: %lu mv\r\n",m1); // 从共享内存中读取数据 // printf("共享内存内容:%s\n", shm_addr); printf("灯状态:%s\n", (strcmp(lednow, "on") == 0) ? "开" : "关"); printf("蜂鸣器状态:%s\n", (strcmp(beepnow, "on") == 0) ? "开" : "关"); //把要输出的内容显示到显示屏上,50表示x的偏移量,5表示距离上一个分配框的距离 //把adc数据写入BUF0 snprintf(BUF1, 100, "ADC值:%lu", m1); snprintf(BUF2, 100, "灯状态:%s\n", (strcmp(lednow, "on") == 0) ? "开" : "关"); snprintf(BUF3, 50, "蜂鸣器状态:%s\n", (strcmp(beepnow, "on") == 0) ? "开" : "关"); fontPrint(f1, bm1 ,50 ,5,buf, 0x00FFFF00, 0); fontPrint(f2, bm2, 5,40, BUF1, 0xFF000000, 0); fontPrint(f4, bm3,100,5, BUF2, 0xFF33CC66,750); fontPrint(f3, bm4,100,40, BUF3, 0xFFD70000, 0); //bm妥善地放置到LCD上显示出来 showbitmap(bm1, 10, 0, p); showbitmap(bm2, 200, 50, p); showbitmap(bm3, 100, 200, p);//为了让文本有一种居中对齐的效果,所以右边偏移量也-200 showbitmap(bm4, 100, 270, p); sleep(1); } // 分离共享内存与当前进程 if (shmdt(shm_addr) == -1) { perror("shmdt"); return 1; } // 删除共享内存对象 if (shmctl(shmid, IPC_RMID, NULL) == -1) { perror("shmctl"); return 1; } close(fd); return 0; }
这个adc_test2.c里面集成了控制蜂鸣器开关的代码,集成了接收云端命令控制led灯开关和蜂鸣器开关的代码,还整合了所有的设备信息向ubuntu发送的功能,还有在lcd上显示设备信息的功能,所以代码比较长,大家仅供参考。
buzzer.c代码:
#include "head.h" #define BUZZER_IOCTL_SET_FREQ 1 #define BUZZER_IOCTL_STOP 0 void Usage(char *args) { printf("Usage: %s <on/off> <freq>\n",args); return ; } //定义一个全局变量 int buzzer_fd; ## 最后 **自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。** **深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。** **因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。** ![img](https://img-blog.csdnimg.cn/img_convert/269da7a2d07f8e8278ce9154d9feadbb.png) ![img](https://img-blog.csdnimg.cn/img_convert/04912a1eb7fa719af8f01fc62ac3224b.jpeg) ![img](https://img-blog.csdnimg.cn/img_convert/65f1559f61b5069ac181cf301107a33f.png) ![img](https://img-blog.csdnimg.cn/img_convert/65e6a2122bc2b957b286ca9038fc2b06.png) ![img](https://img-blog.csdnimg.cn/img_convert/ba3035ca2e316e279be0bfdb2d961646.png) ![img](https://img-blog.csdnimg.cn/img_convert/2c72b4f6bd4fb593e24b15ac516d0736.png) ![](https://img-blog.csdnimg.cn/img_convert/cf584ea6eee456d9267be5db3039bba5.png) **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!** [**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289) **由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!! 整合了所有的设备信息向ubuntu发送的功能,还有在lcd上显示设备信息的功能,所以代码比较长,大家仅供参考。 buzzer.c代码:
#include “head.h”
#define BUZZER_IOCTL_SET_FREQ 1
#define BUZZER_IOCTL_STOP 0
void Usage(char *args)
{
printf(“Usage: %s <on/off> \n”,args);
return ;
}
//定义一个全局变量
int buzzer_fd;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-bO0DOpsl-1715682465863)]
[外链图片转存中…(img-RiE9M8p1-1715682465863)]
[外链图片转存中…(img-ylfeJ6iI-1715682465864)]
[外链图片转存中…(img-3BHbnKRU-1715682465864)]
[外链图片转存中…(img-FAU3YUHq-1715682465865)]
[外链图片转存中…(img-Gec1JD1e-1715682465865)]
[外链图片转存中…(img-hDCrgsmB-1715682465866)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。