在Quartus上进行简单的软核配置,增加串口的配置,命名为rs232。如下:
然后就可以在Nios上进行软件开发了。当然首先要先在Nios上built(建立)一下(才能出现system.h等文件,在xxx_syslib/Debug/system_description里面,xxx为工程名称),system.h的内容与软核的模块一一对应。一旦软核发生变化,就需要重新编译,重新产生system.h文件。
我想实现通过串口的PC与DE2通信,就是说DE2能发数据到PC机进行显示,PC能发数据到DE2上。
有两种不同的编程方法,第一种是利用寄存器操作,就是通过Nios内部的HAL库宏调用直接操作,这一种比较麻烦,源代码如下:
//UART发送一个字节子程序
void uart_send_byte(alt_u8 data)
{
alt_u16 status; //16位
do{
status=IORD_ALTERA_AVALON_UART_STATUS(RS232_BASE);//读取串口状态寄存器,0x40第六位为trdy--传送好没有
} while(!(status&0x0040)); //等待发送完成
IOWR_ALTERA_AVALON_UART_TXDATA(RS232_BASE, data);
}
//UART发送多个字节子程序
void uart_send_string(alt_u8* str,alt_u16 len)
{
while(len--){
uart_send_byte(*str ++);
}
}
//UART接收子程序
alt_u16 uart_receive_byte(void)
{
alt_u16 status; //16位
alt_u16 temp; //还是16位
do{
status=IORD_ALTERA_AVALON_UART_STATUS(RS232_BASE);
} while(!(status&0x0080)); //等待接收完成
temp=IORD_ALTERA_AVALON_UART_RXDATA(RS232_BASE);
return temp;
}
//串口接收中断服务程序
void uart_ISR(void * context,alt_u32 id)
{
alt_u16 temp = uart_receive_byte(); //通过uart_receive_byte将接收到的字符通过uart_send_byte
uart_send_byte(temp); //发回去回显
}
//串口中断初始化
int uart_init()
{
IOWR_ALTERA_AVALON_UART_CONTROL(RS232_BASE, 0x0080);//接收中断使能
IOWR_ALTERA_AVALON_UART_STATUS(RS232_BASE, 0x0); //清状态标志
IOWR_ALTERA_AVALON_UART_RXDATA(RS232_BASE, 0x0); //清接收寄存器
alt_irq_register(RS232_IRQ,NULL,(void *)uart_ISR); //串口中断注册
return 0;
}
int main()
{
alt_u8* buffer = "Hello FPGA\n";
if(!uart_init()){
printf("uart init success\n");
} else {
printf("uart init failed\n");
}
uart_send_string(buffer, strlen(buffer));
while(1){
}
return 0;
}
这样就可以通过串口调试助手在PC机上收到DE2发来的"Hello FPGA “了。同时PC机可以发送数据给DE2,DE2收到后会马上传回PC进行回显。总之,是实现想要的功能了,虽然过程很繁琐。
第二种方法是直接调用C语言标准函数,程序如下:
int main()
{
alt_u8* buffer = "Hello FPGA\n";
FILE *fp; //串口文件
fp = fopen("/dev/rs232", "w");
if(fp){
fprintf(fp, buffer);
}
fclose(fp);
return 0;
}
最后在PC机的串口调试助手输出结果如下:
第二种方法的确是简单了很多,不用管那些底层的寄存器操作,比如初始化啊什么的,直接打开设备文件(有一个问题,就是那个设备文件还不知道是放在哪里),输出就搞定了,不过我想这个过程要是打印不出就很难进行调试。这也许是这种方法的一个缺点吧,还有就是不知道那些寄存器的具体操作,就对这个软核的寄存器没有一个比较深入的了解,要使用更丰富灵活的功能也许就显得牵强了。所以最好知道两种方法怎么用,什么时候该用哪一种。
还有一个很无语的问题就是之前看了一个帖子(帖子链接http://blog.chinaaet.com/detail/7328.html),关了CPU的高速缓存。导致后来用第二种方法一直没有成功,甚至其他输出(jtag_uart,LCD1602等)都存在问题。我那些配置和程序都是按照师兄之前的来做,想了好久,后来才想起唯一不同的就是师兄没有关闭高速缓存,因为之前问师兄这个问题,他好像也不知道,马上果断开启,重新编译和建立,再次烧入,终于可以。其实是在做1602LCD开发时才发现这个问题的,之前串口弄了我两三天,一直存在问题,很郁闷,但是虽然这样,却让我接触和了解了更多的东西,对以后的开发过程是有益的。
所以觉得遇到一些莫名其妙的困难时,不要害怕和放弃,先尽力尝试解决,回顾整个过程,思考哪里可能出错,逐个排错,最后一定能够解决,即使一时半会解决不了,以后也有可能突然就很容易的解决了,而且这个解决错误的过程才是最重要的,太容易的东西不会留下深刻印象,也就不能学到东西。所以不要害怕失败,失败只是成功的累积。
用户377235 2012-11-5 14:30
第二种方法是Linux下的C吧?