C——Linux下的串口编程

18 篇文章 1 订阅
15 篇文章 0 订阅

之前在学习安信可A7模块时,是在PC上使用串口调试助手做了GPS的坐标数据信息的采集,同时分析了一些语句的含义。在这过程中,涉及到对嵌入式开发人员一个非常重要的知识:串口通信。在前篇也说到,我们将会自己写程序来对GPS数据进行解析,而这些数据正是靠串口来传输的。所以,本篇博文将进行关于串口通信的学习。

一、串口接头

首先我们得知道串口长什么样,常用的串口接头有两种,一种是9针串口(简称DB-9),一种是25针串口(简称DB-25)。每种接头都有公头和母头之分,其中带针状的接头是公头,而带孔状的接头是母头。
以DB9为例,如图:
这里写图片描述
各个针脚功能说明:
这里写图片描述
在TXD和RXD数据线上:
  (1)逻辑1为-3~-15V的电压
  (2)逻辑0为3~15V的电压
在RTS、CTS、DSR、DTR和DCD等控制线上:
  (1)信号有效(ON状态)为3~15V的电压
  (2)信号无效(OFF状态)为-3~-15V的电压
这是由通信协议RS-232C规定的(请看后文)。

注:一般我们需要的就是2,3,5接口,连接时是TXD接RXD,RXD接TXD,GND接GND。自己的TXD口接RXD口,自发自收,测试串口是否正常。

二、串口通信基础知识

OK,知道了串口的样子了,接下来就要更进一步,学习串口通信的基础知识了。

1、什么是串口通信?

