0%

前几天花了4.3美元在TI官网买了一开MSP430FR2433 LaunchPad™ Development Kit
(MSPEXP430FR2433),今天花一点时间来个简单的入门。板子很简单见下图
TIM截图20180113204831.png

开发板自带一个调试工具和串口调试工具,性价比还是挺高的。
开发板的资源见下图:

TIM截图20180113205502.png

首先我们先来一个简单的点灯例程,接下来从新建工程----编写点灯程序----效果演示顺序开始介绍

创建一个CCS工程

CCS其实就是eclipse安装了TI的一些开发插件,CCS的安装教程就不提了比较简单,从TI官网下载CCS,选择单片机的型号,接下来基本上是下一步就行了。接下来主要讲如何新建工程

File > New > CCS Project
具体配置如下:

  • Target:MSP430FR2433
  • Project name:Hello_Led
  • Location:随自己的意愿
  • Project templates and examples : Empty Project(with main.c)

    FIG2

开始编写自己的程序

上面我们创建好了MSP430的工程,具体如下:
fig3
创建工程后系统已经添加好了msp430的头文件

1
#include <msp430.h>

当然也可以自己根据具体型号添加头文件,我用的是MSP430FR2433,所以我们可以改成#include <msp430fr2433.h>这个头文件包含了 MSP430FR2433 的寄存器定义和内置函数。
main函数部分,以下是闪灯的程序,也是CCS自带的示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode
P1DIR |= BIT0; // Set P1.0 to output direction

for(;;) {
volatile unsigned int i; // volatile to prevent optimization

P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR

i = 10000; // SW Delay
do i--;
while(i != 0);
}
return 0;
}

1
P1DIR |= BIT0;

这一行中,我们将 P1.0 引脚设置为输出(P1.0 与开发板上 Led1 相连)。在 MSP430 中,P1DIR 是一个控制 Port1 引脚方 向的八位寄存器。如果你把某一位配置为 0,则它作输入用,反之 是输出。BIT0 是一个系统定义的常量,即 0x0001(详见<msp430fr2433.h>)。

如果一切顺利的话,现在我们可以把我们的程序下载到单片机运行了。

将程序下载到单片机

TIM截图20180113203355编译按钮

TIM截图20180113203408Debug 按钮,编译通过之后,我们按这个按钮会下载程序并进入 DEBUG 模式

TIM截图20180113203554红色按钮终止 DEBUG 模式

LED 程序已经下载到单片机中,如果你观察到红色的 LED 灯会随着按键亮灭,那么恭喜你,你已经完成了第一 个 MSP430的项目。

前言

MQTT是IBM开发的一个即时通讯协议,面向M2M和物联网的连接,采用轻量级发布和订阅消息传输机制,并且有可能成为物联网的重要组成部分。

ESP8266是一款物美价廉的Wi-Fi芯片,集成Tensilica L106 钻石系列的32 位处理器和片上SRAM,多达17 个GPIO口,并拥有IIC、IIS、UART、PWM、IR遥控等片上资源。

ESP8266还提供官方的软件开发开发包(SDK),目前最新版本是「ESP8266 NONOS SDK V2.2.0」。

这篇文章主要讲解如何使用ESP8266作为MQTT客户端,并连上在本地电脑搭建的MQTT服务器。

开发环境

首先简单说明一下博主的开发环境:

  • ESP8266开发环境:ESP8266 IDE 2.0
  • ESP8266 SDK版本:ESP8266 NONOS SDK V2.2.0
  • MQTT服务器:Apollo 1.7.1(本地搭建)
  • 操作系统:64位 Win10系统
  • ESP8266开发板:NodeMCU(4MB Flash)

导入工程

如果读者和博主使用的开发环境一样,那么步骤1~4就好理解了,不是的话直接看图片和步骤5:

  1. 在IDE环境中通过「File」->「Import」;
  2. 弹窗中选择「C/C++」->「Existing Code as Makefile project」;
  3. 下一步「Browse…」,编译器选择「Cygwin GCC」;
  4. 之后导入的工程目录如上图,其中给「dirver_lib」文件下面的Makeflie添加bak后缀或删除掉,免得编译通不过。
  5. 从「example」文件夹中拷贝esp_mqtt_proj文件夹到主目录,点击编译按钮,如果成功就完成这一步骤了。

img

工程目录

工程目录图

代码分析

img

mqtt例程目录

user_main.c

mqtt_config.h

其中user_main.c不用说了,玩过ESP8266的朋友都知道这是放主代码的地方,其中user_init函数是SDK提供开发者放置初始化代码的地方。下面主要分析mqtt_config.h。

mqtt_config.h代码清单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef __MQTT_CONFIG_H__
#define __MQTT_CONFIG_H__

#define CFG_HOLDER 0x00FF55A4 /* Change this value to load default configurations */
#define CFG_LOCATION 0x79 /* Please don't change or if you know what you doing */
#define MQTT_SSL_ENABLE

/*DEFAULT CONFIGURATIONS*/

#define MQTT_HOST "192.168.1.100" //or "mqtt.yourdomain.com"
#define MQTT_PORT 1883
#define MQTT_BUF_SIZE 1024
#define MQTT_KEEPALIVE 120 /*second*/

#define MQTT_CLIENT_ID "DVES_%08X"
#define MQTT_USER "DVES_USER"
#define MQTT_PASS "DVES_PASS"

#define STA_SSID "DVES_HOME"
#define STA_PASS "yourpassword"
#define STA_TYPE AUTH_WPA2_PSK

