Calendar
载入中。。。
Placard
载入中。。。
Category
载入中。。。
Latest Entries
载入中。。。
Latest Comments
载入中。。。
Last Messages
载入中。。。
User Login
载入中。。。
Links
Information
载入中。。。
Search
Other


Welcome to my blog!
  NiosII Step by Step (5) --- UART(part 1、2)
 

--本篇由Mr_Don版主撰写
常常在不同的论坛上看到很多新学Nios/NiosII的朋友们问几乎同样的问题,
形如:

请问NiosII下应该如何编写串口程序呢?有没有例子能让我参考一下?

每次见到这样的帖子我都想回复他,但又觉得一言难尽,软件开发手册里面是有例子的,但是遗憾的是不够详细,所以即使回复一个人又会有很多人跟帖,感觉一句一句好像总是说不完。现在就在NiosII Step by Step这一部分里面给大家讲讲UART。注意,这只是我个人使用UART IP的经验,可能关于这个IP的很多底层细节都没有涉及到,或者还有一些特性我不知道或尚未使用过。所以这里只是给大家开个如何使用UART IP的头,具体更广泛更深层的应用还得靠大家继续分享你们的经验。毕竟,这只是入门的文档,不过,对于不是很复杂的应用(例如参加竞赛)应该差不多了,呵呵。

首先要清楚UART模块的应用并不难,要对自己有信心。

本文将分为四个部分:
1
UART IP介绍调试串口通信的需要的工具;       
2
)软件开发手册上的程序分析和两个最简单的例子;
3
)实战部分:我个人用这个IP调过的两个不同模块及部分程序分析;
4
)关于仿真以及目前使用该IP发现的问题(---啊???做好心理准备去接受哦,呵呵)

(注:四个部分将分为两个part来介绍,本文是part 1 ,介绍前两个部分内容)

1)部分:UART IP介绍及调试串口通信的工具

UARTUniversal Asynchronous Receiver/Transmitter),通用异步收发器,是嵌入式系统上很常用的一个串行接口。这么说的原因是因为RS-232串口本身由于数据速率比较慢而且误码率相对偏高,正在从笔记本电脑的接口配置中慢慢消失,逐渐被USB接口所代替。但是另一方面,由于其方便、简单、易用等特性,它在嵌入式系统中依然扮演着十分重要的角色。所以Altera才把UART作为一个连接Nios/NosII和其相关外设的IP放在SOPCBuilder里面供用户使用。Nios一代调试甚至用的就是直接是串口。

首先要注意的是:Altera所提供的UART IP虽然实现了RS-232接口的异步时序逻辑,但是不能直接连接或驱动一个RS-232串口。原因在于Altera大多数的FPGA器件不符合RS-232的逻辑电平规则,如果直接连上获驱动可能会损害器件。所以连接通过RS-232串口通信的一个设备时,在Nios/NiosII和外设接口之间要加电压转换芯片(例如 Maxim Max232),这样才能首先保证电气上没问题。所以大家在自制电路板时,一定别忘了这一点。

关于串口通信用到的其他一些位,例如奇偶校验位等,这里不打算涉及,一般按照默认就可以了。另外,数据一桢的位数一般也都是8位,停止位一般也就1位,按默认走,不用改。还有一些选项属于高级一些的应用,这里不打算深究。本文的目标只要教会大家如何用串口就够了,呵呵。

串口调试时建议大家使用串口调试的小工具,这样的工具网上有很多,大家可以随便找找,实在不行我在这个帖子后面给大家附上一个,很好用。在PC上只用这个小工具就够了,可以测试待测模块的收、发。

调试时建议采取的方法:先将待调外设的串口和PC主机的串口连上,然后先看看外设和主机之间能不能通信,如果可以那么就可以继续下一步了;如果不行,那么你的问题多半是出在外设本身上,看看是不是波特率不匹配什么的还是别的什么问题。经过这一步,下来就是验证Nios系统将要使用的串口(已经经过电压转换芯片的转接)是否正常。我们可以通过把它也连接到PC的串口上看看是否能正常通信来验证。怎么验证是否能通信呢?请看下一部分介绍:

