IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于单片机与FPGA的SPI -> 正文阅读

[嵌入式]基于单片机与FPGA的SPI

1.SPI含义

SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议。

?2.步骤

step1 stm32_3pin_to_fpga_input

?prj_fpga_spi_input

??由单片机传送数据到FPGA。

prj_stm32_gpio_wave_3pin

#include "stm32f10x.h" 
#include "usart.h"
void Delay(u32 count) 
{ 
  u32 i=0; 
  for(;i<count;i++); 
} 

void init_gpio_clk(){
  GPIO_InitTypeDef    GPIO_InitStructure;
  //使能PE 端口时钟 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);        
  //PE.10 端口配置 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;           
  // 推挽输出
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     
  //IO 口 速度50MHz 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  // 初始化GPIOE.10
  GPIO_Init(GPIOE, &GPIO_InitStructure);             
  // PE.10 为高
  GPIO_SetBits(GPIOE,GPIO_Pin_10);          
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;           
  GPIO_Init(GPIOE, &GPIO_InitStructure);             
  GPIO_SetBits(GPIOE,GPIO_Pin_12);          
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;           
  GPIO_Init(GPIOE, &GPIO_InitStructure);             
  GPIO_SetBits(GPIOE,GPIO_Pin_14);          

}
void gpio_clk_loop(){
  while(1) {
    GPIO_SetBits  (GPIOE,GPIO_Pin_10);          
    GPIO_ResetBits(GPIOE,GPIO_Pin_10);          
    GPIO_SetBits  (GPIOE,GPIO_Pin_12);          
    GPIO_ResetBits(GPIOE,GPIO_Pin_12);          
    GPIO_SetBits  (GPIOE,GPIO_Pin_14);          
    GPIO_ResetBits(GPIOE,GPIO_Pin_14);          
  }
}

void init_gpio_led(){
  GPIO_InitTypeDef    GPIO_InitStructure;
  //使能PB,PE 端口时钟 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOE, ENABLE);        
  //LED0-->PB.5 端口配置 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;           
  // 推挽输出
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     
  //IO 口 速度50MHz 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  // 初始化GPIOB.5
  GPIO_Init(GPIOB, &GPIO_InitStructure);             
  // PB.5 为低
  GPIO_ResetBits(GPIOB,GPIO_Pin_5);          
  //LED1-->PE.5  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                      
  // 初始化 GPIO
  GPIO_Init(GPIOE, &GPIO_InitStructure);                      
  //PE.5  输出为低      
  GPIO_ResetBits(GPIOE,GPIO_Pin_5);          
}

