| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-07-03 | gingko | 初次建立 | ===== 实验二十:NIOSII之UART串口通信实验 ===== ==== 一、 实验目的与意义 ==== - 了解UART接口模块的工作原理。 - 掌握UART接口模块的使用方法。 - 掌握QuartusII的使用方法。 ==== 二、 实验设备及平台 ==== - iCore4 双核心板[[https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22598974120.15.5923532fsFrHiE&id=551864196684|点击购买]]。 - Blaster(或相同功能)仿真器[[https://item.taobao.com/item.htm?id=554869837940|点击购买]]。 - JLINK(或相同功能)仿真器。 - Micro USB线缆。 - Quartus开发平台。 - 电脑一台。 ==== 三、 硬件连接 ==== {{ :icore4:icore4_fpga_20_0.png?direct |}} 序号与引脚对应表 |序号 |对应端口名称 |对应引脚| |1 |Uart_rxd |PIN_U7| |2 |Uart_txd |PIN_Y7| |3 |gnd |--| ==== 四、 实验内容 ==== === 一、硬件部分 === 1、首先打开实验十八里面建立的工程(所有路径保持不变),如图所示: {{ :icore4:icore4_fpga_20_1.png?direct |图20-1}} 2、下面添加UART接口模块,选择Tools->Qsys,如图所示: {{ :icore4:icore4_fpga_20_2.png?direct |图20-2}} 3、打开已有的noisII工程,如图所示: {{ :icore4:icore4_fpga_20_3.png?direct |图20-3}} {{ :icore4:icore4_fpga_20_4.png?direct |图20-4}} 4、进入后界面如图所示: {{ :icore4:icore4_fpga_20_5.png?direct |图20-5}} 5、在界面左侧选择Interface Protocols->Serial->Serial->UART(RS-232 serial port),然后添加。 {{ :icore4:icore4_fpga_20_6.png?direct |图20-6}} 6、在此界面参数设置如图所示,然后点击Finish: {{ :icore4:icore4_fpga_20_7.png?direct |图20-7}} 7、添加成功后界面如图所示: {{ :icore4:icore4_fpga_20_8.png?direct |图20-8}} 8、对uart模块进行重命名为uart,如图所示: {{ :icore4:icore4_fpga_20_9.png?direct |图20-9}} 9、双击uart模块下面external_connection后面的Double-click to改为uart如图所示。 {{ :icore4:icore4_fpga_20_10.png?direct |图20-10}} 10、下面开始连接时钟线,右击uart下面的clk与clk_0连线: {{ :icore4:icore4_fpga_20_11.png?direct |图20-11}} 11、连接复位线,如图所示。 {{ :icore4:icore4_fpga_20_12.png?direct |图20-12}} 12、连接信号线s1,如图所示: {{ :icore4:icore4_fpga_20_13.png?direct |图20-13}} 13、连接中断信号线,如图所示: {{ :icore4:icore4_fpga_20_14.png?direct |图20-14}} 14、程序代码较大,修改内存大小,如图所示: {{ :icore4:icore4_fpga_20_15.png?direct |图20-15}} {{ :icore4:icore4_fpga_20_16.png?direct |图20-16}} 15、点击System->Assign Base Address重新分配基地址,如图所示: {{ :icore4:icore4_fpga_20_17.png?direct |图20-17}} 16、选择菜单栏中的Generate->Generate,重新编译: {{ :icore4:icore4_fpga_20_18.png?direct |图20-18}} 17、点击Generate开始编译,如图所示: {{ :icore4:icore4_fpga_20_19.png?direct |图20-19}} 18、直接点击关闭即可: {{ :icore4:icore4_fpga_20_20.png?direct |图20-20}} 19、关闭 Qsys 窗口,回到 Quartus 主界面,如图所示: {{ :icore4:icore4_fpga_20_21.png?direct |图20-21}} 20、在此界面右击选择 Update Symbol or Block… {{ :icore4:icore4_fpga_20_22.png?direct |图20-22}} 21、直接点击 OK 即可。 {{ :icore4:icore4_fpga_20_23.png?direct |图20-23}} 22、界面如图所示: {{ :icore4:icore4_fpga_20_24.png?direct |图20-24}} 23、右击 ledcorel 模块生成引脚,如图所示 : {{ :icore4:icore4_fpga_20_25.png?direct |图20-25}} 24、为串口模块端口分配引脚(建议用 tcl 文件导入的方法),如图所示 : {{ :icore4:icore4_fpga_20_26.png?direct |图20-26}} 25、保存并编译工程,编译成功后硬件实现部分就完成了, 下载到 FPGA 中, 下面开 始软件部分的实现。 === 二、软件部分 === 1、点击菜单栏中的 Tool->Nios II Software Build Tools for Eclipse,打开 NIOSII 软件,选 择正确的路径(与 Quartus 工程路径相同),点击 OK。 {{ :icore4:icore4_fpga_20_27.png?direct |图20-27}} 2、选择 Generate BSP,如图所示: {{ :icore4:icore4_fpga_20_28.png?direct |图20-28}} 3、右击 led 选择 Update with Modified Files,如图所示: {{ :icore4:icore4_fpga_20_29.png?direct |图20-29}} 4、将以下代码写到 main.c 中。 /* * FILE : main.c * DESCRIPTION : This file is main files. * Author : XiaomaGee@Gmail.com * Copyright : * * History * -------------------- * Rev : 0.00 * Date : 09/05/2012 * * create. * -------------------- */ //-----------------Include files-------------------------// #include "stdio.h" #include "unistd.h" #include "system.h" #include "string.h" #include "sys/alt_irq.h" unsigned int receive_flag=0; unsigned int receive_count=0; unsigned char receive_buffer[200]; //----------------函数声明-----------------// static int uart_send_byte(unsigned char data); static void uart_send_string(unsigned int len, unsigned char *str); static int uart_init(void); static void uart_ISR(void *context); static int set_baudrate(unsigned int baudrate); typedef struct { volatile unsigned long int DATA; volatile unsigned long int DIRECTION; volatile unsigned long int INTERRUPT_MASK; volatile unsigned long int EDGE_CAPTURE; }PIO_T; typedef struct { union{ struct{ volatile unsigned long int RECEIVE_DATA :8; volatile unsigned long int NC :24; }BITS; volatile unsigned long int WORD; }RXDATA; union{ struct{ volatile unsigned long int TRANSMIT_DATA :8; volatile unsigned long int NC :24; }BITS; volatile unsigned long int WORD; }TXDATA; union{ struct{ volatile unsigned long int PE :1; volatile unsigned long int FE :1; volatile unsigned long int BRK :1; volatile unsigned long int ROE :1; volatile unsigned long int TOE :1; volatile unsigned long int TMT :1; volatile unsigned long int TRDY :1; volatile unsigned long int RRDY :1; volatile unsigned long int E :1; volatile unsigned long int NC :1; volatile unsigned long int DCTS :1; volatile unsigned long int CTS :1; volatile unsigned long int EOP :1; volatile unsigned long int NC1 :19; }BITS; volatile unsigned long int WORD; }STATUS; union{ struct{ volatile unsigned long int IPE :1; volatile unsigned long int IFE :1; volatile unsigned long int IBRK :1; volatile unsigned long int IROE :1; volatile unsigned long int ITOE :1; volatile unsigned long int ITMT :1; volatile unsigned long int ITRDY :1; volatile unsigned long int IRRDY :1; volatile unsigned long int IE :1; volatile unsigned long int TRBK :1; volatile unsigned long int IDCTS :1; volatile unsigned long int RTS :1; volatile unsigned long int IEOP :1; volatile unsigned long int NC :19; }BITS; volatile unsigned long int WORD; }CONTROL; union{ struct{ volatile unsigned long int BAUD_RATE_DIVISOR :16; volatile unsigned long int NC :16; }BITS; volatile unsigned int WORD; }DIVISOR; }UART_ST; #define LED ((PIO_T *)(LED_BASE|1<<31)) #define UART ((UART_ST *)(UART_BASE|1<<31)) //-----------------Function------------------------------// int main() { unsigned char buffer[30] = "Hello! I am iCore4!\n"; uart_init(); while (1) { /*蓝色led灯闪烁*/ LED->DATA = 1; usleep(500000); LED->DATA = 0; usleep(500000); /*串口通信*/ if(receive_flag){ receive_flag = 0;//clear flags memset(buffer,0,50);// clear buffer strcpy(buffer,receive_buffer);//copy buffer uart_send_string(sizeof(buffer),buffer); } uart_send_string(sizeof(buffer),buffer); usleep(500000); } return 0; } /* * === FUNCTION ======================================================= * Name : uart_send_byte * DESCRIPTION : 发送一个Byte * Author : XiaomaGee@Gmail.com * Copyright : * * History * -------------------- * Rev : 0.00 * Date : 06/05/2016 * * create. * -------------------- * ================================================================= */ int uart_send_byte(unsigned char data) { UART->TXDATA.BITS.TRANSMIT_DATA = data; while(!UART->STATUS.BITS.TRDY); return 0; } /* * === FUNCTION ======================================================= * Name : uart_send_string * DESCRIPTION : 串口发送函数 * Author : XiaomaGee@Gmail.com * Copyright : * * History * -------------------- * Rev : 0.00 * Date : 06/05/2016 * * create. * -------------------- * ====================================================================== */ void uart_send_string(unsigned int len, unsigned char *str) { while(len--) { uart_send_byte(*str++); } } /* * === FUNCTION ======================================================= * Name : uart_init * DESCRIPTION : 串口初始化 * Author : XiaomaGee@Gmail.com * Copyright : * * History * -------------------- * Rev : 0.00 * Date : 06/05/2016 * * create. * -------------------- * ================================================================= */ int uart_init(void) { //将波特率设置为9600 //set_baudrate(9600); //将控制寄存器IRRDY置1,在接收准备好后使能中断 UART->CONTROL.BITS.IRRDY=1; //将状态寄存器全部清零 UART->STATUS.WORD=0; //为UART注册中断 alt_irq_register(UART_IRQ,NULL,uart_ISR); return 0; } /* * === FUNCTION ======================================================= * Name : uart_ISR * DESCRIPTION : 串口中断服务函数 * Author : XiaomaGee@Gmail.com * Copyright : * * History * -------------------- * Rev : 0.00 * Date : 06/05/2016 * * create. * -------------------- */ static void uart_ISR(void *context) { //等待状态寄存器RRDY置1,当RRDY为1时表示接收的数据已经传输到RXDATA中 while(!(UART->STATUS.BITS.RRDY)); receive_buffer[receive_count++] = UART->RXDATA.BITS.RECEIVE_DATA; //接收的数据以换行符'\n'为结束标志,所以PC端的发送数据最后必须添加上'\n' if(receive_buffer[receive_count-1]=='\n'){ receive_buffer[receive_count]='\0'; receive_count=0; receive_flag=1; } } /* * === FUNCTION ======================================================= * Name : set_baudrate * DESCRIPTION : 设置波特率 * Author : XiaomaGee@Gmail.com * Copyright : * * History * -------------------- * Rev : 0.00 * Date : 06/05/2016 * * create. * -------------------- * ================================================================= */ int set_baudrate(unsigned int baudrate) { UART->DIVISOR.WORD=(unsigned int)(ALT_CPU_FREQ/baudrate+0.5); return 0; } 5、右击 led 选择 Build Project 编译工程,如图所示: {{ :icore4:icore4_fpga_20_30.png?direct |图20-30}} 6、编译成功后会出现 led build complete,如图所示: {{ :icore4:icore4_fpga_20_31.png?direct |图20-31}} 7、右击 led 选择 Run As…->32 Nios II Hardware,如图所示: {{ :icore4:icore4_fpga_20_32.png?direct |图20-32}} 8、可能出现如下窗口,在 Target Connection 中点击 Refresh Connections。 {{ :icore4:icore4_fpga_20_33.png?direct |图20-33}} 9、点击 RUN {{ :icore4:icore4_fpga_20_34.png?direct |图20-34}} 10、成功后可以看到 FPGA 蓝色 LED 闪烁,串口助手上如下图所示: {{ :icore4:icore4_fpga_20_35.png?direct |图20-35}} ==== 五、 实验现象 ==== * FPGA 蓝色 LED 闪烁,串口助手(Commix)上显示收到的数据(Hello! I am iCore4!)。