赞
踩
目录
UART是一种采用异步串行方式的通用异步收发传输器,在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。
UART串口通信需要两根信号线来实现,一根用于串口发送,另一根负责串口接收。
UART的一帧数据由4部分组成:起始位、数据位、奇偶校验位和停止位。起始位标志着一帧数据的开始,低电平有效;数据位代表一帧数据中的有效数据;校验位分为奇校验和偶校验检测数据是否出错;在空闲状态下总线处于高电平。
UART通信过程中更多数据格式及传输速率时刻设置的,并且要求双方遵循同样的设置。其中起始位;数据位可选5-8位,一般选择8位;校验位一般选择无校验位;停止位一般选择1位。传输速率用波特率表示,波特率表示每秒传输二进制数据的位数,单位时bps(位/秒),常用的波特率有9600、115200等
上位机通过串口调试工具将数据发送给MCU的UART2,MCU的UART2接收到的数据通MCU的UART1发送给FPGA的UART1,FPGA的UART1接收到的数据通过FPGA的UART2发送给上位机。
上位机通过串口调试工具将数据发送给FPGA的UART2,FPGA的UART2接收到的数据通FPGA的UART1发送给MCU的UART1,MCU的UART1接收到的数据通过MCU的UART2发送给上位机。
FPGA主控芯片是EP4CE10F17C8。
在顶层模块上,对uart1和uart2接收到的数据和发送数据进行控制和操作。
顶层模块代码:
- module test(
- input sys_clk, //外部50M时钟
- input sys_rst_n, //外部复位信号,低有效
-
- //uart1接口
- input wire uart1_rxd, //UART接收端口
- output wire uart1_txd, //UART发送端口
-
- //uart2接口
- input wire uart2_rxd, //UART接收端口
- output wire uart2_txd //UART发送端口
- );
-
- wire clk_1m_w;
-
- //parameter define
- parameter CLK_FREQ = 50000000; //定义系统时钟频率
- parameter UART_BPS = 256000; //定义串口波特率
- parameter CMD_PKGEND = 8'h65; //数据包尾
- //uart1接口
- wire uart1_recv_en; //UART1接收完成使能
- wire [7:0] uart1_recv_data; //UART1接收到的数据
-
- reg uart1_send_en; //UART1发送使能
- wire uart1_txd_busy; //UART1发送忙标志
-
- //uart2接口
- wire uart2_recv_en; //UART2接收完成使能
- wire [7:0] uart2_recv_data; //UART2接收到的数据
-
- reg uart2_send_en; //UART2发送使能
- wire uart2_txd_busy; //UART2发送忙标志
-
- //边沿检测接口
- reg uart2_en_d0;
- reg uart2_en_d1;
- wire uart2_en_flag;
-
- //边沿检测接口
- reg uart1_en_d0;
- reg uart1_en_d1;
- wire uart1_en_flag;
-
- //uart2_uart1 fifo写接口
- reg uart2_wrreq;
- wire [7:0] uart2_data_in;
- wire uart2_wrfull;
-
- //uart2_uart1 fifo读接口
- reg uart2_fifo_flag; //uart2_uart1开始读fifo标志
- reg uart2_rdreq;
- wire [7:0] uart2_data_out;
- wire uart2_rdempty;
-
- //uart1_uart2 fifo写接口
- reg uart1_wrreq;
- wire [7:0] uart1_data_in;
- wire uart1_wrfull;
-
- //uart1_uart2 fifo读接口
- reg uart1_fifo_flag; //uart1_uart2开始读fifo标
- reg uart1_rdreq;
- wire [7:0] uart1_data_out;
- wire uart1_rdempty;
-
- //*****************************************************
- //** main code
- //*****************************************************
- //捕获uart2_recv_en上升沿,得到一个时钟周期的脉冲信号
- assign uart2_en_flag = (~uart2_en_d1) & uart2_en_d0;
- //捕获uart1_recv_en上升沿,得到一个时钟周期的脉冲信号
- assign uart1_en_flag = (~uart1_en_d1) & uart1_en_d0;
-
- //UART2和UART1边沿检测
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- uart2_en_d0 <= 1'b0;
- uart2_en_d1 <= 1'b0;
-
- uart1_en_d0 <= 1'b0;
- uart1_en_d1 <= 1'b0;
- end
- else begin
- uart2_en_d0 <= uart2_recv_en;
- uart2_en_d1 <= uart2_en_d0;
-
- uart1_en_d0 <= uart1_recv_en;
- uart1_en_d1 <= uart1_en_d0;
- end
- end
-
- //UART2写进uart2_uart1 FIFO中
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- uart2_wrreq <= 0;
- uart2_fifo_flag <= 0;
- end
- else begin
- if(uart2_en_flag && !uart2_wrfull) begin
- uart2_wrreq <= 1;
- end
- else begin
- uart2_wrreq <= 0;
- end
-
- if(uart2_en_flag && uart2_recv_data == CMD_PKGEND)begin //检测到数据包尾,uart2_uart1 fifo开始读
- uart2_fifo_flag <= 1;
- end
- if(!uart2_en_flag && uart2_rdempty) begin //uart2_uart1 fifo为空时,将uart2_fifo_flag标志置零
- uart2_fifo_flag <= 0;
- end
- end
- end
-
- //uart2_uart1 fifo读 uart1发送
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- uart2_rdreq <= 0;
- uart1_send_en <= 0;
- end
- else begin
- if(uart2_fifo_flag) begin
- //读到数据的下一个周期uart1_txd_busy依旧为0,所以需要增加!uart2_rdreq来延迟一个周期,在第二个周期到来时,uart1_txd_busy为1
- if(!uart2_rdempty && !uart1_txd_busy && !uart2_rdreq)begin
- uart2_rdreq <= 1;
- uart1_send_en <= 1;
- end
- else begin
- uart2_rdreq <= 0;
- uart1_send_en <= 0;
- end
- end
- else begin
- uart2_rdreq <= 0;
- uart1_send_en <= 0;
- end
- end
- end
-
- //UART1写进uart1_uart2 FIFO中
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- uart1_wrreq <= 0;
- uart1_fifo_flag <= 0;
- end
- else begin
- if(uart1_en_flag && !uart1_wrfull) begin
- uart1_wrreq <= 1;
- end
- else begin
- uart1_wrreq <= 0;
- end
-
- if(uart1_en_flag && uart1_recv_data == CMD_PKGEND)begin //检测到数据包尾,uart2_uart1 fifo开始读
- uart1_fifo_flag <= 1;
- end
- if(!uart1_en_flag && uart1_rdempty) begin //uart2_uart1 fifo为空时,将uart2_fifo_flag标志置零
- uart1_fifo_flag <= 0;
- end
- end
- end
-
- //fifo读 uart1_uart2 uart2发送
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- uart1_rdreq <= 0;
- uart2_send_en <= 0;
- end
- else begin
- if(uart1_fifo_flag) begin
- //读到数据的下一个周期uart2_txd_busy依旧为0,所以需要增加!uart1_rdreq来延迟一个周期,在第二个周期到来时,uart2_txd_busy为1
- if(!uart1_rdempty && !uart2_txd_busy && !uart1_rdreq)begin
- uart1_rdreq <= 1;
- uart2_send_en <= 1;
- end
- else begin
- uart1_rdreq <= 0;
- uart2_send_en <= 0;
- end
- end
- else begin
- uart1_rdreq <= 0;
- end
- end
- end
-
- //例化锁相环
- pll_clk u_pll_clk( //时钟分频模块,用于调试
- .inclk0 (sys_clk),
- .c0 (clk_1m_w)
- );
-
- //例化uart1接收模块
- uart_recv #( //串口接收模块
- .CLK_FREQ (CLK_FREQ), //设置系统时钟频率
- .UART_BPS (UART_BPS)) //设置串口接收波特率
- u_uart1_recv(
- .sys_clk (sys_clk),
- .sys_rst_n (sys_rst_n),
-
- .uart_rxd (uart1_rxd),
- .uart_done (uart1_recv_en),
- .uart_data (uart1_recv_data)
- );
-
- //例化uart1发送模块
- uart_send #( //串口发送模块
- .CLK_FREQ (CLK_FREQ), //设置系统时钟频率
- .UART_BPS (UART_BPS)) //设置串口发送波特率
- u_uart1_send(
- .sys_clk (sys_clk),
- .sys_rst_n (sys_rst_n),
-
- .uart_en (uart1_send_en),
- .uart_din (uart2_data_out),
- .uart_txd (uart1_txd),
- .uart_txd_busy (uart1_txd_busy)
- );
-
- //例化uart2接收模块
- uart_recv #( //串口接收模块
- .CLK_FREQ (CLK_FREQ), //设置系统时钟频率
- .UART_BPS (UART_BPS)) //设置串口接收波特率
- u_uart2_recv(
- .sys_clk (sys_clk),
- .sys_rst_n (sys_rst_n),
-
- .uart_rxd (uart2_rxd),
- .uart_done (uart2_recv_en),
- .uart_data (uart2_recv_data)
- );
-
- //例化uart2发送模块
- uart_send #( //串口发送模块
- .CLK_FREQ (CLK_FREQ), //设置系统时钟频率
- .UART_BPS (UART_BPS)) //设置串口发送波特率
- u_uart2_send(
- .sys_clk (sys_clk),
- .sys_rst_n (sys_rst_n),
-
- .uart_en (uart2_send_en),
- .uart_din (uart1_data_out),
- .uart_txd (uart2_txd),
- .uart_txd_busy (uart2_txd_busy)
- );
-
- //例化uart2_uart1 fifo
- uart2_uart1 u_uart2_uart1(
- .wrclk (sys_clk),
-
- .wrreq (uart2_wrreq),
- .data (uart2_recv_data),
- .wrfull (uart2_wrfull),
-
- .rdclk (sys_clk),
-
- .rdreq (uart2_rdreq),
- .q (uart2_data_out),
- .rdempty (uart2_rdempty)
- );
-
- //例化uart1_uart2 fifo
- uart1_uart2 u_uart1_uart2(
- .wrclk (sys_clk),
-
- .wrreq (uart1_wrreq),
- .data (uart1_recv_data),
- .wrfull (uart1_wrfull),
-
- .rdclk (sys_clk),
-
- .rdreq (uart1_rdreq),
- .q (uart1_data_out),
- .rdempty (uart1_rdempty)
- );
-
-
- endmodule
uart接收模块代码:
- module uart_recv(
- input sys_clk, //系统时钟
- input sys_rst_n, //系统复位,低电平有效
-
- input uart_rxd, //UART接收端口
- output reg uart_done, //接收一帧数据完成标志信号
- output reg [7:0] uart_data //接收的数据
- );
-
- //parameter define
- parameter CLK_FREQ = 50000000; //系统时钟频率
- parameter UART_BPS = 115200; //串口波特率
- localparam BPS_CNT = CLK_FREQ/UART_BPS; //为得到指定波特率,
- //需要对系统时钟计数BPS_CNT次
- //reg define
- reg uart_rxd_d0;
- reg uart_rxd_d1;
- reg [15:0] clk_cnt; //系统时钟计数器
- reg [ 3:0] rx_cnt; //接收数据计数器
- reg rx_flag; //接收过程标志信号
- reg [ 7:0] rxdata; //接收数据寄存器
-
- //wire define
- wire start_flag;
-
- //*****************************************************
- //** main code
- //*****************************************************
- //捕获接收端口下降沿(起始位),得到一个时钟周期的脉冲信号
- assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);
-
- //对UART接收端口的数据延迟两个时钟周期
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- uart_rxd_d0 <= 1'b0;
- uart_rxd_d1 <= 1'b0;
- end
- else begin
- uart_rxd_d0 <= uart_rxd;
- uart_rxd_d1 <= uart_rxd_d0;
- end
- end
-
- //当脉冲信号start_flag到达时,进入接收过程
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n)
- rx_flag <= 1'b0;
- else begin
- if(start_flag) //检测到起始位
- rx_flag <= 1'b1; //进入接收过程,标志位rx_flag拉高
- else if((rx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
- rx_flag <= 1'b0; //计数到停止位中间时,停止接收过程
- else
- rx_flag <= rx_flag;
- end
- end
-
- //进入接收过程后,启动系统时钟计数器与接收数据计数器
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- clk_cnt <= 16'd0;
- rx_cnt <= 4'd0;
- end
- else if ( rx_flag ) begin //处于接收过程
- if (clk_cnt < BPS_CNT - 1) begin
- clk_cnt <= clk_cnt + 1'b1;
- rx_cnt <= rx_cnt;
- end
- else begin
- clk_cnt <= 16'd0; //对系统时钟计数达一个波特率周期后清零
- rx_cnt <= rx_cnt + 1'b1; //此时接收数据计数器加1
- end
- end
- else begin //接收过程结束,计数器清零
- clk_cnt <= 16'd0;
- rx_cnt <= 4'd0;
- end
- end
- //根据接收数据计数器来寄存uart接收端口数据
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if ( !sys_rst_n)
- rxdata <= 8'd0;
- else if(rx_flag) //系统处于接收过程
- if (clk_cnt == BPS_CNT/2) begin //判断系统时钟计数器计数到数据位中间
- case ( rx_cnt )
- 4'd1 : rxdata[0] <= uart_rxd_d1; //寄存数据位最低位
- 4'd2 : rxdata[1] <= uart_rxd_d1;
- 4'd3 : rxdata[2] <= uart_rxd_d1;
- 4'd4 : rxdata[3] <= uart_rxd_d1;
- 4'd5 : rxdata[4] <= uart_rxd_d1;
- 4'd6 : rxdata[5] <= uart_rxd_d1;
- 4'd7 : rxdata[6] <= uart_rxd_d1;
- 4'd8 : rxdata[7] <= uart_rxd_d1; //寄存数据位最高位
- default:;
- endcase
- end
- else
- rxdata <= rxdata;
- else
- rxdata <= 8'd0;
- end
- //数据接收完毕后给出标志信号并寄存输出接收到的数据
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- uart_data <= 8'd0;
- uart_done <= 1'b0;
- end
- else if(rx_cnt == 4'd9) begin //接收数据计数器计数到停止位时
- uart_data <= rxdata; //寄存输出接收到的数据
- uart_done <= 1'b1; //并将接收完成标志位拉高
- end
- else begin
- uart_data <= 8'd0;
- uart_done <= 1'b0;
- end
- end
- endmodule
uart发送模块代码:
- module uart_send(
- input sys_clk, //系统时钟
- input sys_rst_n, //系统复位,低电平有效
-
- input uart_en, //发送使能信号
- input [7:0] uart_din, //待发送数据
- output reg uart_txd, //UART发送端口
- output reg uart_txd_busy
- );
-
- //parameter define
- parameter CLK_FREQ = 50000000; //系统时钟频率
- parameter UART_BPS = 115200; //串口波特率
- localparam BPS_CNT = CLK_FREQ/UART_BPS; //为得到指定波特率,对系统时钟计数BPS_CNT次
-
- //reg define
- reg uart_en_d0;
- reg uart_en_d1;
- reg [15:0] clk_cnt; //系统时钟计数器
- reg [ 3:0] tx_cnt; //发送数据计数器
- reg tx_flag; //发送过程标志信号
- reg [ 7:0] tx_data; //寄存发送数据
-
- //wire define
- wire en_flag;
-
- //*****************************************************
- //** main code
- //*****************************************************
- //捕获uart_en上升沿,得到一个时钟周期的脉冲信号
- assign en_flag = (~uart_en_d1) & uart_en_d0;
-
- //对发送使能信号uart_en延迟两个时钟周期
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- uart_en_d0 <= 1'b0;
- uart_en_d1 <= 1'b0;
- end
- else begin
- uart_en_d0 <= uart_en;
- uart_en_d1 <= uart_en_d0;
- end
- end
-
- //当脉冲信号en_flag到达时,寄存待发送的数据,并进入发送过程
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- tx_flag <= 1'b0;
- tx_data <= 8'd0;
- uart_txd_busy <= 1'b0;
- end
- else begin
- if(uart_en) uart_txd_busy <= 1'b1;
-
- if (en_flag) begin //检测到发送使能上升沿
- tx_flag <= 1'b1; //进入发送过程,标志位tx_flag拉高
- tx_data <= uart_din; //寄存待发送的数据
- end
- else if ((tx_cnt == 4'd9)&&(clk_cnt == BPS_CNT - 1))begin //计数到停止位中间时,停止发送过程
- tx_flag <= 1'b0; //发送过程结束,标志位tx_flag拉低
- tx_data <= 8'd0;
- uart_txd_busy <= 1'b0;
- end
- else begin
- tx_flag <= tx_flag;
- tx_data <= tx_data;
- end
- end
- end
- //进入发送过程后,启动系统时钟计数器与发送数据计数器
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n) begin
- clk_cnt <= 16'd0;
- tx_cnt <= 4'd0;
- end
- else if (tx_flag) begin //处于发送过程
- if (clk_cnt < BPS_CNT - 1) begin
- clk_cnt <= clk_cnt + 1'b1;
- tx_cnt <= tx_cnt;
- end
- else begin
- clk_cnt <= 16'd0; //对系统时钟计数达一个波特率周期后清零
- tx_cnt <= tx_cnt + 1'b1; //此时发送数据计数器加1
- end
- end
- else begin //发送过程结束
- clk_cnt <= 16'd0;
- tx_cnt <= 4'd0;
- end
- end
-
- //根据发送数据计数器来给uart发送端口赋值
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if (!sys_rst_n)
- uart_txd <= 1'b1;
- else if (tx_flag)
- case(tx_cnt)
- 4'd0: uart_txd <= 1'b0; //起始位
- 4'd1: uart_txd <= tx_data[0]; //数据位最低位
- 4'd2: uart_txd <= tx_data[1];
- 4'd3: uart_txd <= tx_data[2];
- 4'd4: uart_txd <= tx_data[3];
- 4'd5: uart_txd <= tx_data[4];
- 4'd6: uart_txd <= tx_data[5];
- 4'd7: uart_txd <= tx_data[6];
- 4'd8: uart_txd <= tx_data[7]; //数据位最高位
- 4'd9: uart_txd <= 1'b1; //停止位
- default: ;
- endcase
- else
- uart_txd <= 1'b1; //空闲时发送端口为高电平
- end
-
- endmodule
STM32的主控芯片是STM32F103RCT6。
main.c代码:
- #include "sys.h"
- #include "usart.h"
-
- int main(void)
- {
- u8 t;
- u8 len;
- delay_init(); //延时函数初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
- uart1_init(256000); //串口初始化为25600
- uart2_init(256000);
- printf("初始化成功\r\n");
- while(1)
- {
- if(USART2_RX_STA&0x8000)
- {
- len=USART2_RX_STA&0x3fff;//得到此次接收到的数据长度
-
- for(t=0;t<len;t++)
- {
- USART1->DR=USART2_RX_BUF[t];
- while((USART1->SR&0X40)==0);//等待发送结束
- }
-
- USART2_RX_STA=0;
- }
- else if(USART1_RX_STA&0x8000)
- {
- len=USART1_RX_STA&0x3fff;//得到此次接收到的数据长度
- for(t=0;t<len;t++)
- {
- USART2->DR=USART1_RX_BUF[t];
- while((USART2->SR&0X40)==0);//等待发送结束
- }
- USART1_RX_STA=0;
- }
- else
- {
- delay_ms(10);
- }
- }
- }
usart.c文件代码:
- #include "sys.h"
- #include "usart.h"
-
- u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
- u16 USART1_RX_STA=0; //接收状态标记
-
- u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
- u16 USART2_RX_STA=0; //接收状态标记
-
- void uart1_init(u32 bound){
- //GPIO端口设置
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
-
- //USART1_TX GPIOA.9
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
- GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
-
- //USART1_RX GPIOA.10初始化
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
- GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
-
- //Usart1 NVIC 配置
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
-
- //USART 初始化设置
-
- USART_InitStructure.USART_BaudRate = bound;//串口波特率
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
- USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
- USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
-
- USART_Init(USART1, &USART_InitStructure); //初始化串口1
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
- USART_Cmd(USART1, ENABLE); //使能串口1
-
- }
-
- void uart2_init(u32 bound){
- //GPIO端口设置
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
-
- //USART2_TX GPIOA.2
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
- GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2
-
- //USART2_RX GPIOA.3初始化
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
- GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3
-
- //Usart2 NVIC 配置
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
-
- //USART 初始化设置
-
- USART_InitStructure.USART_BaudRate = bound;//串口波特率
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
- USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
- USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
-
- USART_Init(USART2, &USART_InitStructure); //初始化串口2
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口2接受中断
- USART_Cmd(USART2, ENABLE); //使能串口2
-
- }
-
- void USART1_IRQHandler(void) //串口1中断服务程序
- {
- u8 Res;
-
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x65结尾)
- {
-
- Res =USART_ReceiveData(USART1); //读取接收到的数据
- if((USART1_RX_STA&0x8000)==0)//接收未完成
- {
- USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ;
- USART1_RX_STA++;
- if(Res==0x65) USART1_RX_STA|=0x8000; //接收完成了
- else if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收
-
- }
- }
- }
-
- void USART2_IRQHandler(void)
- {
- u8 Res;
-
- if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是65结尾)
- {
- Res =USART_ReceiveData(USART2); //读取接收到的数据
- if((USART2_RX_STA&0x8000)==0)//接收未完成
- {
- USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ;
- USART2_RX_STA++;
- if(Res==0x65) USART2_RX_STA|=0x8000; //接收完成了
- else if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收
- }
- }
- }
-
- //重定向c库函数printf到串口,重定向后可使用printf函数
- int fputc(int ch, FILE *f)
- {
- /* 发送一个字节数据到串口 */
- USART_SendData(USART2, (uint8_t) ch);
-
- /* 等待发送完毕 */
- while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
- return (ch);
- }
usart.h文件代码:
- #ifndef __USART_H
- #define __USART_H
- #include "stdio.h"
- #include "sys.h"
-
- #define USART1_REC_LEN 200 //定义最大接收字节数 200
- #define USART2_REC_LEN 200 //定义最大接收字节数 200
-
- extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
- extern u16 USART1_RX_STA; //接收状态标记
-
- extern u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
- extern u16 USART2_RX_STA; //接收状态标记
-
- void uart1_init(u32 bound);
- void uart2_init(u32 bound);
-
- #endif
波特率不宜选太高,会导致通信不了;
FPGA方面注意FIFO读请求置1后,在下一个时钟周期读的数据才会更新,所以uar待t发送的数据要延时一周期后再接收fifo读到的数据。
FPGA方面的uart发送模块需要注意FIFO每读取一次数据uart发送一次,所以增加了uart_txd_busy,防止fifo连续读数据。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。