2)部分:软件开发手册上的程序分析和两个最简单的例子

先看第一个:

#i nclude <stdio.h>
int main ()
{
printf("Hello world.\n");
return 0;
}

真是熟悉得不能再熟悉了。但是这个程序很值得说一说。
首先看它的头文件<stdio.h>,这说明两个问题。第一,NiosII的编程是支持ANSI C库的;第二,这里使用的是有关标准IO的库,这就说明程序里的printf语句是把输出结果送到标准输出流上。那么这个标准输出流是什么,又在哪里呢?请看下图:

 


打开一个hello_world的样板工程,再打开System Libraries Properties选项,你会看到:

看见了正中间的三个“jtag_uart”了么?现在的stdout\ stdin\ stderr都是导向jtag_uart的,所以当你运行这个工程(Run As NiosII Hardware)时,你才可以看到“Hello from NiosII!”显示在NiosII IDE下面的console 显示框里。因为那里就是jtag_uart接口的用户界面。

那么如果我们改变stdout\ stdin\ stderr的位置会怎样呢?请看下图:


现在我已经将stdout\stdin改成了pc_uart。这是我在SOPCBuilder里面自己添加的一个UART IP接口,用于连接NiosIIPC,主要就是用来调试NiosII能否和PC之间通信。

这个时候你再次运行该工程(Run As NiosII Hardware)你会发现“Hello from NiosII!”不显示了!呵呵,注意,结果只是不显示在NiosII IDE下的console里面了,但不代表就不显示了。相反,结果转而送往pc_uart这个接口,而不是jtag_uart接口了。也就是说这时候你在PC上的串口调试工具下才可以看见相应的结果(前提是必须波特率及其它的一些串口基本设置必须匹配)。

以上就是一个输出字符流的重定向过程。输入流的控制也可类比于此。如果把stdin重新改成jtag_uart,那么你在NiosII IDEconsole下面就可以对硬件芯片里面运行着的NiosII处理器发送接受自用户的自符(可以是普通的字符,也可以是某种命令字符)。同样,如果stdin还是用pc_uart,那么输送自符只能在PC机上的串口工具里完成。

怎么样,一个这么简单的程序其实还是比你想的要复杂一些吧?呵呵,不用怕,经过上面的介绍,你已经对于NiosII下的字符流输入输出有了一定的了解了。其实这是一种很重要的字符流重定向的方法。还有一种自符流定向的方法我很快就在下面介绍。这里想就这种方法再多说上两句。如果你在SOPCBuilder里面添加了要用的串口通信模块的UART接口(例如最典型的GPS设备),你不用编写程序就可以直接从设备中接收数据,方法就是把stdin定向成gps_uart(名字随便起),stdout设为jtag_uart,你就会发现只需要对收到的数据编写程序进行包分解处理就行了,而接收数据的过程NiosII IDE已经自动帮你搞定了,呵呵。

不过这个方法有个很大的局限性。很明显,System Libraries Properties选项下给出的只有stdout\ stdin\ stderr三个选项,而一般stderr用的不多,所以实际上你只能最多同时使用两个不同的串口通信的外设模块。除去调试NiosII本身用的jtag_uart(把stdout设为jtag_uart),你只能用一个模块了,而且该模块只能实现输入一种功能。这是不够的,如果遇到要调试GSM这样交互性很强的模块,你就真没办法了,因为你不仅需要向它发送命令,还需要接收该模块的反馈(例如你发送“AT”,它应该反馈回来“OK”),可是还需要在jtag_uart console下观察输出和反馈回来的结果啊。而stdin/stdout都被GSM已经占了,jtag_uart形同虚设,根本看不到发出去和收到的字符(甚至不可能发出去),所以这样是肯定不行的。

建议:以上的方法只适用于刚学习NiosII下串口编程的朋友,如果你想在你的系统上集成两个或者两个以上的串口外设(包括jtag_uart),那么请用第二种方法。


下面介绍第二种串口编程的方法,我们还是从一个简单的例子看起吧:

#i nclude <stdio.h>
#i nclude <string.h>

