刘彦文-OMAP35XX(EL-ARM860)嵌入式系统实践教程 第4章 实验例程_第1页
刘彦文-OMAP35XX(EL-ARM860)嵌入式系统实践教程 第4章 实验例程_第2页
刘彦文-OMAP35XX(EL-ARM860)嵌入式系统实践教程 第4章 实验例程_第3页
刘彦文-OMAP35XX(EL-ARM860)嵌入式系统实践教程 第4章 实验例程_第4页
刘彦文-OMAP35XX(EL-ARM860)嵌入式系统实践教程 第4章 实验例程_第5页
已阅读5页,还剩88页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、2013/01OMAP35xx(EL-ARM860)嵌入式系统实践教程嵌入式系统实践教程 刘彦文刘彦文()说明:本教程可作为EL-ARM860实验平台实验内容讲授使用。授课可使用刘彦文编著,清华大学出版社出版的嵌入式系统原理及接口技术教材。第4章 实验例程 4.1 读取、转换时间函数编程举例 Linux系统中,涉及到时间较为常用的三个名词术语是:n GMT(Greenwich Mean Time),格林尼治标准时间。格林尼治标准时间的正午是指太阳横穿格林尼治子午线的时间。有时GMT也表示格林尼治那个位置所处的时区。n UTC(Coordinated Universal Time),世界标准时间

2、,是由原子钟提供的时间,比格林尼治标准时间更为准确。UTC是法文单词首字母的缩写。n CST(China Standard Time),中国标准时间,或称北京时间。n我们现在所说的标准时间,通常是指UTC时间。n北京时间CST=UTC+8小时。n另外,本节中所说的时间,除了我们通常所说的时间外,还包含日期。4.1.1Linux查看、设置时间的命令 查看时间n使用date命令可以查看时间,通常显示的是当地时区的时间,例如北京时间: rootlocalhost # date 2013年 01月 10日 星期四 16:02:19 CST 上述内容分别表示:年、月、日、星期、时、分、秒以及CST,是主

3、机Linux的输出。n有的目标板,配置为显示UTC时间,例如: rootTechv_OMAP35xx:# date Thu Jan 10 16:15:31 UTC 2013 设置时间 主机Linux设置时间后,会保留;目标板设置时间后,加电或RESET后不保留。以下是主机显示、设置时间举例。 使用参数u表示UTC时间 设置时间可以使用命令及参数: date u MMDDhhmmYYYY.ss 其中u表示UTC,从MM开始的参数分别表示月、日、时、分、年和秒。 例如: rootlocalhost # date -u 011016302013.30 2013年 01月 10日 星期四 16:30:

4、30 UTC 系统会将设置的UTC时间,自动转换成CST时间显示,例如输入date命令后,会显示: rootlocalhost # date 2013年 01月 11日 星期五 00:31:42 CST 不使用参数u表示按当地时间设置 以下设置没有设置秒,缺省值为0: rootlocalhost # date 011016322013 2013年 01月 10日 星期四 16:32:00 CST rootlocalhost # date 2013年 01月 10日 星期四 16:32:11 CST4.1.2 常用的读取、转换时间的函数n所有的Linux系统,把GMT时间的1970年1月1日0时

5、0分0秒,作为时间的起点,所有时间都是从那时起,以经过的秒数来计算。n时间通过一个预定义的类型time_t来处理,这是一个以秒计算的时间的整数类型,是一个长整型,与处理时间的函数一起定义在头文件time.h中。 time()函数 例如代码: #include time_t the_time;/*定义类型*/ (void)time(&the_time);/*得到时间值,单位为秒*/ printf(“Raw time is %ldn”,the_time);/*输出时间值*/ 上述代码能够输出从Linux时间起点,到time函数读 取那一刻所经过的时间的秒数。 关于time()函数进一步的用

