书接上期,和大家分享了web下发命令控制led之后呢,相信大家已经迫不及待的想要试一下是不是蜂鸣器也能响起来呢!哈哈哈,别说是你们了,我也有点迫不及待,其实led的控制中,我们把框架已经解释的非常清楚了,所以接下来要做的事情就变得非常简单了,只需要怎么办呢,就是往框架里面添加具体的蜂鸣器控制内容;下面我们具体来看看!
首先使用CGI打通HTML和A9平台,使得两者能够沟通起来;这个文件呢最终能够生成a9_beep.cgi文件,再拷贝到A9平台的BOA服务器下的cgi-bin目录下进行存放,这样HTML在下发命令后,通过该文件进行解析控制命令字,进而通过消息队列进行进程间通信,紧接着应用层的主框架接收请求线程(pthread_client_request.c)从消息队列中读取数据,进行判断是那个类型的数据(具体是哪一个设备),之后唤醒对应的睡眠线程(pthread_buzzer.c),唤醒后进行对应的硬件操作(ioctl);
#include
#include "cgic.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 8
struct msg
{
long type;
long msgtype;
unsigned char text[N];
};
int cgiMain()
{
key_t key;
char buf[N];
char sto_no[2];
int msgid;
struct msg msg_buf;
memset(&msg_buf,0,sizeof(msg_buf));
cgiFormString("beep",buf,N); //beep网页键值进行接收,接收8个字节
cgiFormString("store",sto_no,2);
if((key = ftok("/tmp", 'g')) < 0) //创建IPC对象键值(生成一个IPC对象),用于消息队列,参数1是指定的文件名,参数2是子序号
{
perror("ftok");
exit(1);
}
if((msgid = msgget(key, 0666)) < 0) //创建一个消息队列
{
perror("msgget");
exit(1);
}
switch (buf[0])
{
case '0':
{
//关闭蜂鸣器
msg_buf.text[0] = ((sto_no[0] - 48)) << 6 | (1 << 4) | (0 << 0); //sto_no[0]-48表示从网页拿到的是字符串,这里需要转化为数字,48就是0的ASCII码,再向左移动6位(协议制定6 7位为平台编号)
//4-5位置为为设备编号,表示操作哪一个设备,led还是蜂鸣器,0-4位(操作掩码)表示关闭打开等操作
break;
}
case '1':
{
//打开蜂鸣器
msg_buf.text[0] = ((sto_no[0] - 48)) << 6 | (1 << 4) | (1 << 0);
break;
}
case '2':
{
//自动报警关闭
msg_buf.text[0] = ((sto_no[0] - 48)) << 6 | (1 << 4) | (2 << 0);
break;
}
case '3':
{
//自动关闭打开
msg_buf.text[0] = ((sto_no[0] - 48)) << 6 | (1 << 4) | (3 << 0);
break;
}
}
msg_buf.type = 1L; //1L表示home1
msg_buf.msgtype = 2L; //表示设备编号led还是..
msgsnd(msgid, &msg_buf,sizeof(msg_buf)-sizeof(long),0); //向消息队列中写入消息,将消息发出,在A9端进行接收
//这里发送的字节数为sizeof(msg_buf)-sizeof(long)的原因是由于不需要传送消息类型,只需要传送具体的消息大小即可(也就是msg结构体的第一个变量不需要作为发送的有效字节传送)
sto_no[0] -= 48; //为了后面生成是哪一个操作引起网页反馈(生成二级网页名序号)
cgiHeaderContentType("text/html\n\n");
fprintf(cgiOut, "\n");
fprintf(cgiOut, "My CGI \n");
fprintf(cgiOut, "");
fprintf(cgiOut, "send sucess
");
//fprintf(cgiOut, "返回");
fprintf(cgiOut, "", sto_no[0]);
fprintf(cgiOut, "\n");
fprintf(cgiOut, "\n");
return 0;
}
#include "data_global.h"
#include "linuxuart.h"
//消息队列id
extern int msgid;
//ipc对象键值
extern key_t key;
//锁资源
extern pthread_mutex_t mutex_client_request,
mutex_refresh,
mutex_sqlite,
mutex_transfer,
mutex_analysis,
mutex_sms,
mutex_buzzer,
mutex_led,
mutex_camera;
//条件变量
extern pthread_cond_t cond_client_request,
cond_refresh,
cond_sqlite,
cond_transfer,
cond_analysis,
cond_sms,
cond_buzzer,
cond_led,
cond_camera;
//模块的控制命令字
extern unsigned char cmd_led;
extern unsigned char cmd_buzzer;
extern unsigned char cmd_fan;
//GPRS模块的电话号
extern char recive_phone[12] ;
extern char center_phone[12] ;
//消息队列通信结构体
struct msg msgbuf;
void *pthread_client_request(void *arg)
{
if((key = ftok("/tmp",'g')) < 0){
perror("ftok failed .\n");
exit(-1);
}
msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666); //检测消息队列中是否有这个键值,如果有则返回对应的-1,没有则创建并返回创建消息队列的id
if(msgid == -1) {
if(errno == EEXIST){ //如果已经存在
msgid = msgget(key,0777); //设置权限为0777
}else{
perror("fail to msgget");
exit(1);
}
}
printf("pthread_client_request\n");
while(1){
bzero(&msgbuf,sizeof(msgbuf)); //清理操作,但一般使用memset,功能更加强大一点
printf("wait form client request...\n");
msgrcv (msgid, &msgbuf, sizeof (msgbuf) - sizeof (long), 1L, 0); //从消息队列中读取消息
printf ("Get %ldL msg\n", msgbuf.msgtype); //打印消息类型
printf ("text[0] = %#x\n", msgbuf.text[0]); //打印消息内容
//判断消息类型,从而确定是哪一个设备
switch(msgbuf.msgtype){
case 1L:
//1L的类型是led的消息类型,此时上锁,等待消息内容也就是控制命令字复制完成后解锁,通过pthread_cond_signal唤醒pthread_led.c这个led线程,进行led的具体硬件操作
pthread_mutex_lock(&mutex_led);
printf("hello led\n");
cmd_led = msgbuf.text[0];
pthread_mutex_unlock(&mutex_led);
pthread_cond_signal(&cond_led);
break;
case 2L:
//2L表示beep的消息类型
//这里呢相信大家天赋异禀,看懂了上面led的,beep也不是问题
pthread_mutex_unlock(&mutex_buzzer);
printf("hello beep1\n");
pthread_mutex_lock(&mutex_buzzer);
cmd_buzzer = msgbuf.text[0];
pthread_mutex_unlock(&mutex_buzzer);
pthread_cond_signal(&cond_buzzer);
break;
}
}
}
#endif
首先呢这个线程起初处于睡眠状态,当请求线程赋值完成控制命令字后,发送信号唤醒蜂鸣器线程;
#include "data_global.h"
#include "buzzer.h"
//第2N个元素表示声调 第2N+1个元素表示该声调的时间
unsigned char MUSIC[1000] ={
//祝你平安
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,
0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,
0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,
0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,
0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,
0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,
0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,
0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,
0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,
0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,
0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,
0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,
//路边的野华不要采
0x30,0x1C,0x10,0x20,0x40,0x1C,0x10,0x18,0x10,0x20,0x10,0x1C,0x10,0x18,0x40,0x1C,
0x20,0x20,0x20,0x1C,0x20,0x18,0x20,0x20,0x80,0xFF,0x20,0x30,0x1C,0x10,0x18,0x20,
0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,
0x30,0x80,0xFF,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,
0x20,0x2B,0x40,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,
0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0x20,0x30,0x1C,0x10,0x20,
0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x15,0x1F,
0x05,0x20,0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,
0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,
0x20,0x26,0x20,0x20,0x20,0x30,0x30,0x20,0x30,0x1C,0x10,0x18,0x40,0x1C,0x20,0x20,
0x20,0x26,0x40,0x13,0x60,0x18,0x20,0x15,0x40,0x13,0x40,0x18,0x80,0x00,
};
extern pthread_mutex_t mutex_buzzer;
extern pthread_cond_t cond_buzzer;
//A9蜂鸣器控制线程.
void *pthread_buzzer(void *arg)
{
printf("pthread_buzzer\n");
int i = 0;
int fd;
beep_desc_t beeper;
fd = open(BEEPER_DEV, O_RDWR);
if ( fd == -1 ) {
perror("open beeper failed.\n");
return NULL;
}
printf("fd :%d.\n",fd);
while(1) {
//pthread_mutex_unlock(&mutex_buzzer);
pthread_mutex_lock(&mutex_buzzer);
printf("buzzer ioctl:************\n");
pthread_cond_wait(&cond_buzzer, &mutex_buzzer);
printf("buzzer ioctl:************\n");
if(cmd_buzzer == 0x51)
{
ioctl(fd,BEEP_ON);
for(i = 0;i < sizeof(MUSIC)/sizeof(MUSIC[0]); i += 2)
{
beeper.tcnt = MUSIC[i];
beeper.tcmp = MUSIC[i]/2;
ioctl(fd,BEEP_FREQ,&beeper);
usleep(MUSIC[i+1] * 20000);
}
}
pthread_mutex_unlock(&mutex_buzzer);
}
printf("music play over....\n");
close(fd);
}
当然一定要在A9平台加载beep的驱动哦!
至此呢蜂鸣器的控制完结了,是不是感觉非常简单呢,这个就是照猫画虎了;可以说没啥技术含量,但是其中的细节还是值得大家注意的!最后呢希望大家能够遇到困难后,经过折腾后把这个操作完成!因为只有遇到了问题才能吸取教训,要是每一件事情都一次性过,那么当真正的问题出来的时候,我们往往显得黔驴技穷,所以在平时就要锻炼自己的能力,遇到问题不要着急,解决问题的过程就是成长!最后,各位小伙伴们如果有收获,可以点赞收藏哦,你们的认可是我创作的动力,一起加油!