当前位置:   article > 正文

FPGA与STM32之间的UART通信实验_fpga和单片机uart通信电路

fpga和单片机uart通信电路

目录

1.UART串口介绍

2.实验任务

3.FPGA代码

4.STM32代码

5.总结

1.UART串口介绍

        UART是一种采用异步串行方式的通用异步收发传输器,在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。

        UART串口通信需要两根信号线来实现,一根用于串口发送,另一根负责串口接收。

        UART的一帧数据由4部分组成:起始位、数据位、奇偶校验位和停止位。起始位标志着一帧数据的开始,低电平有效;数据位代表一帧数据中的有效数据;校验位分为奇校验和偶校验检测数据是否出错;在空闲状态下总线处于高电平。

        UART通信过程中更多数据格式及传输速率时刻设置的,并且要求双方遵循同样的设置。其中起始位;数据位可选5-8位,一般选择8位;校验位一般选择无校验位;停止位一般选择1位。传输速率用波特率表示,波特率表示每秒传输二进制数据的位数,单位时bps(位/秒),常用的波特率有9600、115200等

2.实验任务

  • 上位机通过串口调试工具将数据发送给MCU的UART2,MCU的UART2接收到的数据通MCU的UART1发送给FPGA的UART1,FPGA的UART1接收到的数据通过FPGA的UART2发送给上位机。

  • 上位机通过串口调试工具将数据发送给FPGA的UART2,FPGA的UART2接收到的数据通FPGA的UART1发送给MCU的UART1,MCU的UART1接收到的数据通过MCU的UART2发送给上位机。

