历史上的今天
返回首页

历史上的今天

今天是:2025年06月03日(星期二)

正在发生

2020年06月03日 | 基于STM32单片机的64Mbit单对单通信

2020-06-03 来源:elecfans

简单的一种应用,ARM芯片作为master,flash为slaver,实现单对单通信。ARM主控芯片STM32F103,flash芯片为MACRONIX INTERNATIONAL的MX25L6465E,64Mbit。


SPI应该是嵌入式外围中最简单的一种应用了吧!一般SPI应用有两种方法:软件仿真,手动模拟产生时序和应用主控芯片的SPI控制器。


一般采用第二种方法比较好,比较稳定。应用主控芯片的SPI控制器,要点:正确的初始化SPI、操作SPI各寄存器和正确理解flash的时序。下面是过程,采用的是STM32F10X自带的库函数

1、初始化:void SpiFlashIniTIalzaTIon(void);

要知道硬件是怎么连接的,是SPI1还是SPI2连接到flash中去,通过连接图知道我们要操作的是SPI2。初始化大概3个部分,配置时钟;配置GPIO;配置SPI2。这里要注意的是,CS片选脚是作为普通的GPIO来使用,输出方式为“推挽式输出”,其他CLK,MISO,MOSI为“复用功能推挽式输出”;

代码:

void SpiFlashIniTIalzaTIon(void)

{

/*初始化的SPI,GPIO结构体*/

SPI_InitTypeDef SPI_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE); /*在RCC_APB1ENB中使能SPI2时钟(位14)*/

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);/*因为与SPI2相关的4个引脚和GPIOB相*/

/*关,GPIOB时钟(位3),这句现在还不 */

/*确定要不要,待调试时再确定 */

/*上面这一句是必须的,因为CS脚是当做GPIO来使用的,2011-01-30调试*/

/*配置SPI_FLASH_CLK(PB13),SPI_FLASH_MISO(PB14),SPI_FLASH_MOSI(PB15)*/

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; /*复用功能推挽式输出*/

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init( GPIOB, &GPIO_InitStructure);

/*配置输入SPI_FLASH_CS(PB12)*/

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; /*推挽式输出*/

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init( GPIOB, &GPIO_InitStructure);

SPI_FLASH_CS_SET; /*不选flash*/

/* SPI2配置 增加于2010-01-13*/

/* 注意: 在SPI_NSS_Soft模式下,SSI位决定了NSS引脚上(PB12)的电平,

* 而SSM=1时释放了NSS引脚,NSS引脚可以用作GPIO口*/

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; /*双线双向全双工BIDI MODE=0*/

SPI_InitStructure.SPI_Mode = SPI_Mode_Master; /*SSI位为1,MSTR位为1*/

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; /*SPI发送接收8位帧结构*/

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /*CPOL=1,CPHA=1,模式3*/

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; /*内部NSS信号由SSI位控制,SSM=1*/

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; /*波特率预分频值为4*/

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; /*数据传输从MSB位开始*/

SPI_InitStructure.SPI_CRCPolynomial = 7; /*复位默认值*/

SPI_Init(SPI_SELECT, &SPI_InitStructure);

SPI_Cmd(SPI_SELECT,ENABLE); /*使能SPI2*/

}

2、正确的操作SPI控制器;

这里需要注意的是理解SPI状态寄存器,特别是SPI_SR位7忙标志位BSY要小心,每次操作SPI要先读SPI_SR,BSY不忙才可下一步,然后就是操作缓冲器了。这里还有一个问题曾经困扰了我好久,SPI的时序问题,就是CLK怎么输出时序,最后我的理解是SPI每发送一个字节,CLK就自动会产生时序,如果没发送,CLK也就停止,这样节省了功耗。于是,如果SPI要接收字节,就必须先要发一个字节,例如发一个SPI_DUMMY_BYTE,Dummy byte有些flash有定义有些没有,没有的话自己随便定义一个,只要不和命令字相同就可以了。

u8 SpiFlashSendByte(u8 send_data);

u8 SpiFlashReceiveByte(void);

代码:

/*功能: SPI发送一个字节

*参数: send_data: 待发送的字节

*返回: 无*/

u8 SpiFlashSendByte(u8 send_data)

