这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
nios_ii之uart串口通信实验 [2020/07/03 16:54] zgf |
nios_ii之uart串口通信实验 [2022/03/22 10:31] (当前版本) sean |
||
---|---|---|---|
行 2: | 行 2: | ||
|技术支持电话|**0379-69926675-801**||| | |技术支持电话|**0379-69926675-801**||| | ||
|技术支持邮件|Gingko@vip.163.com||| | |技术支持邮件|Gingko@vip.163.com||| | ||
- | |技术论坛|http://www.eeschool.org||| | ||
^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ||
| V1.0 | 2020-07-03 | gingko | 初次建立 | | | 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 中。 | ||
+ | <code 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; | ||
+ | } | ||
+ | </code> | ||
+ | 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!)。 | ||
+ |