嵌入式系统综合设计说明书
题 目:智能车系统—MP3播放器设计与实现 学生姓名:杜继凤
组 员:王嘉敏 杜继凤
学 院:信息工程学院
班 级:计算机11-2班
指导教师:庄旭菲 王晓强 蒋贵良 刘志强
2014 年 3 月 15 日
嵌入式项目T-CAR 智能小车是嵌入式技术和物联网技术结合的产物。TCAR 以三星高端微处理器为主控实现主要控制工作,将WIFI 无线通信与ZIGBEE 近距离无线组网通信相结合实现近距离和远程无线控制、信息采集等功能。T-CAR 即可作为互联网终端、物联网网关,也可以和工业控制、智能家居等系统融合使用。
本课题目的是在ARM-Linux 嵌入式环境下实现网络功能,系统主要由硬件层、内核层、应用层三部分构成。由于Linux 具有可移植度高、自由、免费等特性,最近几年,它在移动设备和个人电脑领域的应用也越来越广泛,因此我们选择Linux 操作系统,鉴于以上应用领域对用户界面友好性方面的要求,几乎所有的此类应用都是采用图形用户界面。播放界面采用Qt 设计,Qt 是创造图形用户界面的最流行的跨平台GUI 工具箱之一。这里将通过一个使用Qt 技术的简单mp3播放器的实现,详细描述Linux 环境下的图形界面编程技术。
本实训课程是嵌入式应用开发方向的实训课程,主要介绍嵌入式应用程序的开发技术,课程内容涉及C 语法及核心库、嵌入式Linux 开发环境、嵌入式Linux 应用开发流程。在内容组织上,以案例贯穿课程的始终。通过一系列案例的学习使学员能基本掌握嵌入式Linux 应用程序开发的基本技术,能开发出有图形界面,可交互,具有一定业务逻辑的嵌入式Linux 应用程序。
关键字:嵌入式;QT ;mp3播放器;
前言................................................................ 1
第一章 概述 ....................................................... 2
1.1课程设计目的................................................. 2
1.2课程背景与要求............................................... 2
1.2.1课程设计背景 ........................................... 2
1.2.2课程设计要求 ........................................... 3
1.3课程设计环境................................................. 3
第二章 设计方案 ................................................... 4
2.1设计功能..................................................... 4
2.2 设计思路 .................................................... 4
第三章 软件设计..................................................... 5
3.1模块流程图................................................... 5
3.2 Madplay 移植 ................................................ 6
3.3程序清单..................................................... 6
3.3.1音乐播放器服务器程序实现 ............................... 6
3.3.2音乐播放器客户端程序实现 .............................. 19
第四章 调试过程.................................................... 24
4.1硬件连接.................................................... 24
4.2软件连接.................................................... 24
4.2.1 操作系统.............................................. 24
4.2.2 系统软件.............................................. 24
4.2.3 工具软件.............................................. 24
4.2.4 文档和资源............................................ 25
4.3实验步骤.................................................... 25
4.4 出现的问题和解决方法 ....................................... 25
4.5运行结果截屏................................................ 26
第五章 总结........................................................ 28
参考文献........................................................... 29
前言
随着社会的日益信息化,计算机和网络已经全面渗透到日常生活的每一个角落。对于我们每个人来说,需要的已经不再仅仅是那种放在桌上处理文档、进行工作管理和生产控制的计算机机器。任何一个普通人都可能拥有从小到大的各种使用嵌入式技术的电子产品,小到MP3、PDA 等微型数字化产品,大到网络家电、智能家电、车载电子设备等。目前,各种各样的新型嵌入式系统设备在应用数量上已经远远超过了通用计算机。在工业和服务领域中,使用嵌入式技术的数字机床、智能工具、工业机器人、服务机器人正在逐渐改变着传统的工业生产和服务方式。
MP3是嵌入式的最主要应用之一,高端的MP3已经不仅仅着眼于实现音乐播放这一简单功能,而是同时具备了文本浏览、图片浏览、甚至视频播放等强大功能。本文重点讨论了基于WIFI 智能车的控制系统为主其中MP3的功能的实现,包括开发环境建立、内核配置与编译、Qt 开发等一系列详细过程。
近几年,嵌入式系统技术得到了广泛的应用,普适计算、无线传感器网络、可重构计算等新兴技术的出现又为嵌入式系统技术的研究与应用注入了新的活力。智能手机、信息家电、汽车电子、家用机器人„„嵌入式系统已“无处不在”。嵌入式系统是当今最热门的概念之一。
作为一个系统,往往是在硬件和软件双螺旋式交替发展的支撑下逐渐趋于稳定和成熟,嵌入式系统也不例外。
第一章 概述
嵌入式项目T-CAR 智能小车是嵌入式技术和物联网技术结合的产物。TCAR 以三星高端微处理器为主控实现主要控制工作,将WIFI 无线通信与ZIGBEE 近距离无线组网通信相结合实现近距离和远程无线控制、信息采集等功能。T-CAR 即可作为互联网终端、物联网网关,也可以和工业控制、智能家居等系统融合使用。
1.1课程设计目的
嵌入式系统设计与实践课程设计介绍基本设计与实现方法,是为计算机科学与技术专业本科生开设的一门重要的专业课程。是对以前所学很多知识的汇总和深化。通过三周的设计,能把以前很多所学的理论联系实际,培养学生的实验动手能力和创新意识,使学生对嵌入式系统有更全面的认识,掌握嵌入式系统的设计与开发的方法,为将来进行嵌入式应用系统的设计与开发奠定基础。
1.2课程背景与要求
1.2.1课程设计背景
物联网是一个基于互联网、 传统电信网等信息承载体, 让所有能够被独立寻址的普通物理对象实现互联互通的网络。物联网通过智能感知、识别技术与普适计算、泛在网络的融合应用,被称为继计算机、互联网之后世界信息产业发展的第三次浪潮。物联网被视为互联网的应用拓展,应用创新是物联网发展的核心,以用户体验为核心的创新 2.0 是物联网发展的灵魂。随着物联网的发展,越来越多的物联网控制终端将涌现,对于相关技术的学习需求和基于该领域的就业机会将大增,本智能车就是在此前提下诞生的。
该智能车具有很强的操控性、可玩性,同时融入嵌入式物联网相关技术,使学员可在相对轻松愉悦的环境中学习各种技术,让嵌入式技术的学习变得不在枯燥。
本车设计之初既考虑了可产品化空间,也考虑了技术知识点的涵盖,使学习更能明确目标;同时本项目在选材上也考虑了项目的手工打造的可能性,意在锻
炼学员的动手实践能力,只要学习者有兴趣,即可按所提供的材料清单和学习的相关技术自行打造,我们更希望能培养学习者的创客精神和创业欲望与意识。
1.2.2课程设计要求
要求采用C/S架构,完成对网络音乐播放器软件的分析、设计、编码、测试等工作。
音乐播放器功能说明:服务器实现完整的音乐播放器功能,客户端通过网络实现控制操作。
包括如下:
1、Madplay 音乐播放器移植。
2、音乐播放器服务器设计,通过网络接收客户端请求并执行对应动作,实现音乐播放、暂停、上一首、下一首、播放列表、停止等功能;
3、QT 客户端界面设计,要求利用qt 设计控制客户端界面,实现通过网络向服务器发送命令请求等功能。
1.3课程设计环境
环境要求:操作系统:windows 7+ubuntu虚拟系统
平台:vim 编辑器,GNU 工具链,Qtcreator 集成开发环境 开发语言:C/C++
文档环境:windows office
2.1设计功能
音乐播放器功能说明:服务器实现完整的音乐播放器功能,客户端通过网络实现控制操作。
包括如下:
1、Madplay 音乐播放器移植;
2、音乐播放器服务器设计,通过网络接收客户端请求并执行对应动作,实现音乐播放、暂停、上一首、下一首、播放列表、停止等功能;
3、QT 客户端界面设计,要求利用qt 设计控制客户端界面,实现通过网络向服务器发送命令请求等功能。
2.2 设计思路
1、开发环境搭建,虚拟机配置相关vim 编辑器,gcc 编译器等相关软件配置。
2、madplay 音乐播放器移植,包括libmad 音频解码库的使用,,所以首先需要移植madplay ,具体方法如下:
1)创建安装库的路径 sudo mkdir /opt/arm/madplay/lib
2)进入madplay 源码目录 执行./build
3 ) 测试将madplay 和库文件复制到根文件系统, 配置LD_LIBRARY_PATH,执行madplay xxx.mp3。
3、服务器端程序设计,采用C 语言在Linux 环境在完成音乐播放器功能。
4、利用Qtcreator 设计客户端界面,实现向服务器发送控制命令等功能
3.1模块流程图
图1.1模块流程图
3.2 Madplay 移植
1) 首先建立一个mp3 文件夹,进入到mp3 文件夹后再建立两个文件夹,一个存放源码,一个存放安装文件。在home 下,mkdir 两个文件夹:madplay-src 、madplay 。依次解压四个源码包到madplay 目录下:tar zxvf XXX.tar.gz
(2) 编译zlib-1.1.4
进入zlib 源文件目录,依此执行./configure9 / 26make make install
(3) 编译libid3tag
进入tag 源码目录,依此执行./configure make make install
(4) 编译libmad
进入libmad 源码,依此执行./configuremake
注:使用的是高版本的ARM-LINUX-GCC 如4.4.6 编译器,MAKE 时可能会出现”CCL:ERROR:UNRECOGNIZED COMMAND LINE OPTION “-FFORCE-MEM””错误,这是因为这个高版本的GCC 没有”-FFORCEMEM”参数,解决的办法是在LIBMAD 文件中的MAKEFILE 里面查找”-FFORCE-MEM”,将其删除即可 make install
(5) 编译madplay
进入madplay 源码目录,依此执行./configure –-with alsa make make install
(6) 测试madplay
执行命令(配置环境变量) :export LD_LIBRARY_PATH
=$LD_LIBRARY_PATH/usr/local/lib
运行:madplay xx.mp3
3.3程序清单
3.3.1音乐播放器服务器程序实现
1.player.c
#include "common.h"
#include "socket.h"
#include "player.h"/*孙子进程id 号*/
pid_t gradchild;/*子进程id 号*/
pid_t pid;/*共享内存描述标记*/
int shmid;
char *p_addr;/*共享内存内容格式*//*|gradchild(孙子进程PID) |+ |空一个字节|+ currentsong(当前播放列表的节点指针)
|*//*listhead for music*/
struct song* head;/*创建歌曲名的双向循环链表*/
struct song *creat_song_list(void)
{FILE *fd;
ssize_t size;
size_t len;
char *line = NULL;
struct song *p1;
struct song *p2;
int res=system("ls ./song > song_list");
if(res == -1) perror("system");
fd = fopen("song_list","rb");
if(fd==NULL){
perror("fopen");}
p1 = (struct song *)malloc(sizeof(struct song));
printf("==================================song
list=====================================\n");
res=system("ls ./song");
if(res == -1) perror("system");
printf("\n");
printf("================================================================================\n");
size = getline(&line,&len,fd);
strncpy(p1->songname,line,strlen(line));
head = p1;
int n=strlen(line);
(head->songname)[n]='\0';
while((size = getline(&line,&len,fd)) != -1) //从文件中读取一行,直到出错或者到文件尾EOF 返回-1
{p2 = p1;
p1 = (struct song *)malloc(sizeof(struct song));
strncpy(p1->songname,line,strlen(line));
p2->next = p1;
p1->prev = p2;
int n=strlen(line);
(p1->songname)[n]='\0';}
p1->next = head;
head->prev = p1;
p1 = NULL;
p2 = NULL;
res=system("rm -rf song_list");
if(res == -1) perror("system");
return head;}/*MP3 音乐播放器-->播放音乐函数*/
void play(struct song *currentsong)
{pid_t newfd;
char *c_addr;
void *tempaddr;
char *p;
int len;
char my_song[2048]="./song/";
while(currentsong)
{printf("currentsong size=%d\n",strlen(currentsong->songname));/*子进程创建孙子进程*/
newfd = fork();
if(newfd == -1)
{perror("fork");
exit(1);}
else if(newfd == 0) //孙子进程
{printf("play fork success!\n");/*把歌曲名加上根路径*/
strcat(my_song,currentsong->songname);
p = my_song;
len = strlen(p);/*去掉文件名最后的'\0'*/
my_song[len-1]='\0';
printf("THIS SONG IS %s size=%d\n",my_song,strlen(my_song)); /*运行madplay 播放器,播放MP3*/
execl("/usr/local/sbin/madplay","madplay",my_song,NULL);//播放当前列表MP3 音乐
printf("\n\n\n");}
else //子进程
{/*内存映射*/
tempaddr = shmat(shmid,0,0);
c_addr = (char *)tempaddr;/*把孙子进程的id 和当前播放歌曲的节点指针传入共享内存*/
memcpy(c_addr,&newfd,sizeof(pid_t));
memcpy(c_addr + sizeof(pid_t)+1,¤tsong,4);/*使用wait 阻塞子进程,直到孙子进程播放完才能被唤醒;当被唤醒时,表示播放MP3 期间没有按键按下,则继续顺序播放下一首MP3*/
if(newfd == wait(NULL))
{currentsong = currentsong->next;
printf("THE NEXT SONG IS %s\n",currentsong->songname);}}}}
/*MP3 音乐播放器-->调用play 函数播放音乐*/
void startplay(pid_t *childpid,struct song *my_song)
{pid_t pid;//如果没有音乐正在播放并且不是处于暂停状态
if((play_flag == 0) && (play_pause_flag != 1)){
play_flag = 1;
play_stop_flag = 0;/*创建子进程*/
pid = fork();
if(pid > 0){ //父进程
*childpid = pid; //子进程PID 初始化
sleep(1);/*读取共享内存保存的pid, 初始化孙子进程的pid*/
/*p_addr 指向共享内存,保存的是孙子进程的ID*/
memcpy(&gradchild,p_addr,sizeof(pid_t));}
else if(0 == pid){ //子进程/*子进程播放MP3 函数*/
play(my_song);}}//如果没有音乐正在播放并处于暂停状态
else if((play_flag == 0) && (play_pause_flag == 1)){
play_flag = 1;
play_pause_flag = 0;
conti_play(gradchild);}
else
return;}
/*MP3 音乐播放器-->暂停播放*/
void my_pause(pid_t pid)
{if((play_flag == 1) && (play_pause_flag == 0)){
printf("=======================PAUSE!PRESS PLAY TO
CONTINUE===================\n");
kill(pid,SIGSTOP); //对孙子进程发送SIGSTOP 信号
play_pause_flag = 1;
play_flag = 0;}
else
return;}
/*MP3 音乐播放器-->继续播放*/
void conti_play(pid_t pid)
{printf("===============================CONTINUE=============================\n");
kill(pid,SIGCONT); //对孙子进程发送SIGCONT 信号}
/*MP3 音乐播放器-->播放下一首*/
/*只有正在播放音乐的状态下,上一首和下一首才有作用*/
void next(pid_t next_pid)
{int res;
if(play_flag == 0){
return;}
else{
struct song *nextsong;
printf("===============================NEXTMP3=============================\n");
/*从共享内存获得孙子进程播放歌曲的节点指针*/
memcpy(&nextsong,p_addr + sizeof(pid_t)+1,4);
/*指向下首歌曲的节点*/
nextsong = nextsong->next;
/*杀死当前歌曲播放的子进程,孙子进程*/
res = kill(pid,SIGKILL);
if(res == -1){
perror("kill next pid error");
return;}
res = kill(next_pid,SIGKILL);
if(res == -1){
perror("kill next next_pid error");
res=system("killall madplay");
if(res == -1) perror("system");}
//wait(NULL);
play_flag = 0;
startplay(&pid,nextsong);}}
/*MP3 音乐播放器-->播放上一首*/
void prev(pid_t prev_pid)
{int res;
if(play_flag == 0){
return;}
else {
struct song *prevsong;
/*从共享内存获得孙子进程播放歌曲的节点指针*/
printf("===============================PRIORMP3======================
=======\n");
memcpy(&prevsong,p_addr + sizeof(pid_t)+1,4);
/*指向上首歌曲的节点*/
prevsong = prevsong->prev;
/*杀死当前歌曲播放的子进程,孙子进程*/
res = kill(pid,SIGKILL);
if(res == -1){
perror("kill prev pid error");
return;}
res = kill(prev_pid,SIGKILL);
if(res == -1){
perror("kill prev prev_pid error");
res=system("killall madplay");
if(res == -1) perror("system");}
//wait(NULL);
play_flag = 0;
startplay(&pid,prevsong);}}
/*MP3 音乐播放器-->停止播放*/
void my_stop(pid_t g_pid)
{int res;
if(play_stop_flag == 1){//如果已经停止,直接返回
return;}
if((play_flag == 1) || (play_pause_flag == 1)){
printf("=======================STOP!PRESS PLAY TO
START===================\n");
res = kill(pid,SIGKILL); //对子进程发送SIGKILL 信号
if(res == -1){
perror("stop pid error");
return;}
res = kill(g_pid,SIGKILL); //对孙子进程发送SIGKILL 信号
if(res == -1){
perror("stop g_pid error");
res=system("killall madplay");
if(res == -1) perror("system");}
play_flag = 0;
play_stop_flag = 1;
play_pause_flag = 0;}
else
return;}
/*MP3 音乐播放器-->播放列表*/
/*搜索列表音乐名字与歌曲相匹配,并杀死正在播放歌曲进程而播放对应列表音乐*/
void playlist(pid_t childpid,char *listsong)
{int res;
play_flag = 0;
if(strncmp(head->songname,listsong,4) == 0){
res = kill(pid,SIGKILL);
if(res == -1){
perror("playlist kill pid error");
return;}
res = kill(childpid,SIGKILL);
if(res == -1){
perror("playlist kill childpid error");
res=system("killall madplay");
if(res == -1) perror("system");}
wait(NULL);
startplay(&pid,head);
return ;}
struct song *nextsong=head->next;
do{
if(strncmp(nextsong->songname,listsong,4)==0){
res = kill(pid,SIGKILL);
if(res == -1){
perror("playlist kill pid error");
return;}
res = kill(childpid,SIGKILL);
if(res == -1){
perror("playlist kill childpid error");
res=system("killall madplay");
if(res == -1) perror("system");}
wait(NULL);
startplay(&pid,nextsong);
return;}
nextsong=nextsong->next;
}while(nextsong!=head);}
/*接收客户端命令*/
void recvcmd(void)
{int cmd=0;
char buf[SIZE];
memset(buf,0,sizeof(buf));
while(1){
int len = recvfrom(server_sockfd,&cmd,4,0,(struct
sockaddr*)&server_addr,&sin_size);
if(len
continue;}
switch (cmd){
case PLAY:
startplay(&pid,head);
break;
case PAUSE:
my_pause(gradchild);
break;
case STOP:
my_stop(gradchild);
break;
case NEXT:
next(gradchild);
break;
case PREV:
prev(gradchild);
break;
case LISTSONG:
memset(buf,0,sizeof(buf));
len=recvfrom(server_sockfd,buf,sizeof(buf),0,(struct sockaddr*)&client_addr,&sin_size);
if(len>0){
printf("recv listbuf = %s\n",buf);
playlist(gradchild,buf);}
break;
default:
puts("not find the cmd!");
break;}}}
int main()
{/*创建播放列表*/
head=creat_song_list();
/*共享内存:用于存放子进程ID ,播放列表位置*/
void *tempaddr;
if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)
perror("shmget");
tempaddr = shmat(shmid,0,0);
if(tempaddr == (void *)-1){
perror("shmat");}
p_addr = (char *)tempaddr;
memset(p_addr,'\0',1024);
/*初始化MP3 播放停止标志*/
play_flag=0;
play_stop_flag=0;
play_pause_flag=0;
//初始化网络
int res=create_socket();
if(res
perror("create_socket");}
//接收控制命令(死循环);
recvcmd();
return 0;}
2.play.h
#ifndef PLAYER_H
#define PLAYER_H
/*共享内存申请标记*/
#define PERM S_IRUSR|S_IWUSR
#define SIZE 1024
struct song
{char songname[1024];
struct song *prev;
struct song *next;};
char *playsong;
/*播放标记*/
int play_flag;
int play_stop_flag;
int play_pause_flag;
/*保存接收到的字符串(推送过来的消息)*/
char temp_str[100];
unsigned int pos;
extern void play(struct song *currentsong);
extern struct song *creat_song_list(void);
extern void startplay(pid_t *childpid,struct song *my_song); extern void my_pause(pid_t pid);
extern void my_stop(pid_t g_pid);
extern void conti_play(pid_t pid);
extern void next(pid_t next_pid);
extern void prev(pid_t prev_pid);
extern void playlist(pid_t childpid,char *listsong); #endif
3.socket.c
#include "socket.h"
int server_sockfd;
socklen_t sin_size;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int create_socket()
{memset(&server_addr, 0, sizeof(server_addr));
/* 初始化网络信息*/
server_addr.sin_family = AF_INET; //设置为IP 通信
server_addr.sin_addr.s_addr = INADDR_ANY; //无限制
server_addr.sin_port = htons(8000);
if ((server_sockfd = socket(PF_INET,SOCK_DGRAM,0))
if(bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))
return -1;}
return 1;
sin_size = sizeof(struct sockaddr_in);}
4.socket.h
#ifndef SOCKET_H
#define SOCKET_H
#include "common.h"
#define PLAY 11
#define PAUSE 12
#define STOP 13
#define CONTINUE 14
#define NEXT 15
#define PREV 16
#define LISTSONG 18
extern int server_sockfd;
extern socklen_t sin_size;
extern struct sockaddr_in server_addr;
extern struct sockaddr_in client_addr;
extern int create_socket();
#endif
5.common.h
#ifndef __COMMON_H
#define __COMMON_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERROR -1
#endif
6.makefile
name=*.c
BIN=player
FLAGS=-g -O2 -Wall
default:gcc $(FLAGS) $(name) -o $(BIN)__
3.3.2音乐播放器客户端程序实现
1,player.cpp
#include "player.h"
#include "ui_player.h"
#include "listmusic.h"
#include "socket.h"
player::player(QWidget *parent) :
QDialog(parent),
ui(new Ui::player)
{ui->setupUi(this);
init_socket();}
player::~player()
{delete ui;}
void player::on_play_clicked()
{int cmd = 0;
int len;
cmd = PLAY;
len=sendto(client_sockfd, &cmd, 4,0, (struct sockaddr *)&client_addr, sin_size);
if (len
return;}}
void player::on_pause_clicked()
{int cmd = PAUSE;
int len=sendto(client_sockfd,&cmd,4,0,(struct sockaddr
*)&client_addr,sin_size);
if(len
return ;}}
void player::on_next_clicked()
{int cmd = NEXT;
int len=sendto(client_sockfd, &cmd, 4,0, (struct sockaddr
*)&client_addr, sin_size);
if (len
return;}}
void player::on_prev_clicked()
{int cmd = PREV;
int len=sendto(client_sockfd, &cmd, 4,0, (struct sockaddr
*)&client_addr, sin_size);
if (len
网络数据失败")));
return;}}
void player::on_listbutton_clicked()
{player xy3;
listmusic l;//l.setWindowFlags(Qt::FramelessWindowHint);
l.setGeometry(850,250,250,350);//l.show();
if(l.exec()==Accepted){
xy3.show();}}
void player::on_stop_clicked()
{int cmd = STOP;
int len=sendto(client_sockfd, &cmd, 4,0, (struct sockaddr
*)&client_addr, sin_size);
if (len
return;}}
2.play.h
#ifndef PLAYER_H
#define PLAYER_H
#include
#include
#include
#include
#include
#include
#include
#include
#include "socket.h"
namespace Ui {
class player;}
class player : public QDialog
{Q_OBJECT
public:
explicit player(QWidget *parent = 0);
~player();
private slots:
void on_play_clicked();
void on_pause_clicked();
void on_next_clicked();
void on_prev_clicked();
void on_listbutton_clicked();
void on_stop_clicked();
private:
Ui::player *ui;};
#endif // PLAYER_H
3.socket.cpp
#include "socket.h"
/* 网络通信变量*/
int client_sockfd;
int len;
int sin_size;
struct sockaddr_in client_addr;
void init_socket()
{/* 创建socket 跟设备进行通信*/
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //服务器IP //client_addr.sin_addr.s_addr = inet_addr("192.168.1.6"); client_addr.sin_port = htons(8000);
if ((client_sockfd = socket(PF_INET,SOCK_DGRAM,0))
exit(-1);}
sin_size = sizeof(struct sockaddr_in);}
#ifndef SOCKET_H
#define SOCKET_H
4.socket.h
/* 网络数据头文件*/
#include
#include /* See NOTES */
#include
#include
#include
#include
#include
#include
#include
#include
#define PLAY 11
#define PAUSE 12
#define STOP 13
#define CONTINUE 14
#define NEXT 15
#define PREV 16
#define LISTSONG 18
extern void init_socket();
extern int client_sockfd;
extern int len;
extern int sin_size;
extern struct sockaddr_in client_addr;
#endif // SOCKET_H
第四章 调试过程
4.1硬件连接
实训机器的硬件配置要求如下:
硬件类型 主讲机器 学员机器
CPU:(主讲机器)基本 Intel Pentium 系列2.0GHz 以上,推荐Intel Pentium 系列双核;
(学员机器)Intel Pentium 系列1.6GHz 以上, 推荐Intel Pentium 系列2.0GHz 以上。
内存:(主讲机器)基本 DDR3 系列内存2GB 容量 DDR3 系列内存2 容量,推荐 DDR3 系列内存4GB 容量 DDR3 系列内存4GB 容量硬盘;
(学员机器)基本 不小于60GB 容量 不小于60GB 容量,推荐 120GB 以上容量 120GB 以上容量。
4.2软件连接
4.2.1 操作系统
1. 学生机器使用ubuntu 12.04 系列32 位操作系统 或
windows+VMware 虚拟系统。
2. 讲师机器使用ubuntu 12.04 系列32 位操作系统。
4.2.2 系统软件
1.GCC (Linux 下C 语言编译工具)
2. 文本编辑工具:vim 或其他文本编辑工具
3.qtcreate 集成开发环境
4.2.3 工具软件
1.telnet 远程登陆工具
2. 如果没有投影仪,需要屏幕共享工具。
4.2.4 文档和资源
1.man 手册 c 语言库函数帮组页:
2. 实训全套代码(随附件一起提供)
4.3实验步骤
智能车内置MP3 播放程序,采用基于madplay 的音乐播放器,所以首先需要移植madplay ,具体方法如下:
1)创建安装库的路径 sudo mkdir /opt/arm/madplay/lib
2)进入madplay 源码目录 执行./build
3) 测试将madplay 和库文件复制到根文件系统, 配置
LD_LIBRARY_PATH,执行madplay xxx.mp3。
音乐播放器应用程序采用多进程控制音乐播放,暂停,上一首,下一首播放等功能。参考代码:
system("madplay north.mp3 &");
//利用system 函数调用madplay 播放器播放*.mp3 音乐
system("killall -9 madplay");
//利用system 函数调用killall 命令将madplay 终止掉
system("killall -STOP madplay &");
//利用system 函数调用killall 命令将madplay 暂停
system("killall -CONT madplay &");
//利用system 函数调用killall 命令恢复madplay 的播放
4.4 出现的问题和解决方法
出现的问题:
1.car.cpp 文件中没有socket 这个类
2. 把小车的IP 地址定义错误
3. 小车的端口和服务器的端口弄反了
4.lee 这个参数没有声明
5. 分号用成了汉语的分号
6.Save 这个函数的使用格式出现了错误
7. 一些函数的参数的使用不正确
8. 参数中的类型定义出现错误使显示结果不正确
9. 使用ui 时,没有进行转到槽,使得程序出现错误 解决的方法:
1. 上网查阅相关资料而后改正
2. 和同学一起探讨
3. 向老师获得帮助
4. 查阅实验手册进行对照后改正错误
5. 查看出现错误的地方根据自己的经验改正 改正方式:
1. 在car.cpp 中添加socket.h
2. 参看实验手册改正端口和IP 地址
3. 改正参数的类型
4. 参阅错误函数的使用方法,而后改正错误
5. 从新Push Botton,然后转到槽
6. 把分号改为字母的分号
4.5运行结果截屏
模拟播放器:
播放列表:
第五章 总结
该项目从历时3周的时间,我已经完成了该项目的所有工作。从开始接到课程题目到系统的实现,再到课程文章的完成,每走一步对我来说都是新的尝试与挑战,这也是我在大学期间独立完成的最大的项目。在这段时间里,我学到了很多知识也有很多感受,从对Linux 下图形界面应用程序开发一无所知,对GTK ,GStreamer ,QT 等相关技术很不了解的状态,我开始了独立的学习和试验,查看相关的资料和书籍,让自己头脑中模糊的概念逐渐清晰,使自己非常稚嫩作品一步步完善起来,每一次改进都是我学习的收获,每一次代码的成功运行都会让我兴奋好一段时间。
虽然我的论文作品不是很成熟,还有很多不足之处,但我可以自豪的说,这里面的每一段代码,都有我的劳动。当看着自己的播放器能够完美的播放出动听的歌曲,真是莫大的幸福和欣慰。我相信其中的酸甜苦辣最终都会化为甜美的甘泉。
这次做设计报告的经历也会使我终身受益,我感受到做论文是要真真正正用心去做的一件事情,是真正的自己学习的过程和研究的过程,没有学习就不可能有研究的能力,没有自己的研究,就不会有所突破。
在学习中,我更了解到自己知识的不足和有限,通过达内老师的讲解,使我学会了不少我不了解的知识,使我受益匪浅,将学到的知识应用于实践当中。当然,在以后的学习或工作中,我也会不断的充实自己,学习更多新的知识,来丰富自己。
参考文献
【1】王道乾 刘定智 文俊浩,基于ARM 处理器的MP3播放器分析与实现, 计算机工程与设计[L],2007,28(7):1595~1597
【2】王 奇, 基于嵌入式linux 的多媒体音乐播放器的设计与实现, 信息技术
[L],2009, (6):102~104
【3】王建民 张宏壮, 基于Qt 的嵌入式媒体播放器系统的设计, 微计算机信息(嵌入式与SOC )[L],2008,24(7-2):64~66
【4】达内公司 智能车实验说明书
【5】达内公司 达内实训大纲(内蒙古工业大学)
【6】unix 高级环境编程
【7】linux 设备驱动第三版
嵌入式系统综合设计说明书
题 目:智能车系统—MP3播放器设计与实现 学生姓名:杜继凤
组 员:王嘉敏 杜继凤
学 院:信息工程学院
班 级:计算机11-2班
指导教师:庄旭菲 王晓强 蒋贵良 刘志强
2014 年 3 月 15 日
嵌入式项目T-CAR 智能小车是嵌入式技术和物联网技术结合的产物。TCAR 以三星高端微处理器为主控实现主要控制工作,将WIFI 无线通信与ZIGBEE 近距离无线组网通信相结合实现近距离和远程无线控制、信息采集等功能。T-CAR 即可作为互联网终端、物联网网关,也可以和工业控制、智能家居等系统融合使用。
本课题目的是在ARM-Linux 嵌入式环境下实现网络功能,系统主要由硬件层、内核层、应用层三部分构成。由于Linux 具有可移植度高、自由、免费等特性,最近几年,它在移动设备和个人电脑领域的应用也越来越广泛,因此我们选择Linux 操作系统,鉴于以上应用领域对用户界面友好性方面的要求,几乎所有的此类应用都是采用图形用户界面。播放界面采用Qt 设计,Qt 是创造图形用户界面的最流行的跨平台GUI 工具箱之一。这里将通过一个使用Qt 技术的简单mp3播放器的实现,详细描述Linux 环境下的图形界面编程技术。
本实训课程是嵌入式应用开发方向的实训课程,主要介绍嵌入式应用程序的开发技术,课程内容涉及C 语法及核心库、嵌入式Linux 开发环境、嵌入式Linux 应用开发流程。在内容组织上,以案例贯穿课程的始终。通过一系列案例的学习使学员能基本掌握嵌入式Linux 应用程序开发的基本技术,能开发出有图形界面,可交互,具有一定业务逻辑的嵌入式Linux 应用程序。
关键字:嵌入式;QT ;mp3播放器;
前言................................................................ 1
第一章 概述 ....................................................... 2
1.1课程设计目的................................................. 2
1.2课程背景与要求............................................... 2
1.2.1课程设计背景 ........................................... 2
1.2.2课程设计要求 ........................................... 3
1.3课程设计环境................................................. 3
第二章 设计方案 ................................................... 4
2.1设计功能..................................................... 4
2.2 设计思路 .................................................... 4
第三章 软件设计..................................................... 5
3.1模块流程图................................................... 5
3.2 Madplay 移植 ................................................ 6
3.3程序清单..................................................... 6
3.3.1音乐播放器服务器程序实现 ............................... 6
3.3.2音乐播放器客户端程序实现 .............................. 19
第四章 调试过程.................................................... 24
4.1硬件连接.................................................... 24
4.2软件连接.................................................... 24
4.2.1 操作系统.............................................. 24
4.2.2 系统软件.............................................. 24
4.2.3 工具软件.............................................. 24
4.2.4 文档和资源............................................ 25
4.3实验步骤.................................................... 25
4.4 出现的问题和解决方法 ....................................... 25
4.5运行结果截屏................................................ 26
第五章 总结........................................................ 28
参考文献........................................................... 29
前言
随着社会的日益信息化,计算机和网络已经全面渗透到日常生活的每一个角落。对于我们每个人来说,需要的已经不再仅仅是那种放在桌上处理文档、进行工作管理和生产控制的计算机机器。任何一个普通人都可能拥有从小到大的各种使用嵌入式技术的电子产品,小到MP3、PDA 等微型数字化产品,大到网络家电、智能家电、车载电子设备等。目前,各种各样的新型嵌入式系统设备在应用数量上已经远远超过了通用计算机。在工业和服务领域中,使用嵌入式技术的数字机床、智能工具、工业机器人、服务机器人正在逐渐改变着传统的工业生产和服务方式。
MP3是嵌入式的最主要应用之一,高端的MP3已经不仅仅着眼于实现音乐播放这一简单功能,而是同时具备了文本浏览、图片浏览、甚至视频播放等强大功能。本文重点讨论了基于WIFI 智能车的控制系统为主其中MP3的功能的实现,包括开发环境建立、内核配置与编译、Qt 开发等一系列详细过程。
近几年,嵌入式系统技术得到了广泛的应用,普适计算、无线传感器网络、可重构计算等新兴技术的出现又为嵌入式系统技术的研究与应用注入了新的活力。智能手机、信息家电、汽车电子、家用机器人„„嵌入式系统已“无处不在”。嵌入式系统是当今最热门的概念之一。
作为一个系统,往往是在硬件和软件双螺旋式交替发展的支撑下逐渐趋于稳定和成熟,嵌入式系统也不例外。
第一章 概述
嵌入式项目T-CAR 智能小车是嵌入式技术和物联网技术结合的产物。TCAR 以三星高端微处理器为主控实现主要控制工作,将WIFI 无线通信与ZIGBEE 近距离无线组网通信相结合实现近距离和远程无线控制、信息采集等功能。T-CAR 即可作为互联网终端、物联网网关,也可以和工业控制、智能家居等系统融合使用。
1.1课程设计目的
嵌入式系统设计与实践课程设计介绍基本设计与实现方法,是为计算机科学与技术专业本科生开设的一门重要的专业课程。是对以前所学很多知识的汇总和深化。通过三周的设计,能把以前很多所学的理论联系实际,培养学生的实验动手能力和创新意识,使学生对嵌入式系统有更全面的认识,掌握嵌入式系统的设计与开发的方法,为将来进行嵌入式应用系统的设计与开发奠定基础。
1.2课程背景与要求
1.2.1课程设计背景
物联网是一个基于互联网、 传统电信网等信息承载体, 让所有能够被独立寻址的普通物理对象实现互联互通的网络。物联网通过智能感知、识别技术与普适计算、泛在网络的融合应用,被称为继计算机、互联网之后世界信息产业发展的第三次浪潮。物联网被视为互联网的应用拓展,应用创新是物联网发展的核心,以用户体验为核心的创新 2.0 是物联网发展的灵魂。随着物联网的发展,越来越多的物联网控制终端将涌现,对于相关技术的学习需求和基于该领域的就业机会将大增,本智能车就是在此前提下诞生的。
该智能车具有很强的操控性、可玩性,同时融入嵌入式物联网相关技术,使学员可在相对轻松愉悦的环境中学习各种技术,让嵌入式技术的学习变得不在枯燥。
本车设计之初既考虑了可产品化空间,也考虑了技术知识点的涵盖,使学习更能明确目标;同时本项目在选材上也考虑了项目的手工打造的可能性,意在锻
炼学员的动手实践能力,只要学习者有兴趣,即可按所提供的材料清单和学习的相关技术自行打造,我们更希望能培养学习者的创客精神和创业欲望与意识。
1.2.2课程设计要求
要求采用C/S架构,完成对网络音乐播放器软件的分析、设计、编码、测试等工作。
音乐播放器功能说明:服务器实现完整的音乐播放器功能,客户端通过网络实现控制操作。
包括如下:
1、Madplay 音乐播放器移植。
2、音乐播放器服务器设计,通过网络接收客户端请求并执行对应动作,实现音乐播放、暂停、上一首、下一首、播放列表、停止等功能;
3、QT 客户端界面设计,要求利用qt 设计控制客户端界面,实现通过网络向服务器发送命令请求等功能。
1.3课程设计环境
环境要求:操作系统:windows 7+ubuntu虚拟系统
平台:vim 编辑器,GNU 工具链,Qtcreator 集成开发环境 开发语言:C/C++
文档环境:windows office
2.1设计功能
音乐播放器功能说明:服务器实现完整的音乐播放器功能,客户端通过网络实现控制操作。
包括如下:
1、Madplay 音乐播放器移植;
2、音乐播放器服务器设计,通过网络接收客户端请求并执行对应动作,实现音乐播放、暂停、上一首、下一首、播放列表、停止等功能;
3、QT 客户端界面设计,要求利用qt 设计控制客户端界面,实现通过网络向服务器发送命令请求等功能。
2.2 设计思路
1、开发环境搭建,虚拟机配置相关vim 编辑器,gcc 编译器等相关软件配置。
2、madplay 音乐播放器移植,包括libmad 音频解码库的使用,,所以首先需要移植madplay ,具体方法如下:
1)创建安装库的路径 sudo mkdir /opt/arm/madplay/lib
2)进入madplay 源码目录 执行./build
3 ) 测试将madplay 和库文件复制到根文件系统, 配置LD_LIBRARY_PATH,执行madplay xxx.mp3。
3、服务器端程序设计,采用C 语言在Linux 环境在完成音乐播放器功能。
4、利用Qtcreator 设计客户端界面,实现向服务器发送控制命令等功能
3.1模块流程图
图1.1模块流程图
3.2 Madplay 移植
1) 首先建立一个mp3 文件夹,进入到mp3 文件夹后再建立两个文件夹,一个存放源码,一个存放安装文件。在home 下,mkdir 两个文件夹:madplay-src 、madplay 。依次解压四个源码包到madplay 目录下:tar zxvf XXX.tar.gz
(2) 编译zlib-1.1.4
进入zlib 源文件目录,依此执行./configure9 / 26make make install
(3) 编译libid3tag
进入tag 源码目录,依此执行./configure make make install
(4) 编译libmad
进入libmad 源码,依此执行./configuremake
注:使用的是高版本的ARM-LINUX-GCC 如4.4.6 编译器,MAKE 时可能会出现”CCL:ERROR:UNRECOGNIZED COMMAND LINE OPTION “-FFORCE-MEM””错误,这是因为这个高版本的GCC 没有”-FFORCEMEM”参数,解决的办法是在LIBMAD 文件中的MAKEFILE 里面查找”-FFORCE-MEM”,将其删除即可 make install
(5) 编译madplay
进入madplay 源码目录,依此执行./configure –-with alsa make make install
(6) 测试madplay
执行命令(配置环境变量) :export LD_LIBRARY_PATH
=$LD_LIBRARY_PATH/usr/local/lib
运行:madplay xx.mp3
3.3程序清单
3.3.1音乐播放器服务器程序实现
1.player.c
#include "common.h"
#include "socket.h"
#include "player.h"/*孙子进程id 号*/
pid_t gradchild;/*子进程id 号*/
pid_t pid;/*共享内存描述标记*/
int shmid;
char *p_addr;/*共享内存内容格式*//*|gradchild(孙子进程PID) |+ |空一个字节|+ currentsong(当前播放列表的节点指针)
|*//*listhead for music*/
struct song* head;/*创建歌曲名的双向循环链表*/
struct song *creat_song_list(void)
{FILE *fd;
ssize_t size;
size_t len;
char *line = NULL;
struct song *p1;
struct song *p2;
int res=system("ls ./song > song_list");
if(res == -1) perror("system");
fd = fopen("song_list","rb");
if(fd==NULL){
perror("fopen");}
p1 = (struct song *)malloc(sizeof(struct song));
printf("==================================song
list=====================================\n");
res=system("ls ./song");
if(res == -1) perror("system");
printf("\n");
printf("================================================================================\n");
size = getline(&line,&len,fd);
strncpy(p1->songname,line,strlen(line));
head = p1;
int n=strlen(line);
(head->songname)[n]='\0';
while((size = getline(&line,&len,fd)) != -1) //从文件中读取一行,直到出错或者到文件尾EOF 返回-1
{p2 = p1;
p1 = (struct song *)malloc(sizeof(struct song));
strncpy(p1->songname,line,strlen(line));
p2->next = p1;
p1->prev = p2;
int n=strlen(line);
(p1->songname)[n]='\0';}
p1->next = head;
head->prev = p1;
p1 = NULL;
p2 = NULL;
res=system("rm -rf song_list");
if(res == -1) perror("system");
return head;}/*MP3 音乐播放器-->播放音乐函数*/
void play(struct song *currentsong)
{pid_t newfd;
char *c_addr;
void *tempaddr;
char *p;
int len;
char my_song[2048]="./song/";
while(currentsong)
{printf("currentsong size=%d\n",strlen(currentsong->songname));/*子进程创建孙子进程*/
newfd = fork();
if(newfd == -1)
{perror("fork");
exit(1);}
else if(newfd == 0) //孙子进程
{printf("play fork success!\n");/*把歌曲名加上根路径*/
strcat(my_song,currentsong->songname);
p = my_song;
len = strlen(p);/*去掉文件名最后的'\0'*/
my_song[len-1]='\0';
printf("THIS SONG IS %s size=%d\n",my_song,strlen(my_song)); /*运行madplay 播放器,播放MP3*/
execl("/usr/local/sbin/madplay","madplay",my_song,NULL);//播放当前列表MP3 音乐
printf("\n\n\n");}
else //子进程
{/*内存映射*/
tempaddr = shmat(shmid,0,0);
c_addr = (char *)tempaddr;/*把孙子进程的id 和当前播放歌曲的节点指针传入共享内存*/
memcpy(c_addr,&newfd,sizeof(pid_t));
memcpy(c_addr + sizeof(pid_t)+1,¤tsong,4);/*使用wait 阻塞子进程,直到孙子进程播放完才能被唤醒;当被唤醒时,表示播放MP3 期间没有按键按下,则继续顺序播放下一首MP3*/
if(newfd == wait(NULL))
{currentsong = currentsong->next;
printf("THE NEXT SONG IS %s\n",currentsong->songname);}}}}
/*MP3 音乐播放器-->调用play 函数播放音乐*/
void startplay(pid_t *childpid,struct song *my_song)
{pid_t pid;//如果没有音乐正在播放并且不是处于暂停状态
if((play_flag == 0) && (play_pause_flag != 1)){
play_flag = 1;
play_stop_flag = 0;/*创建子进程*/
pid = fork();
if(pid > 0){ //父进程
*childpid = pid; //子进程PID 初始化
sleep(1);/*读取共享内存保存的pid, 初始化孙子进程的pid*/
/*p_addr 指向共享内存,保存的是孙子进程的ID*/
memcpy(&gradchild,p_addr,sizeof(pid_t));}
else if(0 == pid){ //子进程/*子进程播放MP3 函数*/
play(my_song);}}//如果没有音乐正在播放并处于暂停状态
else if((play_flag == 0) && (play_pause_flag == 1)){
play_flag = 1;
play_pause_flag = 0;
conti_play(gradchild);}
else
return;}
/*MP3 音乐播放器-->暂停播放*/
void my_pause(pid_t pid)
{if((play_flag == 1) && (play_pause_flag == 0)){
printf("=======================PAUSE!PRESS PLAY TO
CONTINUE===================\n");
kill(pid,SIGSTOP); //对孙子进程发送SIGSTOP 信号
play_pause_flag = 1;
play_flag = 0;}
else
return;}
/*MP3 音乐播放器-->继续播放*/
void conti_play(pid_t pid)
{printf("===============================CONTINUE=============================\n");
kill(pid,SIGCONT); //对孙子进程发送SIGCONT 信号}
/*MP3 音乐播放器-->播放下一首*/
/*只有正在播放音乐的状态下,上一首和下一首才有作用*/
void next(pid_t next_pid)
{int res;
if(play_flag == 0){
return;}
else{
struct song *nextsong;
printf("===============================NEXTMP3=============================\n");
/*从共享内存获得孙子进程播放歌曲的节点指针*/
memcpy(&nextsong,p_addr + sizeof(pid_t)+1,4);
/*指向下首歌曲的节点*/
nextsong = nextsong->next;
/*杀死当前歌曲播放的子进程,孙子进程*/
res = kill(pid,SIGKILL);
if(res == -1){
perror("kill next pid error");
return;}
res = kill(next_pid,SIGKILL);
if(res == -1){
perror("kill next next_pid error");
res=system("killall madplay");
if(res == -1) perror("system");}
//wait(NULL);
play_flag = 0;
startplay(&pid,nextsong);}}
/*MP3 音乐播放器-->播放上一首*/
void prev(pid_t prev_pid)
{int res;
if(play_flag == 0){
return;}
else {
struct song *prevsong;
/*从共享内存获得孙子进程播放歌曲的节点指针*/
printf("===============================PRIORMP3======================
=======\n");
memcpy(&prevsong,p_addr + sizeof(pid_t)+1,4);
/*指向上首歌曲的节点*/
prevsong = prevsong->prev;
/*杀死当前歌曲播放的子进程,孙子进程*/
res = kill(pid,SIGKILL);
if(res == -1){
perror("kill prev pid error");
return;}
res = kill(prev_pid,SIGKILL);
if(res == -1){
perror("kill prev prev_pid error");
res=system("killall madplay");
if(res == -1) perror("system");}
//wait(NULL);
play_flag = 0;
startplay(&pid,prevsong);}}
/*MP3 音乐播放器-->停止播放*/
void my_stop(pid_t g_pid)
{int res;
if(play_stop_flag == 1){//如果已经停止,直接返回
return;}
if((play_flag == 1) || (play_pause_flag == 1)){
printf("=======================STOP!PRESS PLAY TO
START===================\n");
res = kill(pid,SIGKILL); //对子进程发送SIGKILL 信号
if(res == -1){
perror("stop pid error");
return;}
res = kill(g_pid,SIGKILL); //对孙子进程发送SIGKILL 信号
if(res == -1){
perror("stop g_pid error");
res=system("killall madplay");
if(res == -1) perror("system");}
play_flag = 0;
play_stop_flag = 1;
play_pause_flag = 0;}
else
return;}
/*MP3 音乐播放器-->播放列表*/
/*搜索列表音乐名字与歌曲相匹配,并杀死正在播放歌曲进程而播放对应列表音乐*/
void playlist(pid_t childpid,char *listsong)
{int res;
play_flag = 0;
if(strncmp(head->songname,listsong,4) == 0){
res = kill(pid,SIGKILL);
if(res == -1){
perror("playlist kill pid error");
return;}
res = kill(childpid,SIGKILL);
if(res == -1){
perror("playlist kill childpid error");
res=system("killall madplay");
if(res == -1) perror("system");}
wait(NULL);
startplay(&pid,head);
return ;}
struct song *nextsong=head->next;
do{
if(strncmp(nextsong->songname,listsong,4)==0){
res = kill(pid,SIGKILL);
if(res == -1){
perror("playlist kill pid error");
return;}
res = kill(childpid,SIGKILL);
if(res == -1){
perror("playlist kill childpid error");
res=system("killall madplay");
if(res == -1) perror("system");}
wait(NULL);
startplay(&pid,nextsong);
return;}
nextsong=nextsong->next;
}while(nextsong!=head);}
/*接收客户端命令*/
void recvcmd(void)
{int cmd=0;
char buf[SIZE];
memset(buf,0,sizeof(buf));
while(1){
int len = recvfrom(server_sockfd,&cmd,4,0,(struct
sockaddr*)&server_addr,&sin_size);
if(len
continue;}
switch (cmd){
case PLAY:
startplay(&pid,head);
break;
case PAUSE:
my_pause(gradchild);
break;
case STOP:
my_stop(gradchild);
break;
case NEXT:
next(gradchild);
break;
case PREV:
prev(gradchild);
break;
case LISTSONG:
memset(buf,0,sizeof(buf));
len=recvfrom(server_sockfd,buf,sizeof(buf),0,(struct sockaddr*)&client_addr,&sin_size);
if(len>0){
printf("recv listbuf = %s\n",buf);
playlist(gradchild,buf);}
break;
default:
puts("not find the cmd!");
break;}}}
int main()
{/*创建播放列表*/
head=creat_song_list();
/*共享内存:用于存放子进程ID ,播放列表位置*/
void *tempaddr;
if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)
perror("shmget");
tempaddr = shmat(shmid,0,0);
if(tempaddr == (void *)-1){
perror("shmat");}
p_addr = (char *)tempaddr;
memset(p_addr,'\0',1024);
/*初始化MP3 播放停止标志*/
play_flag=0;
play_stop_flag=0;
play_pause_flag=0;
//初始化网络
int res=create_socket();
if(res
perror("create_socket");}
//接收控制命令(死循环);
recvcmd();
return 0;}
2.play.h
#ifndef PLAYER_H
#define PLAYER_H
/*共享内存申请标记*/
#define PERM S_IRUSR|S_IWUSR
#define SIZE 1024
struct song
{char songname[1024];
struct song *prev;
struct song *next;};
char *playsong;
/*播放标记*/
int play_flag;
int play_stop_flag;
int play_pause_flag;
/*保存接收到的字符串(推送过来的消息)*/
char temp_str[100];
unsigned int pos;
extern void play(struct song *currentsong);
extern struct song *creat_song_list(void);
extern void startplay(pid_t *childpid,struct song *my_song); extern void my_pause(pid_t pid);
extern void my_stop(pid_t g_pid);
extern void conti_play(pid_t pid);
extern void next(pid_t next_pid);
extern void prev(pid_t prev_pid);
extern void playlist(pid_t childpid,char *listsong); #endif
3.socket.c
#include "socket.h"
int server_sockfd;
socklen_t sin_size;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int create_socket()
{memset(&server_addr, 0, sizeof(server_addr));
/* 初始化网络信息*/
server_addr.sin_family = AF_INET; //设置为IP 通信
server_addr.sin_addr.s_addr = INADDR_ANY; //无限制
server_addr.sin_port = htons(8000);
if ((server_sockfd = socket(PF_INET,SOCK_DGRAM,0))
if(bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))
return -1;}
return 1;
sin_size = sizeof(struct sockaddr_in);}
4.socket.h
#ifndef SOCKET_H
#define SOCKET_H
#include "common.h"
#define PLAY 11
#define PAUSE 12
#define STOP 13
#define CONTINUE 14
#define NEXT 15
#define PREV 16
#define LISTSONG 18
extern int server_sockfd;
extern socklen_t sin_size;
extern struct sockaddr_in server_addr;
extern struct sockaddr_in client_addr;
extern int create_socket();
#endif
5.common.h
#ifndef __COMMON_H
#define __COMMON_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERROR -1
#endif
6.makefile
name=*.c
BIN=player
FLAGS=-g -O2 -Wall
default:gcc $(FLAGS) $(name) -o $(BIN)__
3.3.2音乐播放器客户端程序实现
1,player.cpp
#include "player.h"
#include "ui_player.h"
#include "listmusic.h"
#include "socket.h"
player::player(QWidget *parent) :
QDialog(parent),
ui(new Ui::player)
{ui->setupUi(this);
init_socket();}
player::~player()
{delete ui;}
void player::on_play_clicked()
{int cmd = 0;
int len;
cmd = PLAY;
len=sendto(client_sockfd, &cmd, 4,0, (struct sockaddr *)&client_addr, sin_size);
if (len
return;}}
void player::on_pause_clicked()
{int cmd = PAUSE;
int len=sendto(client_sockfd,&cmd,4,0,(struct sockaddr
*)&client_addr,sin_size);
if(len
return ;}}
void player::on_next_clicked()
{int cmd = NEXT;
int len=sendto(client_sockfd, &cmd, 4,0, (struct sockaddr
*)&client_addr, sin_size);
if (len
return;}}
void player::on_prev_clicked()
{int cmd = PREV;
int len=sendto(client_sockfd, &cmd, 4,0, (struct sockaddr
*)&client_addr, sin_size);
if (len
网络数据失败")));
return;}}
void player::on_listbutton_clicked()
{player xy3;
listmusic l;//l.setWindowFlags(Qt::FramelessWindowHint);
l.setGeometry(850,250,250,350);//l.show();
if(l.exec()==Accepted){
xy3.show();}}
void player::on_stop_clicked()
{int cmd = STOP;
int len=sendto(client_sockfd, &cmd, 4,0, (struct sockaddr
*)&client_addr, sin_size);
if (len
return;}}
2.play.h
#ifndef PLAYER_H
#define PLAYER_H
#include
#include
#include
#include
#include
#include
#include
#include
#include "socket.h"
namespace Ui {
class player;}
class player : public QDialog
{Q_OBJECT
public:
explicit player(QWidget *parent = 0);
~player();
private slots:
void on_play_clicked();
void on_pause_clicked();
void on_next_clicked();
void on_prev_clicked();
void on_listbutton_clicked();
void on_stop_clicked();
private:
Ui::player *ui;};
#endif // PLAYER_H
3.socket.cpp
#include "socket.h"
/* 网络通信变量*/
int client_sockfd;
int len;
int sin_size;
struct sockaddr_in client_addr;
void init_socket()
{/* 创建socket 跟设备进行通信*/
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //服务器IP //client_addr.sin_addr.s_addr = inet_addr("192.168.1.6"); client_addr.sin_port = htons(8000);
if ((client_sockfd = socket(PF_INET,SOCK_DGRAM,0))
exit(-1);}
sin_size = sizeof(struct sockaddr_in);}
#ifndef SOCKET_H
#define SOCKET_H
4.socket.h
/* 网络数据头文件*/
#include
#include /* See NOTES */
#include
#include
#include
#include
#include
#include
#include
#include
#define PLAY 11
#define PAUSE 12
#define STOP 13
#define CONTINUE 14
#define NEXT 15
#define PREV 16
#define LISTSONG 18
extern void init_socket();
extern int client_sockfd;
extern int len;
extern int sin_size;
extern struct sockaddr_in client_addr;
#endif // SOCKET_H
第四章 调试过程
4.1硬件连接
实训机器的硬件配置要求如下:
硬件类型 主讲机器 学员机器
CPU:(主讲机器)基本 Intel Pentium 系列2.0GHz 以上,推荐Intel Pentium 系列双核;
(学员机器)Intel Pentium 系列1.6GHz 以上, 推荐Intel Pentium 系列2.0GHz 以上。
内存:(主讲机器)基本 DDR3 系列内存2GB 容量 DDR3 系列内存2 容量,推荐 DDR3 系列内存4GB 容量 DDR3 系列内存4GB 容量硬盘;
(学员机器)基本 不小于60GB 容量 不小于60GB 容量,推荐 120GB 以上容量 120GB 以上容量。
4.2软件连接
4.2.1 操作系统
1. 学生机器使用ubuntu 12.04 系列32 位操作系统 或
windows+VMware 虚拟系统。
2. 讲师机器使用ubuntu 12.04 系列32 位操作系统。
4.2.2 系统软件
1.GCC (Linux 下C 语言编译工具)
2. 文本编辑工具:vim 或其他文本编辑工具
3.qtcreate 集成开发环境
4.2.3 工具软件
1.telnet 远程登陆工具
2. 如果没有投影仪,需要屏幕共享工具。
4.2.4 文档和资源
1.man 手册 c 语言库函数帮组页:
2. 实训全套代码(随附件一起提供)
4.3实验步骤
智能车内置MP3 播放程序,采用基于madplay 的音乐播放器,所以首先需要移植madplay ,具体方法如下:
1)创建安装库的路径 sudo mkdir /opt/arm/madplay/lib
2)进入madplay 源码目录 执行./build
3) 测试将madplay 和库文件复制到根文件系统, 配置
LD_LIBRARY_PATH,执行madplay xxx.mp3。
音乐播放器应用程序采用多进程控制音乐播放,暂停,上一首,下一首播放等功能。参考代码:
system("madplay north.mp3 &");
//利用system 函数调用madplay 播放器播放*.mp3 音乐
system("killall -9 madplay");
//利用system 函数调用killall 命令将madplay 终止掉
system("killall -STOP madplay &");
//利用system 函数调用killall 命令将madplay 暂停
system("killall -CONT madplay &");
//利用system 函数调用killall 命令恢复madplay 的播放
4.4 出现的问题和解决方法
出现的问题:
1.car.cpp 文件中没有socket 这个类
2. 把小车的IP 地址定义错误
3. 小车的端口和服务器的端口弄反了
4.lee 这个参数没有声明
5. 分号用成了汉语的分号
6.Save 这个函数的使用格式出现了错误
7. 一些函数的参数的使用不正确
8. 参数中的类型定义出现错误使显示结果不正确
9. 使用ui 时,没有进行转到槽,使得程序出现错误 解决的方法:
1. 上网查阅相关资料而后改正
2. 和同学一起探讨
3. 向老师获得帮助
4. 查阅实验手册进行对照后改正错误
5. 查看出现错误的地方根据自己的经验改正 改正方式:
1. 在car.cpp 中添加socket.h
2. 参看实验手册改正端口和IP 地址
3. 改正参数的类型
4. 参阅错误函数的使用方法,而后改正错误
5. 从新Push Botton,然后转到槽
6. 把分号改为字母的分号
4.5运行结果截屏
模拟播放器:
播放列表:
第五章 总结
该项目从历时3周的时间,我已经完成了该项目的所有工作。从开始接到课程题目到系统的实现,再到课程文章的完成,每走一步对我来说都是新的尝试与挑战,这也是我在大学期间独立完成的最大的项目。在这段时间里,我学到了很多知识也有很多感受,从对Linux 下图形界面应用程序开发一无所知,对GTK ,GStreamer ,QT 等相关技术很不了解的状态,我开始了独立的学习和试验,查看相关的资料和书籍,让自己头脑中模糊的概念逐渐清晰,使自己非常稚嫩作品一步步完善起来,每一次改进都是我学习的收获,每一次代码的成功运行都会让我兴奋好一段时间。
虽然我的论文作品不是很成熟,还有很多不足之处,但我可以自豪的说,这里面的每一段代码,都有我的劳动。当看着自己的播放器能够完美的播放出动听的歌曲,真是莫大的幸福和欣慰。我相信其中的酸甜苦辣最终都会化为甜美的甘泉。
这次做设计报告的经历也会使我终身受益,我感受到做论文是要真真正正用心去做的一件事情,是真正的自己学习的过程和研究的过程,没有学习就不可能有研究的能力,没有自己的研究,就不会有所突破。
在学习中,我更了解到自己知识的不足和有限,通过达内老师的讲解,使我学会了不少我不了解的知识,使我受益匪浅,将学到的知识应用于实践当中。当然,在以后的学习或工作中,我也会不断的充实自己,学习更多新的知识,来丰富自己。
参考文献
【1】王道乾 刘定智 文俊浩,基于ARM 处理器的MP3播放器分析与实现, 计算机工程与设计[L],2007,28(7):1595~1597
【2】王 奇, 基于嵌入式linux 的多媒体音乐播放器的设计与实现, 信息技术
[L],2009, (6):102~104
【3】王建民 张宏壮, 基于Qt 的嵌入式媒体播放器系统的设计, 微计算机信息(嵌入式与SOC )[L],2008,24(7-2):64~66
【4】达内公司 智能车实验说明书
【5】达内公司 达内实训大纲(内蒙古工业大学)
【6】unix 高级环境编程
【7】linux 设备驱动第三版