{

/*检查Busy位,SPI的SR中的位7,SPI通信是否为忙,直到不忙跳出*/

//while( SET==SPI_I2S_GetFlagStatus(SPI_SELECT, SPI_I2S_FLAG_BSY));

/*检查TXE位,SPI的SR中的位1,发送缓冲器是否为空,直到空跳出*/

while( RESET==SPI_I2S_GetFlagStatus(SPI_SELECT,SPI_I2S_FLAG_TXE));

SPI_I2S_SendData(SPI_SELECT, send_data); /*发送一个字节*/

/*发送数据后再接收一个字节*/

while( RESET==SPI_I2S_GetFlagStatus(SPI_SELECT, SPI_I2S_FLAG_RXNE) );

return( SPI_I2S_ReceiveData(SPI_SELECT) );

}

/*功能: SPI接收flash的一个字节

*参数: 接收到的字节

*返回: 无*/

u8 SpiFlashReceiveByte(void)

{

*检查RXNE位,SPI的SR中位0,确定接收缓冲器是有数据的*/

return(SpiFlashSendByte(SPI_DUMMY_BYTE));

}

3、理解flash的读写操作

首先,写数据之前必须要擦除,因为所有的flash只能从1变为0,擦除将flash全部置1,写的时候相应位置0。

读写操作这部分,flash芯片手册详细的说明了操作步骤,需要注意的是:flash MX25L64的状态寄存器。对flash操作之前,先读flash_SR,确保WIP=0(flash空闲),对flash擦除、编程等操作确保WEL=1(flash能够接受擦出编程等操作)。

在对flash进行写操作时,要理解一点:对flash写数据(也就是Page Program(PP),Command 02)是基于页(256bytes)为单位的,如果数据写到页的末尾,会从当前页的首地址继续开始写剩余的数据,这样就有可能造成成数据的丢失,注意就可以了!主要是理解手册中的这段话:The Page Program(PP) instruction is for programming the memory to be "0"......If the eight least significant address bits(A7-A0) are not all 0,all transmitted data going beyond the end of the current page are grogrammed fromthe start address of the same page(from the address A7-A0 are all 0).If more than 256 bytes are sent to the device,the data of the last 256-byte is programmed at the requtest page and previous data will be disregarded. If less than 256 bytes .......

代码:

/*功能: 在指定地址处开始从flash读取数据

参数: pData_from_flash,读取到的数据存放指针

address_to_read, 待读取的数据开始地址,地址格式有效位为:A23-A0

返回: 指向读取到的数据指针pData_from_flash

*/

