原创 串口通信的两种编程方式

2010-10-4 21:25 3820 4 5 分类: FPGA/CPLD

在Quartus上进行简单的软核配置,增加串口的配置,命名为rs232。如下:


30d6b40d-9eb9-437d-9702-43086925fe5b.jpg


 


然后就可以在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机的串口调试助手输出结果如下:

0843a8a0-e07a-4c6e-a997-575984861d79.jpg

 


第二种方法的确是简单了很多,不用管那些底层的寄存器操作,比如初始化啊什么的,直接打开设备文件(有一个问题,就是那个设备文件还不知道是放在哪里),输出就搞定了,不过我想这个过程要是打印不出就很难进行调试。这也许是这种方法的一个缺点吧,还有就是不知道那些寄存器的具体操作,就对这个软核的寄存器没有一个比较深入的了解,要使用更丰富灵活的功能也许就显得牵强了。所以最好知道两种方法怎么用,什么时候该用哪一种。


还有一个很无语的问题就是之前看了一个帖子(帖子链接http://blog.chinaaet.com/detail/7328.html),关了CPU的高速缓存。导致后来用第二种方法一直没有成功,甚至其他输出(jtag_uart,LCD1602等)都存在问题。我那些配置和程序都是按照师兄之前的来做,想了好久,后来才想起唯一不同的就是师兄没有关闭高速缓存,因为之前问师兄这个问题,他好像也不知道,马上果断开启,重新编译和建立,再次烧入,终于可以。其实是在做1602LCD开发时才发现这个问题的,之前串口弄了我两三天,一直存在问题,很郁闷,但是虽然这样,却让我接触和了解了更多的东西,对以后的开发过程是有益的。


所以觉得遇到一些莫名其妙的困难时,不要害怕和放弃,先尽力尝试解决,回顾整个过程,思考哪里可能出错,逐个排错,最后一定能够解决,即使一时半会解决不了,以后也有可能突然就很容易的解决了,而且这个解决错误的过程才是最重要的,太容易的东西不会留下深刻印象,也就不能学到东西。所以不要害怕失败,失败只是成功的累积。

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户377235 2012-11-5 14:30

第二种方法是Linux下的C吧?

相关推荐阅读
用户894691 2011-01-12 19:43
冯诺依曼结构和哈佛结构的区别(转)
冯诺依曼架构: 把代码当作一种特殊的数据 来操作;指令总线和数据总线及其存储区域是统一的; 哈佛结构:指令总线和数据总线及其存储区域是分开的,独立的; 关于这个问题,有人说51地址线复用,就是冯诺...
用户894691 2011-01-12 19:21
软中断和硬中断的区别(转)
①硬中断是由外部事件引起的因此具有随机性和突发性;软中断是执行中断指令产生的,无面外部施加中断请求信号,因此中断的发生不是随机的而是由程序安排好的。②硬中断的中断响应周期,CPU需要发中断回合信号(N...
用户894691 2011-01-09 21:00
C++引用&和指针在作为形参时的区别
int n; int &m = n; 在C++中,多了一个C语言没有的引用声明符&,如上,m就是n的引用,简单的说m就是n的别名,两者在内存中占同样的位置,不对m开辟新的内存空间,对m...
用户894691 2010-12-15 11:54
new和malloc的区别(转)
1、new 是c++中的操作符,malloc是c 中的一个函数2、new 不止是分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员的...
用户894691 2010-11-26 20:20
some words
当你思维只对准一个对手的时候,你已经输了一半。你的思维整天围着它转,你的思维已经被限死,而且将对手踩下去就意味着自己站起来了吗?2010-10-14 吃亏是福。2010-11-21 “我们之所以会心累...
用户894691 2010-11-21 16:13
(转)c++中char * 和 char []的区别
c++中char * 和 char []的区别发布于:2010-3-17 10:19:15 已被阅读: 119 在实习过程中发现了一个以前一直默认的错误,同样char *c = "abc"和char ...
我要评论
1
4
关闭 站长推荐上一条 /3 下一条