串口通信(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种通讯方式。
串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。

2、串口通信协议

在串口通信中,常用的协议包括RS-232、RS-422和RS-485。
•RS-232:标准串口,最常用的一种串行通讯接口。有三种类型(A,B和C),它们分别采用不同的电压来表示on和off。最被广泛使用的是RS-232C,它将mark(on)比特的电压定义为-3V到-12V之间,而将space(off)的电压定义到+3V到+12V之间。传送距离最大为约15米,最高速率为20kb/s。RS-232是为点对点(即只用一对收、发设备)通讯而设计的,其驱动器负载为3~7kΩ。所以RS-232适合本地设备之间的通信。
•RS-422:最大传输距离为1219米,最大传输速率为10Mb/s。其平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能达到最大传输距离。只有在很短的距离下才能获得最高速率传输。一般100米长的双绞线上所能获得的最大传输速率仅为1Mb/s。
•RS-485:从RS-422基础上发展而来的,最大传输距离约为1219米,最大传输速率为10Mb/s。平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能使用规定最长的电缆长度。只有在很短的距离下才能获得最高速率传输。一般100米长双绞线最大传输速率仅为1Mb/s。

3、同步通信?异步通信?

同步通信:是一种比特同步通信技术,要求发收双方具有同频同相的同步时钟信号,只需在传送报文的最前面附加特定的同步字符,使发收双方建立同步,此后便在同步时钟的控制下逐位发送/接收。如:SPI总线。
异步通信:指两个互不同步的设备通过计时机制或其他技术进行数据传输。也就是说,双方不需要共同的时钟。发送方可以随时传输数据,而接收方必须在信息到达时准备好接收。如:串口(UART)。
接下来在后续的串口编程中讨论的都是异步通信,所以对同步通信不做过多的赘述了。
这里提一下UART和USART,实际上,从字面意思即可理解:
UART:universal asynchronous receiver and transmitter(通用异步收/发器)。
USART:universal synchronous asynchronous receiver and transmitter(通用同步/异步收/发器)。
USART在UART基础上增加了同步功能,即USART是UART的增强型。
我常使用的S3C2440上就是支持的UART。

3、通信方式

•单工模式(Simplex Communication):单向的数据传输。通信双方中,一方为发送端,一方则为接收端。信息只能沿一个方向传输,使用一根传输线。双方是固定的。
•半双工模式(Half Duplex):通信使用同一根传输线,既可以发送数据又可以接收数据,但不能同时进行发送和接收。数据传输允许数据在两个方向上传输,但是,在任何时刻只能由其中的一方发送数据,另一方接收数据。
•全双工模式(Full Duplex)通信允许数据同时在两个方向上传输。因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。在全双工模式中,每一端都有发送器和接收器,有两条传输线,信息传输效率高。

4、数据格式

我们有必要先弄清楚异步通信的数据格式。
这里写图片描述
(1)起始位:起始位必须是持续一个比特时间的“0”,标志传输一个字符的开始。
(2)数据位:数据位紧跟在起始位之后,是通信中的真正有效信息。数据位的位数可以由通信双方共同约定,一般可以是5位、7位或8位。传输数据时先传送字符的低位,后传送字符的高位。
(3)奇偶校验位:奇偶校验位仅占一位,用于进行奇校验或偶校验,奇偶检验位不是必须有的。如果是奇校验,需要保证传输的数据总共有奇数个“1”;如果是偶校验,需要保证传输的数据总共有偶数个“1”。
  举例来说,假设传输的数据位为01001100,如果是奇校验,则奇校验位为0(要确保总共有奇数个1),如果是偶校验,则偶校验位为1(要确保总共有偶数个1)。
  由此可见,奇偶校验位仅是对数据进行简单的置逻辑高位或逻辑低位,不会对数据进行实质的判断,这样做的好处是接收设备能够知道一个位的状态,有可能判断是否有噪声干扰了通信以及传输的数据是否同步。
(4)停止位:停止位可以是是1位、1.5位或2位,可以由软件设定。它一定是“1”,标志着传输一个字符的结束。
(5)空闲位:空闲位是指从一个字符的停止位结束到下一个字符的起始位开始,表示线路处于空闲状态,必须由高电平来填充。

好了,一些基础知识暂时先到这里,更深入的知识得自己自行了解了,接下来便是重头戏,在Linux下的串口编程了。

===========================================
这里同时可以参考我之前的博文:STM8串口 (有相关经验的话)。对比一下两者的区别来进行学习。

===========================================

1、首先是操作串口需要包含的头文件:

#include <stdio.h>   /*标准输入输出的定义*/
#include <errno.h>  /*错误号定义*/
#include <sys/stat.h>
#include <fcntl.h>  /*文件控制定义*/
#include <termios.h>    /*PPSIX 终端控制定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <sys/types.h>
#include <unistd.h> /*UNIX 标准函数定义*/

2、串口相关操作
打开串口:
我们都知道,在Linux下,除了网络设备,其余的都是文件的形式。串口设备也一样在/dev下。
这里写图片描述
所以我们可以通过open系统调用/函数来访问它。
示例:fd = open("/dev/ttyUSB0",O_RDWR|O_NOCTTY|O_NDELAY);
O_NOCTTY:可以告诉Linux这个程序不会成为这个端口上的“控制终端”.如果不这样做的话,所有的输入,比如键盘上过来的Ctrl+C中止信号等等,会影响到你的进程。
O_NDELAY:标志则是告诉Linux,这个程序并不关心DCD信号线的状态——也就是不关心端口另一端是否已经连接。

读写串口:
与普通文件一样,使用read,write函数。
示例:read(fd,buff,8);
write(fd,buff,8);

串口属性设置:
最基本的设置串口包括波特率设置,效验位和停止位设置。这由通信双方协定。

很多系统都支持POSIX终端(串口)接口.程序可以利用这个接口来改变终端的参数,比如,波特率,字符大小等等.要使用这个端口的话,你必须将<termios.h>头文件包含到你的程序中。这个头文件中定义了终端控制结构体和POSIX控制函数。

最重要的就是这个结构体:

struct termios
      {
      tcflag_t  c_iflag;  //输入选项
      tcflag_t  c_oflag;  //输出选项
      tcflag_t  c_cflag;  //控制选项
      tcflag_t  c_lflag;  //行选项
      cc_t      c_cc[NCCS]; //控制字符
      }; 

其中我们更关注的是c_cflag控制选项。其中包含了波特率、数据位、校验位、停止位的设置。
它可以支持很多常量名称其中设置数据传输率为相应的数据传输率前要加上“B”。
c_cflag成员不能直接对其初始化,而要将其通过与、或操作使用其中的某些选项。
设置串口属性主要是配置termios结构体中的各个变量,大致流程如下:

1.使用函数tcgetattr保存原串口属性
struct termios newtio,oldtio;
tcgetattr(fd,&oldtio);

2.通过位掩码的方式激活本地连接和接受使能选项:CLOCAL和CREAD
newtio.c_cflag | = CLOCAL | CREAD;

3.使用函数cfsetispeed和cfsetospeed设置数据传输率
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);