void SpiFlashReadData( u8 *pData_from_flash, u

推荐阅读

史海拾趣

东晶(ECEC)公司的发展小趣事

近年来,随着电子信息技术的快速发展和智能化趋势的加剧,东晶电子也面临着新的机遇和挑战。为了适应市场变化和满足客户需求,公司开始实施战略转型和升级。公司加大了对新型电子元器件的研发力度,推动产品向微型化、功能化、高精度方向发展。同时,公司还积极开拓新领域和新市场,拓展业务范围和市场份额。这些举措为公司未来的发展奠定了坚实的基础。

请注意,这些故事是基于已知信息的概括性描述,并非具体的历史事件。在实际情况中,东晶电子的发展历程可能更加复杂和多样化。

Heatron LED Integration公司的发展小趣事

Heatron LED Integration自成立以来,便致力于LED照明技术的创新。公司拥有一支由光学、机电设计及热管理专家组成的研发团队,不断突破技术瓶颈。在早期,公司研发出了一款高性能的8英寸LED模块,该模块凭借其出色的亮度和能效比,迅速在市场上获得了认可。这一创新不仅提升了产品的市场竞争力,也为公司后续的技术积累和市场拓展奠定了坚实基础。

绿索超容(GreenSource)公司的发展小趣事

Heatron LED Integration自成立以来,便致力于LED照明技术的创新。公司拥有一支由光学、机电设计及热管理专家组成的研发团队,不断突破技术瓶颈。在早期,公司研发出了一款高性能的8英寸LED模块,该模块凭借其出色的亮度和能效比,迅速在市场上获得了认可。这一创新不仅提升了产品的市场竞争力,也为公司后续的技术积累和市场拓展奠定了坚实基础。

Curtis Industries公司的发展小趣事

随着电子行业的不断发展,Curtis Industries公司意识到技术创新的重要性。公司投入大量资源进行技术研发,成功推出了一系列具有行业领先水平的产品。其中,公司在某一关键领域的突破性技术,不仅解决了行业内的技术难题,还为公司赢得了广泛的赞誉。Curtis Industries因此成为了电子行业的技术创新引领者,推动了整个行业的发展。

ASC Capacitors公司的发展小趣事

ASC Capacitors的创始人,凭借对电子行业的深厚情感和对电容技术的独到见解,于XXXX年创立了这家公司。他们深知电容在电子行业中的重要性,因此立志要打造一家专业制造高质量电容器的企业。从最初的几间厂房和几名员工,ASC Capacitors凭借坚韧不拔的精神和对技术的执着追求,逐渐在电子行业中崭露头角。

爱普特半导体(APTSEMI)公司的发展小趣事

凭借卓越的产品性能和稳定的市场表现,爱普特半导体的市场占有率持续提升。目前,公司在国内非ARM核MCU市场的出货量已经位居第一,市场占有率也遥遥领先。这一成绩的取得,不仅彰显了爱普特在MCU行业的领先地位,也反映了公司在技术创新和市场拓展方面的强大实力。随着公司研发能力的不断提升和市场布局的逐步完善,相信爱普特在未来的市场竞争中将继续保持领先地位。

这些故事只是爱普特半导体发展过程中的一部分,它们共同展现了公司在电子行业中的崛起和成长。作为一家坚持自主创新、构建高端人才队伍、与大型企业战略合作、践行纯国产化发展理念并持续提升市场占有率的企业,爱普特半导体在电子行业的发展道路上正稳步前行。

问答坊 | AI 解惑

在使用QUARTUS时硬件下载接口

我在使用自己的笔记本时,出现下面的情况 而且AVAILABLE HARDWARE ITEM中没有可添加的硬件选项 知道的教一下怎么弄…

查看全部问答>

proteus中虚拟串口的使用

本人正在做毕业设计,用到一个gps模块,与笔记本通信的时候用到的是com5,可是proteus中的虚拟串口确只有com4,这个问题怎么解决,请教各位高手。谢谢…

查看全部问答>

c/c++语言与汇编语言混合编程问题--跪求,,

源代码附上: test.c文件,内容如下: #include extern unsigned int usqr(unsigned x); int main() { int a,b; a=82; b=usqr(a); printf(\"b is % d\\n\",b); } usqr_32.s汇编文件,内容如下(实现开平方运算) .section .text .glo ...…

查看全部问答>

帧同步系统的FPGA设计与实现资料下载

欢迎大家下载帧同步系统的FPGA设计与实现!…

查看全部问答>

单片机学习

各位大哥,大姐:你们好!我以前有8位机单片机的编程的基础,现在我想跟进单片机的发展,不知大家有什么好的建议呢?有什么好的资料能否共享下?…

查看全部问答>

adoce数据库问题

我记得我以前用vb写应用程序访问access数据库的时候,可以用ado控件进行绑定,就是说再应用程序界面,每个文本框都可以和表里面的一项绑定,请问在用evc开发access数据库中怎么部能用这个功能呢?…

查看全部问答>

关于示波器

   很高兴认识大家,敝司是专业生产示波器的产家,任何问题,欢迎来赐教!…

查看全部问答>

msp430郭天祥学习板例程

这是先前用的开发板的例程。蛮有意思,请多关照…

查看全部问答>

前天收到了【EEWORLD大学堂TI教室】的礼品,但不是LaunchPad

快递盒子是正方形扁盒子,拿到快递后想,LaunchPad的包装盒没这么薄吧? 打开一看是个TI的皮壳笔记本和一个TI的小包。 说好的LaunchPad呢? 是不是我没有被TI审核通过? TI可是每年要给咱学校提供赞助的啊。。。…

查看全部问答>

寻找经验丰富的无线射频工程师合作做项目

寻找经验丰富的 无线射频工程师 合作做项目!有意联系QQ:149464963,主要是1G以下的射频领域,没有相关经验的勿扰!谢谢!…

查看全部问答>