#define MQTT_RECONNECT_TIMEOUT 5 /*second*/

#define DEFAULT_SECURITY 0
#define QUEUE_BUFFER_SIZE 2048

#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
//PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/

#endif // __MQTT_CONFIG_H__

在这个文件中,有几个宏定义可能需要修改的

  • MQTT_HOST,MQTT服务器地址
  • MQTT_PORT,MQTT服务器端口
  • MQTT_USER,MQTT服务器用户名
  • MQTT_PASS,MQTT服务器密码
  • STA_SSID,WI-FI帐号
  • STA_PASS,WI-FI密码

还有一个最重要的宏定义——CFG_HOLDER,因为这个MQTT示例在ESP8266运行过一次后会把这些信息保存到FLASH中,如果要继续修改这些信息,记得要修改CFG_HOLDER这个宏定义,改成另一个数值即可。

CFG_HOLDER作的用是:在CFG_Load函数中,如果发现从FLASH读取出来的CFG_HOLDER数值和宏定义的不一样,则会更新这些信息,并保存到FLASH中。不修改CFG_HOLDER的话可能会发觉明明用户名和密码都正确但是就是连接不上去。

修改代码及测试

修改代码

根据上面分析,下面我们就可以修改示例代码:

  1. STA_SSIDSTA_PASS修改为自己的WiFI名和密码;
  2. 修改MQTT_USERMQTT_PASS为对应的MQTT服务器的用户名和密码,Apollo服务器默认是adminpassword
  3. 修改MQTT_HOSTMQTT_PORT为MQTT服务器IP和PORT,目前是使用本地的MQTT服务器,所以是修改为自己电脑的IP和61613端口,PORT是整型值;
  4. 根据MQTT服务器的协议不同,可能需要使用MQTT v3.1.1版本,所以把PROTOCOL_NAMEv31注释掉,使用PROTOCOL_NAMEv311。源码的PROTOCOL_NAMEv311前面没有#define,自己加上就行。
  5. 最后,修改CFG_HOLDER,以让这些配置生效,直接给原来CFG_HOLDER定义的数值加1即可。

img

修改示例配置

编译下载

编译,查看Console窗口,如果输出

img

编译信息

那说明代码已经编译成功。另外要注意,ESP8266 SDK v2.0以后版本生成的eagle.irom0text.bin烧写起始地址是0x10000,而之前的版本烧写地址是0x40000;eagle.flash.bin还是0x00000。由于博主使用的是4MB Flash的ESP8266,所以也建议读者先确定手头的ESP8266是不是4MB Flash(即32Mbit Flash,注意单位!4MB=32Mbit,Flash一般是以bit计算!)

另外如果Problems窗口报Errors的,只要Console窗口编译通过,就可以不用管。

下载配置参考图片:

img

下载配置

提醒:blank.bin和default.bin烧写一次就行,另外也要留意不同的Flash大小,blank.bin和default.bin烧写地址也不同。

上电测试

如果前面一切顺利,打开串口,设置波特率为115200,上电后前面的乱码不用管,之后串口打印信息如下,省略了一部分信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
> load ...
> default configuration
> MQTT_InitConnection
> MQTT_InitClient

WIFI_INIT

> ……(省略)

> connected with **[你的WiFi名]**, channel 6
> dhcp client start...
> STATION_IDLE
> STATION_IDLE
> ip:**[WiFi分配给ESP8266的IP]**,mask:255.255.255.0,gw:**[WiFi网关IP]**
> TCP: Connect to ip **[MQTT服务器IP:PORT]**
> MQTT: Connected to broker **[MQTT服务器IP:PORT]**
> MQTT: Sending, type: 1, id: 0000
> TCP: Sent
> TCP: data received 4 bytes
> MQTT: Connected to **[MQTT服务器IP:PORT]**
> MQTT: Connected
> MQTT: queue subscribe, topic"/mqtt/topic/0", id: 1
> MQTT: queue subscribe, topic"/mqtt/topic/1", id: 2
> MQTT: queue subscribe, topic"/mqtt/topic/2", id: 3
> MQTT: queuing publish, length: 23, queue size(66/2048)
> MQTT: queuing publish, length: 25, queue size(91/2048)
> MQTT: queuing publish, length: 25, queue size(118/2048)
> ……

其中加粗带方括号的字段根据测试环境不同而不同。

同时看源码和串口信息可知,ESP8266向MQTT服务器订阅了三个主题,假设使用的是本地搭建的MQTT服务器,那么查看MQTT服务器后台就可以看到:

img

ESP8266MQTT示例代码订阅

同时在后台的Connects页面也可以看到ESP8266的链接:

img

ESP8266后台链接

MQTT本地服务器搭建教程Windows版链接在后面。

另外博主已经用ESP8266的MQTT连接上了OneNET云,连接该云需要注释掉下面这条语句,在user_init函数下。

1
MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0);

原因是OneNET不支持,否则连接不上。

其他


前言

现在物联网这么火,当然不能落伍,MQTT极有可能成为物联网应用最广的协议,因此需要一个MQTT测试环境就很有必要了

开发环境

系统: Ubuntu 16.04.3 LTS

代理服务器 :Apache-Apollo-1.7.1

准备工作

1. 安装Java环境

由于搭建Apollo环境变量需要有JAVA_HOME,这个时候需要安装JDK,具体安装参考《Ubuntu安装JDK1.8.0并配置环境变量

2. Apache-Apollo-1.7.1下载及解压

首先是下载Apache-Apollo,下载页面:http://www.apache.org/dyn/closer.cgi?path=activemq/activemq-apollo/1.7.1/apache-apollo-1.7.1-unix-distro.tar.gz