3.FPGA代码

        FPGA主控芯片是EP4CE10F17C8。

        在顶层模块上,对uart1和uart2接收到的数据和发送数据进行控制和操作。

        顶层模块代码:

  1. module test(
  2. input sys_clk, //外部50M时钟
  3. input sys_rst_n, //外部复位信号,低有效
  4. //uart1接口
  5. input wire uart1_rxd, //UART接收端口
  6. output wire uart1_txd, //UART发送端口
  7. //uart2接口
  8. input wire uart2_rxd, //UART接收端口
  9. output wire uart2_txd //UART发送端口
  10. );
  11. wire clk_1m_w;
  12. //parameter define
  13. parameter CLK_FREQ = 50000000; //定义系统时钟频率
  14. parameter UART_BPS = 256000; //定义串口波特率
  15. parameter CMD_PKGEND = 8'h65; //数据包尾
  16. //uart1接口
  17. wire uart1_recv_en; //UART1接收完成使能
  18. wire [7:0] uart1_recv_data; //UART1接收到的数据
  19. reg uart1_send_en; //UART1发送使能
  20. wire uart1_txd_busy; //UART1发送忙标志
  21. //uart2接口
  22. wire uart2_recv_en; //UART2接收完成使能
  23. wire [7:0] uart2_recv_data; //UART2接收到的数据
  24. reg uart2_send_en; //UART2发送使能
  25. wire uart2_txd_busy; //UART2发送忙标志
  26. //边沿检测接口
  27. reg uart2_en_d0;
  28. reg uart2_en_d1;
  29. wire uart2_en_flag;
  30. //边沿检测接口
  31. reg uart1_en_d0;
  32. reg uart1_en_d1;
  33. wire uart1_en_flag;
  34. //uart2_uart1 fifo写接口
  35. reg uart2_wrreq;
  36. wire [7:0] uart2_data_in;
  37. wire uart2_wrfull;
  38. //uart2_uart1 fifo读接口
  39. reg uart2_fifo_flag; //uart2_uart1开始读fifo标志
  40. reg uart2_rdreq;
  41. wire [7:0] uart2_data_out;
  42. wire uart2_rdempty;
  43. //uart1_uart2 fifo写接口
  44. reg uart1_wrreq;
  45. wire [7:0] uart1_data_in;
  46. wire uart1_wrfull;
  47. //uart1_uart2 fifo读接口
  48. reg uart1_fifo_flag; //uart1_uart2开始读fifo标
  49. reg uart1_rdreq;
  50. wire [7:0] uart1_data_out;
  51. wire uart1_rdempty;
  52. //*****************************************************
  53. //** main code
  54. //*****************************************************
  55. //捕获uart2_recv_en上升沿,得到一个时钟周期的脉冲信号
  56. assign uart2_en_flag = (~uart2_en_d1) & uart2_en_d0;
  57. //捕获uart1_recv_en上升沿,得到一个时钟周期的脉冲信号
  58. assign uart1_en_flag = (~uart1_en_d1) & uart1_en_d0;
  59. //UART2和UART1边沿检测
  60. always @(posedge sys_clk or negedge sys_rst_n) begin
  61. if (!sys_rst_n) begin
  62. uart2_en_d0 <= 1'b0;
  63. uart2_en_d1 <= 1'b0;
  64. uart1_en_d0 <= 1'b0;
  65. uart1_en_d1 <= 1'b0;
  66. end
  67. else begin
  68. uart2_en_d0 <= uart2_recv_en;
  69. uart2_en_d1 <= uart2_en_d0;
  70. uart1_en_d0 <= uart1_recv_en;
  71. uart1_en_d1 <= uart1_en_d0;
  72. end
  73. end
  74. //UART2写进uart2_uart1 FIFO中
  75. always @(posedge sys_clk or negedge sys_rst_n) begin
  76. if (!sys_rst_n) begin
  77. uart2_wrreq <= 0;
  78. uart2_fifo_flag <= 0;
  79. end
  80. else begin
  81. if(uart2_en_flag && !uart2_wrfull) begin
  82. uart2_wrreq <= 1;
  83. end
  84. else begin
  85. uart2_wrreq <= 0;
  86. end
  87. if(uart2_en_flag && uart2_recv_data == CMD_PKGEND)begin //检测到数据包尾,uart2_uart1 fifo开始读
  88. uart2_fifo_flag <= 1;
  89. end
  90. if(!uart2_en_flag && uart2_rdempty) begin //uart2_uart1 fifo为空时,将uart2_fifo_flag标志置零
  91. uart2_fifo_flag <= 0;
  92. end
  93. end
  94. end
  95. //uart2_uart1 fifo读 uart1发送
  96. always @(posedge sys_clk or negedge sys_rst_n) begin
  97. if (!sys_rst_n) begin
  98. uart2_rdreq <= 0;
  99. uart1_send_en <= 0;
  100. end
  101. else begin
  102. if(uart2_fifo_flag) begin
  103. //读到数据的下一个周期uart1_txd_busy依旧为0,所以需要增加!uart2_rdreq来延迟一个周期,在第二个周期到来时,uart1_txd_busy为1
  104. if(!uart2_rdempty && !uart1_txd_busy && !uart2_rdreq)begin
  105. uart2_rdreq <= 1;
  106. uart1_send_en <= 1;
  107. end
  108. else begin
  109. uart2_rdreq <= 0;
  110. uart1_send_en <= 0;
  111. end
  112. end
  113. else begin
  114. uart2_rdreq <= 0;
  115. uart1_send_en <= 0;
  116. end
  117. end
  118. end
  119. //UART1写进uart1_uart2 FIFO中
  120. always @(posedge sys_clk or negedge sys_rst_n) begin
  121. if (!sys_rst_n) begin
  122. uart1_wrreq <= 0;
  123. uart1_fifo_flag <= 0;
  124. end
  125. else begin
  126. if(uart1_en_flag && !uart1_wrfull) begin
  127. uart1_wrreq <= 1;
  128. end
  129. else begin
  130. uart1_wrreq <= 0;
  131. end
  132. if(uart1_en_flag && uart1_recv_data == CMD_PKGEND)begin //检测到数据包尾,uart2_uart1 fifo开始读
  133. uart1_fifo_flag <= 1;
  134. end
  135. if(!uart1_en_flag && uart1_rdempty) begin //uart2_uart1 fifo为空时,将uart2_fifo_flag标志置零
  136. uart1_fifo_flag <= 0;
  137. end
  138. end
  139. end
  140. //fifo读 uart1_uart2 uart2发送
  141. always @(posedge sys_clk or negedge sys_rst_n) begin
  142. if (!sys_rst_n) begin
  143. uart1_rdreq <= 0;
  144. uart2_send_en <= 0;
  145. end
  146. else begin
  147. if(uart1_fifo_flag) begin
  148. //读到数据的下一个周期uart2_txd_busy依旧为0,所以需要增加!uart1_rdreq来延迟一个周期,在第二个周期到来时,uart2_txd_busy为1
  149. if(!uart1_rdempty && !uart2_txd_busy && !uart1_rdreq)begin
  150. uart1_rdreq <= 1;
  151. uart2_send_en <= 1;
  152. end
  153. else begin
  154. uart1_rdreq <= 0;
  155. uart2_send_en <= 0;
  156. end
  157. end
  158. else begin
  159. uart1_rdreq <= 0;
  160. end
  161. end
  162. end
  163. //例化锁相环
  164. pll_clk u_pll_clk( //时钟分频模块,用于调试
  165. .inclk0 (sys_clk),
  166. .c0 (clk_1m_w)
  167. );
  168. //例化uart1接收模块
  169. uart_recv #( //串口接收模块
  170. .CLK_FREQ (CLK_FREQ), //设置系统时钟频率
  171. .UART_BPS (UART_BPS)) //设置串口接收波特率
  172. u_uart1_recv(
  173. .sys_clk (sys_clk),
  174. .sys_rst_n (sys_rst_n),
  175. .uart_rxd (uart1_rxd),
  176. .uart_done (uart1_recv_en),
  177. .uart_data (uart1_recv_data)
  178. );
  179. //例化uart1发送模块
  180. uart_send #( //串口发送模块
  181. .CLK_FREQ (CLK_FREQ), //设置系统时钟频率
  182. .UART_BPS (UART_BPS)) //设置串口发送波特率
  183. u_uart1_send(
  184. .sys_clk (sys_clk),
  185. .sys_rst_n (sys_rst_n),
  186. .uart_en (uart1_send_en),
  187. .uart_din (uart2_data_out),
  188. .uart_txd (uart1_txd),
  189. .uart_txd_busy (uart1_txd_busy)
  190. );
  191. //例化uart2接收模块
  192. uart_recv #( //串口接收模块
  193. .CLK_FREQ (CLK_FREQ), //设置系统时钟频率
  194. .UART_BPS (UART_BPS)) //设置串口接收波特率
  195. u_uart2_recv(
  196. .sys_clk (sys_clk),
  197. .sys_rst_n (sys_rst_n),
  198. .uart_rxd (uart2_rxd),
  199. .uart_done (uart2_recv_en),
  200. .uart_data (uart2_recv_data)
  201. );
  202. //例化uart2发送模块
  203. uart_send #( //串口发送模块
  204. .CLK_FREQ (CLK_FREQ), //设置系统时钟频率
  205. .UART_BPS (UART_BPS)) //设置串口发送波特率
  206. u_uart2_send(
  207. .sys_clk (sys_clk),
  208. .sys_rst_n (sys_rst_n),
  209. .uart_en (uart2_send_en),
  210. .uart_din (uart1_data_out),
  211. .uart_txd (uart2_txd),
  212. .uart_txd_busy (uart2_txd_busy)
  213. );
  214. //例化uart2_uart1 fifo
  215. uart2_uart1 u_uart2_uart1(
  216. .wrclk (sys_clk),
  217. .wrreq (uart2_wrreq),
  218. .data (uart2_recv_data),
  219. .wrfull (uart2_wrfull),
  220. .rdclk (sys_clk),
  221. .rdreq (uart2_rdreq),
  222. .q (uart2_data_out),
  223. .rdempty (uart2_rdempty)
  224. );
  225. //例化uart1_uart2 fifo
  226. uart1_uart2 u_uart1_uart2(
  227. .wrclk (sys_clk),
  228. .wrreq (uart1_wrreq),
  229. .data (uart1_recv_data),
  230. .wrfull (uart1_wrfull),
  231. .rdclk (sys_clk),
  232. .rdreq (uart1_rdreq),
  233. .q (uart1_data_out),
  234. .rdempty (uart1_rdempty)
  235. );
  236. endmodule

         uart接收模块代码:

  1. module uart_recv(
  2. input sys_clk, //系统时钟
  3. input sys_rst_n, //系统复位,低电平有效
  4. input uart_rxd, //UART接收端口
  5. output reg uart_done, //接收一帧数据完成标志信号
  6. output reg [7:0] uart_data //接收的数据
  7. );
  8. //parameter define
  9. parameter CLK_FREQ = 50000000; //系统时钟频率
  10. parameter UART_BPS = 115200; //串口波特率
  11. localparam BPS_CNT = CLK_FREQ/UART_BPS; //为得到指定波特率,
  12. //需要对系统时钟计数BPS_CNT次
  13. //reg define
  14. reg uart_rxd_d0;
  15. reg uart_rxd_d1;
  16. reg [15:0] clk_cnt; //系统时钟计数器
  17. reg [ 3:0] rx_cnt; //接收数据计数器
  18. reg rx_flag; //接收过程标志信号
  19. reg [ 7:0] rxdata; //接收数据寄存器
  20. //wire define
  21. wire start_flag;
  22. //*****************************************************
  23. //** main code
  24. //*****************************************************
  25. //捕获接收端口下降沿(起始位),得到一个时钟周期的脉冲信号
  26. assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);
  27. //对UART接收端口的数据延迟两个时钟周期
  28. always @(posedge sys_clk or negedge sys_rst_n) begin
  29. if (!sys_rst_n) begin
  30. uart_rxd_d0 <= 1'b0;
  31. uart_rxd_d1 <= 1'b0;
  32. end
  33. else begin
  34. uart_rxd_d0 <= uart_rxd;
  35. uart_rxd_d1 <= uart_rxd_d0;
  36. end
  37. end
  38. //当脉冲信号start_flag到达时,进入接收过程
  39. always @(posedge sys_clk or negedge sys_rst_n) begin
  40. if (!sys_rst_n)
  41. rx_flag <= 1'b0;
  42. else begin
  43. if(start_flag) //检测到起始位
  44. rx_flag <= 1'b1; //进入接收过程,标志位rx_flag拉高
  45. else if((rx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
  46. rx_flag <= 1'b0; //计数到停止位中间时,停止接收过程
  47. else
  48. rx_flag <= rx_flag;
  49. end
  50. end
  51. //进入接收过程后,启动系统时钟计数器与接收数据计数器
  52. always @(posedge sys_clk or negedge sys_rst_n) begin
  53. if (!sys_rst_n) begin
  54. clk_cnt <= 16'd0;
  55. rx_cnt <= 4'd0;
  56. end
  57. else if ( rx_flag ) begin //处于接收过程
  58. if (clk_cnt < BPS_CNT - 1) begin
  59. clk_cnt <= clk_cnt + 1'b1;
  60. rx_cnt <= rx_cnt;
  61. end
  62. else begin
  63. clk_cnt <= 16'd0; //对系统时钟计数达一个波特率周期后清零
  64. rx_cnt <= rx_cnt + 1'b1; //此时接收数据计数器加1
  65. end
  66. end
  67. else begin //接收过程结束,计数器清零
  68. clk_cnt <= 16'd0;
  69. rx_cnt <= 4'd0;
  70. end
  71. end
  72. //根据接收数据计数器来寄存uart接收端口数据
  73. always @(posedge sys_clk or negedge sys_rst_n) begin
  74. if ( !sys_rst_n)
  75. rxdata <= 8'd0;
  76. else if(rx_flag) //系统处于接收过程
  77. if (clk_cnt == BPS_CNT/2) begin //判断系统时钟计数器计数到数据位中间
  78. case ( rx_cnt )
  79. 4'd1 : rxdata[0] <= uart_rxd_d1; //寄存数据位最低位
  80. 4'd2 : rxdata[1] <= uart_rxd_d1;
  81. 4'd3 : rxdata[2] <= uart_rxd_d1;
  82. 4'd4 : rxdata[3] <= uart_rxd_d1;
  83. 4'd5 : rxdata[4] <= uart_rxd_d1;
  84. 4'd6 : rxdata[5] <= uart_rxd_d1;
  85. 4'd7 : rxdata[6] <= uart_rxd_d1;
  86. 4'd8 : rxdata[7] <= uart_rxd_d1; //寄存数据位最高位
  87. default:;
  88. endcase
  89. end
  90. else
  91. rxdata <= rxdata;
  92. else
  93. rxdata <= 8'd0;
  94. end
  95. //数据接收完毕后给出标志信号并寄存输出接收到的数据
  96. always @(posedge sys_clk or negedge sys_rst_n) begin
  97. if (!sys_rst_n) begin
  98. uart_data <= 8'd0;
  99. uart_done <= 1'b0;
  100. end
  101. else if(rx_cnt == 4'd9) begin //接收数据计数器计数到停止位时
  102. uart_data <= rxdata; //寄存输出接收到的数据
  103. uart_done <= 1'b1; //并将接收完成标志位拉高
  104. end
  105. else begin
  106. uart_data <= 8'd0;
  107. uart_done <= 1'b0;
  108. end
  109. end
  110. endmodule

        uart发送模块代码:

  1. module uart_send(
  2. input sys_clk, //系统时钟
  3. input sys_rst_n, //系统复位,低电平有效
  4. input uart_en, //发送使能信号
  5. input [7:0] uart_din, //待发送数据
  6. output reg uart_txd, //UART发送端口
  7. output reg uart_txd_busy
  8. );
  9. //parameter define
  10. parameter CLK_FREQ = 50000000; //系统时钟频率
  11. parameter UART_BPS = 115200; //串口波特率
  12. localparam BPS_CNT = CLK_FREQ/UART_BPS; //为得到指定波特率,对系统时钟计数BPS_CNT次
  13. //reg define
  14. reg uart_en_d0;
  15. reg uart_en_d1;
  16. reg [15:0] clk_cnt; //系统时钟计数器
  17. reg [ 3:0] tx_cnt; //发送数据计数器
  18. reg tx_flag; //发送过程标志信号
  19. reg [ 7:0] tx_data; //寄存发送数据
  20. //wire define
  21. wire en_flag;
  22. //*****************************************************
  23. //** main code
  24. //*****************************************************
  25. //捕获uart_en上升沿,得到一个时钟周期的脉冲信号
  26. assign en_flag = (~uart_en_d1) & uart_en_d0;
  27. //对发送使能信号uart_en延迟两个时钟周期
  28. always @(posedge sys_clk or negedge sys_rst_n) begin
  29. if (!sys_rst_n) begin
  30. uart_en_d0 <= 1'b0;
  31. uart_en_d1 <= 1'b0;
  32. end
  33. else begin
  34. uart_en_d0 <= uart_en;
  35. uart_en_d1 <= uart_en_d0;
  36. end
  37. end
  38. //当脉冲信号en_flag到达时,寄存待发送的数据,并进入发送过程
  39. always @(posedge sys_clk or negedge sys_rst_n) begin
  40. if (!sys_rst_n) begin
  41. tx_flag <= 1'b0;
  42. tx_data <= 8'd0;
  43. uart_txd_busy <= 1'b0;
  44. end
  45. else begin
  46. if(uart_en) uart_txd_busy <= 1'b1;
  47. if (en_flag) begin //检测到发送使能上升沿
  48. tx_flag <= 1'b1; //进入发送过程,标志位tx_flag拉高
  49. tx_data <= uart_din; //寄存待发送的数据
  50. end
  51. else if ((tx_cnt == 4'd9)&&(clk_cnt == BPS_CNT - 1))begin //计数到停止位中间时,停止发送过程
  52. tx_flag <= 1'b0; //发送过程结束,标志位tx_flag拉低
  53. tx_data <= 8'd0;
  54. uart_txd_busy <= 1'b0;
  55. end
  56. else begin
  57. tx_flag <= tx_flag;
  58. tx_data <= tx_data;
  59. end
  60. end
  61. end
  62. //进入发送过程后,启动系统时钟计数器与发送数据计数器
  63. always @(posedge sys_clk or negedge sys_rst_n) begin
  64. if (!sys_rst_n) begin
  65. clk_cnt <= 16'd0;
  66. tx_cnt <= 4'd0;
  67. end
  68. else if (tx_flag) begin //处于发送过程
  69. if (clk_cnt < BPS_CNT - 1) begin
  70. clk_cnt <= clk_cnt + 1'b1;
  71. tx_cnt <= tx_cnt;
  72. end
  73. else begin
  74. clk_cnt <= 16'd0; //对系统时钟计数达一个波特率周期后清零
  75. tx_cnt <= tx_cnt + 1'b1; //此时发送数据计数器加1
  76. end
  77. end
  78. else begin //发送过程结束
  79. clk_cnt <= 16'd0;
  80. tx_cnt <= 4'd0;
  81. end
  82. end
  83. //根据发送数据计数器来给uart发送端口赋值
  84. always @(posedge sys_clk or negedge sys_rst_n) begin
  85. if (!sys_rst_n)
  86. uart_txd <= 1'b1;
  87. else if (tx_flag)
  88. case(tx_cnt)
  89. 4'd0: uart_txd <= 1'b0; //起始位
  90. 4'd1: uart_txd <= tx_data[0]; //数据位最低位
  91. 4'd2: uart_txd <= tx_data[1];
  92. 4'd3: uart_txd <= tx_data[2];
  93. 4'd4: uart_txd <= tx_data[3];
  94. 4'd5: uart_txd <= tx_data[4];
  95. 4'd6: uart_txd <= tx_data[5];
  96. 4'd7: uart_txd <= tx_data[6];
  97. 4'd8: uart_txd <= tx_data[7]; //数据位最高位
  98. 4'd9: uart_txd <= 1'b1; //停止位
  99. default: ;
  100. endcase
  101. else
  102. uart_txd <= 1'b1; //空闲时发送端口为高电平
  103. end
  104. endmodule

4.STM32代码

        STM32的主控芯片是STM32F103RCT6。

        main.c代码:

  1. #include "sys.h"
  2. #include "usart.h"
  3. int main(void)
  4. {
  5. u8 t;
  6. u8 len;
  7. delay_init(); //延时函数初始化
  8. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
  9. uart1_init(256000); //串口初始化为25600
  10. uart2_init(256000);
  11. printf("初始化成功\r\n");
  12. while(1)
  13. {
  14. if(USART2_RX_STA&0x8000)
  15. {
  16. len=USART2_RX_STA&0x3fff;//得到此次接收到的数据长度
  17. for(t=0;t<len;t++)
  18. {
  19. USART1->DR=USART2_RX_BUF[t];
  20. while((USART1->SR&0X40)==0);//等待发送结束
  21. }
  22. USART2_RX_STA=0;
  23. }
  24. else if(USART1_RX_STA&0x8000)
  25. {
  26. len=USART1_RX_STA&0x3fff;//得到此次接收到的数据长度
  27. for(t=0;t<len;t++)
  28. {
  29. USART2->DR=USART1_RX_BUF[t];
  30. while((USART2->SR&0X40)==0);//等待发送结束
  31. }
  32. USART1_RX_STA=0;
  33. }
  34. else
  35. {
  36. delay_ms(10);
  37. }
  38. }
  39. }

        usart.c文件代码:

  1. #include "sys.h"
  2. #include "usart.h"
  3. u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
  4. u16 USART1_RX_STA=0; //接收状态标记
  5. u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
  6. u16 USART2_RX_STA=0; //接收状态标记
  7. void uart1_init(u32 bound){
  8. //GPIO端口设置
  9. GPIO_InitTypeDef GPIO_InitStructure;
  10. USART_InitTypeDef USART_InitStructure;
  11. NVIC_InitTypeDef NVIC_InitStructure;
  12. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
  13. //USART1_TX GPIOA.9
  14. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  15. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  17. GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
  18. //USART1_RX GPIOA.10初始化
  19. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  20. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  21. GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
  22. //Usart1 NVIC 配置
  23. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  24. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
  25. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
  26. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
  27. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
  28. //USART 初始化设置
  29. USART_InitStructure.USART_BaudRate = bound;//串口波特率
  30. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  31. USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  32. USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  33. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  34. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
  35. USART_Init(USART1, &USART_InitStructure); //初始化串口1
  36. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  37. USART_Cmd(USART1, ENABLE); //使能串口1
  38. }
  39. void uart2_init(u32 bound){
  40. //GPIO端口设置
  41. GPIO_InitTypeDef GPIO_InitStructure;
  42. USART_InitTypeDef USART_InitStructure;
  43. NVIC_InitTypeDef NVIC_InitStructure;
  44. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
  45. RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
  46. //USART2_TX GPIOA.2
  47. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
  48. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  49. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  50. GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2
  51. //USART2_RX GPIOA.3初始化
  52. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
  53. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  54. GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3
  55. //Usart2 NVIC 配置
  56. NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  57. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
  58. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级3
  59. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
  60. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
  61. //USART 初始化设置
  62. USART_InitStructure.USART_BaudRate = bound;//串口波特率
  63. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  64. USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  65. USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  66. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  67. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
  68. USART_Init(USART2, &USART_InitStructure); //初始化串口2
  69. USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口2接受中断
  70. USART_Cmd(USART2, ENABLE); //使能串口2
  71. }
  72. void USART1_IRQHandler(void) //串口1中断服务程序
  73. {
  74. u8 Res;
  75. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x65结尾)
  76. {
  77. Res =USART_ReceiveData(USART1); //读取接收到的数据
  78. if((USART1_RX_STA&0x8000)==0)//接收未完成
  79. {
  80. USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ;
  81. USART1_RX_STA++;
  82. if(Res==0x65) USART1_RX_STA|=0x8000; //接收完成了
  83. else if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收
  84. }
  85. }
  86. }
  87. void USART2_IRQHandler(void)
  88. {
  89. u8 Res;
  90. if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是65结尾)
  91. {
  92. Res =USART_ReceiveData(USART2); //读取接收到的数据
  93. if((USART2_RX_STA&0x8000)==0)//接收未完成
  94. {
  95. USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ;
  96. USART2_RX_STA++;
  97. if(Res==0x65) USART2_RX_STA|=0x8000; //接收完成了
  98. else if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收数据错误,重新开始接收
  99. }
  100. }
  101. }
  102. //重定向c库函数printf到串口,重定向后可使用printf函数
  103. int fputc(int ch, FILE *f)
  104. {
  105. /* 发送一个字节数据到串口 */
  106. USART_SendData(USART2, (uint8_t) ch);
  107. /* 等待发送完毕 */
  108. while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
  109. return (ch);
  110. }

        usart.h文件代码:

  1. #ifndef __USART_H
  2. #define __USART_H
  3. #include "stdio.h"
  4. #include "sys.h"
  5. #define USART1_REC_LEN 200 //定义最大接收字节数 200
  6. #define USART2_REC_LEN 200 //定义最大接收字节数 200
  7. extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
  8. extern u16 USART1_RX_STA; //接收状态标记
  9. extern u8 USART2_RX_BUF[USART2_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
  10. extern u16 USART2_RX_STA; //接收状态标记
  11. void uart1_init(u32 bound);
  12. void uart2_init(u32 bound);
  13. #endif

5.总结

  • 波特率不宜选太高,会导致通信不了;

  • FPGA方面注意FIFO读请求置1后,在下一个时钟周期读的数据才会更新,所以uar待t发送的数据要延时一周期后再接收fifo读到的数据。

  • FPGA方面的uart发送模块需要注意FIFO每读取一次数据uart发送一次,所以增加了uart_txd_busy,防止fifo连续读数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/905850
推荐阅读
相关标签
  

闽ICP备14008679号