目录
1.项目概述
2.程序框架
3.函数准备
3.1需要函数知识点
3.2编码提醒
4.代码
5.注意事项
1.项目概述
控制端有两个,语音串口UART和Tcp通讯。
执行端有IO输出和IO输入。
2.程序框架
程序分为3部分-------------1.输入控制 2.输出设备 3.主函数-多线程
输入控制的模块----实现指令的收集,并将数据放在一个定义的<cmd.h>头文件种。
输出设备模块----实现设备初始化、设备启动、设备关闭的函数封装放在<device.h>种。
主函数-----实现UART和Tcp两个接收线程,不断接收指令并解析指令调用不同的设备函数封装
亮点,在<.h>封装了一个类,调用<.h>可以编码一个对象,然后用链表将一类对象串起来。
将对象的功能实现都封装成了函数,放在对象的结构体中,使用时直接调用。
3.函数准备
3.1需要函数知识点
main中
- 线程创建、线程退出、线程等待、wiringPi库、链表增加、链表查找
<cmd.h><device.h>中
- 链表创建、函数指针
设备控制、输入控制中
- wiringPi库、结构体赋值、链表增加
3.2编码提醒
出现不能用NULL指针,包含头文件<stdlib.h>
香橙派编译wiringpi库时用gcc buzzer.c -o test -lwiringPi -lwiringPiDev -lpthread -Im -Icrypt -Irt
C语言函数没有return语句时,会返回最后一次赋值的变量的值
函数指针是定义一个指针指向函数,调用时直接用P()或者(*p)()都行,函数名和函数地址一样
指针有点神奇,指针是一个地址,但是同时也可以直接用指针使用地址里的值
没办法:这里的代码在结构体实现里用了函数的递归。错错错。第575课,添加声音识别模块,形参和实参不一样的。形参只是形式,需要函数调用时赋予实参。
炫技:这里的代码用了链表串联设备
堆栈的存储:在函数体前面的变量,后面的函数可以直接用
Orangepi的引脚图
4.代码
main中
#include <stdio.h>
#include <stdlib.h>
#include "contrldevice.h"
#include "inputcmd.h"
#include <string.h>
#include <wiringPi.h>
#include <pthread.h>
#include<unistd.h>struct OutputDevice * pdevicehead=NULL; /*device head */
struct InputDevice * pInputhead=NULL; /*Input head */
struct InputDevice * tmp=NULL;struct OutputDevice *find_cmd_device(char *name,struct OutputDevice * pdevicehead)
{struct OutputDevice *tmp=pdevicehead;if(tmp==NULL ){ /* compare is correct*/return NULL;}else{while(tmp!=NULL){if(0==strcmp(tmp->device_name,name)){return tmp;}tmp=tmp->next;}return NULL;}
}struct InputDevice *find_input_device(char *name,struct InputDevice * pdevicehead)
{struct InputDevice *tmp=pdevicehead;if(tmp==NULL ){ /* compare is correct*/return NULL;}else{while(tmp!=NULL){if(0==strcmp(tmp->cmddevice_name,name)){return tmp;}tmp=tmp->next;}return NULL;}
}void * voice_thread(void *data) /* voice_thread */
{ int nread;struct InputDevice * tmp=find_input_device("voice",pInputhead);if(tmp==NULL){printf("no find voice phead!\r\n");pthread_exit(NULL);}else{if(tmp->init(tmp)==-1){printf("voice init faild!\r\n");pthread_exit(NULL);}}while(1){memset(tmp->cmd,0,sizeof(tmp->cmd)); nread=tmp->getcmd(tmp); /* when uart no data come cmd while get uart overtime */if(nread==0){printf("voice cmd no data arival!\r\n");}else{printf("voice recive %d data:%s\r\n",nread,tmp->cmd);}} }void * sockread_thread(void *data)
{int nread;while(1){memset(tmp->cmd,'\0',sizeof(tmp->cmd));nread=read(tmp->ss_fd,&tmp->cmd,sizeof(tmp->cmd));if(nread==0){ /* cannot recv cmd */ printf("connect is cutdon! \r\n");pthread_exit(NULL);}else{ /*can recive cmd */ printf("server receved %d cmd:%s \r\n",nread,tmp->cmd); }}}void * socket_thread(void *data)
{int nread;pthread_t socketreadthread;tmp=find_input_device("socket",pInputhead);if(tmp==NULL){printf("no find socket phead!\r\n");pthread_exit(NULL);}else{if(tmp->init(tmp)==-1){printf("socket init faild!\r\n");pthread_exit(NULL);}}while(1){if(tmp->getcmd(tmp)==-1){perror("error"); /* get ss_fd error */}/*socket read线程*/pthread_create(&socketreadthread,NULL,sockread_thread,NULL);pthread_join(socketreadthread,NULL); /* 等读线程退出在进行 */}
}int main(void)
{char device_name[32];pthread_t voicethread; pthread_t socketthread; if(-1==wiringPiSetup()){printf("wiringpi init fail!\r\n");return 0;}/*1.指令工厂初始化 加入设备 */pInputhead=add_input_voice(pInputhead);pInputhead=add_input_socket(pInputhead);/*2.设备工厂初始化 加入设备 */pdevicehead=add_device_dingnerlight(pdevicehead);pdevicehead=add_device_restlight(pdevicehead);pdevicehead=add_device_firedetect(pdevicehead);/*2.1找设备 *//*struct OutputDevice * tmp=find_cmd_device(device_name,pdevicehead);while(1){printf("input device name:");scanf("%s",device_name);tmp=find_cmd_device(device_name,pdevicehead);printf("input cmd name 1/2:");scanf("%d",&cmd);switch(cmd){case 1:tmp->init();tmp->open();break;case 2:tmp->init();tmp->close();break;default:printf("no this cmd");break;}}*//*3. 线程池建立*//*3.1 语音线程*/pthread_create(&voicethread,NULL,voice_thread,NULL);/*3.2socket线程*/pthread_create(&socketthread,NULL,socket_thread,NULL);/*3.3摄像头线程*//*3.4 火灾线程*/pthread_join(voicethread,NULL); /*线程等待不让主程序退出*/pthread_join(socketthread,NULL); /*线程等待不让主程序退出*/return 0;
}
contrldevice.h
#include <stdio.h>struct OutputDevice{char device_name[32];int status;int (*init)();int (*open)();int (*close)();int (*read)();int (*changeStatus)();struct OutputDevice *next;};
struct OutputDevice * add_device_dingnerlight(struct OutputDevice *phead);
struct OutputDevice * add_device_restlight(struct OutputDevice *phead);
struct OutputDevice * add_device_firedetect(struct OutputDevice *phead);
inputcmd.h
#include <stdio.h> struct InputDevice{char cmddevice_name[32];char cmd[32];int fd;int ss_fd;int (*init)();int (*getcmd)();struct InputDevice *next;};struct InputDevice * add_input_voice(struct InputDevice *phead);
struct InputDevice * add_input_socket(struct InputDevice *phead);
dingnerlight.c
#include <stdio.h>
#include "contrldevice.h" //include i can use struct
#include <wiringPi.h>#define dingnerlightPin 2
/*struct OutputDevive{char device_name[32];int status;int (*init)();int (*open)();int (*close)();int (*read)();int (*changeStatus)();sturct OutputDevive *next;} */int dingnerlight_init(void)
{pinMode(dingnerlightPin,OUTPUT);digitalWrite(dingnerlightPin,HIGH);return 0;}
int dingnerlight_open(void)
{digitalWrite(dingnerlightPin,LOW);return 0;
}int dingnerlight_close(void)
{digitalWrite(dingnerlightPin,HIGH);return 0;
}struct OutputDevice dingnerlight={ /*"this give valve not init"*/.device_name="dingnerlight",.init=dingnerlight_init,.open=dingnerlight_open,.close=dingnerlight_close
};struct OutputDevice * add_device_dingnerlight(struct OutputDevice *phead)
{if(phead==NULL){return &dingnerlight; }else{dingnerlight.next=phead;phead=&dingnerlight;return phead;}
}
firedetect.c
#include <stdio.h>
#include "contrldevice.h" //include i can use struct
#include <wiringPi.h>#define firedetectPin 6
/*struct OutputDevice{char device_name[32];int status;int (*init)();int (*open)();int (*close)();int (*read)();int (*changeStatus)();sturct OutputDevive *next;} */int firedetect_init(void)
{pinMode(firedetectPin,INPUT);return 0;
}int firedetect_read(void)
{return digitalRead(firedetectPin);
}struct OutputDevice firedetect={ /*"this give valve not init"*/.device_name="firedetect",.init=firedetect_init,.read=firedetect_read
};struct OutputDevice * add_device_firedetect(struct OutputDevice *phead)
{if(phead==NULL){return &firedetect; }else{firedetect.next=phead;phead=&firedetect;return phead;}
}
restlight.c
#include <stdio.h>
#include "contrldevice.h" //include i can use struct
#include <wiringPi.h>#define restlightPin 8
/*struct OutputDevice{char device_name[32];int status;int (*init)();int (*open)();int (*close)();int (*read)();int (*changeStatus)();sturct OutputDevice *next;} */int restlight_init(void)
{pinMode(restlightPin,OUTPUT);digitalWrite(restlightPin,HIGH);return 0;}
int restlight_open(void)
{digitalWrite(restlightPin,LOW);return 0;
}int restlight_close(void)
{digitalWrite(restlightPin,HIGH);return 0;
}struct OutputDevice restlight={ /*"this give valve not init"*/.device_name="restlight",.init=restlight_init,.open=restlight_open,.close=restlight_close
};struct OutputDevice * add_device_restlight(struct OutputDevice *phead)
{if(phead==NULL){return &restlight; }else{restlight.next=phead;return &restlight; }
}
socketcmd.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include "inputcmd.h"/*include i can use struct*/ /*struct InputDevice{char cmddevice_name[32];char cmd[32];int fd;int ss_fd;int (*init)();int (*getcmd)();struct InputDevice *next;}; */int socket_getcmd(struct InputDevice *phead)
{int len;struct sockaddr_in c_ddr; /*save clinet msg*/ /*4.accept come and connect for once*/ len=sizeof(c_ddr);phead->ss_fd=accept(phead->fd,(struct sockaddr *)&c_ddr,&len);if(phead->ss_fd == -1){perror("accept:");}/*5.read from connect ss_fd*/ /*5.2 read*/ printf("conect succese!==========\r\n");return phead->ss_fd;
}int socket_init(struct InputDevice *phead)
{int s_fd;struct sockaddr_in s_ddr; /*build server msg*/ s_fd= socket(AF_INET, SOCK_STREAM, 0);/*1.build a soket specified*/ if(s_fd==-1){perror("error is");}/*2.build all bind*/ s_ddr.sin_family=AF_INET;s_ddr.sin_port=htons(8880);s_ddr.sin_addr.s_addr=htonl(INADDR_ANY);/*give the bind*/ bind(s_fd,(struct sockaddr *)&s_ddr,sizeof(s_ddr));/*3.waite for client*/ listen(s_fd,8);phead->fd=s_fd;return s_fd;
}struct InputDevice struc_socket={.cmd={0},.cmddevice_name="socket",.init=socket_init,.getcmd=socket_getcmd};struct InputDevice * add_input_socket(struct InputDevice *phead)
{if(phead==NULL){return &struc_socket; }else{struc_socket.next=phead;phead=&struc_socket;return phead; }
}
voicecmd.c
//include i can use struct
#include <wiringPi.h>
#include <wiringSerial.h>
#include <stdlib.h>
#include <unistd.h>
#include "inputcmd.h"/*struct InputDevice{char cmddevice_name[32];char cmd[32];int fd;int (*init)();int (*getcmd)();sturct InputDevice *next;} */int voice_getcmd(struct InputDevice *phead)
{int nread;nread=read(phead->fd,phead->cmd,sizeof(phead->cmd));return nread;}int voice_init(struct InputDevice *phead)
{int fd1;if((fd1=serialOpen("/dev/ttyS5",115200))<0){printf("uart init fail!\r\n");exit(-1);}phead->fd=fd1;return fd1;
}struct InputDevice voice={.cmd={0},.cmddevice_name="voice",.init=voice_init,.getcmd=voice_getcmd};struct InputDevice * add_input_voice(struct InputDevice *phead)
{if(phead==NULL){return &voice; }else{voice.next=phead;phead=&voice;return phead; }
}