本帖最后由 wing 于 2014-2-18 11:20 编辑
本次实验的目前是通过web服务用网页方式控制RPI的GPIO,点亮LED或者关掉它.
包括web服务在内全部用c来写.写个web服务不是一件很难的事情,像Apache,nginx之类的现成架构太过臃肿和RPI纤细的身材不太相衬,
控制GPIO方面使用了wiringPi库,下文会介绍如何安装这个库,如想深入了解可以访问http://wiringpi.com/
开发工具使用qtcreator,为了和vi党划清界线这个是首选(不要跟我提月食,这里不是暮光之城).
第一步,我们来安装qtcreator,
步骤很简单只要执行命令
sudo apt-get install qtcreator
这个过程可能需要点时间,总共会下载过百兆的内容,请保证RPI的网络通畅和有充足的电能(如果你是用电池的话)
安装完成后,用root身份运行qtcreator,
初次启用需要设置下 toolchain
Tools > Options > build & run > tool chain > add 选择 GCC
本次实验是通过wiringPi来控制GPIO,为了安装方便首先准备GIT,如果你已经安装了GIT这一步可以跳过.
sudo apt-get install git-core
如果安装过程中出现问题,可以用以下命令修复
sudo apt-get update
sudo apt-get upgrade
安装完GIT后我们来克隆wiringPi
git clone git://git.drogon.net/wiringPi
cd wiringPi
git pull origin
cd wiringPi
./build
完成之后可以使用下面的命令来测试下
gpio -v
gpio readall
正常情况下可以获取到软件版本和所有GPIO当前的状态
好了,到目前为止已经万事具备,那么我们来写程序.
在qtcreator建立一个非qt项目,选择一个用qmake的纯c工程
代码
[pre lang="c" line="1"]#include<sys/socket.h>
#include<errno.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include <wiringPi.h>
#define BUF_LEN 1028
#define SERVER_PORT 8001
#define pinNumber 7
//404找不到指定资源的头部信息
const static char http_head_error[] = "HTTP/1.1 404 Not Found\r\nContent-type: text/html\r\n\r\n";
//200成功的头部信息
const static char http_head_ok[] = "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";
//LED关灯页面
const static char http_body_off[] =
"<html><head><title>RPI_led</title></head>"
"<body><h1>LED 7 is off</h1>"
"<div/><input type='button' value=led_ON onclick=\"location.href='ledon.act';\" />"
"<p><input type='button' value=led_OFF onclick=\"location.href='ledoff.act';\" />"
"</body></html>";
//LED开灯页面
const static char http_body_on[] =
"<html><head><title>RPI_led</title></head>"
"<body><h1>LED 7 is on</h1>"
"<div/><input type='button' value=led_ON onclick=\"location.href='ledon.act';\" />"
"<p><input type='button' value=led_OFF onclick=\"location.href='ledoff.act';\" />"
"</body></html>";
//解析到HTTP请求的文件后,发送相应的网页信息
int http_send_file(char *filename, int sockfd)
{
if((strcmp(filename, "/ledon.act")==0)||(strcmp(filename, "/ledoff.act")==0)){
//通过write函数发送http响应报文;报文包括HTTP响应头和响应内容--HTML内容
write(sockfd, http_head_ok, strlen(http_head_ok));
if (strcmp(filename, "/ledon.act")==0){
write(sockfd, http_body_on, strlen(http_body_on));
//点亮LED...
digitalWrite(pinNumber, 1);
}
if (strcmp(filename, "/ledoff.act")==0){
write(sockfd, http_body_off, strlen(http_body_off));
//关闭LED...
digitalWrite(pinNumber, 0);
}
}
else{
//未找到情况下发送404error响应
write(sockfd, http_head_error, strlen(http_head_error));
}
return 0;
}
//HTTP请求解析
void serve(int sockfd){
char buf[BUF_LEN];
read(sockfd, buf, BUF_LEN);
if(!strncmp(buf, "GET", 3)){
char *file = buf + 4;
char *space = strchr(file, ' ');
*space = '\0';
http_send_file(file, sockfd);
}
}
void main(){
//初始化wiringPi
if (-1 == wiringPiSetup()) {
return;
}
//设置为输出端口
pinMode(pinNumber, OUTPUT);
int sockfd,err,newfd;
struct sockaddr_in addr;
//建立TCP套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
return;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
//这里要注意,端口号一定要使用htons先转化为网络字节序,否则绑定的实际端口
addr.sin_port = htons(SERVER_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))){
return;
}
listen(sockfd, 128);
while(1){
//不间断接收HTTP请求并处理,这里使用单线程
newfd = accept(sockfd, NULL, NULL);
serve(newfd);
close(newfd);
}
}
[/code]
.pro
如果想在qtcreator上顺利编译还要添加 -lwiringPi编译连接
最后来Build下工程,现在已经完成了一个完整的程序了,是完全用IDE写程序的,至此终于可以和vi党划清界限了
什么你也是vi党!!那我就假装是用vi写的程序,然后用下面命令编译
gcc main.c -o http_gpio_test -lwiringpi
注意GPIO定义图,接上LED,
用下面的命令查下RPI的IP地址
ifconfig
root身份运行程序,访问 http://192.168.1.21:8001/ledoff.act 测试下吧
|