或者输入下面命令:

1
2
3
iotts@jacklu:~$ cd /home/iotts/
iotts@jacklu:~$ mkdir apache-apollo
wget http://mirror.bit.edu.cn/apache/activemq/activemq-apollo/1.7.1/apache-apollo-1.7.1-unix-distro.tar.gz

解压源码包:

1
tar -zxvf apache-apollo-1.7.1-unix-distro.tar.gz

配置

进入apache-apollo-1.7.1/bin目录

1
cd apache-apollo-1.7.1/bin/

输入./apollo可以查看帮助
1
2
3
4
5
6
7
8
9
10
iotts@jacklu:~/apache-apollo/apache-apollo-1.7.1/bin$ ./apollo
usage: apollo [--log <log_level>] <command> [<args>]

The most commonly used apollo commands are:
create creates a new broker instance
disk-benchmark Benchmarks your disk's speed
help Display help information
version Displays the broker version

See 'apollo help <command>' for more information on a specific command.

创建MQTT服务器

创建一个Broker示例:./apollo create iotts_broker。执行后就会在bin目录下创建 iotts_broker文件夹。(MQTT服务器都是叫Broker)

1
2
3
4
5
6
7
8
9
10
11
12
iotts@jacklu:~/apache-apollo/apache-apollo-1.7.1/bin$ ./apollo create iotts_broker
Creating apollo instance at: iotts_broker
Generating ssl keystore...

You can now start the broker by executing:

"/home/iotts/apache-apollo/apache-apollo-1.7.1/bin/iotts_broker/bin/apollo-broker" run

Or you can setup the broker as system service and run it in the background:

sudo ln -s "/home/iotts/apache-apollo/apache-apollo-1.7.1/bin/iotts_broker/bin/apollo-broker-service" /etc/init.d/
/etc/init.d/apollo-broker-service start

后面会有提示怎么启动服务器,以及创建一个service。

启动Apollo :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
iotts@jacklu:~/apache-apollo/apache-apollo-1.7.1/bin$ iotts_broker/bin/apollo-broker run

_____ .__ .__
/ _ \ ______ ____ | | | | ____
/ /_\ \\____ \ / _ \| | | | / _ \
/ | \ |_> > <_> ) |_| |_( <_> )
\____|__ / __/ \____/|____/____/\____/
\/|__| Apache Apollo (1.7.1)


Loading configuration file '/home/iotts/apache-apollo/apache-apollo-1.7.1/bin/iotts_broker/etc/apollo.xml'.
INFO | OS : Linux 4.10.0-42-generic (Ubuntu 16.04.3 LTS)
INFO | JVM : Java HotSpot(TM) Server VM 1.8.0_151 (Oracle Corporation)
INFO | Apollo : 1.7.1 (at: /home/iotts/apache-apollo/apache-apollo-1.7.1)
INFO | OS is restricting the open file limit to: 100000
INFO | Accepting connections at: tcp://0.0.0.0:61613
INFO | Accepting connections at: tls://0.0.0.0:61614
INFO | Starting store: leveldb store at /home/iotts/apache-apollo/apache-apollo-1.7.1/bin/iotts_broker/data
INFO | Accepting connections at: ws://0.0.0.0:61623/
INFO | Accepting connections at: wss://0.0.0.0:61624/
INFO | virtual host startup is waiting on store startup
INFO | virtual host startup is no longer waiting. It waited a total of 1 seconds.
INFO | broker startup is waiting on start jetty webserver
INFO | Administration interface available at: https://127.0.0.1:61681/
INFO | Administration interface available at: http://127.0.0.1:61680/
INFO | broker startup is no longer waiting. It waited a total of 7 seconds.

查看打印信息即可知道MQTT要连接的端口和管理页面端口。

然后打开浏览器上,输入 http://127.0.0.1:61680/https://127.0.0.1:61681/
即可进入 Apollo Console 窗口。
微信截图_20180111233348.png

默认的登录id和密码是 admin 和 password
微信截图_20180111233514.png

开发环境

虚拟机 Ubuntu 16.04.3 LTS

JDK安装

通过终端在/usr/local目录下新建java文件夹,命令行:

1
sudo mkdir /usr/local/java

然后进入java目录,命令行:
1
cd /usr/local/java

到官网下载jdk,现在现在的话需要首先注册一下账号:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

不想注册的话可以在我的网盘下载

链接:https://pan.baidu.com/s/1AsQhDn8aAR_IvcaR0N1Miw
提取码:k9k2

下载源码包

解压源码包

解压压缩包,命令行:

1
sudo tar xvf jdk-8u151-linux-i586.tar.gz

然后可以把压缩包删除,命令行:

1
sudo rm jdk-8u151-linux-i586.tar.gz

设置JDK环境变量

这里采用全局设置方法,它是是所有用户的共用的环境变量

1
$sudo gedit ~/.bashrc

命令行下可以输入
1
vi ~/.bashrc

在.bashrc文件末尾输入
1
2
3
4
export JAVA_HOME=/usr/local/java/jdk1.8.0_151  
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

$\color{red}{注意:}$在添加环境变量时中,等号两侧不要加入空格,不然会出现“不是有效的标识符”,因为source /etc/profile 时不能识别多余到空格,会理解为是路径一部分。然后保存。
命令行下输入以下命令生效
1
source ~/.bashrc

检验是否安装成功

重启终端,然后在终端输入如下命令

1
java -version

