当前位置:   article > 正文

FPGA主SPI与STM32从机通信_stm32与fpga的spi通讯

stm32与fpga的spi通讯

目录

概述

FPGA的SPI主机代码

STM32从机

SPI模式配置

SPI参数设置

 SPI的DMA传输配置

STM32从机SPI接收代码


概述

        在这里就不介绍SPI原理了,需要的同学自行查阅。我使用的硬件环境为STM32F407VET6和DE0-nano,如下图。

 使用cubemx配置工程,FPGA使用Quartus软件,时序仿真图如下

FPGA的SPI主机代码

        txd_signal信号为上升沿触发,led0,1,2为调试灯,可去掉。

        一个SCK周期为16个clk周期,我测试时使用50MHz晶振,故SPI时钟为3.125MHz。

        需要改动通信速率可以通过改动cnt1相关值改变。

        时钟相位参考STM32从机配置

  1. //时钟极性高,采样沿上升沿
  2. module SPI_Master(
  3. clk, // 系统时钟
  4. rst, // 复位,低有效
  5. txd_flag, // 高电平表示发送完成处于忙碌状态,低电平表示处于空闲状态
  6. sck, // 时钟输出
  7. cs, // 片选输出
  8. mosi, // 主设备输出信号
  9. miso, // 主设备输入信号
  10. txd_signal, // 发送触发信号,给一个信号发送8bit
  11. rxd_out, // 接收的数据
  12. txd_in, // 发送的数据
  13. led0,
  14. led1,
  15. led2
  16. );
  17. //调试引脚
  18. output led0,led1,led2;
  19. assign led0=txd_signal;
  20. assign led1=txd_flag;
  21. assign led2=cs;
  22. // 输入信号
  23. input clk, rst, miso, txd_signal;
  24. // 输出信号
  25. output reg mosi, txd_flag;
  26. output wire sck, cs;
  27. output reg [7:0] rxd_out;
  28. input [7:0] txd_in;
  29. // 内部寄存器和变量
  30. reg [2:0] txd_start;
  31. reg [2:0] txd_start_outside;
  32. reg [3:0] cnt;
  33. reg [3:0] cnt1;
  34. reg csr;
  35. assign sck = cnt1[3];
  36. assign cs = csr;
  37. // 任务:根据计数器 cnt1 的值更新时钟状态
  38. task clk_states;
  39. if (cnt1 == 4'b0000) begin
  40. cnt1 <= 4'b1111;
  41. cnt <= cnt + 1'b1;
  42. end else
  43. cnt1 <= cnt1 - 1'b1;
  44. endtask
  45. // always 块:根据时钟和复位信号控制发送过程和计数器的更新
  46. always @(posedge clk or negedge rst) begin
  47. if (!rst) begin
  48. // 复位所有状态和寄存器
  49. txd_flag <= 1'b0;
  50. txd_start <= 3'd1;
  51. cnt <= 4'd0;
  52. cnt1 <= 4'b1111;
  53. csr <= 1'b1;
  54. end else begin
  55. if (txd_start == txd_start_outside) begin
  56. csr <= 1'b0;
  57. txd_flag <= 1'b1; // txd_flag 信号与 cs 信号相反,电路当处于通信时为高电平,表示忙碌状态
  58. case (cnt) // 为低电平表示空闲状态
  59. 0: clk_states();//进八次cnt加1,SCK经过一个周期,SCK高电平持续时间为4和CLK
  60. 1: clk_states();
  61. 2: clk_states();
  62. 3: clk_states();
  63. 4: clk_states();
  64. 5: clk_states();
  65. 6: clk_states();
  66. 7: begin
  67. if (cnt1 == 4'b0000) begin
  68. cnt1 <= 4'b1111;
  69. cnt <= 4'd8;
  70. end else
  71. cnt1 <= cnt1 - 1'b1;
  72. end
  73. 8: begin
  74. // 多加一个状态延长 cs 的低电平时间,给从机足够的时间接收数据
  75. txd_start <= txd_start + 1'b1;
  76. cnt <= 4'd0;
  77. end
  78. endcase
  79. end else begin
  80. csr <= 1'b1;
  81. txd_flag <= 1'b0;
  82. end
  83. end
  84. end
  85. // always 块:外部触发发送脉冲,上升沿触发发送一次
  86. always @(posedge txd_signal or negedge rst) begin
  87. if (!rst)
  88. txd_start_outside <= 1'b0;
  89. else begin
  90. if (!txd_flag)
  91. txd_start_outside <= txd_start_outside + 1'b1;
  92. else;
  93. end
  94. end
  95. // always 块:sck 上升沿采样数据
  96. reg [7:0] rxd_outr;
  97. reg [2:0] rec_cnt;
  98. always @(posedge sck or negedge rst) begin
  99. if (!rst) begin
  100. rxd_out <= 8'h00;
  101. rec_cnt <= 3'd0;
  102. end else begin
  103. case (rec_cnt)
  104. 0: begin
  105. rxd_outr[7] <= miso;
  106. rec_cnt <= 3'd1;
  107. end
  108. 1: begin
  109. rxd_outr[6] <= miso;
  110. rec_cnt <= 3'd2;
  111. end
  112. 2: begin
  113. rxd_outr[5] <= miso;
  114. rec_cnt <= 3'd3;
  115. end
  116. 3: begin
  117. rxd_outr[4] <= miso;
  118. rec_cnt <= 3'd4;
  119. end
  120. 4: begin
  121. rxd_outr[3] <= miso;
  122. rec_cnt <= 3'd5;
  123. end
  124. 5: begin
  125. rxd_outr[2] <= miso;
  126. rec_cnt <= 3'd6;
  127. end
  128. 6: begin
  129. rxd_outr[1] <= miso;
  130. rec_cnt <= 3'd7;
  131. end
  132. 7: begin
  133. rxd_outr[0] <= miso;
  134. rxd_out <= {rxd_outr[7:1], miso};
  135. rec_cnt <= 3'd0;
  136. end
  137. default:;
  138. endcase
  139. end
  140. end
  141. // always 块:sck 下降沿时发送数据
  142. reg [2:0] send_cnt;
  143. always @(negedge sck or negedge rst) begin
  144. if (!rst)
  145. send_cnt <= 3'd0;
  146. else begin
  147. case (send_cnt)
  148. 0: begin
  149. mosi <= txd_in[7];
  150. send_cnt <= 3'd1;
  151. end
  152. 1: begin
  153. mosi <= txd_in[6];
  154. send_cnt <= 3'd2;
  155. end
  156. 2: begin
  157. mosi <= txd_in[5];
  158. send_cnt <= 3'd3;
  159. end
  160. 3: begin
  161. mosi <= txd_in[4];
  162. send_cnt <= 3'd4;
  163. end
  164. 4: begin
  165. mosi <= txd_in[3];
  166. send_cnt <= 3'd5;
  167. end
  168. 5: begin
  169. mosi <= txd_in[2];
  170. send_cnt <= 3'd6;
  171. end
  172. 6: begin
  173. mosi <= txd_in[1];
  174. send_cnt <= 3'd7;
  175. end
  176. 7: begin
  177. mosi <= txd_in[0];
  178. send_cnt <= 3'd0;
  179. end
  180. default:;
  181. endcase
  182. end
  183. end
  184. endmodule

STM32从机

SPI模式配置

SPI参数设置

 

 SPI的DMA传输配置

STM32从机SPI接收代码
  1. int main(void)
  2. {
  3. /* USER CODE BEGIN 1 */
  4. /* USER CODE END 1 */
  5. /* MCU Configuration--------------------------------------------------------*/
  6. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  7. HAL_Init();
  8. /* USER CODE BEGIN Init */
  9. /* USER CODE END Init */
  10. /* Configure the system clock */
  11. SystemClock_Config();
  12. /* USER CODE BEGIN SysInit */
  13. /* USER CODE END SysInit */
  14. /* Initialize all configured peripherals */
  15. MX_GPIO_Init();
  16. MX_DMA_Init();
  17. MX_SPI1_Init();
  18. MX_USART1_UART_Init();
  19. /* USER CODE BEGIN 2 */
  20. uint8_t data=0;
  21. HAL_SPI_Receive_DMA(&hspi1,&data,1);
  22. /* USER CODE END 2 */
  23. /* Infinite loop */
  24. /* USER CODE BEGIN WHILE */
  25. while (1)
  26. {
  27. //FPGA RESET
  28. HAL_GPIO_WritePin(RST_GPIO_Port,RST_Pin,GPIO_PIN_RESET);
  29. HAL_Delay(10);
  30. HAL_GPIO_WritePin(RST_GPIO_Port,RST_Pin,GPIO_PIN_SET);
  31. //等待发送空闲
  32. while(HAL_GPIO_ReadPin(txd_flag_GPIO_Port,txd_flag_Pin)==GPIO_PIN_SET){
  33. };
  34. //延迟便于观察串口输出
  35. HAL_Delay(2000);
  36. //上升沿触发FPGA主机发送
  37. HAL_GPIO_WritePin(txd_signal_GPIO_Port,txd_signal_Pin,GPIO_PIN_SET);
  38. HAL_Delay(100);
  39. HAL_GPIO_WritePin(txd_signal_GPIO_Port,txd_signal_Pin,GPIO_PIN_RESET);
  40. //串口打印data查看数据
  41. printf("data is %d \r\n",data);
  42. /* USER CODE END WHILE */
  43. /* USER CODE BEGIN 3 */
  44. }
  45. /* USER CODE END 3 */
  46. }

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

闽ICP备14008679号