基于STM32单片机的64Mbit单对单通信

简单的一种应用,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

基于WS2812B定制的天花板屏幕
ARM/高通/华为组建CCIX联盟 共推处理器架构
智能魔镜,让生活更有温度
电能表应用常见问题有哪些
苹果发布Apple Watch 4,开启可穿戴设备的里程碑
基于STM32单片机的64Mbit单对单通信
mc145027的应用电路
如何将废旧PCB印刷线路板会回收再利用
台积电称美国半导体供应链不完整
MAX9938增益误差小于0.5%、1µA、4焊
电连接器的分类种别
一位IT工程师写给四年前自己的信
探测传感器:一个解决了挪威电力耗能问题且每周省下了8成用电量的传感器!
智能制造趋势不可挡 中国或成全球最大的机器人市场
华为助力爱奇艺完成了5G MEC+CDN的边缘加速业务验证
华为mate9怎么样?华为mate9和华为P10评测对比,颜值与性能神形俱在,你怎么选?
一文读尽对开关电源EMI的等效分析
超声流量计的原理及设计
用勤哲Excel服务器无代码实现通讯企业管理系统
NTC热敏电阻相关推文回顾