模拟SPI程序
SPI编程说明
3:划分FOV(点击创建FOV,然后选择 是 或者 否 即可)。
4:调整原点(点击手动添加,通过控制和调整板子原点,使钢网文件盒板子实际重叠即可。控制移动时调节视野的,调整板子原点才是移动坐标的。)
8:添加拼板(点击开始和结束,选择对应的两个焊盘)
8:添加拼板(选择对应的焊盘点之后,如果需要选择角度的选择角度,之后点击添加即可完成)。
9:编辑基准点(找到基准点,右键点击注册基准点,弹出对话框,点击OK即可完成第一个基准点的注册,再找到另外一个基准点以相同的办法完成即可。如果第二个基准点是粉红色,那就回到选择设定焊盘区域那,再注册一次)。
5:基准点设定(打开编辑基准点,选择基准点列表,双击数字1,即可切换到板子对应的基准点。基准点完成之后,保存基准点也是在这下面)。
5:基准点调节(先把曝光时间设置在3-7之间,点击二值化,再点击拍照,将基准点彻底的与周边颜色区分开来;并保证那个绿色的十字架在MARK点的正中间,以相同的手法,完成另一个基准点的制作,并保存)。
2:当你连续测试几块板子都觉得你这个程序没有问题的话,那么你就到文件选项将这个程序保存;第一次做的时候保存不了,你可以选择点击导出程序。
3:这就是我们的程序制作大概步骤,剩下的一些都是需要自己的摸索的。
10:创建FOV(点击创建,弹出对话框选择是或者否都可以完成FOV的创建)。
11:OK NG(点出OK NG来,然后直接点击生成即可,注意两个都要点击生成的)。
12:程序到此已经做完,剩下的是在SPI软件的调试,所以将做好的程序导出即可。
二:SPI软件调试
1:加载检测程序(打到手动模式,选择文件选项,点击打开程序,选择加载程序,选择所需要打开的程序,双击或者选择再打开。)
51单片机模拟 SPI 总线的方法
51单片机模拟 SPI 总线的方法1 引言SPI(Serial Peripheral Interface--串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。
外围设置FLASHRAM、网络控制器、LCD显示驱动器、A/D转换器和MCU等。
SPI总线系统可直接与各个厂家生产的多种标准外围器件直接接口,该接口一般使用4条线:串行时钟线(SCK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低电平有效的从机选择线SS(有的SPI接口芯片带有中断信号线INT或INT、有的SPI接口芯片没有主机输出/从机输入数据线MOSI)。
由于SPI系统总线一共只需3~4位数据线和控制即可实现与具有SPI总线接口功能的各种I/O器件进行接口,而扩展并行总线则需要8根数据线、8~16位地址线、2~3位控制线,因此,采用SPI总线接口可以简化电路设计,节省很多常规电路中的接口器件和I/O口线,提高设计的可靠性。
由此可见,在MCS51系列等不具有SPI接口的单片机组成的智能仪器和工业测控系统中,当传输速度要求不是太高时,使用SPI总线可以增加应用系统接口器件的种类,提高应用系统的性能。
2 SPI总线的组成利用SPI总线可在软件的控制下构成各种系统。
如1个主MCU和几个从MCU、几个从MCU 相互连接构成多主机系统(分布式系统)、1个主MCU和1个或几个从I/O设备所构成的各种系统等。
在大多数应用场合,可使用1个MCU作为控机来控制数据,并向1个或几个从外围器件传送该数据。
从器件只有在主机发命令时才能接收或发送数据。
其数据的传输格式是高位(MSB)在前,低位(LSB)在后。
SPI总线接口系统的典型结构。
当一个主控机通过SPI与几种不同的串行I/O芯片相连时,必须使用每片的允许控制端,这可通过MCU的I/O端口输出线来实现。
但应特别注意这些串行I/O芯片的输入输出特性:首先是输入芯片的串行数据输出是否有三态控制端。
51单片机模拟spi串行接口程序
{
unsigned char BitCounter;
for(BitCounter=8; BiCounter!=0; BitCounter--)
{ CLK=0;
DataI=0; // write
if(val&0x80) DataI=1;
val<<=1;
CLK=1;
if(DataO)val|=1; // read
}
CLK=0;
return val;
}
sbit CLK= P1^5;
sbit DataI=P1^7;
sbiபைடு நூலகம் DataO=P1^6;
#define SD_Disable() CS=1 //片选关
#define SD_Enable() CS=0 //片选开
val<<=1;
CLK=1;
if(DataO)val|=1; // read
}
CLK=0;
return val;
}
sbit CLK= P1^5;
sbit DataI=P1^7;
sbit DataO=P1^6;
#define SD_Disable() CS=1 //片选关
#define SD_Enable() CS=0 //片选开
unsigned char SPI_TransferByte(unsigned char val)
{
unsigned char BitCounter;
for(BitCounter=8; BiCounter!=0; BitCounter--)
{ CLK=0;
Linux下SPI驱动测试程序
Linux下的SPI总线驱动(一)2013-04-12 15:08:46分类:LINUX版权所有,转载请说明转自一.SPI理论介绍SPI总线全名,串行外围设备接口,是一种串行的主从接口,集成于很多微控制器内部。
和I2C使用2根线相比,SPI总线使用4根线:MOSI (SPI 总线主机输出/ 从机输入)、MISO (SPI总线主机输入/从机输出)、SCLK(时钟信号,由主设备产生)、CS(从设备使能信号,由主设备控制)。
由于SPI总线有专用的数据线用于数据的发送和接收,因此可以工作于全双工,当前市面上可以找到的SPI外围设备包括RF芯片、智能卡接口、E2PROM、RTC、触摸屏传感器、ADC。
SCLK信号线只由主设备控制,从设备不能控制信号线。
同样,在一个基于SPI的设备中,至少有一个主控设备。
这样传输的特点:这样的传输方式有一个优点,与普通的串行通讯不同,普通的串行通讯一次连续传送至少8位数据,而SPI允许数据一位一位的传送,甚至允许暂停,因为SCLK 时钟线由主控设备控制,当没有时钟跳变时,从设备不采集或传送数据。
也就是说,主设备通过对SCLK时钟线的控制可以完成对通讯的控制。
SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。
不同的SPI 设备的实现方式不尽相同,主要是数据改变和采集的时间不同,在时钟信号上沿或下沿采集有不同定义,具体请参考相关器件的文档。
在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。
在多个从设备的系统中,每个从设备需要独立的使能信号,硬件上比I2C 系统要稍微复杂一些。
二.SPI驱动移植我们下面将的驱动的移植是针对Mini2440的SPI驱动的移植Step1:在Linux Source Code中修改arch/arm/mach-s3c2440/文件,加入头文件:#include <linux/spi/>#include <../mach-s3c2410/include/mach/>然后加入如下代码:static struct spi_board_info s3c2410_spi0_board[] ={[0] = {.modalias = "spidev", us_num = 0, hip_select = 0, rq = IRQ_EINT9, ax_speed_hz = 500 * 1000,in_cs = S3C2410_GPG(2),.num_cs = 1, us_num = 0, pio_setup = s3c24xx_spi_gpiocfg_bus0_gpe11_12_13, odalias = "spidev",.bus_num = 1,.chip_select = 0,.irq = IRQ_EINT2,.max_speed_hz = 500 * 1000,}};static struct s3c2410_spi_info s3c2410_spi1_platdata = {.pin_cs = S3C2410_GPG(3),.num_cs = 1,.bus_num = 1,.gpio_setup = s3c24xx_spi_gpiocfg_bus1_gpg5_6_7,};Step2:在mini2440_devices[]平台数组中添加如下代码:&s3c_device_spi0,&s3c_device_spi1,Step3:最后在mini2440_machine_init函数中加入如下代码:&s3c2410_spi0_platdata;spi_register_board_info(s3c2410_spi0_board, ARRAY_SIZE(s3c2410_spi0_board)); &s3c2410_spi1_platdata;spi_register_board_info(s3c2410_spi1_board, ARRAY_SIZE(s3c2410_spi1_board)); Step4:最后需要修改arch/arm/plat-s3c24xx/KConfig文件找到config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13boolhelpSPI GPIO configuration code for BUS0 when connected toGPE11, GPE12 and GPE13.config S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7boolhelpSPI GPIO configuration code for BUS 1 when connected toGPG5, GPG6 and GPG7.修改为config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13bool "S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13"helpSPI GPIO configuration code for BUS0 when connected toGPE11, GPE12 and GPE13.config S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7bool "S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7"helpSPI GPIO configuration code for BUS 1 when connected toGPG5, GPG6 and GPG7.Step5:最后make menuconfig配置,选中System Type和SPI support相应文件Step6:执行make生成zInage,将编译好的内核导入开发板,并且编译测试程序运行即可。
运用4个普通IO口模拟SPI程序等
运用 4 个普通 I/O 口模拟 SPI 程序源代码
/******************************************************************** 函 数 名:uchar SpiReadWrite(uchar dat) 功 能:SPI 发送接收一个数据 说 明: 调 用: 入口参数: 出口参数: ***********************************************************************/ uchar SpiReadWrite(uchar dat) { uchar i,temp; temp=0; SCK=0; _nop_(); for(i=0;i<8;i++) { if(dat & 0x80) { MOSI=1; }
单片机IO口模拟SPI四种模式的程序
单⽚机IO⼝模拟SPI四种模式的程序#include "iom8535v.h"#define _CPOL 1#define _CPHA 0#define SCK_IO DDRA|=0X01#define MOSI_IO DDRA|=0X02#define MISO_IO DDRA&=0XFB#define SSEL_IO DDRA|=0X08#define SCK_D(X) (X?(PORTA|=0X01):(PORTA&=0XFE))#define MOSI_D(X) (X?(PORTA|=0X02):(PORTA&=0XFD))#define SSEL_D(X) (X?(PORTA|=0X08):(PORTA&=0XF7))#define MISO_I() (PINA&0X04)void delay(){unsigned char m,n;for(n=0;n<5;n++);for(m=0;m<100;m++);}void SPI_Init(void){SCK_IO ;MOSI_IO ;MISO_IO ;SSEL_IO ;SSEL_D(1);MOSI_D(1);#if _CPOL==0SCK_D(0);#elseSCK_D(1);#endif}#if _CPOL==0&&_CPHA==0 //MODE 0 0void SPI_Send_Dat(unsigned char dat){unsigned char n;for(n=0;n<8;n++){SCK_D(0);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(1);}SCK_D(0);}unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;for(n=0;n<8;n++){SCK_D(0);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(1);}SCK_D(0);return dat;}#endif#if _CPOL==1&&_CPHA==0 //MODE 1 0 void SPI_Send_Dat(unsigned char dat){unsigned char n;for(n=0;n<8;n++){SCK_D(1);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(0);}SCK_D(1);}unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;for(n=0;n<8;n++){SCK_D(1);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(0);}SCK_D(1);return dat;}#endif#if _CPOL==0&&_CPHA==1 //MODE 0 1 void SPI_Send_Dat(unsigned char dat){unsigned char n;SCK_D(0);for(n=0;n<8;n++){SCK_D(1);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(0);}}unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;for(n=0;n<8;n++){SCK_D(1);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(0);}SCK_D(0);return dat;}#endif//////////////////////////////////////////////////////////////////////////////////////////////////////////////#if _CPOL==1&&_CPHA==1 //MODE 1 1 void SPI_Send_Dat(unsigned char dat){unsigned char n;SCK_D(1);for(n=0;n<8;n++){SCK_D(0);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(1);}}unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;SCK_D(0);for(n=0;n<8;n++){ SCK_D(0);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(1);}SCK_D(1);return dat;}#endifvoid main(){SPI_Init();DDRB = 0XFF;//#if _CPOL//SCK_D(0);//#endifwhile(1){//SSEL_D(0);//SPI_Send_Dat(0x01);//SPI_Send_Dat(0x31);//SSEL_D(1);SSEL_D(0);SPI_Send_Dat(0x81);PORTB =SPI_Receiver_Dat();SSEL_D(1);//delay();}}。
SPI完整程序
SPI接口源程序module simple_spi_top(// 8bit WISHBONE bus slave interfaceinput wire clk_i, // clockinput wire rst_i, // reset (asynchronous active low)input wire cyc_i, // cycleinput wire stb_i, // strobeinput wire [1:0] adr_i, // addressinput wire we_i, // write enableinput wire [7:0] dat_i, // data inputoutput reg [7:0] dat_o, // data outputoutput reg ack_o, // normal bus terminationoutput reg inta_o, // interrupt output// SPI portoutput reg sck_o, // serial clock outputoutput wire mosi_o, // MasterOut SlaveINinput wire miso_i // MasterIn SlaveOut);//// Module body//reg [7:0] spcr; // Serial Peripheral Control Register ('HC11 naming) wire [7:0] spsr; // Serial Peripheral Status register ('HC11 naming)reg [7:0] sper; // Serial Peripheral Extension registerreg [7:0] treg, rreg; // Transmit/Receive register// fifo signalswire [7:0] rfdout;reg wfre, rfwe;wire rfre, rffull, rfempty;wire [7:0] wfdout;wire wfwe, wffull, wfempty;// misc signalswire tirq; // transfer interrupt (selected number of transfers done) wire wfov; // write fifo overrun (writing while fifo full)reg [1:0] state; // statemachine statereg [2:0] bcnt;//// Wishbone interfacewire wb_acc = cyc_i & stb_i; // WISHBONE accesswire wb_wr = wb_acc & we_i; // WISHBONE write access// dat_ialways @(posedge clk_i or negedge rst_i)if (~rst_i)beginspcr <= #1 8'h10; // set master bitsper <= #1 8'h00;endelse if (wb_wr)beginif (adr_i == 2'b00)spcr <= #1 dat_i | 8'h10; // always set master bitif (adr_i == 2'b11)sper <= #1 dat_i;end// write fifoassign wfwe = wb_acc & (adr_i == 2'b10) & ack_o & we_i; assign wfov = wfwe & wffull;// dat_oalways @(posedge clk_i)case(adr_i) // synopsys full_case parallel_case2'b00: dat_o <= #1 spcr;2'b01: dat_o <= #1 spsr;2'b10: dat_o <= #1 rfdout;2'b11: dat_o <= #1 sper;endcase// read fifoassign rfre = wb_acc & (adr_i == 2'b10) & ack_o & ~we_i;// ack_oalways @(posedge clk_i or negedge rst_i)if (~rst_i)ack_o <= #1 1'b0;elseack_o <= #1 wb_acc & !ack_o;// decode Serial Peripheral Control Registerwire spie = spcr[7]; // Interrupt enable bitwire spe = spcr[6]; // System Enable bitwire dwom = spcr[5]; // Port D Wired-OR Mode Bit wire mstr = spcr[4]; // Master Mode Select Bit wire cpol = spcr[3]; // Clock Polarity Bitwire cpha = spcr[2]; // Clock Phase Bitwire [1:0] spr = spcr[1:0]; // Clock Rate Select Bits// decode Serial Peripheral Extension Registerwire [1:0] icnt = sper[7:6]; // interrupt on transfer countwire [1:0] spre = sper[1:0]; // extended clock rate selectwire [3:0] espr = {spre, spr};// generate status registerwire wr_spsr = wb_wr & (adr_i == 2'b01);reg spif;always @(posedge clk_i)if (~spe)spif <= #1 1'b0;elsespif <= #1 (tirq | spif) & ~(wr_spsr & dat_i[7]);reg wcol;always @(posedge clk_i)if (~spe)wcol <= #1 1'b0;elsewcol <= #1 (wfov | wcol) & ~(wr_spsr & dat_i[6]);assign spsr[7] = spif;assign spsr[6] = wcol;assign spsr[5:4] = 2'b00;assign spsr[3] = wffull;assign spsr[2] = wfempty;assign spsr[1] = rffull;assign spsr[0] = rfempty;// generate IRQ output (inta_o)always @(posedge clk_i)inta_o <= #1 spif & spie;//// hookup read/write buffer fifofifo4 #(8)rfifo(.clk ( clk_i ),.rst ( rst_i ),.clr ( ~spe ),.din ( treg ),.we ( rfwe ),.dout ( rfdout ),.re ( rfre ),.full ( rffull ),.empty ( rfempty )),wfifo(.clk ( clk_i ),.rst ( rst_i ),.clr ( ~spe ),.din ( dat_i ),.we ( wfwe ),.dout ( wfdout ),.re ( wfre ),.full ( wffull ),.empty ( wfempty ));//// generate clk dividerreg [11:0] clkcnt;always @(posedge clk_i)if(spe & (|clkcnt & |state))clkcnt <= #1 clkcnt - 11'h1;elsecase (espr) // synopsys full_case parallel_case4'b0000: clkcnt <= #1 12'h0; // 2 -- original M68HC11 coding 4'b0001: clkcnt <= #1 12'h1; // 4 -- original M68HC11 coding 4'b0010: clkcnt <= #1 12'h3; // 16 -- original M68HC11 coding 4'b0011: clkcnt <= #1 12'hf; // 32 -- original M68HC11 coding4'b0100: clkcnt <= #1 12'h1f; // 84'b0101: clkcnt <= #1 12'h7; // 644'b0110: clkcnt <= #1 12'h3f; // 1284'b0111: clkcnt <= #1 12'h7f; // 2564'b1000: clkcnt <= #1 12'hff; // 5124'b1001: clkcnt <= #1 12'h1ff; // 10244'b1010: clkcnt <= #1 12'h3ff; // 20484'b1011: clkcnt <= #1 12'h7ff; // 4096endcase// generate clock enable signalwire ena = ~|clkcnt;// transfer statemachinealways @(posedge clk_i)if (~spe)beginstate <= #1 2'b00; // idlebcnt <= #1 3'h0;treg <= #1 8'h00;wfre <= #1 1'b0;rfwe <= #1 1'b0;sck_o <= #1 1'b0;endelsebeginwfre <= #1 1'b0;rfwe <= #1 1'b0;case (state) //synopsys full_case parallel_case2'b00: // idle statebeginbcnt <= #1 3'h7; // set transfer countertreg <= #1 wfdout; // load transfer registersck_o <= #1 cpol; // set sckif (~wfempty) beginwfre <= #1 1'b1;state <= #1 2'b01;if (cpha) sck_o <= #1 ~sck_o;endend2'b01: // clock-phase2, next dataif (ena) beginsck_o <= #1 ~sck_o;state <= #1 2'b11;end2'b11: // clock phase1if (ena) begintreg <= #1 {treg[6:0], miso_i};bcnt <= #1 bcnt -3'h1;if (~|bcnt) beginstate <= #1 2'b00;sck_o <= #1 cpol;rfwe <= #1 1'b1;end else beginstate <= #1 2'b01;sck_o <= #1 ~sck_o;endend2'b10: state <= #1 2'b00;endcaseendassign mosi_o = treg[7];// count number of transfers (for interrupt generation)reg [1:0] tcnt; // transfer countalways @(posedge clk_i)if (~spe)tcnt <= #1 icnt;else if (rfwe) // rfwe gets asserted when all bits have been transferedif (|tcnt)tcnt <= #1 tcnt - 2'h1;elsetcnt <= #1 icnt;assign tirq = ~|tcnt & rfwe;endmodule******************************************************************************* // 4 entry deep fast fifomodule fifo4(clk, rst, clr, din, we, dout, re, full, empty);parameter dw = 8;input clk, rst;input clr;input [dw:1] din;input we;output [dw:1] dout;input re;output full, empty;reg [dw:1] mem[0:3];reg [1:0] wp;reg [1:0] rp;wire [1:0] wp_p1;wire [1:0] wp_p2;wire [1:0] rp_p1;wire full, empty;reg gb;always @(posedge clk or negedge rst)if(!rst) wp <= #1 2'h0;elseif(clr) wp <= #1 2'h0;elseif(we) wp <= #1 wp_p1;assign wp_p1 = wp + 2'h1;assign wp_p2 = wp + 2'h2;always @(posedge clk or negedge rst)if(!rst) rp <= #1 2'h0;elseif(clr) rp <= #1 2'h0;elseif(re) rp <= #1 rp_p1; assign rp_p1 = rp + 2'h1;// Fifo Outputassign dout = mem[ rp ];// Fifo Inputalways @(posedge clk)if(we) mem[ wp ] <= #1 din;// Statusassign empty = (wp == rp) & !gb;assign full = (wp == rp) & gb;// Guard Bit ...always @(posedge clk)if(!rst) gb <= #1 1'b0;elseif(clr) gb <= #1 1'b0;elseif((wp_p1 == rp) & we) gb <= #1 1'b1;elseif(re) gb <= #1 1'b0; endmodule。
AT45DB161(中文)
关于模拟SPI总线读写A TDB161一、芯片概述DataFlash-A T45DB161 B是美国Atmel公司推出的大容量串行Flash存储器产品,采用NOR技术制造,可用于存储数据或程序代码,其产品型号为A T 4 5一DBxxxx,容量从lM 到256M。
A T45DB161B是DataFlash系列中的中档产品,单片容量为1 6Mb,其引脚及功能分别为:/CS:片选信号,SCK:串行时钟输入信号;SI:串行输入。
SO:串行输出。
/wP:写保护引脚,/RESET:复位引脚。
RDY/BUSY:准备好/忙信号。
NC:未用引脚。
A T45 DB 1 61B的内部逻辑结构分为三个部分:存储页阵列(主存)、缓存与I/O接口。
A T45DB161B的存储页面大小为52 8字节,整个存储器共分为409 6页,片内集成了两个52 8字节的SRAM 缓存。
A TDB161系列存储器可以按地址从低到高顺序读写,也可以随机读写任一字节的数据。
对于顺序读数据,可以使用连续读主存页阵列命令(操作码6 8 H 或E 8 H)从给定的起始地址开始连续读出数据,中间不需用户干预。
也可使用读单页主存命令(操作码5 2 H 或D2H),自行提供页地址读取数据。
对于顺序写数据,可以使用通过缓存写主存页命令(操作码82H 或85H ),直接将数据写人主存。
也可以先使用写缓存命令(操作码84H 或8 7H),将数据写入缓存,在适当的时刻再使用缓存写主存页命令(操作码8 3H 或86H),将缓存中的数据写入主存。
因此可以灵活的选择不同的读写方式对存储器进行读写操作。
在这里使用顺序读写Fla sh操作命令,并配合SPI模式0时序对Flash进行读写。
A TDB161具有16M的存储空间,可以存储较大的数据,而且是通过SPI总线来访问的,所以不占用什么资源。
A TDB161有16M的存储空间,有三个区域,4092页,每页有528(512)BYTE,还有两个缓冲区。
M25P80的模拟SPI总线读写程序
* 功能描述: 写功能寄存器
* 函数说明:
* 调用函数:M25P80_SPI_Write8,MP25_WriteEnable
* 全局变量:无
* 输 入: 无
* 返 回: 无
* 设 计 者:
日期:
* 修 改 者:
日期:
* 版 本:VER 1.0
*****************************************************************
} }
/****************************************************************
*****
*
* 函 数 名:MP25_WriteEnable
* 功能描述: 写使能
* 函数说明: PP,SE,BE,WRSR 之前必须进行写使能
* 调用函数:M25P80_SPI_Write8
能有 1 变 0,不能从 0 到 1,结果在调式的时候不断的向首地址写数,然
后都给变成 0,接下来回读数据全 0,当时还以为是自己的时序没搞定
呢.无意间换了个地址重写重读,数据正常。/于是乎"天才的"我认为是
首地址已经被我写坏(调试的时候不停现数据还是不对.才想起 FLASH
* 功能描述: 基于 SPI 总线的 24 位数据写操作
* 函数说明: 实现 SPI 总线的 24 位数据写操作
* 调用函数:
* 全局变量:无
* 输 入: 无
* 返 回: 无
* 设 计 者:
日期:
* 修 改 者:
日期:
* 版 本:VER 1.0
*****************************************************************
SPIM模拟器
改进版本:读入与输出
例: a = x + y; b=x-y # lixianfeng – 2010/09/20 … … main: ## Get first number from user, put into $t0. …… ## Get second number from user, put into $t1. …… # Print out $t2 & $t3 move $a0, $t2 # move the number to print into $a0 li $v0, 1 # load syscall print_int into $v0 syscall # make the syscall move $a0, $t2 li $v0, 1 syscall jr $ra
27
斐波那契数列
# fib.s – computing Fibonacci numbers # fib(n) = fib(n-2) + fib(n-1) for n > 1; otherwise fib(n) = 1 # Registers used: # $a0: parameter, initially n # $s0: placeholder for parameter n # $s1: fib(n-1) # $s2: fib(n-2) .text fib: ## Part 1. Preamble as a callee subu $sp, $sp, 32 # create its stack frame sw $ra, 28($sp) # save the return address sw $fp, 24($sp) # save $fp of caller sw $s0, 20($sp) # callee saved registers sw $s1, 16($sp) # callee saved registers sw $s2, 12($sp) # … addu $fp, $sp, 32 # move $fp to the frame base ## Other parts…
浅析spi flash驱动及其程序
浅析spi flash驱动及其程序SPI Flash 首先它是个Flash,Flash是什么东西就不多说了(非易失性存储介质),分为NOR和NAND两种(NOR和NAND的区别本篇不做介绍)。
SPI一种通信接口。
那么严格的来说SPI Flash是一种使用SPI通信的Flash,即,可能指NOR也可能是NAND。
但现在大部分情况默认下人们说的SPI Flash指的是SPI NorFlash。
早期Norflash 的接口是parallel的形式,即把数据线和地址线并排与IC的管脚连接。
但是后来发现不同容量的Norflash不能硬件上兼容(数据线和地址线的数量不一样),并且封装比较大,占用了较大的PCB板位置,所以后来逐渐被SPI(串行接口)Norflash所取代。
同时不同容量的SPI Norflash管脚也兼容封装也更小。
,至于现在很多人说起NOR flash直接都以SPI flash来代称。
NorFlash根据数据传输的位数可以分为并行(Parallel,即地址线和数据线直接和处理器相连)NorFlash和串行(SPI,即通过SPI接口和处理器相连)NorFlash;区别主要就是:1、SPI NorFlash每次传输一bit位的数据,parallel连接的NorFlash每次传输多个bit位的数据(有x8和x16bit两种);2、SPI NorFlash比parallel便宜,接口简单点,但速度慢。
NandFlash是地址数据线复用的方式,接口标准统一(x8bit和x16bit),所以不同容量再兼容性上基本没什么问题。
但是目前对产品的需求越来越小型化以及成本要求也越来越高,所以SPI NandFlash渐渐成为主流,并且采用SPI NANDFlash方案,主控也可以不需要传统NAND控制器,只需要有SPI接口接口操作访问,从而降低成本。
另外SPI NandFlash封装比传统的封装也小很多,故节省了PCB板的空间。
运用4个普通IO口模拟SPI程序等.
#define ATT_CS
PORTB.5
#define ATT_SEL PORTB.6 #define ATT_REST PORTB.1 #define SET7022_Din PORTB|=(1<<2) #define CLR7022_Din PORTB&=~(1<<2) #define SET7022_SCLK PORTB|=(1<<4) #define CLR7022_SCLK PORTB&=~(1<<4) #define SET7022_CS #define CLR7022_CS PORTB|=(1<<5) PORTB&=~(1<<5)
else MOSI=0; dat<<=1; SCK=1; _nop_(); _nop_(); _nop_(); _nop_(); temp<<=1; if(MISO)temp++; SCK=0; _nop_(); _nop_(); _nop_(); _nop_(); } return temp; }
/************************************************************ *************************/ ulong Read_SPI(uchar comm) { uchar j; ulong rbyte=0; if(ATT_SIG==0) { SET7022_CS; CLR7022_SCLK; CLR7022_CS; #asm("cli") for( j=0;j<8;j++) { //关中断 //使能 SPI
2、SPI 简介: 同步外设接口(SPI)是由摩托罗拉公司开发的全双工同步串行总线,该总线大量 用在与 EEPROM、ADC、FLASH 和显示驱动器之类的慢速外设器件通信。 SPI(Serial Peripheral Interface)是一种串行同步通讯协议,由一个主设 备和一个或多个从设备组成, 主设备启动一个与从设备的同步通讯,从而完成数 据的交换。通讯时,数据由 MOSI 输出,MISO 输入,数据在时钟的上升或下 降沿由 MOSI 输出, 在紧接着的下降或上升沿由 MISO 读入, 这样经过 8/16 次 时钟的改变,完成 8/16 位数据的传输。
模拟spiC程序
return rcv;
}
u8 Soft_SPI_ReadWrite_Byte(u8 send_data)
{
u8 i;
u8 rcv;
// Soft_SPI_CLK = 0;
Soft_SPI_MISO_IN(); //设置MISO为输入模式
for(i = 0;i < 8;i++)
/**********************************************************
* @ File name -> soft_spi.c
* @ Version -> V1.0
* @ Date -> 11-15-2013
* @ Brief -> GPIO模拟SPI接口函数
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; //CLK and MOSI
* 函数功能 ---> 模拟SPI发送数据函数
* 入口参数 ---> send_data: 要发送的数据
* 返回参数 ---> 接收到的数据
* 功能说明 ---> 优先发送MSB,需要先发送LSB的请修改此函数
**********************************************************/
使用MCU的GPIO模拟SPI
用GPIO模拟SPI协议的实现一SPI协议概括SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。
是Motorola首先在其MC68HCXX系列处理器上定义的。
SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,比如AT91RM9200.SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。
也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)。
(1)SDO –主设备数据输出,从设备数据输入(2)SDI –主设备数据输入,从设备数据输出(3)SCLK –时钟信号,由主设备产生(4)CS –从设备使能信号,由主设备控制其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效。
这就允许在同一总线上连接多个SPI设备成为可能。
接下来就负责通讯的3根线了。
通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。
这就是SCK时钟线存在的原因,由SCK提供时钟脉冲,SDI,SDO 则基于此脉冲完成数据传输。
数据输出通过SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。
完成一位数据传输,输入也使用同样原理。
这样,在至少8次时钟信号的改变(上沿和下沿为一次),就可以完成8位数据的传输。
要注意的是,SCK信号线只由主设备控制,从设备不能控制信号线。
同样,在一个基于SPI的设备中,至少有一个主控设备。
恩智浦半导体FlexIO模拟通信和定时外设应用笔记说明书
恩智浦半导体文档编号:AN12174 应用笔记第0版,2018年6月使用 FlexIO 模拟通信和定时外设1. 简介FlexIO 是用在 Kinetis 和 S32K 微控制器系列上的新外设模块。
它具有高度可配置性,能够模拟各种通信协议,例如本文档中提到的UART、I2C、SPI、I2S和LIN,以及其它一些通讯协议,像J1850、I3C、曼彻斯特。
FlexIO 作为微控制器的一个独立外设模块,并不能替代任何通信外设。
FlexIO 的主要特点是可以根据用户的需求来直接构建自己的外设。
本文的示例代码基于 S32K SDK(包含在S32DS_v2018 中的软件开发套件中)和 Bare Metal 的配置代码,以便于更好地了解什么是FlexIO。
通过这些示例,用户可以模拟不同的通信协议和 PWM 信号。
目录1. 简介 (1)2. FlexIO 模块概述 (2)3. 使用FlexIO 模拟UART (4)3.1. 简介 (4)3.2. 配置移位器和定时器 (7)3.3. 函数说明 (10)3.4. 运行例程 (11)4. 使用FlexIO模拟双SPI (12)4.1. 移位器和定时器的配置 (14)4.2. 软件概述 (18)4.3. 操作实现 (20)4.4. 运行例程 (20)5. 使用FlexIO模拟I2C总线主设备 (24)5.1. 简介 (24)5.2. 总体说明 (24)5.3. 移位器和定时器的配置 (25)5.4. 软件概述 (27)5.5. 执行 (30)5.6. 运行例程 (31)6. 使用FlexIO生成PWM (32)6.1. 简介 (32)6.2. 总体概述 (33)6.3. 定时器的配置 (33)6.4. 软件实现概述 (35)6.5. 运行例程 (36)7. 使用FlexIO 模拟I2S 总线Master (36)7.1. 总体概述 (37)7.2. 移位器和定时器的配置 (38)7.3. 软件实现概述 (40)7.4. 运行例程 (40)8. 使用FlexIO模拟 LIN主/从 (41)8.1. 简介 (41)8.2. 使用FlexIO模拟LIN (41)8.3. 配置移位器和定时器 (42)9. 结论 (45)10. 修订历史 (45)FlexIO 模块概述2. FlexIO 模块概述FlexIO 模块具有以下主要硬件资源:∙移位器∙定时器∙引脚可以从 FLEXIO_PARAM 寄存器中获取特定MCU 里面这些资源数量。
SPI编程说明
SPI编程说明(开关机与AOI一样)注明:所有的步骤在saki界面底部都有显示,做程序之前所有的步骤都为粉红色,每做完一步变绿,直到所有都变绿后,程序做完。
所以做程序时,可根据下面的提示来做,更容易记忆。
步骤一般是:Gerber size&Origin——Pad——Fiducial Mark——FOV.如下图所示,前面已经做完了两步,有两个变绿的。
图一.进入编程界面1.双击桌面上的spi软件(如图1示)图标。
图1出现如下图2示对话框,点击Ok进入。
图2出现图3图4对话框。
图3图4点击OK进入。
2.File——Pad Control View(如图5所示)。
进入图6界面。
图5图6 二.导入gerber数据。
3.单击图6界面下的Gerber Import(图6、图7所示)。
图7出现如图8示界面。
点击选择Gerber数据。
(图8、图9)图8选完Gerber后,点击OK完成。
出现如图10所示画面。
图10图11三.完成gerber size&oringin 步骤。
4.点击Zoom in按钮。
进行放大。
5.点击按钮。
然后框出板子区域.。
出现如图12所示对话框。
图12根据实际情况设置板子尺寸。
并将Origin选择成第一个。
(图10)四.完成Pad一步。
6.点击work area按钮。
再次框出检测区域。
(根据板子大小)。
7.点击work area旁边的按钮,生成焊盘。
五.完成Fiducial Mark步骤。
8.点击Zoom in放大后,点击Pad 按钮。
如图13所示,选择两个Mark 点(左上角和右下角位置)。
图13注意:因为Gerber file 里所给的Mark点与我们实际设定的Mark点有偏差,所以需要在下面的步骤中移动Mark点。
9.选中两个Mark点后,右键(图14)出现如图15对话框。
图14图15因为了解到实际Mark 点与Gerber 数据中所给Mark 点偏差为Y 方向上的5000,所以将Y 一项改为-5000。
SPI协议详解
SPI协议详解SPI的四种模式是什么,然后你不会,总是会有点尴尬。
读了这篇文章,你会对SPI协议有一定的认识,也会对你的面试有帮助。
协议是为了规范收发双方的,好的协议不仅需要速度的保证,还需要传输稳定,可拓展等等。
#SPI协议简介SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。
是Motorola首先在其MC68HCXX系列处理器上定义的。
SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器等芯片,还有数字信号处理器和数字信号解码器之间。
SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,比如AT91RM9200。
SPI主从模式硬件连接如下图4种工作模式波形时序如下图:#协议心得SPI接口时钟配置心得:在主设备配置SPI接口时钟的时候一定要弄清楚从设备的时钟要求,因为主设备的时钟极性和相位都是以从设备为基准的。
因此在时钟极性的配置上一定要搞清楚从设备是在时钟的上升沿还是下降沿接收数据,是在时钟的下降沿还是上升沿输出数据。
但要注意的是,主设备的SDO连接从设备的SDI,从设备的SDO连接主设备的SDI。
从设备SDI接收的数据是主设备的SDO发送过来的,主设备SDI接收的数据是从设备SDO发送过来的,所以主设备这边SPI时钟极性的配置(即SDO的配置)跟从设备的SDI接收数据的极性是相反的,跟从设备SDO发送数据的极性是相同的。
下面这段话是Sychip Wlan8100 Module Spec上说的,充分说明了时钟极性是如何配置的:The 81xx module will always input data bits at the rising edge of the clock, and the host will always output data bits on the falling edge of the clock.意思是:主设备在时钟的下降沿发送数据,从设备在时钟的上升沿接收数据。
运用4个普通IO口模拟SPI程序等
运用4个普通I/O口模拟SPI程序源代码收藏/********************************************************************函数名:uchar SpiReadWrite(uchar dat)功能:SPI发送接收一个数据说明:调用:入口参数:出口参数:***********************************************************************/ uchar SpiReadWrite(uchar dat){uchar i,temp;temp=0;SCK=0;_nop_();for(i=0;i<8;i++){if(dat & 0x80){MOSI=1;}else MOSI=0;dat<<=1;SCK=1;_nop_();_nop_();_nop_();_nop_();temp<<=1;if(MISO)temp++;SCK=0;_nop_();_nop_();_nop_();_nop_();}return temp;}1、SPI总线速度:波特率可以高达5Mbps,具体速度大小取决于SPI硬件。
例如,Xicor公司的SPI串行器件传输速度能达到5MHz;ATMEL的AT45DB021B,20 MHz Max Clock Frequency;LPC2214的SPI,最大数据位速率为输入时钟速率的1/8。
2、SPI简介:同步外设接口(SPI)是由摩托罗拉公司开发的全双工同步串行总线,该总线大量用在与EEPROM、ADC、FLASH和显示驱动器之类的慢速外设器件通信。
SPI(Serial Peripheral Interface)是一种串行同步通讯协议,由一个主设备和一个或多个从设备组成,主设备启动一个与从设备的同步通讯,从而完成数据的交换。
通讯时,数据由MOSI 输出,MISO 输入,数据在时钟的上升或下降沿由MOSI 输出,在紧接着的下降或上升沿由MISO 读入,这样经过8/16 次时钟的改变,完成8/16 位数据的传输。
SPI总线信号特性和完整性的测试程序与规定
SPI总线信号特性和完整性的测试程序与规定1. 简介SPI(Serial Peripheral Interface)总线是一种常用于串行通信的接口标准,用于在微控制器和外部设备之间传输数据。
为了确保SPI总线的正常工作和数据的可靠传输,需要进行信号特性和完整性的测试。
2. 测试程序为了测试SPI总线的信号特性和完整性,可以采用以下步骤和程序:1. 设置SPI主设备和从设备:确定SPI主设备和从设备的连接方式和参数设置,包括时钟频率、数据位数、传输模式等。
2. 发送测试数据:主设备向从设备发送特定的测试数据,可以是不同类型和长度的数据。
3. 接收数据并验证:从设备接收主设备发送的数据,并进行验证。
验证可以包括数据位的正确性、时序的准确性等。
4. 记录测试结果:记录测试过程中的数据发送和接收情况,以及验证结果。
3. 测试规定为了确保测试的准确性和可比性,应根据以下规定进行SPI总线信号特性和完整性的测试:1. 测试环境:测试应在稳定的实验环境中进行,尽量减少外界干扰。
2. 测试设备:选择合适的SPI主设备和从设备,确保设备的质量和性能符合要求。
3. 测试参数:根据实际需求选择合适的测试参数,包括时钟频率、数据位数、传输模式等。
4. 测试数据:选择不同类型和长度的测试数据,覆盖各种可能的情况。
5. 测试记录:记录测试过程中的数据发送和接收情况,以及验证结果,确保测试结果可追溯和可重复。
4. 注意事项在进行SPI总线信号特性和完整性的测试时,需要注意以下事项:1. 保持一致性:在进行不同测试之间,保持测试环境、设备和参数的一致性,确保测试结果的可比性。
2. 测试时间:根据实际需求,合理安排测试的时间和频率,以充分覆盖可能的情况。
3. 故障排除:在测试过程中,如果发现异常情况或测试结果与预期不符,应及时进行故障排除,确保测试的准确性和可靠性。
5. 总结SPI总线信号特性和完整性的测试是确保SPI总线正常工作和数据可靠传输的重要步骤。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
写程序:void SPIx_WriteByte(u8 TxData){u8 j=0;SPI_FLASH_CLK_LOW(); //clk=0if(TxData&0x80){SPI_FLASH_DI_HIGH();} //mosi=1else{SPI_FLASH_DI_LOW();} //mosi=0for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH(); //clk=1,一个上升沿写入一位for(j=0;j<5;j++); //延时SPI_FLASH_CLK_LOW(); //clk=0if(TxData & 0x40){SPI_FLASH_DI_HIGH();} //mosi=1else{SPI_FLASH_DI_LOW();} //mosi=0for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH();for(j=0;j<5;j++);SPI_FLASH_CLK_LOW();if(TxData&0x20){SPI_FLASH_DI_HIGH();} //mosi=1else{SPI_FLASH_DI_LOW();} //mosi=0for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH();for(j=0;j<5;j++);SPI_FLASH_CLK_LOW();if(TxData&0x10){SPI_FLASH_DI_HIGH();} //mosi=1else{SPI_FLASH_DI_LOW();} //mosi=0for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH();for(j=0;j<5;j++);SPI_FLASH_CLK_LOW();if(TxData&0x08){SPI_FLASH_DI_HIGH();} //mosi=1else{SPI_FLASH_DI_LOW();} //mosi=0for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH();for(j=0;j<5;j++);SPI_FLASH_CLK_LOW();if(TxData&0x04){SPI_FLASH_DI_HIGH();} //mosi=1else{SPI_FLASH_DI_LOW();} //mosi=0for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH();for(j=0;j<5;j++);SPI_FLASH_CLK_LOW();if(TxData&0x02){SPI_FLASH_DI_HIGH();} //mosi=1else{SPI_FLASH_DI_LOW();} //mosi=0for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH();for(j=0;j<5;j++);SPI_FLASH_CLK_LOW(); //clk=0if(TxData&0x01){SPI_FLASH_DI_HIGH();}else{SPI_FLASH_DI_LOW();}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH(); //clk=1for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW(); //clk=0}读程序0x80==0x80u8 SPIx_ReadByte(void){u8 i=0,j=0;for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH(); //clk=1if(GPIOC->IDR&0x80==0x80){i=i+0x80;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW(); //clk=0,下降沿读数for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x80==0x80){i=i+0x40;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x80==0x80){i=i+0x20;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x80==0x80){i=i+0x10;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x80==0x80){i=i+0x08;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x80==0x80){i=i+0x04;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x80==0x80){i=i+0x02;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x80==0x80){i=i+0x01;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();return i;}读程序0x40==0x40u8 SPIx_ReadByte(void){u8 i=0,j=0;for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH(); //clk=1if(GPIOC->IDR&0x40==0x40){i=i+0x80;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW(); //clk=0,下降沿读数for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x40==0x40){i=i+0x40;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x40==0x40){i=i+0x20;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x40==0x40){i=i+0x10;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x40==0x40){i=i+0x08;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x40==0x40){i=i+0x04;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x40==0x40){i=i+0x02;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x40==0x40){i=i+0x01;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();return i;}读程序0x20==0x20u8 SPIx_ReadByte(void){u8 i=0,j=0;for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH(); //clk=1if(GPIOC->IDR&0x20==0x20){i=i+0x80;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW(); //clk=0,下降沿读数for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x20==0x20){i=i+0x40;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x20==0x20){i=i+0x20;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x20==0x20){i=i+0x10;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x20==0x20){i=i+0x08;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x20==0x20){i=i+0x04;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x20==0x20){i=i+0x02;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x20==0x20){i=i+0x01;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();return i;}读程序0x10==0x10读程序0x08==0x08读程序0x04==0x04读程序0x02==0x02u8 SPIx_ReadByte(void){u8 i=0,j=0;for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH(); //clk=1if(GPIOC->IDR&0x02==0x02){i=i+0x80;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW(); //clk=0,下降沿读数for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x02==0x02){i=i+0x40;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x02==0x02){i=i+0x20;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x02==0x02){i=i+0x10;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x02==0x02){i=i+0x08;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x02==0x02){i=i+0x04;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x02==0x02){i=i+0x02;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x02==0x02){i=i+0x01;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();return i;}读程序0x01==0x01u8 SPIx_ReadByte(void){u8 i=0,j=0;for(j=0;j<3;j++); //延时SPI_FLASH_CLK_HIGH(); //clk=1if(GPIOC->IDR&0x01==0x01){i=i+0x80;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW(); //clk=0,下降沿读数for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x01==0x01){i=i+0x40;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x01==0x01){i=i+0x20;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x01==0x01){i=i+0x10;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x01==0x01){i=i+0x08;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x01==0x01){i=i+0x04;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x01==0x01){i=i+0x02;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();for(j=0;j<5;j++);SPI_FLASH_CLK_HIGH();if(GPIOC->IDR&0x01==0x01){i=i+0x01;}for(j=0;j<3;j++); //延时SPI_FLASH_CLK_LOW();return i;}。