看看是否安装成功,成功则显示如下:
1
2
3
4
5
iotts@jacklu:~$ java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) Client VM (build 25.151-b12, mixed mode)
iotts@jacklu:~$

1.创建数据库

在MySql数据库中创建一个名为Sensor_server的数据库,如下图:
微信截图_20180111003012.png
在数据库中创建一个名为sensor_test的数据表,使用如下SQL语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE IF NOT EXISTS `sensor_test` (
`id` int(11) NOT NULL,
`sen_id` int(11) NOT NULL,
`temp` int(11) NOT NULL,
`humi` int(11) NOT NULL,
`pm25` int(11) NOT NULL,
`pm10` int(11) NOT NULL,
`pm100` int(11) NOT NULL,
`co2` int(11) NOT NULL,
`ze08` int(11) NOT NULL,
`tvoc` int(11) NOT NULL,
`timeStamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

微信截图_20180111001007.png

2.创建PHP文件

2.1 创建数据库连接PHP文件

创建名为database.php 的文件,写入以下代码:

1
2
3
4
5
6
<?php
$connect=mysqli_connect('localhost','用户名(最好不用root)','数据库密码','sensor_server');

if(mysqli_connect_errno($connect)) printf("Failed to connect");
else printf("Success to Connect\r\n");
?>

2.2 创建数据库操作PHP文件

创建名为process.php 的文件,写入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
header("Content-type:text/html;charset=utf-8");
date_default_timezone_set("Asia/Shanghai");
echo "当前时间是 " . date("H:i:s")."<br>";
include("database.php");
$sen_id=$_POST['sen_id'];
$pm25=$_POST['pm25'];
$pm10=$_POST['pm10'];
$co2=$_POST['co2'];
$tvoc=$_POST['tvoc'];
$pm100=$_POST['pm100'];
$ze08=$_POST['ze08'];
$temp=$_POST['temp'];
$humi=$_POST['humi'];
$id=$_POST['id'];
print_r($_POST);
mysqli_query($connect,"INSERT INTO sensor_test(pm25,pm10,pm100,co2,tvoc,temp,humi,ze08,id,sen_id) VALUES('$pm25','$pm10','$pm100','$co2','$tvoc','$temp','$humi','$ze08','$id','$sen_id')");

mysqli_close($connect);
?>

原文链接
注:以下全部代码的执行环境为VC++ 6.0

在程序中,可能需要为某些整数定义一个别名,我们可以利用预处理指令#define来完成这项工作,您的代码可能是:

1
2
3
4
5
6
7
#define MON  1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7

在此,我们定义一种新的数据类型,希望它能完成同样的工作。这种新的数据类型叫枚举型。

1. 定义一种新的数据类型 - 枚举型

以下代码定义了这种新的数据类型 - 枚举型

1
2
3
4
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};

(1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。

(2) DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。

(3) 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。

(4) 可以人为设定枚举成员的值,从而自定义某个范围内的整数。

(5) 枚举型是预处理指令#define的替代。

(6) 类型定义以分号;结束。

2. 使用枚举类型对变量进行声明

新的数据类型定义完成后,它就可以使用了。我们已经见过最基本的数据类型,如:整型int, 单精度浮点型float, 双精度浮点型double, 字符型char, 短整型short等等。用这些基本数据类型声明变量通常是这样:

1
2
3
4
5
6
7
8
char     a; //变量a的类型均为字符型char
char letter;
int x,
y,
z; //变量x,y和z的类型均为整型int
int number;
double m, n;
double result; //变量result的类型为双精度浮点型double

既然枚举也是一种数据类型,那么它和基本数据类型一样也可以对变量进行声明。

方法一:枚举类型的定义和变量的声明分开

1
2
3
4
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
1
2
3
4
enum DAY yesterday;
enum DAY today;
enum DAY tomorrow; //变量tomorrow的类型为枚举型enum DAY
enum DAY good_day, bad_day; //变量good_day和bad_day的类型均为枚举型enum DAY

方法二:类型定义与变量声明同时进行:

1
2
3
4
5
6
7
8
9
10
enum //跟第一个定义不同的是,此处的标号DAY省略,这是允许的。
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday; //变量workday的类型为枚举型enum DAY
1
enum week { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} days; //变量days的类型为枚举型enum week
1
enum BOOLEAN { false, true } end_flag, match_flag; //定义枚举类型并声明了两个枚举型变量

方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明:

1
2
3
4
5
6
7
8
9
10
typedef enum workday
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday; //此处的workday为枚举型enum workday的别名
1
workday today, tomorrow; //变量today和tomorrow的类型为枚举型workday,也即enum workday

enum workday中的workday可以省略:

1
2
3
4
5
6
7
8
9
10
typedef enum
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday; //此处的workday为枚举型enum workday的别名
1
workday today, tomorrow; //变量today和tomorrow的类型为枚举型workday,也即enum workday

也可以用这种方式:

1
2
3
4
5
6
7
8
9
10
typedef enum workday
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
};
1
workday today, tomorrow; //变量today和tomorrow的类型为枚举型workday,也即enum workday

注意:同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。错误示例如下所示:

$\color{red}{错误声明一:}$存在同名的枚举类型

1
2
3
4
5
6
typedef enum
{
wednesday,
thursday,
friday
} workday;
1
2
3
4
5
6
typedef enum WEEK
{
saturday,
sunday = 0,
monday,
} workday;

$\color{red}{错误声明二:}$存在同名的枚举成员

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef enum
{
wednesday,
thursday,
friday
} workday_1;

typedef enum WEEK
{
wednesday,
sunday = 0,
monday,
} workday_2;

3.使用枚举类型的变量

3.1 对枚举型的变量赋值。

实例将枚举类型的赋值与基本数据类型的赋值进行了对比:

方法一:先声明变量,再对变量赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<stdio.h>

/* 定义枚举类型 */
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };

void main()
{
/* 使用基本数据类型声明变量,然后对变量赋值 */
int x, y, z;

x = 10;
y = 20;
z = 30;

/* 使用枚举类型声明变量,再对枚举型变量赋值 */
enum DAY yesterday, today, tomorrow;

yesterday = MON;
today = TUE;
tomorrow = WED;

printf("%d %d %d \n", yesterday, today, tomorrow);
}

方法二:声明变量的同时赋初值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

/* 定义枚举类型 */
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };

void main()
{
/* 使用基本数据类型声明变量同时对变量赋初值 */
int x=10, y=20, z=30;

/* 使用枚举类型声明变量同时对枚举型变量赋初值 */
enum DAY yesterday = MON,
today = TUE,
tomorrow = WED;

printf("%d %d %d \n", yesterday, today, tomorrow);
}

方法三:定义类型的同时声明变量,然后对变量赋值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

/* 定义枚举类型,同时声明该类型的三个变量,它们都为全局变量 */
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN } yesterday, today, tomorrow;

/* 定义三个具有基本数据类型的变量,它们都为全局变量 */
int x, y, z;

void main()
{
/* 对基本数据类型的变量赋值 */
x = 10; y = 20; z = 30;

/* 对枚举型的变量赋值 */
yesterday = MON;
today = TUE;
tomorrow = WED;

printf("%d %d %d \n", x, y, z); //输出:10 20 30
printf("%d %d %d \n", yesterday, today, tomorrow); //输出:1 2 3
}

方法四:类型定义,变量声明,赋初值同时进行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

/* 定义枚举类型,同时声明该类型的三个变量,并赋初值。它们都为全局变量 */
enum DAY
{
MON=1,
TUE,
WED,
THU,
FRI,
SAT,
SUN
}
yesterday = MON, today = TUE, tomorrow = WED;

/* 定义三个具有基本数据类型的变量,并赋初值。它们都为全局变量 */
int x = 10, y = 20, z = 30;

void main()
{
printf("%d %d %d \n", x, y, z); //输出:10 20 30
printf("%d %d %d \n", yesterday, today, tomorrow); //输出:1 2 3
}

3.2 对枚举型的变量赋整数值时,需要进行类型转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };

void main()
{
enum DAY yesterday, today, tomorrow;

yesterday = TUE;
today = (enum DAY) (yesterday + 1); //类型转换
tomorrow = (enum DAY) 30; //类型转换
//tomorrow = 3; //错误

printf("%d %d %d \n", yesterday, today, tomorrow); //输出:2 3 30
}

3.3 使用枚举型变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<stdio.h>

enum
{
BELL = '\a',
BACKSPACE = '\b',
HTAB = '\t',
RETURN = '\r',
NEWLINE = '\n',
VTAB = '\v',
SPACE = ' '
};

enum BOOLEAN { FALSE = 0, TRUE } match_flag;

void main()
{
int index = 0;
int count_of_letter = 0;
int count_of_space = 0;

char str[] = "I'm Ely efod";

match_flag = FALSE;

for(; str[index] != '\0'; index++)
if( SPACE != str[index] )
count_of_letter++;
else
{
match_flag = (enum BOOLEAN) 1;
count_of_space++;
}

printf("%s %d times %c", match_flag ? "match" : "not match", count_of_space, NEWLINE);
printf("count of letters: %d %c%c", count_of_letter, NEWLINE, RETURN);
}

输出:

1
2
3
match 2 times
count of letters: 10
Press any key to continue

4. 枚举类型与sizeof运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>

enum escapes
{
BELL = '\a',
BACKSPACE = '\b',
HTAB = '\t',
RETURN = '\r',
NEWLINE = '\n',
VTAB = '\v',
SPACE = ' '
};

enum BOOLEAN { FALSE = 0, TRUE } match_flag;

void main()
{
printf("%d bytes \n", sizeof(enum escapes)); //4 bytes
printf("%d bytes \n", sizeof(escapes)); //4 bytes

printf("%d bytes \n", sizeof(enum BOOLEAN)); //4 bytes
printf("%d bytes \n", sizeof(BOOLEAN)); //4 bytes
printf("%d bytes \n", sizeof(match_flag)); //4 bytes

printf("%d bytes \n", sizeof(SPACE)); //4 bytes
printf("%d bytes \n", sizeof(NEWLINE)); //4 bytes
printf("%d bytes \n", sizeof(FALSE)); //4 bytes
printf("%d bytes \n", sizeof(0)); //4 bytes
}

5. 综合举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<stdio.h>

enum Season
{
spring, summer=100, fall=96, winter
};

typedef enum
{
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
Weekday;

void main()
{
/* Season */
printf("%d \n", spring); // 0
printf("%d, %c \n", summer, summer); // 100, d
printf("%d \n", fall+winter); // 193

Season mySeason=winter;
if(winter==mySeason)
printf("mySeason is winter \n"); // mySeason is winter

int x=100;
if(x==summer)
printf("x is equal to summer\n"); // x is equal to summer

printf("%d bytes\n", sizeof(spring)); // 4 bytes

/* Weekday */
printf("sizeof Weekday is: %d \n", sizeof(Weekday)); //sizeof Weekday is: 4

Weekday today = Saturday;
Weekday tomorrow;
if(today == Monday)
tomorrow = Tuesday;
else
tomorrow = (Weekday) (today + 1); //remember to convert from int to Weekday
}

ubuntu关机和重启命令

linux下常用的关机命令有:shutdown、halt、poweroff、init;重启命令有:reboot。下面本文就主要介绍一些常用的关机命令以及各种关机命令之间的区别和具体用法。

阅读全文 »

Linux下的压缩解压缩命令详解及实例

实例:压缩服务器上当前目录的内容为xxx.zip文件

1
zip -r xxx.zip ./*

解压zip文件到当前目录
1
unzip filename.zip

另:有些服务器没有安装zip包执行不了zip命令,但基本上都可以用tar命令的,实例如下:

1
tar -zcvf /home/zdzlibs.tar.gz /home/zdz/java/zdzlibs/

linux zip命令

zip -r myfile.zip ./*
将当前目录下的所有文件和文件夹全部压缩成myfile.zip文件,-r表示递归压缩子目录下所有文件.

2.unzip
unzip -o -d /home/sunny myfile.zip
把myfile.zip文件解压到 /home/sunny/
-o:不提示的情况下覆盖文件;
-d:-d /home/sunny 指明将文件解压缩到/home/sunny目录下;

3.其他
zip -d myfile.zip smart.txt
删除压缩文件中smart.txt文件
zip -m myfile.zip ./rpm_info.txt

向压缩文件中myfile.zip中添加rpm_info.txt文件

要使用 zip 来压缩文件,在 shell 提示下键入下面的命令:

zip -r filename.zip filesdir

在这个例子里,filename.zip 代表你创建的文件,filesdir 代表你想放置新 zip 文件的目录。-r 选项指定你想递归地(recursively)包括所有包括在 filesdir 目录中的文件。

要抽取 zip 文件的内容,键入以下命令:

unzip filename.zip

你可以使用 zip 命令同时处理多个文件和目录,方法是将它们逐一列出,并用空格间隔:

zip -r filename.zip file1 file2 file3 /usr/work/school

上面的命令把 file1、file2、 file3、以及 /usr/work/school 目录的内容(假设这个目录存在)压缩起来,然后放入 filename.zip 文件中。

tar 命令详解

  -c: 建立压缩档案

  -x:解压

  -t:查看内容

  -r:向压缩归档文件末尾追加文件

  -u:更新原压缩包中的文件

  这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个。下面的参数是根据需要在压缩或解压档案时可选的。

  -c: 建立压缩档案

  -x:解压

  -t:查看内容

  -r:向压缩归档文件末尾追加文件

  -u:更新原压缩包中的文件

  下面的参数-f是必须的

  -f: 使用档案名字,切记,这个参数是最后一个参数,后面只能接档案名。

  # tar -cf all.tar *.jpg

  这条命令是将所有.jpg的文件打成一个名为all.tar的包。-c是表示产生新的包,-f指定包的文件名。

  # tar -rf all.tar *.gif

  这条命令是将所有.gif的文件增加到all.tar的包里面去。-r是表示增加文件的意思。

  # tar -uf all.tar logo.gif

  这条命令是更新原来tar包all.tar中logo.gif文件,-u是表示更新文件的意思。

  # tar -tf all.tar

  这条命令是列出all.tar包中所有文件,-t是列出文件的意思

  # tar -xf all.tar

  这条命令是解出all.tar包中所有文件,-t是解开的意思

  压缩

  tar –cvf jpg.tar *.jpg //将目录里所有jpg文件打包成tar.jpg

  tar –czf jpg.tar.gz *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用gzip压缩,生成一个gzip压缩过的包,命名为jpg.tar.gz

  tar –cjf jpg.tar.bz2 *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用bzip2压缩,生成一个bzip2压缩过的包,命名为jpg.tar.bz2

  tar –cZf jpg.tar.Z *.jpg //将目录里所有jpg文件打包成jpg.tar后,并且将其用compress压缩,生成一个umcompress压缩过的包,命名为jpg.tar.Z

  rar a jpg.rar *.jpg //rar格式的压缩,需要先下载rar for linux

  zip jpg.zip *.jpg //zip格式的压缩,需要先下载zip for linux

  解压

  tar –xvf file.tar //解压 tar包

  tar -xzvf file.tar.gz //解压tar.gz

  tar -xjvf file.tar.bz2 //解压 tar.bz2

  tar –xZvf file.tar.Z //解压tar.Z

  unrar e file.rar //解压rar

  unzip file.zip //解压zip

  总结

  1、*.tar 用 tar –xvf 解压

  2、*.gz 用 gzip -d或者gunzip 解压

  3、.tar.gz和.tgz 用 tar –xzf 解压

  4、*.bz2 用 bzip2 -d或者用bunzip2 解压

  5、*.tar.bz2用tar –xjf 解压

  6、*.Z 用 uncompress 解压

  7、*.tar.Z 用tar –xZf 解压

  8、*.rar 用 unrar e解压

  9、*.zip 用 unzip 解压

  Linux中tar命令详解(转载的资料)

  2008年04月17日 星期四 15:37

  tar命令

  tar 可以为文件和目录创建档案。利用tar,用户可以为某一特定文件创建档案(备份文件),也可以在档案中改变文件,或者向档案中加入新的文件。tar最初被 用来在磁带上创建档案,现在,用户可以在任何设备上创建档案,如软盘。利用tar命令,可以把一大堆的文件和目录全部打包成一个文件,这对于备份文件或将 几个文件组合成为一个文件以便于网络传输是非常有用的。Linux上的tar是GNU版本的。

  语法:tar [主选项+辅选项] 文件或者目录

  使用该命令时,主选项是必须要有的,它告诉tar要做什么事情,辅选项是辅助使用的,可以选用。

  主选项:

  c 创建新的档案文件。如果用户想备份一个目录或是一些文件,就要选择这个选项。

  r 把要存档的文件追加到档案文件的未尾。例如用户已经作好备份文件,又发现还有一个目录或是一些文件忘记备份了,这时可以使用该选项,将忘记的目录或文件追加到备份文件中。

  t 列出档案文件的内容,查看已经备份了哪些文件。

  u 更新文件。就是说,用新增的文件取代原备份文件,如果在备份文件中找不到要更新的文件,则把它追加到备份文件的最后。

  x 从档案文件中释放文件。

  辅助选项:

  b 该选项是为磁带机设定的。其后跟一数字,用来说明区块的大小,系统预设值为20(20*512 bytes)。

  f 使用档案文件或设备,这个选项通常是必选的。

  k 保存已经存在的文件。例如我们把某个文件还原,在还原的过程中,遇到相同的文件,不会进行覆盖。

  m 在还原文件时,把所有文件的修改时间设定为现在。

  M 创建多卷的档案文件,以便在几个磁盘中存放。

  v 详细报告tar处理的文件信息。如无此选项,tar不报告文件信息。

  w 每一步都要求确认。

  z 用gzip来压缩/解压缩文件,加上该选项后可以将档案文件进行压缩,但还原时也一定要使用该选项进行解压缩。

  Linux下的压缩文件剖析

  对于刚刚接触Linux的人来说,一定会给Linux下一大堆各式各样的文件名给搞晕。别个不说,单单就压缩文件为例,我们知道在Windows下最常见 的压缩文件就只有两种,一是,zip,另一个是.rap。可是Linux就不同了,它有.gz、.tar.gz、tgz、bz2、.Z、.tar等众多的 压缩文件名,此外windows下的.zip和.rar也可以在Linux下使用,不过在Linux使用.zip和.rar的人就太少了。本文就来对这些 常见的压缩文件进行一番小结,希望你下次遇到这些文件时不至于被搞晕。

  在具体总结各类压缩文件之前呢,首先要弄清两个概念:打包和压缩。打包是指将一大堆文件或目录什么的变成一个总的文件,压缩则是将一个大的文件通过一些压 缩算法变成一个小文件。为什么要区分这两个概念呢?其实这源于Linux中的很多压缩程序只能针对一个文件进行压缩,这样当你想要压缩一大堆文件时,你就 得先借助另它的工具将这一大堆文件先打成一个包,然后再就原来的压缩程序进行压缩。

  Linux下最常用的打包程序就是tar了,使用tar程序打出来的包我们常称为tar包,tar包文件的命令通常都是以.tar结尾的。生成tar包后,就可以用其它的程序来进行压缩了,所以首先就来讲讲tar命令的基本用法:

  tar命令的选项有很多(用man tar可以查看到),但常用的就那么几个选项,下面来举例说明一下:

  # tar -cf all.tar *.jpg

  这条命令是将所有.jpg的文件打成一个名为all.tar的包。-c是表示产生新的包,-f指定包的文件名。

  # tar -rf all.tar *.gif

  这条命令是将所有.gif的文件增加到all.tar的包里面去。-r是表示增加文件的意思。

  # tar -uf all.tar logo.gif

  这条命令是更新原来tar包all.tar中logo.gif文件,-u是表示更新文件的意思。

  # tar -tf all.tar

  这条命令是列出all.tar包中所有文件,-t是列出文件的意思

  # tar -xf all.tar

  这条命令是解出all.tar包中所有文件,-t是解开的意思

  以上就是tar的最基本的用法。为了方便用户在打包解包的同时可以压缩或解压文件,tar提供了一种特殊的功能。这就是tar可以在打包或解包的同时调用其它的压缩程序,比如调用gzip、bzip2等。

  1) tar调用gzip

  gzip是GNU组织开发的一个压缩程序,.gz结尾的文件就是gzip压缩的结果。与gzip相对的解压程序是gunzip。tar中使用-z这个参数来调用gzip。下面来举例说明一下:

  # tar -czf all.tar.gz *.jpg

  这条命令是将所有.jpg的文件打成一个tar包,并且将其用gzip压缩,生成一个gzip压缩过的包,包名为all.tar.gz

  # tar -xzf all.tar.gz

  这条命令是将上面产生的包解开。

  2) tar调用bzip2

  bzip2是一个压缩能力更强的压缩程序,.bz2结尾的文件就是bzip2压缩的结果。与bzip2相对的解压程序是bunzip2。tar中使用-j这个参数来调用gzip。下面来举例说明一下:

  # tar -cjf all.tar.bz2 *.jpg

  这条命令是将所有.jpg的文件打成一个tar包,并且将其用bzip2压缩,生成一个bzip2压缩过的包,包名为all.tar.bz2

  # tar -xjf all.tar.bz2

  这条命令是将上面产生的包解开。

  3)tar调用compress

  compress也是一个压缩程序,但是好象使用compress的人不如gzip和bzip2的人多。.Z结尾的文件就是bzip2压缩的结果。与 compress相对的解压程序是uncompress。tar中使用-Z这个参数来调用gzip。下面来举例说明一下:

  # tar -cZf all.tar.Z *.jpg

  这条命令是将所有.jpg的文件打成一个tar包,并且将其用compress压缩,生成一个uncompress压缩过的包,包名为all.tar.Z

  # tar -xZf all.tar.Z

  这条命令是将上面产生的包解开

  有了上面的知识,你应该可以解开多种压缩文件了,下面对于tar系列的压缩文件作一个小结:

  1)对于.tar结尾的文件

  tar -xf all.tar

  2)对于.gz结尾的文件

  gzip -d all.gz

  gunzip all.gz

  3)对于.tgz或.tar.gz结尾的文件

  tar -xzf all.tar.gz

  tar -xzf all.tgz

  4)对于.bz2结尾的文件

  bzip2 -d all.bz2

  bunzip2 all.bz2

  5)对于tar.bz2结尾的文件

  tar -xjf all.tar.bz2

  6)对于.Z结尾的文件

  uncompress all.Z

  7)对于.tar.Z结尾的文件

  tar -xZf all.tar.z

  另外对于Window下的常见压缩文件.zip和.rar,Linux也有相应的方法来解压它们:

  1)对于.zip

  linux下提供了zip和unzip程序,zip是压缩程序,unzip是解压程序。它们的参数选项很多,这里只做简单介绍,依旧举例说明一下其用法:

  # zip all.zip *.jpg

  这条命令是将所有.jpg的文件压缩成一个zip包

  # unzip all.zip

  这条命令是将all.zip中的所有文件解压出来

  2)对于.rar

  要在linux下处理.rar文件,需要安装RAR for Linux,可以从网上下载,但要记住,RAR for Linux

  不是免费的;然后安装:

  # tar -xzpvf rarlinux-3.2.0.tar.gz

  # cd rar

  # make

  这样就安装好了,安装后就有了rar和unrar这两个程序,rar是压缩程序,unrar是解压程序。它们的参数选项很多,这里只做简单介绍,依旧举例说明一下其用法:

  # rar a all *.jpg

  这条命令是将所有.jpg的文件压缩成一个rar包,名为all.rar,该程序会将.rar 扩展名将自动附加到包名后。

  # unrar e all.rar

  这条命令是将all.rar中的所有文件解压出来

  到此为至,我们已经介绍过linux下的tar、gzip、gunzip、bzip2、bunzip2、compress、uncompress、 zip、unzip、rar、unrar等程式,你应该已经能够使用它们对.tar、.gz、.tar.gz、.tgz、.bz2、.tar.bz2、. Z、.tar.Z、.zip、.rar这10种压缩文件进行解压了,以后应该不需要为下载了一个软件而不知道如何在Linux下解开而烦恼了。而且以上方 法对于Unix也基本有效。

  本文介绍了linux下的压缩程式tar、gzip、gunzip、bzip2、bunzip2、 compress、uncompress、zip、unzip、rar、unrar等程式,以及如何使用它们对.tar、.gz、.tar.gz、. tgz、.bz2、.tar.bz2、.Z、.tar.Z、.zip、.rar这10种压缩文件进行操作

要查看Ubuntu操作系统的位数是32位还是64位,可以通过以下命令来查看:

查看long的位数,返回32或64

可以在终端terminal下输入命令:

1
getconf LONG_BIT

输出结果
1
32

2018-01-16 20-46-51屏幕截图.png
也可以输入:
1
uname -a

输出结果:
1
Linux jacklu 4.13.0-26-generic #29~16.04.2-Ubuntu SMP Tue Jan 9 21:38:24 UTC 2018 i686 i686 i686 GNU/Linux

2018-01-16 20-47-17屏幕截图.png

查看Ubuntu版本:

方法一

在终端中执行下列指令:

1
cat /etc/issue

可以查看当前正在运行的 Ubuntu 的版本号。其输出结果类似下面的内容:
1
Ubuntu 16.04.3 LTS \n \l

2018-01-16 20-48-47屏幕截图.png

方法二

使用 lsb_release 命令也可以查看 Ubuntu 的版本号,与方法一相比,内容更为详细。执行指令如下:

1
sudo lsb_release -a

将输出结果:
1
2
3
4
5
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.3 LTS
Release: 16.04
Codename: xenial

2018-01-16 20-48-27屏幕截图.png

原文链接
1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库。
因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的
状态下,其他的用户也可以任意地登录和修改MySQL的信息。可以采用将MySQL对
外的端口封闭,并且停止Apache以及所有的用户进程的方法实现服务器的准安全
状态。最安全的状态是到服务器的Console上面操作,并且拔掉网线。

2.修改MySQL的登录设置:

1
# vim /etc/my.cnf 

[mysqld]的段中加上一句:
1
skip-grant-tables 

例如:
1
2
3
4
[mysqld] 
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
skip-grant-tables

保存并且退出vi。

3.重新启动mysqld

1
2
3
# service mysqld restart 
Stopping MySQL: [ OK ]
Starting MySQL: [ OK ]

4.登录并修改MySQL的root密码
1
2
3
4
5
6
7
8
9
10
11
12
# mysql 
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3 to server version: 3.23.56
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> USE mysql ;
Database changed
mysql> UPDATE user SET Password = password ( 'new-password' ) WHERE User = 'root' ;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 2 Changed: 0 Warnings: 0
mysql> flush privileges ;
Query OK, 0 rows affected (0.01 sec)
mysql> quit

5.将MySQL的登录设置修改回来
1
# vim /etc/my.cnf 

将刚才在[mysqld]的段中加上的skip-grant-tables删除
保存并且退出vim

6.重新启动mysqld

1
2
3
# service mysqld restart 
Stopping MySQL: [ OK ]
Starting MySQL: [ OK ]