6、法,见例4.1。 gmtime()函数 gmtime()函数能够把以秒表示的时间值,转换成用户易读格式的值。 gmtime()函数把底层时间值分解为一个结构,该结构包含一些常用的成员: #include struct tm *gmtime(const time_t timeval); tm结构被定义为至少包含表4-1所示的成员。tm成员成员含义含义tm成员成员含义含义int tm_sec秒,秒,061int tm_year从从1900年算起的年年算起的年数数int tm_min分,分,059int tm_wday星期几,星期几,06,0表示周日表示周日int tm_hour时,时,023int

7、 tm_yday年份中的日,年份中的日,0365int tm_mday月份中的日,月份中的日,131int tm_isdst是否夏令时是否夏令时int tm_mon月,月,011,0表示表示1月月注:注:tm_sec的范围允许临时闰的范围允许临时闰1秒或秒或2秒。秒。表表4-1 tm结构至少包含的成员结构至少包含的成员n函数gmtime()按GMT返回时间。n如果要看当地时区的时间,可以使用localtime()函数,使用方法是在程序中,用localtime()函数代替gmtime()函数。n有些小规模的目标板,生产商把当地时区的时间直接设置为GMT时间,使用者要引起注意。 ctime()函数

8、n函数ctime()返回一个长度为26个字符、有固定格式、表示当地时间的字符串,函数格式为: char *ctime(const time_t *timeval);n函数ctime()输出字符串格式见例4.1。n函数ctime()将底层的时间值,即秒值,转换成用户易读格式的值。 4.1.3 读取、转换时间的函数编程举例 编程举例 【例4.1】以下为读取、转换并输出时间的程序,程序名为time.c,源程序保存在主机Linux,路径为/home/nfs1/01_time。n程序中time()函数读取时间的秒值;gmtime()函数将这个秒值转换成一个结构,保存在tm_ptr中;ctime()函数把

9、秒值转换成一个字符串;printf()函数将秒值、结构、字符串输出。sleep(3)函数表示休眠3秒,然后重复读取秒值、转换成结构和字符串输出。n程序代码为:#include #include /*#include */int main() struct tm *tm_ptr; time_t the_time; (void)time(&the_time); tm_ptr=gmtime(&the_time); printf(Raw time is %ldn,the_time); printf(date:%2d/%2d/%2dn, tm_ptr-tm_year, tm_ptr-tm