4.通过位掩码设置字符大小。
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;

5.设置奇偶效验位需要用到两个termios中的成员:c_cflag和c_iflag。首先要激活c_cflag中的校验位使能标志PARENB和是否进行奇偶效验,同时还要激活c_iflag中的奇偶效验使能。
设置奇校验:
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
设置偶校验:
newtio.c_iflag |= (INPCK|ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag |= ~PARODD;

6.激活c_cflag中的CSTOPB设置停止位。若停止位为1,则清除CSTOPB;若停止位为0,则激活CSTOPB。
newtio.c_cflag &= ~CSTOPB;

7.设置最少字符和等待时间。在对接收字符和等待时间没有特别要求的情况下,可以将其设置为0。
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;

8.调用函数”tcflush(fd,queue_selector)”来处理要写入引用的对象,queue_selector可能的取值有以下几种。
TCIFLUSH:刷新收到的数据但是不读
TCOFLUSH:刷新写入的数据但是不传送
TCIOFLUSH:同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送。

9.激活配置。在完成配置后,需要激活配置使其生效。使用tcsetattr()函数。
int tcsetattr(int filedes,int opt,const struct termios *termptr);

最后贴出串口配置的完整代码:

/*********************************************************************************
  *      Copyright:  (C) 2017 TangBin<tangbinmvp@gmail.com>
  *                  All rights reserved.
  *
  *       Filename:  s_uart1.c
  *    Description:  This file 
  *                 
  *        Version:  1.0.0(06/04/2017)
  *         Author:  TangBin <tangbinmvp@gmail.com>
  *      ChangeLog:  1, Release initial version on "06/04/2017 07:51:59 PM"
  *                 
  ********************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>


int set_serial(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
    struct termios newttys1,oldttys1;

     /*保存原有串口配置*/
     if(tcgetattr(fd,&oldttys1)!=0) 
     {
          perror("Setupserial 1");
          return -1;
     }
     bzero(&newttys1,sizeof(newttys1));
     newttys1.c_cflag|=(CLOCAL|CREAD ); /*CREAD 开启串行数据接收,CLOCAL并打开本地连接模式*/

     newttys1.c_cflag &=~CSIZE;/*设置数据位*/
     /*数据位选择*/   
     switch(nBits)
     {
         case 7:
             newttys1.c_cflag |=CS7;
             break;
         case 8:
             newttys1.c_cflag |=CS8;
             break;
     }
     /*设置奇偶校验位*/
     switch( nEvent )
     {
         case '0':  /*奇校验*/
             newttys1.c_cflag |= PARENB;/*开启奇偶校验*/
             newttys1.c_iflag |= (INPCK | ISTRIP);/*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特  */
             newttys1.c_cflag |= PARODD;/*启用奇校验(默认为偶校验)*/
             break;
         case 'E':/*偶校验*/
             newttys1.c_cflag |= PARENB; /*开启奇偶校验  */
             newttys1.c_iflag |= ( INPCK | ISTRIP);/*打开输入奇偶校验并去除字符第八个比特*/
             newttys1.c_cflag &= ~PARODD;/*启用偶校验*/
             break;
         case 'N': /*无奇偶校验*/
             newttys1.c_cflag &= ~PARENB;
             break;
     }
     /*设置波特率*/
    switch( nSpeed )  
    {
        case 2400:
            cfsetispeed(&newttys1, B2400);
            cfsetospeed(&newttys1, B2400);
            break;
        case 4800:
            cfsetispeed(&newttys1, B4800);
            cfsetospeed(&newttys1, B4800);
            break;
        case 9600:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
        case 115200:
            cfsetispeed(&newttys1, B115200);
            cfsetospeed(&newttys1, B115200);
            break;
        default:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
    }
     /*设置停止位*/
    if( nStop == 1)/*设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB*/
    {
        newttys1.c_cflag &= ~CSTOPB;/*默认为一位停止位; */
    }
    else if( nStop == 2)
    {
        newttys1.c_cflag |= CSTOPB;/*CSTOPB表示送两位停止位*/
    }

    /*设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/
    newttys1.c_cc[VTIME] = 0;/*非规范模式读取时的超时时间;*/
    newttys1.c_cc[VMIN]  = 0; /*非规范模式读取时的最小字符数*/
    tcflush(fd ,TCIFLUSH);/*tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */

     /*激活配置使其生效*/
    if((tcsetattr( fd, TCSANOW,&newttys1))!=0)
    {
        perror("com set error");
        return -1;
    }

    return 0;
}

