完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本设计在FPGA用32个寄存器构建了一个8bit*32的ROM,可通过STM32使用SPI写入命令字节来实现对32个寄存器的读写操作。
命令字节的格式: bit 7:读写控制位, 1:W 0:R bit6-bit2:寄存器地址 bit1-bit0:未使用 stm32的代码基于正电原子的探索者开发板和工程,使用软件模拟SPI,FPGA使用Verilog编写。 SPI的特性为:时钟空闲时为高电平,在时钟的下降沿将数据输出,在时钟的上升沿读取数据。 主要代码: FPGA代码: 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 |
|
|
|
SMT32部分
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 = %drn",error_num); } read_num++; if(read_num%100==0) { printf("error_num = %drn",error_num); } printf("send = %d rec_num = %d read_num = %drn",key,rec,read_num); rec = 0; //if(key==5) //else printf("key = %d ERRORrn",key); delay_ms(100); } t++; } } 运行结果 读写上万次无错误 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1752 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1611 浏览 1 评论
1052 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1666 浏览 2 评论
1926浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
711浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
560浏览 3评论
583浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
544浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 18:08 , Processed in 0.838905 second(s), Total 48, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号