
最近在调试spi flash的擦写,问题是flash擦写uboot时,不成功。原来的uboot丢失。 测试发现是因为擦能成功,但是写时的地址不是secent大小,一个secent大小为64K 看datasheet上说,擦的长度可以是page,secent或block,即4K,32K,64K 我就用4K来擦除,但是不行。还是一样。 之后在网上看了看,貌似听说4K擦除的flash很少。我用的是mxic的flash。 就改为64K擦除。 出现只能写一次,第二次写就会失败。 原因一直不明白。 最后也不知道动了什么地方造成其好了。 动的地方为: 改spi mode3为mode0 改spi clk从1M到2M最大支持50M 改bootload的引导,从0x8400到0x10000 改擦写大小为0x80000。 写了五六次,没啥事。 什么原因也懒的查了。 应该是flash未写数据时,可以写数据,但写了数据之后,一定要先擦除再写数据才行。应该是这个原因造成只能擦一次。
1 FPGA与MCU,DSP,ARM等区别
MCU等是属于软件编程,程序是顺序执行,即使像DSP有多级流水线,但是程序总体还是顺序的。
FPGA是属于硬件编程,程序是并行执行的,可以有多个进程,同时执行不同的功能。
2 FPGA实现UART,IIC,SPI。
如果是简单的应用(比如说不用校验等等),完全可以自己写,例如下面的程序,VHDL写的,既可以作为UART发送程序(改改就是接收),也可以做SPI发送或者接收(加一个时钟)。
如果需要较完善的功能的话,建议使用IP核,往上有很多免费的UART,IIC,SPI等接口的IP核,功能及代码都给你写好了的,提供输入输出接口,方便应用。
process(Clk)
variable temp : integer range 0 to 7;
begin
if Clk'event and Clk='1' then
if Reset = '0' then
TxD <= '1';
BitCnt <= "00000";
SL<='1';
TReg<=(others=>'0');
temp:=0;
elsif Load = '0' and temp=0 then
TxD <= '1';
SL<='1';
BitCnt <= "00000";
temp:=0;
elsif Load='1' and temp=0 then
temp:=1;
elsif temp=1 then
case BitCnt is
when "00000" =>
TReg <= Addr_Data;
SL<='0';
TxD <= '0';
BitCnt <= BitCnt + 1;
temp:=1;
when "00001" | "00010" | "00011" |
"00100" | "00101" | "00110" |
"00111" | "01000" | "01001" |
"01010" | "01011" | "01100" |
"01101" | "01110" | "01111" =>
TxD <= TReg(0);
TReg <= '1' & TReg(14 downto 1);
BitCnt <= BitCnt + 1;
temp:=1;
when "10000" =>
SL<='1';
TxD <= '1';
TReg <= '1' & TReg(14 downto 1);
BitCnt <= "00000";
temp:=0;
when others => NULL;
end case;
ELSE
TXD<='1';
SL<='1';
end if;
end if;
end process;
针对 树莓派 封装的 UWP应用 类,以下代码未经测试,聊以抛砖引玉:
using System;
using SystemCollectionsGeneric;
using SystemLinq;
using SystemText;
using SystemThreadingTasks;
using WindowsDevicesGpio;
using WindowsStorageStreams;
using WindowsDevicesEnumeration;
using WindowsDevicesSerialCommunication;
using WindowsDevicesI2c;
using WindowsDevicesSpi;
namespace SlotAgentAppServices
{
public class DevicesHelper
{
public static void GPIO(int eLevel=0, int ioPortNumber = 5)
{
// 获得系统板载缺省GPIO controller
GpioController gpio = GpioControllerGetDefault();
if (gpio == null)
return; // 如果系统板载无可用GPIO,则返回
// 打开指定的GPIO
using (GpioPin pin = gpioOpenPin(ioPortNumber))
{
// Latch HIGH value first This ensures a default value when the pin is set as output
pinWrite(eLevel==0 GpioPinValueLow: GpioPinValueHigh);
// 设置IO为输出方向
pinSetDriveMode(GpioPinDriveModeOutput);
} //关闭 pin - will revert to its power-on state
}
#region 示例代码
/
(一)GPIO接口使用
/
public void GPIO()
{
// Get the default GPIO controller on the system
GpioController gpio = GpioControllerGetDefault();
if (gpio == null)
return; // GPIO not available on this system
// Open GPIO 5
using (GpioPin pin = gpioOpenPin(5))
{
// Latch HIGH value first This ensures a default value when the pin is set as output
pinWrite(GpioPinValueHigh);
// Set the IO direction as output
pinSetDriveMode(GpioPinDriveModeOutput);
} // Close pin - will revert to its power-on state
}
/
(二) UART接口
Pin 8 - UART0 TX
Pin 10- UART0 RX
下面的例子先是初始化UART0,然后做了一次读 *** 作和一次写 *** 作
/
public async void Serial()
{
string aqs = SerialDeviceGetDeviceSelector("UART0"); / Find the selector string for the serial device /
var dis = await DeviceInformationFindAllAsync(aqs); / Find the serial device with our selector string /
SerialDevice SerialPort = await SerialDeviceFromIdAsync(dis[0]Id); / Create an serial device with our selected device /
/ Configure serial settings /
SerialPortWriteTimeout = TimeSpanFromMilliseconds(1000);
SerialPortReadTimeout = TimeSpanFromMilliseconds(1000);
SerialPortBaudRate = 9600;
SerialPortParity = SerialParityNone;
SerialPortStopBits = SerialStopBitCountOne;
SerialPortDataBits = 8;
/ Write a string out over serial /
string txBuffer = "Hello Serial";
DataWriter dataWriter = new DataWriter();
dataWriterWriteString(txBuffer);
uint bytesWritten = await SerialPortOutputStreamWriteAsync(dataWriterDetachBuffer());
/ Read data in from the serial port /
const uint maxReadLength = 1024;
DataReader dataReader = new DataReader(SerialPortInputStream);
uint bytesToRead = await dataReaderLoadAsync(maxReadLength);
string rxBuffer = dataReaderReadString(bytesToRead);
}
/
使用上面的例子时,需要在Packageappxmanifest 中修改下权限修改如下
<Capabilities>
<DeviceCapability Name="serialcommunication">
<Device Id="any">
<Function Type="name:serialPort" />
</Device>
</DeviceCapability>
</Capabilities>
/
/
(三)I2C 总线
Pin 3 - I2C1 SDA
Pin 5 - I2C1 SCL
下面的例子首先初始化I2C1 然后向地址为0x40的I2C设备写数据
/
public async void I2C()
{
// Get a selector string for bus "I2C1"
string aqs = I2cDeviceGetDeviceSelector("I2C1");
// Find the I2C bus controller with our selector string
var dis = await DeviceInformationFindAllAsync(aqs);
if (disCount == 0)
return; // bus not found
// 0x40 is the I2C device address
var settings = new I2cConnectionSettings(0x40);
// Create an I2cDevice with our selected bus controller and I2C settings
using (I2cDevice device = await I2cDeviceFromIdAsync(dis[0]Id, settings))
{
byte[] writeBuf = { 0x01, 0x02, 0x03, 0x04 };
deviceWrite(writeBuf);
}
}
/
(四) SPI 总线
Pin 19 - SPI0 MOSI
Pin 21 - SPI0 MISO
Pin 23 - SPI0 SCLK
Pin 24 - SPI0 CS0
Pin 26 - SPI0 CS1
下面的例子向SPI0 做了一次写 *** 作
/
public async void SPI()
{
// Get a selector string for bus "SPI0"
string aqs = SpiDeviceGetDeviceSelector("SPI0");
// Find the SPI bus controller device with our selector string
var dis = await DeviceInformationFindAllAsync(aqs);
if (disCount == 0) ;
return; // "SPI0" not found on this system
// Use chip select line CS0
var settings = new SpiConnectionSettings(0);
// Create an SpiDevice with our bus controller and SPI settings
using (SpiDevice device = await SpiDeviceFromIdAsync(dis[0]Id, settings))
{
byte[] writeBuf = { 0x01, 0x02, 0x03, 0x04 };
deviceWrite(writeBuf);
}
}
#endregion
}
}
实现单片机和PC机进行SPI通讯方法:\x0d\1:电路设计\x0d\设计的电路,利用两片AT89C52芯片,一片做为发送模块,一片做为接收模块。分别编写发送和接收程序,实现数据的发送和接受。通过LED显示接收到的数据。通过示波器观察输出的波形。\x0d\2:编写程序\x0d\根据设计好的电路及题目要求分别编写数据发送程序和数据接收程序。①:数据发送程序#define\x0d\ucharunsignedchar\x0d\#defineuintunsignedint\x0d\\x0d\#defineulongunsignedlong\x0d\//---------------------------#include\x0d\#include\x0d\//---------------------------sbitSPICLK=P1^0;//时钟信号sbitMOSI=P1^1;//主器件数据输出,从器件数据输入sbitMISO=P1^2;//主器件数据输入,从器件数据输出\x0d\sbitSS=P1^3;//从器件使能信号\x0d\voidDat_Transmit(uchardat)//发送数据程序\x0d\{uchari,datbuf;\x0d\datbuf=dat;\x0d\SS=1;while(SS){;}for(i=0;i\x0d\#include\x0d\//---------------------------sbitSPICLK=P1^0;//时钟信号sbitMOSI=P1^1;//主器件数据输出,从器件数据输入sbitMISO=P1^2;//主器件数据输入,从器件数据输出sbitSS=P1^3;//从器件使能信号\x0d\\x0d\//---------------------------voidNop(void)\x0d\{;\x0d\}\x0d\voidDelay(uchart){while(t--){;}\x0d\}\x0d\\x0d\ucharData_Receive(void)//数据接收程序\x0d\{uchari,dat=0,temp;bit\x0d\bt;\x0d\\x0d\SPICLK=1;MISO=1;SS=0;\x0d\//选中器件\x0d\Nop();Nop();\x0d\for(i=0;i回答于 2022-12-14
以上就是关于怎么通过verilog对spi flash读写全部的内容,包括:怎么通过verilog对spi flash读写、FPGA 怎么实现UART串口和IIC口或SPI 通讯可以大概说一下吗、用C#怎么写UART、SPI、I2C、CAN总线上测试时的数据程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)