SPI FLASH 波形测量演示实例

通常MCU,MPU,FPGA等控制类芯片都会外挂FLASH芯片存储程序,这也是非常常见的。一般的,控制芯片和Flash之间采用最多通信方式是SPI协议。SPI分为二线,三线,四线,具体根据实际情况选择。那么四线制使用是比较广泛的。

SPI:Serial Peripheral Interface,即串行外设接口协议。

SPI Flash四线制信号解释:

①CS:Chip select;也写作NSS或SS(Slave select),表示从设备选择信号,低电平有效。

②MOSI:Master output Slave input;也叫SDI(Serial data input),表示从设备的数据输入。

③MISO:Master input Slave output;也叫SDO(Serial data output),表示从设备的数据输出。

④SCLK:Serial clock;也写作SCK,表示串行时钟。

为了初步了解SPI-FLASH实际通讯波形和时序,以下图为例,采用四线制测量了上电瞬间控制芯片和flash之间的通讯信号:即CS,MOSI,MISO,SCLK。目的是为了验证程序启动时的工作情况,从而进一步了解SPI通信的工作过程。

电路原理图:

分别用示波器测量CS、SCLK、MISO(DO)、MOSI(DI)波形如下,

其中在MOSI引脚没有测试到波形,这是因为主设备是向Flash中读取数据即代码。如果是主设备往从设备Flash中写数据的话,在MOSI引脚上是可以测试到一连串的数据的。