10、_mon+1,tm_ptr-tm_mday); printf(time: %2d/%2d/%2dn, tm_ptr-tm_hour,tm_ptr-tm_min,tm_ptr-tm_sec); printf(The date is:%sn,ctime(&the_time); sleep(3); (void)time(&the_time); tm_ptr=gmtime(&the_time); printf(Raw time is %ldn,the_time); printf(date:%2d/%2d/%2dn, tm_ptr-tm_year,tm_ptr-tm_mon+1,

11、 tm_ptr-tm_mday); printf(time: %2d/%2d/%2dn, tm_ptr-tm_hour,tm_ptr-tm_min, tm_ptr-tm_sec); printf(The date is: %sn,ctime(&the_time); return 0; 程序运行结果解释 例4.1的源代码经过交叉编译,产生的可执行文件为time,能够在目标板运行。 运行可执行文件前,为了与程序输出的时间对比,可以先用date命令查看目标板的时间: rootTechv_OMAP35xx:/# date Fri Jan 11 10:45:00 UTC 2013在目标板运行可执

12、行文件time,输出内容为:rootTechv_OMAP35xx:/# cd /tmp/01_timerootTechv_OMAP35xx:/var/volatile/tmp/01_time# ./timeRaw time is 1357901145date: 113/ 1/11time: 10/45/45The date is:Fri Jan 11 10:45:45 2013 Raw time is 1357901148 date: 113/ 1/11 time: 10/45/48 The date is: Fri Jan 11 10:45:48 2013 上述内容中,Raw time对应的

13、是秒数;date对应的是113/1/1,表示从1900年算起经过113年(2013年)的1月1日,time对应的是时/分/秒;然后是ctime()函数产生的字符串。4.1.4 例4.1对应的Makefile文件 对例4.1代码进行编译的Makefile文件内容如下: rootlocalhost 01_time# vi Makefile CC = /usr/local/arm/arm-2007q3/bin/arm-none-linux-gnueabi-gcc all: $(CC) -o time time.c clean: -rm -f *.o time 4.1.5 执行例4.1程序前的操作过程

14、举例 进入例4.1程序所在目录并显示程序名 rootlocalhost nfs1# cd /home/nfs1/01_time rootlocalhost 01_time# ls -l 总计 20 -rwxr-xr-x 1 root root 116 11-19 17:09 Makefile -rwxr-xr-x 1 root root 5813 11-19 17:09 time -rwxr-xr-x 1 root root 959 2012-04-16 time.c -rwxr-xr-x 1 root root 1456 2012-04-16 time.o 检查或设置主机、目标板IP地址 在

15、主机终端窗口设置主机Linux IP地址 rootlocalhost 01_time# ifconfig eth0 192.168.1.5 在目标板终端窗口设置目标板Linux IP地址 Techv_OMAP35xx login: root rootTechv_OMAP35xx:# ifconfig eth0 192.168.1.9 eth0: link down rootTechv_OMAP35xx:# eth0: link up, 100Mbps, full-duplex1 在目标板终端窗口测试与主机网络连接状况 rootTechv_OMAP35xx:# ping 192.168.1.5

16、在目标板终端窗口挂接NFS # mount -o soft,nolock,rsize=1024 -v 192.168.1.5:/home/nfs1 /tmp 在主机终端窗口编译源程序 rootlocalhost 01_time# make 在目标板进入相应目录、显示文件名、执行文件 rootTechv_OMAP35xx:/# cd tmp/01_time rootTechv_OMAP35xx:/var/volatile/tmp/01_time# ls Makefile time time.c time.o rootTechv_OMAP35xx:/var/volatile/tmp/01_time

17、# ./time4.2 串行端口及 标准输入/输出/错误编程举例4.2.1 串行通信基础 并行通信及串行通信图4.1 并行通信及串行通信示意图(a) 并行通信 (b)串行通信 串行通信基本概念 数据传输方式n串行通信时,数据在两个站A与B之间的传输,可分为单工方式、半双工方式和全双工方式三种,如图4.2所示。图4.2 串行通信的三种方式 通信速率 通信速率反映数据传输速度的快慢,主要有数据传输率和波特率两个指标。 传输率 传输率定义为每秒传送二进制数的位数(亦称比特数),以位秒(bps)为单位。传输率反映了串行通信的速率。传输率等于每秒传送的字符数和每个字符位数的乘积。例如,每秒传送120个字

18、符,每个字符包含10位(1个起始位,7个数据位,1个奇偶校验位,1个停止位),则传输率为: 120字符秒10位字符1200bps 波特率 波特率定义为1位二进制数传送时间的倒数。每次传送1位数时,波特率的大小和传输率相等。 一般异步通信的波特率在300波特115200波特之间。 信号的调制/解调 串行端口通常用12V表示高、低电平,这些信号在远距离传输时会发生衰减和畸变,以致信号传到接收端时已经是一个难以分辨的信号。如果从这样的信号中提取数据,会使误码率大大上升。解决这个问题的方法是改变信号传输的形式。图4.3 串行通信使用MODEM对信号进行调制和解调 通信的方式n串行通信可分为同步传输方式

19、和异步传输方式两种。同步通信通常靠同步时钟信号来实现数据的发送和接收,同步通信方式目前较少使用。异步通信是一种利用一帧字符中的起始位和停止位来完成收发同步的通信方式。 n异步通信接口电路以“帧(Frame)”为传送单位,其中包含了一个字符的信息。一帧由起始位开始,停止位结束。两个帧之间为空闲位,一帧信息由712位二进制数组成。其格式如图4.4所示。每帧数据由以下四个部分组成。图4.4 异步通信数据帧格式举例 串行通信接口n串行通信接口通常仅仅指的是UART,此处我们将电平变换电路和9针D形接插件也放在这里描述。nUART接口有的与微处理器集成在同一个芯片内,如S3C2410A;也有的与微处理器

20、是分开的,作为一个单独的芯片,例如与8086配套使用的8251A。nUART的主要功能有: 接收CPU送来的、以字节为单位的并行数据。 按照CPU送来的控制字,将CPU送来的数据变成帧格式,串行输出。 从串行输入线上以位为单位读入数据,将每一帧变换成一字节数据,等待CPU读取。 判断数据发送缓冲区空、接收缓冲区满,产生相应标志或中断。 检查是否产生错误并设置相应标志位。图4.5 串行通信接口电路组成n连接UART引脚的输出信号及输入信号使用正逻辑表示,但是RS-232C标准要求使用负逻辑。另外RS-232C标准表示逻辑0、1的电平幅值也与TTL电路不同。因此在UART与9针D形接插件之间,必须

21、有电平转换电路,例如MAX3232芯片,可以用作电平转换电路。 RS-232C标准n电子工业协会EIA ( Electronic Industries Association)在1969年公布了一个RS-232C串行通信接口标准。这个标准对串行接口电路中所使用的信号名称和功能、信号电平等作了统一的规定。标准的提出为串行接口部件的互连提供了统一的规范。nRS-232C串行通信接口标准规定如下: 信号电平 RS-232C标准采用负逻辑,规定逻辑真(true,即逻辑1)在5V15V之间,逻辑假(false,即逻辑0)在+5V+15V之间。通常PC机串行口使用12V作为典型的高、低电平,但在嵌入式系统

22、中串行口通常使用5V作为典型的高、低电平。这个电平与计算机本身及I/O接口芯片使用的TTL电平不匹配。为此,必须要用专门的电路来进行电平转换。 典型的电平转换电路,应该能够把TTL电平转换为EIA电平,并且能够把EIA电平转换为TTL电平。 信号定义 表4-2给出了RS-232C接口的部分常用信号的定义。 接插件 RS-232C一般使用25个引脚或9个引脚的D形接插件(连接器),9针D形接插件较为常用,其外观如图4.6所示。图4.6 9针D形接插件外观示意图4.2.2Linux标准输入/输出/错误系统调用编程举例 系统调用、库函数和设备驱动程序nLinux中系统调用、库函数和设备驱动程序之间的

23、关系,如图4.7所示。图4.7 系统调用、库函数和设备驱动程序之间的关系n由图4.7可见,用户程序可以直接使用系统调用;也可以通过库函数(如标准I/O库函数对应的头文件是stdio.h),由库函数去调用系统调用。由系统调用去调用设备驱动程序,驱动硬件设备工作。n系统调用也是一些函数,它们由Linux直接提供,是通向操作系统本身的接口。nLinux系统把不同的设备,抽象成不同的文件;对设备的操作,抽象成对文件的open、read、write、close和ioctl等操作。 Linux标准输入/输出/错误系统调用nLinux标准输入/输出/错误这一术语的含义,是指标准输入设备/标准输出设备/标准错

24、误输出设备。在一个用户程序运行时,系统已经打开了这3个设备,并且返回了相应的文件描述符。nLinux环境中,每个运行的程序被称为进程(process),每个进程有一些与之相关联的文件描述符。文件描述符是一些小数值的整数,通常由用户打开(open)一个文件或设备时产生的返回值得到。n当一个用户程序开始运行时,它一般可以使用3个已经打开设备返回的文件描述符,这3个描述符不是由用户程序中打开(open)操作返回的,而是由系统产生的。这3个文件描述符是: 0表示标准输入,例如read(0,&c,1);表示从标准输入读入一个字符保存在c中; 1表示标准输出,例如write(1,&c,1)

25、;表示输出c中的一个字符到标准输出; 2表示标准错误,例如write(2,&c,1);表示输出c中的一个字符到标准错误。n当一个程序运行结束时,也不用通过这3个文件描述符去关闭(close)对应的文件或设备。 标准输入/输出/错误与串行端口及仿真终端n嵌入式开发系统目标板上运行的程序,通常把标准输入/输出/错误对应的文件,与目标板上第一个串行端口,即/dev/tts/0设备关联起来。对标准输入/输出/错误的操作,就是对该串行端口的读、写操作。由于目标板第一个串行端口通过电缆与主机串行端口连接,主机Linux系统启动minicom仿真终端程序后,目标板运行的程序中的标准输入系统调用,读入

26、的是主机键盘输入内容,而标准输出和标准错误系统调用将输出的信息,通过串口送到主机仿真终端窗口。n使用标准输入/输出/错误系统调用时,不需要对串行端口重新设置波特率、帧格式、有无调制解调器等参数,默认使用目标板Linux内核已经设定的值。 Linux标准输入/输出/错误系统调用编程举例 【例4.2】以下程序是使用标准输入/输出/错误系统调用的一个示例。n在目标板运行这个程序后,用户在主机minicom终端输入一个小写字母并回车,程序会自动输出全部小写字母,然后输出回车;继续输出全部小写字母,输出回车;直到用户按下Ctrl+c,程序终止;如果用户最初输入的不是小写字母,则程序直接退出。n程序代码如

27、下:#include /*#include */#define FALSE 0#define TRUE 1/*-*/int main()char c;int STOP=FALSE;write(2,test std err output is ok.n,27);/*标准错误系统调用*/write(1,start std input test.n,22); /*标准输出系统调用*/write(1,input 1 char from a-z,out a-z string,and reapet.n,49);write (1,if input first char is other char,end.n

28、,39);while (1) read(0,&c,1); /*标准输入系统调用*/ if (c z ) STOP=TRUE; break; write(1,the char is from read() function,std input:n ,44); write(1,&c,1); write(1,n std output,send data to terminal:n,36); c=a; while (STOP=FALSE) write(1,&c,1); c+; usleep(100000); if (c=z+1) c=n;write(1,&c,1);c=

29、a; write(1,exit from program.n,19);exit(0);n目标板程序执行过程中,在主机仿真终端输出如下信息: test std err output is ok. start std input test. input 1 char from a-z out a-z string,and reapet. if input first char is other char,end. a std output,send data to terminal: abcdefghijklmnopqrstuvwxyz abc Makefile文件代码如下: CC = /usr/

30、local/arm/arm-2007q3/bin/arm-none-linux-gnueabi-gcc all: $(CC) -o term term.c clean: -rm -f *.o term4.2.3Linux串行端口编程举例 文件、设备及系统调用nLinux环境中,文件具有非常重要的意义,文件为操作系统服务,对设备的操作提供了一个简单而一致的接口。n在Linux中,一切都是文件。n用户程序完全可以像使用文件那样使用盘文件、目录、串行端口、打印机及其他设备。例4.4中,用户程序将一个串行端口映射为一个文件,然后使用系统调用,对这个文件进行操作,内核通过调用对应的设备驱动程序,对串行端

31、口硬件进行操作。n用于访问设备驱动程序的系统调用有: open:打开文件或设备 read:对打开的文件或设备执行读操作 write:对打开的文件或设备执行写操作 close:关闭文件或设备 ioctl:把控制信息传递给设备驱动程序nopen系统调用,创建了一条到达文件或设备的访问路径,如果调用成功,返回一个系统文件描述符,其他几个系统调用,能够使用这个描述符对指定的文件或设备进行操作。nopen系统调用中常用参数的含义如下所示: O_RDONLY,规定以读方式打开; O_WRONLY,规定以写方式打开; O_RDWR,规定以读、写方式打开。nread系统调用,从文件描述符相关联的文件里,读入指

32、定字节个数的数据,存入指定的数据区。调用成功,返回实际读入的字节个数,允许实际读入字节个数小于指定字节个数。如果返回为0,表示未读入数据,已到了文件尾;如果返回-1,表示出错。从目标板串口连接的终端键盘读入数据时,输入数据后按下回车键,数据才能由终端程序送到用户程序的read函数。nwrite系统调用,是把写缓冲区的指定字节个数的数据,写入与文件描述符关联的文件中。它的返回值是实际写入的字节数。如果返回0,表示未写入任何数据;如果返回-1,表示调用中出现了错误。nclose系统调用,用于终止文件描述符与对应文件或设备之间的关联。close调用成功时返回0,错误时返回-1。 串行端口设备与文件关

33、联及系统调用举例n在例4.3代码中,前半部分是将串行端口/dev/ttyS0与文件关联,使用系统调用对文件进行读写操作。这些操作实际上是通过目标板指定的串口,对串口连接的主机Linux下minicom仿真终端,进行读写操作。例4.3代码中后半部分,是Linux标准输入/输出/错误系统调用,其读写操作同样是对目标板连接的主机Linux下minicom仿真终端进行读写操作。n例4.3代码串行端口参数没有重新设置,仍使用系统默认的波特率、帧格式,不使用调制解调器。n【例4.3】以下程序中,fp是系统文件描述符;nread是实际读写字节个数;buffer是读写缓冲区。程序先打开/dev/ttyS0文件

34、(串行端口),然后对其读、写,最后关闭。后半部分程序中函数的含义同例4.2。n程序代码如下:#include #include #include #include #include #define COM1 /dev/ttyS2/*-*/int main()char buffer80;int nread;int fp;fp=open(COM1,O_RDWR);if (fp=-1) write(2,/dev/ttyS2 open err,exit.n,26); exit (0); write(1,n plese input char string,from /dev/ttyS2:n,43);nr

35、ead=read(fp,buffer,80);if (nread=-1) write(2,/dev/ttyS2 read err,exit.n,26); exit (0); write(1,n- from /dev/ttyS2 read string, out to /dev/tty2:-n,63);if (write(fp,buffer,nread)!=nread) write(2,/dev/ttyS2 write err,exit.n,27); exit(0); else write(fp,from /dev/ttyS2 read char string,has output.ok.n,4

36、8);close(fp);write(1,n please input char string from std in:n,40);nread=read(0,buffer,80);if (nread=-1) write(2,std in read err,exit.n,22); exit(0); write(1,n- from std in read string, out to std out:-n,56);if (write(1,buffer,nread)!=nread) write(2,std out write err,exitn,23);exit (0); else write(1,

37、from std in read char string,has output.nn,42);exit(0);执行程序及输出结果举例如下:rootTechv_OMAP35xx:/var/volatile/tmp/03_tty1# ./term plese input char string,from /dev/ttyS2:abcd- from /dev/ttyS2 read string, out to /dev/tty2:-abcdfrom /dev/ttyS2 read char string,has output.ok. please input char string from std

38、 in:qwer- from std in read string, out to std out:-qwerfrom std in read char string,has output.以上程序在目标板的/tmp/03_tty1目录,可执行文件名为term。4.2.4C语言标准输入/输出/错误函数编程举例 标准库函数n为了给设备和磁盘文件提供更高层次的接口,Linux发行版提供了一系列的标准函数库,每个库对应一个头文件,每个头文件中含有若干函数原型。高级语言编程使用这些库函数时,应该包含对应的头文件。 math.h头文件,包含acos、asin、atan、cos、log等数学函数。 cty

39、pe.h头文件,包含isalnum、isalpha、iscntrl、isdigit等字符处理函数。 string.h头文件,包含memcmp、memcpy、memmove、memset等字符串处理函数。 stdio.h头文件,包含fgetc、fopen、fprintf、fread、printf等缓冲文件系统的输入/输出函数。n此外还有动态内存分配函数对应的头文件stdlib.h(或mallo.h)。 标准I/O库及自动打开的3个文件流n标准I/O库(stdio)对应的头文件是stdio.h。n标准I/O库提供了许多复杂的函数,用于格式化输出和扫描输入,同时能够满足设备的缓冲I/O需求。 n标准I/O库中常用的库函数有: fopen、frea

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论