第一步,在sopc里增加一个串口
第二步:操作UART的三种方法
(1)直接寄存器操作。
NIOS II 的串口编程有多种方式,很多地方给的程序大多数更像纯C语言写法,占用程序空间比较大,这里以一个更像单片机串口的程序,占用空间当对而言要小,且对像工业控制的数据传输更实用简单些(个人觉得)。
extern unsigned char leddata[8];
//UART发送一个字节子程序
void Uart_send(unsigned char data)
{
alt_u16 status;
status=IORD_ALTERA_AVALON_UART_STATUS(UART_BASE);
while(!(status&0x0040))//等待发送完成
status=IORD_ALTERA_AVALON_UART_STATUS(UART_BASE);
IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE,data);
}
//UART发送多个字节子程序
void Uart_send_n(unsigned char *ptr,unsigned char n)
{
for(;n>0;n--)
{
Uart_send(*ptr);
ptr++;
}
}
//UART接收子程序
int Uart_receive(void)
{
alt_u16 status;
int temp;
status=IORD_ALTERA_AVALON_UART_STATUS(UART_BASE);
while(!(status&0x0080))//等待发送完成
status=IORD_ALTERA_AVALON_UART_STATUS(UART_BASE);
temp=IORD_ALTERA_AVALON_UART_RXDATA(UART_BASE);
return temp;
}
//串口接收中断服务程序
void Uart_ISR(void * context,alt_u32 id)
{
unsigned char temp;
temp=IORD_ALTERA_AVALON_UART_RXDATA(UART_BASE);
leddata[5]=temp;
}
//串口中断初始化
void Uart_init()
{
IOWR_ALTERA_AVALON_UART_CONTROL(UART_BASE, 0x80);//接收中断使能
IOWR_ALTERA_AVALON_UART_STATUS(UART_BASE, 0x0);//清状态标志
// IOWR_ALTERA_AVALON_UART_RXDATA(UART_BASE, 0x0);//清接收寄存器
alt_irq_register(UART_IRQ,0,Uart_ISR);//中断注册,此处编译总出现警告,还请 高手能指点。warning: implicit declaration of function `alt_irq_register' test3 uart_zx.h
}
程序中接收部分写了一个扫描的和一个中断的,可跟据需要选择。我想中断接收的更实用些吧。
其中UART_BASE请更换为你自己UART的名字即可。
(2)类似C语言的操作,用printf函数。(编译过程太慢!可以喝杯茶了!)
使用这种方法要加上这一句 #include
别忘了在System library Properties 的stdout/stdin 选择你的串口。
int main ()
{
printf("Hello world./n");
return 0;
}
执行上述程序可以看到效果!
(3)转载(没试过)
下面介绍第三种串口编程的方法,我们还是从一个简单的例子看起吧:
#i nclude
#i nclude
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/后面的外设名改改就是了。例如我要操作NiosII与PC之间的通信,只要改为/dev/pc_uart就行啦。
再延伸一点,如果你的系统里面要添加四个使用串口流的设备,分别是JTAG UART、PC UART、GSM UART、GPS 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设计这三个选项就是为了方便懒人和初学者,呵呵)