int main (void)
{
char* msg = “hello world”;
FILE* fp;
fp = fopen (“/dev/jtag_uart”, “r+”);
if (fp)
{
fprintf(fp, “%s”,msg);
fclose (fp);
}
return 0;
}

这种方法才是标准的串口操作方法。说实话,NiosII下的串口编程比Nios下的已经简化了很多。Nios下的串口操作要调用Altera自定义的函数,而NiosII下,由于有了HAL(详见NiosII step by step 2关于HAL的介绍)的存在,串口编程已经成为标准的文件操作了。

我们知道,在Unix/Linux等操作系统里所有的流操作都可以看成是文件,NiosII吸收了这一点(可能是因为Nios吸收了Cygwin的很多特性吧,呵呵),把对串口的流操作也当成了一种文件操作。操作一个串口时,只需要对它相应的设备驱动读写数据就好了。
fp = fopen (“/dev/jtag_uart”, “r+”);
这个语句的意思就是打开jtag_uart的驱动,并且可以对其进行读写(r+),

if (fp)
{
fprintf(fp, “%s”,msg);
fclose (fp);
}

这段语句的意思就是如果文件打开没问题,指针句柄有效,就可以用fprintf语句向这个串口写数据了,这里要写的数据是一个字符串。写完之后关闭文件。你看,所有的操作几乎与C语言下的文件操作没什么区别,呵呵,唯一不同的就是待操作的文件是你要操作的外设,而不是一个文件

利用这种方法,你可以立刻举一反三,只要改动一点点,就可以操作所有的串口外设了。要改动的就是/dev/jtag_uart,把/dev/后面的外设名改改就是了。例如我要操作NiosIIPC之间的通信,只要改为/dev/pc_uart就行啦。

再延伸一点,如果你的系统里面要添加四个使用串口流的设备,分别是JTAG UARTPC UARTGSM UARTGPS UART,那么对于每个外设,只要编写四个相应的文件操作程序就行了:

fp = fopen (“/dev/jtag_uart”, “r+”);
fp = fopen (“/dev/pc_uart”, “r+”);
fp = fopen (“/dev/gps_uart”, “r+”);
fp = fopen (“/dev/gsm_uart”, “r+”);

当然,不要把所有外设的操作都写在一个程序里,应该分开写,最后分成不同的函数,再最后集成到一个main函数里。这是编程细节方面的问题了,不多说了。

以上介绍的方法就是我们一般会采用的方法,具有很大的灵活性,可随时更改、添加外设程序,克服了第一种方法的局限性。

说到这里,你应该知道其实第一种方法就是第二种方法的在NiosII IDE里面的隐含集成,其实图形用户界面背后也不过就是第二种方法的程序,只是stdin/stdout/stder都是由你指定罢了,呵呵。(估计Altera设计这三个选项就是为了方便懒人和初学者,呵呵)

好了,这就是part 1 的内容了,先写到这里,后面我会为大家继续添加part 2 的内容。相信看到这里,你已经对NiosII下的串口编程有了一定的认识了吧,加油,呵呵。

NiosII Step by Step (5) --- UARTpart 2
(续)--进阶篇
上一次的NiosII Step by Step (5) --- UARTpart 1)已经给大家讲了如何使用UART这个IP和两种常用的编程技巧。这次的part 2里将会给大家讲两个实际的应用例子,以及过去使用该IP时发现的问题。

3)部分:实战部分:个人用这个IP调过的两个不同模块及部分程序分析

这部分将向大家举两个串口程序的例子,一个是关于GPS信息接收的程序分析,一个是GSM模块操作的程序分析。程序都是自己以前编的,所以水平有限,可能没有过多的考虑程序性能的问题,还请大家谅解。

只要是串口通信的设备都可以通过PC机上的串口调试程序来调试,所以建议初次调试从设备本身和PC的串口开始。当然不用串口调试程序,用Windows自带的超级终端也可以,只是个人感觉不太好用,呵呵。<

[ 阅读全文 | 回复(0) | 引用通告 | 编辑

  Post  by  jearome 发表于 2006-9-6 12:25:00
发表评论:
载入中。。。
载入中。。。