如果以上对大家有些帮助的话,请点赞支持一下或分享,谢谢~

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
方波/三角波/正弦波信号发生器(ICL8038) 该信号发生器采用了精密波形发生器单片集成电路ICL8038。该电路能够产生高精度正弦波,方波,三角波,所需外部元件少。频率可通过外部元件调节。ICL8038的正弦波形失真=1%,三角波线性失真=0.1%,占空比调节范围为2%~98%。 ICL8038的第10脚外接定时电容,该电容的容值决定了输出波形的频率,电路中的定时电容从C1至C8决定了信号频率的十个倍频程,从500μF开始,依次减小十倍,直到5500pF,频率范围对应为0.05Hz~0.5 Hz~5Hz~50Hz~500Hz~5kHz~50kHz~500kHz。电路中的V1、R7、R8构成缓冲放大器,R9 为电位器,用于改变输出波形的幅度。 附:基于ICL8038函数信号发生器的设计 本设计是以ICL8038 和AT89C2051 为核心设计的数控及扫频函数信号发生器。ICL8038 作为函数信号源 结合外围电路产生占空比和幅度可调的正弦波、方波、三角波; 该函数信号发生器的频率可调范围为1~100kHz, 步进为0.1kHz, 波形稳定, 无明显失真。 1.系统设计框图 如图1 为系统设计框图。本设计是利用键盘设置相应的频率值, 根据所设置频率段选择相应电容, 经计算获得相应数字量送数字电位器实现D/A 转换, 同时与参考电压( 本例为5.5V) 相加后形成数控调压去控制ICL8038 第8 脚, 这样即可由ICL8038 实现对应频率值的矩形波、三角波和正弦波。方波幅度经衰减后送单片机可测得信号源频率并由数码管显示。 2.电路原理图 图2 为电路原理图。其中AT89C2051 是8 位单片机, 其中: P1.4~P1.7、P1.2、P1.3、P3.0、P3.1 作为数 码显示; P3.3、P3.5 、P3.7 作为键盘输入口; P3.4 作为计数口, 用于测量信号源频率;P3.0~P3.2 作为数字电位器的SPI总线; P1.1、P1.0 可根据需要扩展继电器或模拟开关选择ICL8038第10 脚( CAP) 与第11 脚间的电容C。 MCP41010 是8 位字长的数字电位器, 采用三总线SPI 接口。/CS: 片选信号, 低电平有效; SCK:时钟信号输入端; SI: 串行数据输入端, 用于寄存器的选择及数据输入。MCP41010 可作为数字电位器, 也可以作为D/A 转换器, 本设计是将MCP41010 接成8 位字长的D/A 转换器, MCP41010 根据输入的串行数据, 对基准电压进行分压后由中间抽头输出模拟电压, 即VPWO =DN/256VREF ( 式中VREF=5V) 。 函数发生电路ICL8038, 图2所示是一个占空比和一个频率连续可调的函数发生电路。ICL8038是一种函数发生器集成块, 通过外围电路的设计, 可以产生高精密度的正弦波、方波、三角波信号, 选择不同参数的外电阻和电容等器件, 可以获得频率在0.01Hz~300kHz 范围内的信号。通过调节RW2 可使占空比在2%~98%可调。第10 脚( CAP) 与第11 脚间的电容C 起到很重要的作用, 它的大小决定了输出信号频率的大小, 当C 确定后, 调节ICL8038 第8 脚的电压可改变信号源的输出频率。从ICL8038 引脚9(要接上拉电阻)输出的波形经衰减后送单片机P3.4 进行频率测量。 正弦函数信号由三角波函数信号经过非线性变换而获得。利用二极管的非线性特性, 可以将三角波信号的上升和下降斜率逐次逼近正弦波的斜率。ICL8038 中的非线性网络是由4 级击穿点的非线性逼近网络构成。一般说来, 逼近点越多得到的正弦波效果越好, 失真度也越小, 在本芯片中N= 4, 失真度可以小于1。在实测中得到正弦信号的失真度可达0.5 左右。其精度效果相当满意。为了进一步减小正弦波的失真度, 可采用图2 所示电路中两个电位器RW3 和RW4 所组成的电路, 调整它们可使正弦波失真度减小。当然, 如果矩形波的占空比不是50% , 矩形波不再是方波, 引脚2 输出也就不再是正弦波了。 图2 电路原理图 经实验发现, 在电路设计中接10 脚和11 脚的电容值和性能是整个电路的关键器件, 电容值的确定也就确定电路能产生的频率范围, 电容性能的好坏直接影响信号频率的稳定性、波形的失真度, 由于该芯片是通过恒流源 对C 充放电来产生振荡的, 故振荡频率的稳定性就受到外接电容及恒流源电流的影响, 若要使输出频率稳定, 必须采用以下措施:外接电阻、电容的温度特性要好; 外部电源应稳定; 电容应选用漏电小、质量好的非极化电容器。 3.实验结果 当±12V 工作电源时, 输出频率如下表: 失真度情况, 实验数据如下表: 4.软件流程图 图3 为软件流程图。T0 设为计数器,T1 设为定时器(初值为5ms)。5ms 启动主循环, 主要用于键盘扫描及扫描显示, 图2 中K0 作为控制键, K1 作为调整键, K2 作为增加键; 上电时程序进入频率设置模式, 按一下K0 键程序进入数控模式, 按二下K0 键程序进入扫频模式, 按三下K0 键程序进入频率设置模式, 周而复始。在频率设置模式, 由K1 键和K2 键完成频率设置。 图3 软件流程图
以下是一个简单的SPI Flash读写驱动程序示例,使用的是Linux内核自带的SPI驱动接口。 #include <linux/module.h> #include <linux/spi/spi.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #define FLASH_PAGE_SIZE 256 #define FLASH_SECTOR_SIZE 4096 #define FLASH_BLOCK_SIZE 65536 struct spi_flash { struct mtd_info mtd; struct spi_device *spi; }; static int spi_flash_probe(struct spi_device *spi) { struct spi_flash *flash; struct mtd_partition *parts; int nparts, err; flash = kzalloc(sizeof(struct spi_flash), GFP_KERNEL); if (!flash) { dev_err(&spi->dev, "Failed to allocate memory for spi_flash\n"); return -ENOMEM; } flash->spi = spi; /* Set up MTD structure */ flash->mtd.name = spi->modalias; flash->mtd.owner = THIS_MODULE; flash->mtd.type = MTD_NORFLASH; flash->mtd.flags = MTD_CAP_NORFLASH; flash->mtd.erasesize = FLASH_BLOCK_SIZE; flash->mtd.writesize = FLASH_PAGE_SIZE; flash->mtd.writebufsize = FLASH_PAGE_SIZE; /* Register MTD device */ err = mtd_device_register(&flash->mtd, NULL, 0); if (err) { dev_err(&spi->dev, "Failed to register MTD device, error %d\n", err); kfree(flash); return err; } /* Set up partition table */ nparts = get_mtd_device_partitions(&flash->mtd, &parts, 0); if (nparts <= 0) { dev_err(&spi->dev, "Failed to create partition table\n"); mtd_device_unregister(&flash->mtd); kfree(flash); return -EINVAL; } /* Print information about the device */ dev_info(&spi->dev, "SPI Flash device detected, %d partitions.\n", nparts); dev_info(&spi->dev, "Flash device size %llu bytes, erase size %d bytes, write size %d bytes.\n", (unsigned long long)flash->mtd.size, flash->mtd.erasesize, flash->mtd.writesize); return 0; } static int spi_flash_remove(struct spi_device *spi) { struct spi_flash *flash = spi_get_drvdata(spi); mtd_device_unregister(&flash->mtd); kfree(flash); return 0; } static const struct of_device_id spi_flash_of_match[] = { { .compatible = "spansion, s25fl064k", }, { /* end of table */ } }; MODULE_DEVICE_TABLE(of, spi_flash_of_match); static struct spi_driver spi_flash_driver = { .driver = { .name = "spi_flash", .owner = THIS_MODULE, .of_match_table = spi_flash_of_match, }, .probe = spi_flash_probe, .remove = spi_flash_remove, }; static int __init spi_flash_init(void) { return spi_register_driver(&spi_flash_driver); } static void __exit spi_flash_exit(void) { spi_unregister_driver(&spi_flash_driver); } module_init(spi_flash_init); module_exit(spi_flash_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("SPI Flash driver"); MODULE_ALIAS("spi:spi_flash"); 以上代码定义了一个名为spi_flash的驱动程序,它基于Linux内核自带的SPI驱动接口,并提供了一个MTD设备,可以进行SPI Flash的读写操作。在probe函数中,驱动程序会初始化MTD设备,并创建分区表。在remove函数中,驱动程序会注销MTD设备。在spi_flash_init函数中,驱动程序会注册SPI驱动程序。在spi_flash_exit函数中,驱动程序会注销SPI驱动程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值