void gpio_led_tick_loop(int n){
  int count = n;
  while(count) 
  {
    if(n > 0){
      count = count - 1;
    }
    GPIO_SetBits(GPIOE,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    Delay(2000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(2000000); 
    
    GPIO_SetBits(GPIOE,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    Delay(2000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(2000000); 
   
    GPIO_SetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
   
    GPIO_SetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
   
    GPIO_SetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(4000000); 
  }
}
int main(void) 
{   
  init_gpio_clk();
  init_gpio_led();
  gpio_led_tick_loop(1);
  gpio_clk_loop();
}

step2 stm32_SPI_to_fpga_input

prj_fpga_spi_input

module spi_bus(
  I_CLK     ,
  I_CS      ,
  I_SCLK    ,
  I_SDIN    ,
  O_DOUT    ,
  O_DOV     ,
  O_TESTOUT1);


input I_CLK    ;
input I_CS     ;
input I_SCLK   ;
input I_SDIN    ;

output O_TESTOUT1;

reg  R1_I_CS  ,R2_I_CS ,R3_I_CS  ;
reg  R1_I_SCLK ,R2_I_SCLK,R3_I_SCLK ;
reg  R1_I_SDIN ,R2_I_SDIN,R3_I_SDIN ;
reg  W_I_CS_up , W_I_CS_down, W_I_SCLK_up;

reg [32-1:0] R_sdin_shift, R_out_buf;
output [32-1:0] O_DOUT;
output          O_DOV ;   
reg             O_DOV ;   

always @ (*) begin
  W_I_CS_up   = ((R3_I_CS == 1'b0)&&( R2_I_CS == 1'b1)) ? 1'b1 : 1'b0;
  W_I_CS_down = ((R3_I_CS == 1'b1)&&( R2_I_CS == 1'b0)) ? 1'b1 : 1'b0;
  W_I_SCLK_up  = ((R3_I_SCLK == 1'b0)&&( R2_I_SCLK == 1'b1)) ? 1'b1 : 1'b0;
end
always @ (posedge I_CLK) begin
  R1_I_CS   <= I_CS       ;
  R1_I_SCLK <= I_SCLK     ;
  R1_I_SDIN <= I_SDIN     ;
  R2_I_CS   <= R1_I_CS    ;
  R2_I_SCLK <= R1_I_SCLK  ;
  R2_I_SDIN <= R1_I_SDIN  ;
  R3_I_CS   <= R2_I_CS    ;
  R3_I_SCLK <= R2_I_SCLK  ;
  R3_I_SDIN <= R2_I_SDIN  ;
end
always @ (posedge I_CLK) begin
  if(W_I_CS_down)
    R_sdin_shift <= 0;
  else
    if(W_I_SCLK_up)
      R_sdin_shift <= {R_sdin_shift[30:0],R2_I_SDIN};
  if(W_I_CS_up)
    R_out_buf <= R_sdin_shift;
  O_DOV <= W_I_CS_up;
end
assign O_DOUT = R_out_buf;


assign O_TESTOUT1 =  W_I_SCLK_up ;

endmodule

?这个程序是32位输出,SPI的数据传给FPGA。

prj_stm32_SPI_to_fpga_input

#include "stm32f10x.h" 
#include "usart.h"
void Delay(u32 count) 
{ 
  u32 i=0; 
  for(;i<count;i++){
   __nop(); 
  }
} 

#define PIN_MY_SPI_O_SCLK GPIO_Pin_10
#define PIN_MY_SPI_O_CS   GPIO_Pin_12
#define PIN_MY_SPI_O_SDA  GPIO_Pin_14

#define PORT_MY_SPI_O_SCLK GPIOE
#define PORT_MY_SPI_O_CS   GPIOE
#define PORT_MY_SPI_O_SDA  GPIOE

void init_spi_pin(){
  GPIO_InitTypeDef    GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);     //使能PE 端口时钟 
  GPIO_InitStructure.GPIO_Pin = PIN_MY_SPI_O_SCLK;              //PE.PIN 端口配置 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          // 推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO 口 速度50MHz 
  GPIO_Init(PORT_MY_SPI_O_SCLK, &GPIO_InitStructure);                    // 初始化GPIOE.PIN
  GPIO_SetBits(PORT_MY_SPI_O_SCLK,PIN_MY_SPI_O_SCLK);                        // PE.PIN 为高
  
  GPIO_InitStructure.GPIO_Pin = PIN_MY_SPI_O_CS;           
  GPIO_Init(PORT_MY_SPI_O_CS, &GPIO_InitStructure);             
  GPIO_SetBits(PORT_MY_SPI_O_CS,PIN_MY_SPI_O_CS);          
  
  GPIO_InitStructure.GPIO_Pin = PIN_MY_SPI_O_SDA;           
  GPIO_Init(GPIOE, &GPIO_InitStructure);             
  GPIO_SetBits(PORT_MY_SPI_O_SDA,PIN_MY_SPI_O_SDA);          

}

void spi_wr_cs(int val){
  GPIO_WriteBit(PORT_MY_SPI_O_CS,PIN_MY_SPI_O_CS      ,(val&0x1)?Bit_SET:Bit_RESET    );
}
void spi_wr_sck(int val){
  GPIO_WriteBit(PORT_MY_SPI_O_SCLK,PIN_MY_SPI_O_SCLK      ,(val&0x1)?Bit_SET:Bit_RESET    );
}
void spi_wr_sda_out(int val){
  GPIO_WriteBit(PORT_MY_SPI_O_SDA,PIN_MY_SPI_O_SDA      ,(val&0x1)?Bit_SET:Bit_RESET    );
}


void spi_wr_32bit_MSB_first(unsigned char B3,unsigned char B2,unsigned char B1,unsigned char B0){
  int delay_unit = 5;
  int i = 0, j = 0;
  unsigned char byte4[4] = {0};
  unsigned char buf = 0;
  byte4[3] = B3; byte4[2] = B2; byte4[1] = B1; byte4[0] = B0;

  
  spi_wr_cs(1);
  spi_wr_sck(1);
  spi_wr_sda_out(1);
  // drop down cs
  spi_wr_cs(0);
  Delay(1);
  // drop down sck
  spi_wr_sck(0);
  Delay(1);
  // put data
  for(j = 0; j < 4; j ++){
    buf = byte4[3-j];
    for(i = 0; i < 8; i ++){
      spi_wr_sda_out((buf&0x80) >> 7);
      buf = buf << 1;
      Delay(1);
      spi_wr_sck(1);
      Delay(1);
      spi_wr_sck(0);
    }
  }
  spi_wr_cs(1);
  spi_wr_sck(1);
}


void spi_wr_test_loop(){
  while(1) {
    spi_wr_cs(1);
    spi_wr_cs(0);
    spi_wr_sck(1);
    spi_wr_sck(1);
    spi_wr_sck(0);
    spi_wr_sck(0);
    spi_wr_sda_out(1);
    spi_wr_sda_out(1);
    spi_wr_sda_out(1);
    spi_wr_sda_out(0);
    spi_wr_sda_out(0);
    spi_wr_sda_out(0);
  }
}

void spi_wr_data_loop(){
  while(1) {
    spi_wr_32bit_MSB_first(0xA5, 0xA7, 0xA9, 0xAB);
    spi_wr_32bit_MSB_first(0x5A, 0x5B, 0x5C, 0x5D);
  }
}

void init_gpio_led(){
  GPIO_InitTypeDef    GPIO_InitStructure;
  //使能PB,PE 端口时钟 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOE, ENABLE);        
  //LED0-->PB.5 端口配置 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;           
  // 推挽输出
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     
  //IO 口 速度50MHz 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  // 初始化GPIOB.5
  GPIO_Init(GPIOB, &GPIO_InitStructure);             
  // PB.5 为低
  GPIO_ResetBits(GPIOB,GPIO_Pin_5);          
  //LED1-->PE.5  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                      
  // 初始化 GPIO
  GPIO_Init(GPIOE, &GPIO_InitStructure);                      
  //PE.5  输出为低      
  GPIO_ResetBits(GPIOE,GPIO_Pin_5);          
}

void gpio_led_tick_loop(int n){
  int count = n;
  while(count) 
  {
    if(n > 0){
      count = count - 1;
    }
    GPIO_SetBits(GPIOE,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    Delay(2000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(2000000); 
    
    GPIO_SetBits(GPIOE,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    Delay(2000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(2000000); 
   
    GPIO_SetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
   
    GPIO_SetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
   
    GPIO_SetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(1000000); 
    GPIO_ResetBits(GPIOB,GPIO_Pin_5); 
    GPIO_ResetBits(GPIOE,GPIO_Pin_5); 
    Delay(4000000); 
  }
}
int main(void) 
{   
  init_spi_pin();
  init_gpio_led();
  gpio_led_tick_loop(1);
  // spi_wr_test_loop();
  spi_wr_data_loop();
}

输出32位数据,要分成4次,每次8位。

step3 stm32_SPI_write_fpga_addr_decode

prj_fpga_spi_input_bus_addr_decode

?

prj_stm32_SPI_to_fpga_bus_addr_decode

stm32通过spi读取fpga的地址。

step4 stm32_SPI_read_select_write_fpga_addr_decode

prj_fpga_spi_input_bus_read_write

?实现fpga与单片机的互传,并在单片机的显示屏上显示

prj_stm32_SPI_to_fpga_bus_read_write?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-27 12:01:45  更:2021-08-27 12:02:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:31:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码