赞
踩
关于SPI的主机和从机请看;https://blog.csdn.net/qq_40893012/article/details/103995154
本设计在FPGA用32个寄存器构建了一个8bit*32的ROM,可通过STM32使用SPI写入命令字节来实现对32个寄存器的读写操作。
命令字节的格式:
bit 7:读写控制位,
1:W
0:R
bit6-bit2:寄存器地址
bit1-bit0:未使用
stm32的代码基于正电原子的探索者开发板和工程,使用软件模拟SPI,FPGA使用Verilog编写。
SPI的特性为:时钟空闲时为高电平,在时钟的下降沿将数据输出,在时钟的上升沿读取数据。
主要代码:
1 SPI从机部分
- // 32位二段式状态机spi模块
- module spi_slave16bit(
- input wire clk,
- input rst_n,
- input wire CS,
- input wire SCK,
- input wire MOSI,
- output reg MISO,
- output reg [5:0]rom_addr,
- output reg busy,//spi给fpga其他模块,busy=1时,禁止FPGA读写
- input wire[15:0] data_to_out,
- output reg[15:0] data_had_receive,
- output rxd_over //rx 2byte will generate pulse
- );
-
- reg [1:0] state;
- parameter IDLE = 2'b00;
- parameter TRANS = 2'b01;
- parameter WAIT = 2'b10;
- reg [1:0]CS_buf;
- wire CS_falling_flag;
- wire CS_rising_flag;
- always@(posedge clk)
- begin
- CS_buf[1] <= CS_buf[0];
- CS_buf[0] <= CS;
- end
- assign CS_falling_flag = CS_buf[1] &(~CS_buf[0]);
- assign CS_rising_flag = (~CS_buf[1]) & CS_buf[0];
- reg [1:0]SCK_buf;
- wire SCK_falling_flag;
- wire SCK_rising_flag;
- always@(posedge clk)
- begin
- SCK_buf[1] <= SCK_buf[0];
- SCK_buf[0] <= SCK;
- end
- assign SCK_falling_flag = SCK_buf[1]&(~SCK_buf[0]);
- assign SCK_rising_flag = (~SCK_buf[1])&SCK_buf[0];
- reg [5:0]count;
- // state machine
- always@(posedge clk)
- begin
-
- case(state)
- IDLE:begin
- if(CS_falling_flag==1) state <= TRANS;
- end
- TRANS:begin
- if(count == 6'b010000) state <= WAIT; // 传完16个数
- else if (CS_rising_flag==1) state <= IDLE; // 意外结束
- end
- WAIT:begin
- if (CS_rising_flag) state <= IDLE;
- end
- endcase
- end
-
- // count
- always@(posedge clk)
- begin
- case(state)
- IDLE: count<=6'b0;
- TRANS:begin
- if(SCK_rising_flag == 1) count <= count + 6'b1;
- end
- endcase
- end
-
- // MISO
- always@(posedge clk)
- begin
- if ((state == TRANS)&&(SCK_falling_flag == 1))
- begin
- case(count)
- 6'b000000: MISO <= data_to_out[15];
- 6'b000001: MISO <= data_to_out[14];
- 6'b000010: MISO <= data_to_out[13];
- 6'b000011: MISO <= data_to_out[12];
- 6'b000100: MISO <= data_to_out[11];
- 6'b000101: MISO <= data_to_out[10];
- 6'b000110: MISO <= data_to_out[9];
- 6'b000111: MISO <= data_to_out[8];
- 6'b001000: MISO <= data_to_out[7];
- 6'b001001: MISO <= data_to_out[6];
- 6'b001010: MISO <= data_to_out[5];
- 6'b001011: MISO <= data_to_out[4];
- 6'b001100: MISO <= data_to_out[3];
- 6'b001101: MISO <= data_to_out[2];
- 6'b001110: MISO <= data_to_out[1];
- 6'b001111: MISO <= data_to_out[0];
- /* 6'b010000: MISO <= data_to_out[15];
- 6'b010001: MISO <= data_to_out[14];
- 6'b010010: MISO <= data_to_out[13];
- 6'b010011: MISO <= data_to_out[12];
- 6'b010100: MISO <= data_to_out[11];
- 6'b010101: MISO <= data_to_out[10];
- 6'b010110: MISO <= data_to_out[9];
- 6'b010111: MISO <= data_to_out[8];
- 6'b011000: MISO <= data_to_out[7];
- 6'b011001: MISO <= data_to_out[6];
- 6'b011010: MISO <= data_to_out[5];
- 6'b011011: MISO <= data_to_out[4];
- 6'b011100: MISO <= data_to_out[3];
- 6'b011101: MISO <= data_to_out[2];
- 6'b011110: MISO <= data_to_out[1];
- 6'b011111: MISO <= data_to_out[0]; */
- endcase
- end
- end
-
- // MOSI
- reg rxd_flag_r;
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- rxd_flag_r <= 0;
- else
- begin
- if ((state == TRANS)&&(SCK_rising_flag == 1))
- begin
- case(count)
- 6'b000000: begin data_had_receive[15] <= MOSI;rxd_flag_r<=1'b0;end
- 6'b000001: data_had_receive[14] <= MOSI;
- 6'b000010: data_had_receive[13] <= MOSI;
- 6'b000011: data_had_receive[12] <= MOSI;
- 6'b000100: data_had_receive[11] <= MOSI;
- 6'b000101: begin
- data_had_receive[10] <= MOSI; //set rom addr
- rom_addr[5:0] <= {data_had_receive[15:11],MOSI};
- end
- 6'b000110: data_had_receive[9] <= MOSI;
- 6'b000111: data_had_receive[8] <= MOSI;
- 6'b001000: data_had_receive[7] <= MOSI;
- 6'b001001: data_had_receive[6] <= MOSI;
- 6'b001010: data_had_receive[5] <= MOSI;
- 6'b001011: data_had_receive[4] <= MOSI;
- 6'b001100: data_had_receive[3] <= MOSI;
- 6'b001101: data_had_receive[2] <= MOSI;
- 6'b001110: data_had_receive[1] <= MOSI;
- 6'b001111: begin data_had_receive[0] <= MOSI; rxd_flag_r<=1'b1;end
- /* 6'b010000: data_had_receive[15] <= MOSI;
- 6'b010001: data_had_receive[14] <= MOSI;
- 6'b010010: data_had_receive[13] <= MOSI;
- 6'b010011: data_had_receive[12] <= MOSI;
- 6'b010100: data_had_receive[11] <= MOSI;
- 6'b010101: data_had_receive[10] <= MOSI;
- 6'b010110: data_had_receive[9] <= MOSI;
- 6'b010111: data_had_receive[8] <= MOSI;
- 6'b011000: data_had_receive[7] <= MOSI;
- 6'b011001: data_had_receive[6] <= MOSI;
- 6'b011010: data_had_receive[5] <= MOSI;
- 6'b011011: data_had_receive[4] <= MOSI;
- 6'b011100: data_had_receive[3] <= MOSI;
- 6'b011101: data_had_receive[2] <= MOSI;
- 6'b011110: data_had_receive[1] <= MOSI;
- 6'b011111: data_had_receive[0] <= MOSI; */
- endcase
- end
- end
- end
-
- reg rxd_flag_r0,rxd_flag_r1;
- always@(negedge rst_n or posedge clk)
- begin
- if(!rst_n)
- begin
- rxd_flag_r0 <= 1'b0;
- rxd_flag_r1 <= 1'b0;
- end
- else
- begin
- rxd_flag_r0 <= rxd_flag_r;
- rxd_flag_r1 <= rxd_flag_r0;
- end
- end
- assign rxd_over = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
- // busy
- always@(posedge clk)
- begin
- case(state)
- IDLE: busy <= 0;
- TRANS: busy <= 1;
- WAIT: busy <= 0;
- endcase
- end
-
- endmodule
2 寄存器构成ROM模块
- module spi_rom
- (
- rst,
- rxd_flag,
- reg_addr,
- reg_out,
- rxd_in_spi
- );
-
- input rst,rxd_flag;
- input [5:0] reg_addr;
- input [15:0] rxd_in_spi;
- output reg [7:0] reg_out;
- reg [7:0] REG_ROM[31:0];
-
- always@(negedge rst or posedge rxd_flag)
- begin
- if(!rst)
- begin
- REG_ROM[0] <= 8'd0;
- REG_ROM[1] <= 8'd1;
- REG_ROM[2] <= 8'd2;
- REG_ROM[3] <= 8'd3;
- REG_ROM[4] <= 8'd4;
- REG_ROM[5] <= 8'd5;
- REG_ROM[6] <= 8'd6;
- REG_ROM[7] <= 8'd7;
- REG_ROM[8] <= 8'd8;
- REG_ROM[9] <= 8'd9;
- REG_ROM[10] <= 8'd10;
- REG_ROM[11] <= 8'd11;
- REG_ROM[12] <= 8'd12;
- REG_ROM[13] <= 8'd13;
- REG_ROM[14] <= 8'd14;
- REG_ROM[15] <= 8'd15;
- REG_ROM[16] <= 8'd16;
- REG_ROM[17] <= 8'd17;
- REG_ROM[18] <= 8'd18;
- REG_ROM[19] <= 8'd19;
- REG_ROM[20] <= 8'd20;
- REG_ROM[21] <= 8'd21;
- REG_ROM[22] <= 8'd22;
- REG_ROM[23] <= 8'd23;
- REG_ROM[24] <= 8'd24;
- REG_ROM[25] <= 8'd25;
- REG_ROM[26] <= 8'd26;
- REG_ROM[27] <= 8'd27;
- REG_ROM[28] <= 8'd28;
- REG_ROM[29] <= 8'd29;
- REG_ROM[30] <= 8'd30;
- REG_ROM[31] <= 8'd31;
- end
- else
- begin
- if(rxd_in_spi[15]==1'b1)
- REG_ROM[rxd_in_spi[14:10]] = rxd_in_spi[7:0];
- end
- end
- always@(reg_addr)
- begin
- if(reg_addr[5]==0)
- reg_out=REG_ROM[reg_addr[4:0]];
- else reg_out=8'd0; //if write and next byte will tx 8'b0
-
- end
- /* always@(posedge rxd_flag)
- begin
- if(rxd_in_spi[15]==1'b1)
- REG_ROM[rxd_in_spi[14:10]] = rxd_in_spi[7:0];
- end */
- endmodule
3 顶层模块
- module TEST_MODULE
- (
- clk,
- rst,
- cs,
- sck,
- MOSI,
- MISO,
- led_pin,
- rxd_over
- );
-
- input clk,rst,cs,sck,MOSI;
- output MISO,led_pin,rxd_over;
- wire rxd_flag;
- wire [5:0] rom_addr;
- wire [7:0] reg_out;
- wire [15:0]rxd_in_spi;
- wire spi_busy;
- wire rxd_over;
- wire [7:0] dat_to_out;
-
- //always@(posedge clk)
- //begin
- // if(!spi_busy)
- // dat_to_out[15:8] <= 8'd255;
- //end
- LED_module LED_module_inst
- (
- .clk(clk),
- .rst(rst),
- .led_pin(led_pin)
- );
- spi_slave16bit(
- .clk(clk),
- .rst_n(rst),
- .CS(cs),
- .SCK(sck),
- .MOSI(MOSI),
- .MISO(MISO),
- .rom_addr(rom_addr),
- .busy(spi_busy),//spi给fpga其他模块,busy=1时,禁止FPGA读写
- .data_to_out({8'hff,dat_to_out}),//first byte TX 0hff
- .data_had_receive(rxd_in_spi),
- .rxd_over(rxd_over)
- );
-
- spi_rom spi_rom_inst
- (
- .rst(rst),
- .rxd_flag(rxd_over),
- .reg_addr(rom_addr),
- .reg_out(dat_to_out),
- .rxd_in_spi(rxd_in_spi)
- );
-
- endmodule
1 头文件及部分定义
- #define SPI_CS PGout(7)
- #define SPI_MISO PBin(4)
- #define SPI_MOSI PBout(5)
- #define SPI_CLK PBout(3)
-
- void soft_spi_ioinit(void);
- u8 get_cmd(u8 wr,u8 addr);
- u8 spi_read2byte(u8 reg_addr);
- u8 spi_write2byte(u8 reg_addr,u8 dat);
2 函数声明部分
- void soft_spi_ioinit()
- {
-
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//ʹÄÜGPIOB,GʱÖÓ
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //CS
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//ÆÕͨÊä³öģʽ
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//ÍÆÍìÊä³ö
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;//100MHz
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ
- GPIO_Init(GPIOG, &GPIO_InitStructure);//³õʼ»¯PG6,7
- SPI_CS=1; //SPIƬѡȡÏû
-
-
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ʹÄÜGPIOAʱÖÓ
-
-
- //GPIOFB3,5³õʼ»¯ÉèÖÃ
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;//PB3~5¸´Óù¦ÄÜÊä³ö
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//¸´Óù¦ÄÜ
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//ÍÆÍìÊä³ö
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;//100MHz
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ
- GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯
- SPI_CLK = 1;
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//PB3~5¸´Óù¦ÄÜÊä³ö
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//ÆÕͨÊäÈëģʽ
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;//100M
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ
- GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯
-
- }
-
- u8 get_cmd(u8 wr,u8 addr)//wr=1:w wr=0:r addr:0-31
- {
- u8 reg=0;
- //if(wr) reg = 128;
- reg = wr;
- reg = reg<<5;
- reg = reg+addr;
- reg =reg<<2;
- return reg;
- };
-
- u8 spi_read2byte(u8 reg_addr) //reg_addr:0-31
- {
- u32 tmp=0;
- u8 i=0;
- u8 addr;
- SPI_CS = 1;
- SPI_CLK = 1;
- SPI_CS = 0;
-
- addr = get_cmd(0,reg_addr);
-
- delay_us(1);
- for(i=0;i<8;i++)
- {
- SPI_CLK = 1;
- if(addr&0x80)SPI_MOSI = 1;
- else SPI_MOSI = 0;
- addr = addr<<1;
- delay_us(1);
- SPI_CLK = 0;
- delay_us(1);
- SPI_CLK = 1;
- tmp =tmp<<1;
- tmp = tmp+SPI_MISO;
- }
- delay_us(2);
- for(i=0;i<8;i++)
- {
- SPI_CLK = 1;
- SPI_MOSI = 1;
- delay_us(1);
- SPI_CLK = 0;
- delay_us(1);
- SPI_CLK = 1;
- tmp =tmp<<1;
- tmp = tmp+SPI_MISO;
- }
- SPI_CLK = 1;
- SPI_CS = 1;
-
- return tmp&0x00ff;
-
- }
-
- u8 spi_write2byte(u8 reg_addr,u8 dat)
- {
- u32 tmp=0;
- int i=0;
- u8 addr;
- u8 dat_buff = dat;
- SPI_CS = 1;
- SPI_CLK = 1;
- SPI_CS = 0;
- delay_us(1);
-
- addr = get_cmd(1,reg_addr);
-
- for(i=0;i<8;i++)
- {
- SPI_CLK = 1;
- if(addr&0x80)SPI_MOSI = 1;
- else SPI_MOSI = 0;
- addr = addr<<1;
- delay_us(1);
- SPI_CLK = 0;
- delay_us(1);
- SPI_CLK = 1;
- tmp =tmp<<1;
- tmp = tmp+SPI_MISO;
- }
-
- delay_us(2);
-
- for(i=0;i<8;i++)
- {
- SPI_CLK = 1;
- if(dat_buff&0x80)SPI_MOSI = 1;
- else SPI_MOSI = 0;
- dat_buff = dat_buff<<1;
- delay_us(1);
- SPI_CLK = 0;
- delay_us(1);
- SPI_CLK = 1;
- tmp =tmp<<1;
- tmp = tmp+SPI_MISO;
- }
- SPI_CLK = 1;
- SPI_CS = 1;
-
- return tmp&0x00ff;
- }
3 主函数
- int main(void)
- {
- u8 key,mode;
- u8 t=0;
- u32 error_num=0;
- u32 read_num=0;
- u32 rec=0;
- u8 tmp_buf[33];
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é2
- delay_init(168); //³õʼ»¯ÑÓʱº¯Êý
- uart_init(115200); //³õʼ»¯´®¿Ú²¨ÌØÂÊΪ115200
- LED_Init(); //³õʼ»¯LED
- // LCD_Init(); //LCD³õʼ»¯
- // KEY_Init(); //°´¼ü³õʼ»¯
- // NRF24L01_Init(); //³õʼ»¯NRF24L01
- soft_spi_ioinit();
- //NRF24L01_Read_Reg(reg);
- while(1)
- {
-
- for(t=0;t<32;t++)
- {
- //key = get_reg(0,t);
- key = rand()%100;
- spi_write2byte(t,key);
-
- rec = spi_read2byte(t);
-
- if(rec!=key)
- {
- error_num++;
- printf("error_num = %d\r\n",error_num);
- }
- read_num++;
- if(read_num%100==0)
- {
-
- printf("error_num = %d\r\n",error_num);
- }
- printf("send = %d rec_num = %d read_num = %d\r\n",key,rec,read_num);
- rec = 0;
- //if(key==5)
- //else printf("key = %d ERROR\r\n",key);
- delay_ms(100);
- }
-
-
- t++;
-
-
- }
-
- }
读写上万次无错误
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。