下一篇将具体结合GPS的数据解析,便能更好从整体上理解、学习了。

  • 20
    点赞
  • 161
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
资源大于15MB分2次上传。 清晰度一般。加到11章 第12,13章没有。 第1章 嵌入式系统基础. 1.1 嵌入式系统简介 1.1.1 嵌入式系统定义 1.1.2 嵌入式系统与PC 1.1.3 嵌入式系统的特点 1.2 嵌入式系统的发展 1.2.1 嵌入式系统现状 1.2.2 嵌入式系统发展趋势 1.3 嵌入式操作系统与实时操作系统 1.3.1 Linux 1.3.2 uC/OS 1.3.3 Windows CE 1.3.4 VxWorks 1.3.5 Palm OS 1.3.6 QNX 1.4 嵌入式系统选型 第2章 基于ARM9处理器的硬件开发平台 2.1 ARM处理器简介 2.1.1 ARM公司简介 2.1.2 ARM微处理器核 .2.2 ARM9微处理器简介 2.2.1 与ARM7处理器的比较 2.2.2 三星S3C2410X处理器详解 2.3 FS2410开发平台 第3章 创建嵌入式系统开发环境 3.1 嵌入式Linux的开发环境 3.2 Cygwin 3.3 虚拟机 3.4 交叉编译的预备知识 3.4.1 Make命令和Makefile文件 3.4.2 binutils工具包 3.4.3 gcc编译器 3.4.4 Glibc库 3.4.5 GDB 3.5 交叉编译 3.5.1 创建编译环境 3.5.2 编译binutils 3.5.3 编译bootstrap_gcc 3.5.4 编译Glibc 3.5.5 编译完整的gcc 3.5.6 编译GDB 3.5.7 成果 3.5.8 其他交叉编译方法 3.6 通过二进制软件包创建交叉编译环境 3.7 开发套件 第4章 调试嵌入式系统程序 4.1 嵌入式系统调试方法 4.1.1 实时在线仿真 4.1.2 模拟调试 4.1.3 软件调试 4.1.4 BDM/JTAG调试 4.2 ARM仿真器 4.2.1 techorICE ARM仿真器 4.2.2 ARM仿真器工作原理 4.2.3 ARM仿真器的系统功能层次 4.2.4 使用仿真器和ADS Debugger调试ARM开发板 4.3 JTAG接口 4.3.1 JTAG引脚定义 4.3.2 通过JTAG烧写Flash 4.3.3 烧写Flash技术内幕 第5章 Bootloader 5.1 嵌入式系统的引导代码 5.1.1 初识Bootloader 5.1.2 Bootloader的启动流程 5.2 Bootloader之vivi 5.2.1 vivi简介 5.2.2 vivi的配置与编译 5.2.3 vivi代码导读 5.3 Bootloader之U-Boot 5.3.1 U-Boot代码结构分析 5.3.2 编译U-Boot代码 5.3.3 U-Boot代码导读 5.3.4 U-Boot命令 5.4 FS2410的Bootloader 第6章 Linux系统在ARM平台的移植 6.1 移植的概念 6.2 Linux内核结构 6.3 Linux-2.4内核向ARM平台的移植 6.3.1 根目录 6.3.2 arch目录 6.3.3 arch/arm/boot目录 6.3.4 arch/arm/def-configs目录 6.3.5 arch/arm/kernel目录 6.3.6 arch/arm/mm目录 6.3.7 arch/arm/mach-s3c2410目录 6.4 Linux-2.6内核向ARM平台的移植 6.4.1 定义平台和编译器 6.4.2 arch/arm/mach-s3c2410/devs.c 6.4.3 arch/arm/mach-s3c2410/mach-fs2410.c 6.4.4 串口输出 6.5 编译Linux内核 6.5.1 代码成熟等级选项 6.5.2 通用的一些选项 6.5.3 和模块相关的选项 6.5.4 和块相关的选项 6.5.5 和系统类型相关的选项 6.5.6 和总线相关的选项 6.5.7 和内核特性相关的选项 6.5.8 和系统启动相关的选项 6.5.9 和浮点运算相关的选项 6.5.10 用户空间使用的二进制文件格式的选项 6.5.11 和电源管理相关的选项 6.5.12 和网络协议相关的选项 6.5.13 和设备驱动程序相关的选项 6.5.14 和文件系统相关的选项 6.5.15 和程序性能分析相关的选项 6.5.16 和内核调试相关的选项 6.5.17 和安全相关的选项 6.5.18 和加密算法相关的选项 6.5.19 库选项 6.5.20 保存内核配置 第7章 Linux设备驱动程序开发 7.1 设备驱动概述 7.1.1 设备驱动和文件系统的关系 7.1.2 设备类型分类 7.1.3 内核空间和用户空间.. 7.2 设备驱动基础 7.2.1 设备驱动中关键数据结构 7.2.2 字符设备驱动开发 第8章 网络设备驱动程序开发 8.1 网络设备驱动程序简介 8.1.1 device数据结构 8.1.2 sk_buff数据结构 8.1.3 内核的驱动程序接口 8.2 以太网控制器CS8900A 8.2.1 特性 8.2.2 工作原理 8.2.3 电路连接 8.2.4 引脚 8.2.5 操作模式 8.3 网络设备驱动程序实例 8.3.1 初始化函数 8.3.2 打开函数 8.3.3 关闭函数 8.3.4 发送函数 8.3.5 接收函数 8.3.6 中断处理函数 第9章 USB驱动程序开发 9.1 USB驱动程序简介 9.1.1 USB背景知识 9.1.2 Linux内核对USB规范的支持 9.1.3 OHCI简介 9.2 Linux下USB系统文件结点 9.3 USB主机驱动结构 9.3.1 USB数据传输时序 9.3.2 USB设备连接/断开时序 9.4 主要数据结构及接口函数 9.4.1 数据传输管道 9.4.2 统一的USB数据传输块 9.4.3 USBD数据描述 9.4.4 USBD与HCD驱动程序接口 9.4.5 USBD层的设备管理 9.4.6 设备类驱动与USBD接口 9.5 USBD文件系统接口 9.5.1 设备驱动程序访问 9.5.2 设备拓扑访问 9.5.3 设备信息访问 9.6 设备类驱动与文件系统接口 9.7 USB HUB驱动程序 9.7.1 HUB驱动初始化 9.7.2 HUB Probe相关函数 9.8 OHCI HCD实现 9.8.1 OHCI驱动初始化 9.8.2 与USBD连接 9.8.3 OHCI根HUB 9.9 扫描仪设备驱动程序 9.9.1 USBD接口 9.9.2 文件系统接口 9.10 USB主机驱动在S3C2410X平台的实现 9.10.1 USB主机控制器简介 9.10.2 驱动程序的移植 第10章 图形用户接口 10.1 嵌入式系统中的GUI简介 10.1.1 MicroWindows 10.1.2 MiniGUI 10.1.3 Qt/Embedded 10.2 MiniGUI编程 10.2.1 MiniGUI移植 10.2.2 MiniGUI编程 10.3 初识Qt/Embedded 10.3.1 Qt介绍 10.3.2 系统要求 10.3.3 Qt的架构 10.4 Qt/Embedded嵌入式图形开发基础 10.4.1 建立Qt/Embedded 开发环境 10.4.2 认识Qt/Embedded开发环境 10.4.3 窗体 10.4.4 对话框 10.4.5 外形与感觉 10.4.6 国际化 10.5 Qt/Embedded实战演练 10.5.1 安装Qt/Embedded工具开发包 10.5.2 交叉编译Qt/Embedded库 10.5.3 Hello,World 10.5.4 发布Qt/Embedded程序到目标板 10.5.5 添加一个Qt/Embedded应用到QPE 第11章 Java虚拟机的移植 11.1 Java虚拟机概述 11.1.1 Java虚拟机的概念 11.1.2 J2ME 11.1.3 KVM 11.2 Java虚拟机的移植 11.2.1 获得源码 11.2.2 编译环境的建立 11.2.3 JDK的安装 11.2.4 KVM的移植及编译 11.2.5 KVM的测试 11.3 其他可选的虚拟机 11.4 性能优化
目录 第1章 嵌入式系统基础知识 .1 1.1 嵌入式系统概述 1 1.1.1 嵌入式系统的发展史 2 1.1.2 嵌入式系统的定义与特点 3 1.1.3 嵌入式系统的特点 4 1.2 嵌入式系统的组成 5 1.2.1 嵌入式系统的硬件架构 6 1.2.2 嵌入式操作系统 9 1.2.3 嵌入式应用软件 11 1.3 arm处理器平台介绍 12 1.3.1 arm处理器简介 12 1.3.2 arm处理器系列 13 1.3.3 arm体系结构简介 17 1.3.4 s3c2410处理器简介 18 1.4 嵌入式系统硬件平台选型 22 1.4.1 硬件平台的选择 22 1.4.2 arm处理器选型 23 1.5 嵌入式系统开发概述 25 1.5.1 嵌入式系统开发流程 25 1.5.2 嵌入式软件开发流程 26 .本章小结 31 动手练练 31 第2章 嵌入式linux c语言开发工具 32 2.1 嵌入式linux下c语言概述 32 2.1.1 c语言简史 33 2.1.2 c语言特点 33 2.1.3 嵌入式linux c语言编程环境 34 2.2 嵌入式linux编辑器vi的使用 35 2.2.1 vi的基本模式 35 2.2.2 vi的基本操作 36 2.2.3 vi的使用实例分析 40 2.3 嵌入式linux编译器gcc的使用 41 2.3.1 gcc概述 41 2.3.2 gcc编译流程分析 42 2.3.3 gcc警告提示 45 2.3.4 gcc使用库函数 47 2.3.5 gcc代码优化 49 2.4 嵌入式linux调试器gdb的使用 49 2.4.1 gdb使用实例 50 2.4.2 设置/删除断点 53 2.4.3 数据相关命令 54 2.4.4 调试运行环境相关命令 55 2.4.5 堆栈相关命令 55 2.5 make工程管理器 55 2.5.1 makefile基本结构 56 2.5.2 makefile变量 58 2.5.3 makefile规则 61 2.5.4 make使用 62 2.6 emacs综合编辑器 63 2.6.1 emacs的启动与退出 63 2.6.2 emacs的基本编辑 64 2.6.3 emacs的c模式 66 2.6.4 emacs的shell模式 69 本章小结 70 动手练练 70 第3章 构建嵌入式linux系统 71 3.1 嵌入式系统开发环境的构建 71 3.1.1 嵌入式交叉编译环境搭建 71 3.1.2 minicom和超级终端配置及使用 76 3.1.3 宿主机服务配置 83 3.2 bootloader 87 3.2.1 bootloader的概念 88 3.2.2 bootloader启动流程分析 89 3.2.3 u-boot概述 89 3.2.4 u-boot源码导读 90 3.3 编译嵌入式linux内核 91 3.4 linux内核目录结构 95 3.5 制作文件系统 95 本章小结 97 动手练练 97 第4章 嵌入式linux c语言基础——数据、表达式 98 4.1 嵌入式linux c语言概述 98 4.2 基本数据类型 100 4.2.1 整型家族 100 4.2.2 实型家族 102 4.2.3 字符型家族 103 4.2.4 枚举家族 104 4.2.5 指针家族 105 4.3 变量与常量 107 4.3.1 变量的定义 107 4.3.2 typedef 113 4.3.3 常量定义 114 4.3.4 arm-linux基本数据类型综合应用实例 115 4.4 运算符与表达式 118 4.4.1 算术运算符和表达式 119 4.4.2 赋值运算符和表达式 121 4.4.3 逗号运算符和表达式 123 4.4.4 位运算符和表达式 124 4.4.5 关系运算符和表达式 126 4.4.6 逻辑运算符和表达式 127 4.4.7 sizeof操作符 129 4.4.8 条件(?)运算符 130 4.4.9 运算符优先级总结 131 4.4.10 arm-linux运算符 综合实例 133 本章小结 137 动手练练 137 第5章 嵌入式linux c语言基础——控制语句及函数 138 5.1 嵌入式linux c语言程序结构概述 138 5.1.1 嵌入式linux c语言3种程序结构 138 5.1.2 嵌入式linux c语言基本语句 139 5.2 选择语句 142 5.2.1 if语句 142 5.2.2 switch语句 145 5.2.3 arm-linux选择语句应用实例 147 5.3 循环语句 148 5.3.1 while和do-while语句 148 5.3.2 for循环语句 149 5.3.3 break和continue语句 151 5.3.4 arm-linux循环语句应用实例 152 5.4 goto语句 154 5.4.1 goto语句语法 154 5.4.2 arm-linux中goto语句应用实例 154 5.5 函数的定义与声明 155 5.5.1 c语言函数概述 155 5.5.2 函数定义 157 5.5.3 函数声明 157 5.5.4 arm-linux函数定义与声明实例 158 5.6 函数的参数、值和基本调用 160 5.6.1 函数的参数 160 5.6.2 函数的值 161 5.6.3 函数的基本调用 161 5.7 函数的嵌套、递归调用 162 5.7.1 函数的嵌套调用 162 5.7.2 函数的递归调用 162 5.7.3 arm-linux函数调用应用实例 165 本章小结 167 动手练练 ..167 第6章 嵌入式linux c语言基础——数组、指针与结构 168 6.1 数组 169 6.1.1 一维数组 169 6.1.2 字符串 172 6.1.3 二维数组 174 6.2 指针 175 6.2.1 指针的概念 175 6.2.2 指针变量的操作 177 6.2.3 指针和数组 184 6.2.4 指针高级议题 191 6.3 结构体与联合 196 6.3.1 结构体 196 6.3.2 联合 200 6.3.3 arm-linux指针、结构体使用实例 201 本章小结 203 动手练练 203 第7章 嵌入式linux c语言基础——高级议题 204 7.1 预处理 204 7.1.1 预处理的概念 204 7.1.2 预定义 205 7.1.3 文件包含 211 7.1.4 条件编译 212 7.2 c语言中的内存分配 214 7.2.1 c语言程序所占内存分类 214 7.2.2 堆和栈的区别 215 7.3 嵌入式linux可移植性考虑 216 7.3.1 字长和数据类型 216 7.3.2 数据对齐 218 7.3.3 字节顺序 218 7.4 c和汇编的接口 219 7.4.1 内嵌汇编的语法 219 7.4.2 编译器优化介绍 221 7.4.3 c语言关键字volatile 222 7.4.4 memory描述符 222 7.4.5 gcc对内嵌汇编语言的处理方式 223 本章小结 224 动手练练 224 第8章 嵌入式linux c语言基础——arm linux内核常见数据结构 225 8.1 链表 226 8.1.1 链表概述 226 8.1.2 单向链表 226 8.1.3 双向链表 233 8.1.4 循环链表 234 8.1.5 arm linux中链表使用实例 235 8.2 树、二叉树、平衡树 237 8.2.1 树 237 8.2.2 二叉树 238 8.2.3 平衡树 245 8.2.4 arm linux中红黑树使用实例 247 8.3 哈希表 249 8.3.1 哈希表的概念及作用 249 8.3.2 哈希表的构造方法 250 8.3.3 哈希表的处理冲突方法 252 8.3.4 arm linux中哈希表使用实例 253 本章小结 255 动手练练 255 第9章 文件i/o相关实例 256 9.1 linux系统调用及用户编程接口(api) 257 9.1.1 系统调用 257 9.1.2 用户编程接口(api) 257 9.1.3 系统命令 258 9.2 arm linux文件i/o系统概述 258 9.2.1 虚拟文件系统(vfs) 258 9.2.2 通用文件模型 259 9.2.3 arm linux的设备文件 264 9.3 文件i/o操作 265 9.3.1 不带缓存的文件i/o操作 265 9.3.2 标准i/o开发 276 9.4 嵌入式linux串口应用开发 279 9.4.1 串口概述 279 9.4.2 串口设置详解 280 9.4.3 串口使用详解 284 本章小结 287 动手练练 287 第10章 arm linux进程线程开发实例 288 10.1 arm linux进程线程管理 289 10.1.1 进程描述符及任务结构 289 10.1.2 进程的调度 291 10.1.3 linux中的线程 293 10.1.4 linux中进程间通信 293 10.2 arm linux进程控制相关api 294 10.3 arm linux进程间通信api 301 10.3.1 管道通信 301 10.3.2 信号通信 303 10.3.3 共享内存 308 10.3.4 消息队列 309 10.4 arm linux线程相关api 312 10.5 linux守护进程 317 10.5.1 守护进程概述 317 10.5.2 编写规则 318 10.5.3 守护进程实例 319 本章小结 321 动手练练 321 第11章 arm linux网络开发实例 322 11.1 tcp/ip协议简介 322 11.1.1 tcp/ip的分层模型 322 11.1.2 tcp/ip分层模型特点 324 11.1.3 tcp/ip核心协议 325 11.2 网络基础编程 328 11.2.1 socket概述 328 11.2.2 地址及顺序处理 328 11.2.3 socket基础编程 333 11.3 web服务器 339 11.3.1 web服务器功能 339 11.3.2 web服务器协议 341 11.3.3 web服务器协议 342 11.3.4 运行web服务器 347 11.4 traceroute程序实例 347 11.4.1 traceroute原理简介 347 11.4.2 traceroute实例与分析 348 11.4.3 traceroute实例运行结果 354 本章小结 354 动手练练 354 第12章 嵌入式linux设备驱动开发 355 12.1 设备驱动概述 355 12.1.1 设备驱动简介 355 12.1.2 设备驱动程序的特点 356 12.2 模块编程 357 12.2.1 模块编程简介 357 12.2.2 模块相关命令 357 12.2.3 模块编程流程 358 12.3 字符设备驱动编写 360 12.4 块设备驱动编写 369 12.4.1 块设备驱动程序描述符 369 12.4.2 块设备驱动编写流程 369 12.5 简单的skull驱动实例 375 12.5.1 驱动简介 375 12.5.2 驱动编写流程 376 12.5.3 结果分析 379 12.6 lcd驱动编写实例 379 12.6.1 lcd工作原理 379 12.6.2 lcd驱动实例 382 本章小结 389 动手练练 389 第13章 视频监控系统  390 13.1 视频监控系统概述 390 13.1.1 系统组成 390 13.1.2 音视频服务器 391 13.1.3 音视频客户端 392 13.1.4 通信传输控制协议 393 13.2 基本数据结构 395 13.3 功能实现 398 13.3.1 传输控制 398 13.3.2 用户检验 401 13.3.3 控制命令处理 403 13.3.4 云台转动控制 404 13.3.5 线程相关 407 本章小结 408 动手练练 ...408

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值