OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 14288|回复: 9

stm32通过spi驱动MB85RS2MT铁电,不能读出数据,请教原因?

[复制链接]

1

主题

1

帖子

0

精华

新手入门

积分
25
金钱
25
注册时间
2013-10-26
在线时间
0 小时
发表于 2013-11-2 23:15:29 | 显示全部楼层 |阅读模式
             先声明,本人是单片机菜鸟,请各位指点迷津。
现象:
用stm32的spi接口驱动铁电MB85RS2MT(此芯片兼容FM25H20),问题是用示波器能看到单片机有数据输出,但是我读不出任何数据,读出的都是0x00,不知道是什么原因,发帖求助。下面是我的代码,我会加注释的,方便大家查看。

系统时钟是72MHZ,芯片型号是STM32F103RE

#define FRAM_WREN_INST      0x06                //设置写使能
#define FRAM_WRDI_INST      0x04                //写禁止
#define FRAM_RDSR_INST      0x05                //读状态寄存器
#define FRAM_WRSR_INST      0x01                //写状态寄存器
#define FRAM_READ_INST      0x03                //读存储器数据
#define FRAM_WRITE_INST     0x02            //写存储器数据
#define FRAM_STATUS_REG     0x0                //
#define FRAM_INIT_STATE     0x09        //

//测试代码:
        SPI_write_FRAM('a',0x01); //向地址1写入字节'a'
        t = SPI_read_FRAM(0x01); //从地址1读出字节

结果: t永远是0,为什么啊?
      


void SPI_FRAM_Init(void)
{
    SPI_InitTypeDef  SPI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_SPI1, ENABLE);        

        GPIO_InitStructure.GPIO_Pin = FRAM_CS;  //SPI CS
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
         GPIO_Init(GPIOA, &GPIO_InitStructure);
         GPIO_SetBits(GPIOA,FRAM_CS);

        GPIO_InitStructure.GPIO_Pin = FRAM_SCK | FRAM_MISO | FRAM_MOSI;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
         GPIO_SetBits(GPIOA,FRAM_SCK|FRAM_MISO|FRAM_MOSI);

        GPIO_InitStructure.GPIO_Pin = FRAM_HOLD|FRAM_WP; 
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
         GPIO_Init(GPIOC, &GPIO_InitStructure);
         GPIO_SetBits(GPIOC,FRAM_HOLD|FRAM_WP);
    
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //设置SPI工作模式:设置为主SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                //选择了串行时钟的稳态:时钟悬空高
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //数据捕获于第二个时钟沿
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;                //定义波特率预分频的值:波特率预分频值为256
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
        SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
        SPI_Cmd(SPI1, ENABLE); //使能SPI外设
    delay_us(500);
}

u8 SPIx_WriteByte(u8 TxData)
{
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
    SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
    SPI_I2S_ReceiveData(SPI1);
    
}

u8 SPIx_ReadByte(u8 TxData)
{
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
    SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
    return SPI_I2S_ReceiveData(SPI1); 
}

void SPI_write_FRAM(u8 data,u16 address)//写入一个字节到特定地址空间
{
        u8 addr_tempH,addr_tempM,addr_tempL;
        addr_tempH = (u8)((address>>16)&0x000000ff);      //获取高8位地址
        addr_tempM = (u8)((address>>8)&0x000000ff);   //获取中8位地址
        addr_tempL = (u8)(address&0x000000ff);        //获取低8位地址
        FRAM_Reset_CS;
        SPIx_WriteByte(FRAM_WREN_INST);    //写使能
    FRAM_Set_CS;
    delay_us(100);

        FRAM_Reset_CS;
        SPIx_WriteByte(FRAM_WRITE_INST);   //写存储器寄存器操作码
        SPIx_WriteByte(addr_tempH);            //写入高八位地址,高6位忽略
        SPIx_WriteByte(addr_tempM);             //写入中八位地址
        SPIx_WriteByte(addr_tempL);            //
        SPIx_WriteByte(data);                  //写入数据
        FRAM_Set_CS;
}
        
u8 SPI_read_FRAM(u16 address)//读出特定地址空间的数据
{
        u8 dat,addr_tempH,addr_tempM,addr_tempL;
        addr_tempH = (u8)((address>>16)&0x000000ff);      //获取高8位地址
        addr_tempM = (u8)((address>>8)&0x000000ff);   //获取中8位地址
        addr_tempL = (u8)(address&0x000000ff);        //获取低8位地址
        FRAM_Reset_CS;
        SPIx_WriteByte(FRAM_READ_INST);      //读存储器寄存器操作码        
        SPIx_WriteByte(addr_tempH);
        SPIx_WriteByte(addr_tempM);             //写入中八位地址        
        SPIx_WriteByte(addr_tempL);
        dat=SPIx_ReadByte(0xa5);               //读取数据
        FRAM_Set_CS;
        return (dat);
}
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2015-6-8
在线时间
0 小时
发表于 2015-6-8 21:35:24 | 显示全部楼层
你好,我也是遇到同样的问题,请问你解决了吗,能分享一下吗,谢谢
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
80
金钱
80
注册时间
2015-7-3
在线时间
13 小时
发表于 2017-2-14 15:46:38 | 显示全部楼层
1.WP管教保持为高
2.要先设置状态寄存器
                MB_CS_L;
                SPIx_ReadWriteByte(0x06);                //读取状态寄存器
                MB_CS_H;
                //delay_ms(1);
                MB_CS_L;
                SPIx_ReadWriteByte(0x01);                //设置状态寄存器
                xy2 = SPIx_ReadWriteByte( 0x80 );
                MB_CS_H;

3.写入数据
                SPI_write_MB85RS256A(MR_DATA,MR_ADDR);       
4.读取数据
                ReadData=SPI_read_MB85RS256A(MR_ADDR);//

参考驱动程序:
fram.h
#ifndef __FRAM_H
#define __FRAM_H                            
//#include "stm32f10x.h"            
#include "stm32f10x_spi.h"     

#define MB85RS256A_WREN_INST  0x06                //设置写使能锁存器        //MB85RS256A寄存器定义
#define MB85RS256A_WRDI_INST  0x04                //写禁止
#define MB85RS256A_RDSR_INST  0x05                //读状态寄存器
#define MB85RS256A_WRSR_INST  0x01                //写状态寄存器
#define MB85RS256A_READ_INST  0x03                //读存储器数据
#define MB85RS256A_WRITE_INST 0x02                //写存储器数据
#define MB85RS256A_STATUS_REG 0x0                //
#define MB85RS256A_INIT_STATE 0x09                //
#define MB85RS256A_RDID_INST  0x9F                //读器件ID

#define MB_CS_L                GPIO_ResetBits(GPIOB,GPIO_Pin_11)
#define MB_CS_H                GPIO_SetBits(GPIOB,GPIO_Pin_11)
#define MB_CS                         GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_11)

#define MB_WP_L                GPIO_ResetBits(GPIOB,GPIO_Pin_12)
#define MB_WP_H                GPIO_SetBits(GPIOB,GPIO_Pin_12)
#define MB_WP                 GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_12)

#define MB_SCLK_L        GPIO_ResetBits(GPIOB,GPIO_Pin_13)
#define MB_SCLK_H        GPIO_SetBits(GPIOB,GPIO_Pin_13)
#define MB_MOSI_L        GPIO_ResetBits(GPIOB,GPIO_Pin_15)
#define MB_MOSI_H        GPIO_SetBits(GPIOB,GPIO_Pin_15)

void SPI_Fram_Init(void);
u8 SPIx_ReadWriteByte(u8 data);
void SPI_write_MB85RS256A(u8 data,u16 address);//写入一个字节到特定地址空间
u8 SPI_read_MB85RS256A(u16 address);//读出特定地址空间的数据
void MB85RS256A_WRITE(u16 add, u8 *buf, u16 len);
void MB85RS256A_READ(u16 add, u8 *buf, u16 len);
extern void delay(u32 i);
extern void delay_ms(u32 i);
#endif


fram.c
#include "fram.h"
/********************************************************
//project:STM32F1  SPI2读写MB85RS256A驱动代码  
//date:2015.10.12
//author:chenxuying
//annotation:适用铁电存储器mb85系列读写代码,直接读写一个字节
**********************************************************/
//初始化SPI2 FRAM的IO口
void SPI_Fram_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;  //SPI CS/HOLD
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;//PB14
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15);

        SPI_I2S_DeInit(SPI2);
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //设置SPI工作模式:设置为主SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                //选择了串行时钟的稳态:时钟悬空高
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //数据捕获于第二个时钟沿
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;        //定义波特率预分频的值:波特率预分频值为256
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
        SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
       
        SPI_Cmd(SPI2, ENABLE); //使能SPI外设
        SPIx_ReadWriteByte(0x00);//0x00,0xff,0xaa都行
}  

u8 SPIx_ReadWriteByte(u8 TxData)                           //SPI 发送接收字节
{
        u8 retry=0;                                        
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
        {
                retry++;
                if(retry>200)return 0;
        }                          
        SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
        retry=0;

        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
        {
                retry++;
                if(retry>200)return 0;
        }                                                              
        return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据       
}

void SPI_write_MB85RS256A(u8 data,u16 address)//写入一个字节到特定地址空间
{
        u8 addr_tempH,addr_tempL;
        addr_tempH = (u8)((address&0xff00)>>8);   //获取高8位地址
        addr_tempL = (u8)(address&0x00ff);        //获取低8位地址
        MB_CS_L;
        SPIx_ReadWriteByte(MB85RS256A_WREN_INST);    //写使能
        MB_CS_H;
//         delay(1000);
        MB_CS_L;
        SPIx_ReadWriteByte(MB85RS256A_WRITE_INST);   //写存储器寄存器操作吗
        SPIx_ReadWriteByte(addr_tempH);            //写入高八位地址,高3位忽略
        SPIx_ReadWriteByte(addr_tempL);            //
        SPIx_ReadWriteByte(data);                  //写入数据
        MB_CS_H;
//         MB_CS_L;
//         SPIx_ReadWriteByte(MB85RS256A_WRDI_INST);
//         MB_CS_H;
}

u8 SPI_read_MB85RS256A(u16 address)//读出特定地址空间的数据
{
        u8 dat,addr_tempH,addr_tempL;
        addr_tempH = (u8)((address&0xff00)>>8);
        addr_tempL = (u8)(address&0x00ff);
        MB_CS_L;
        SPIx_ReadWriteByte(MB85RS256A_READ_INST);      //读存储器寄存器操作码
        SPIx_ReadWriteByte(addr_tempH);
        SPIx_ReadWriteByte(addr_tempL);
        dat=SPIx_ReadWriteByte(0x00);               //读取数据,0xAA给予读取数据所需的时钟
        MB_CS_H;
        return (dat);
}

void MB85RS256A_WRITE(u16 add, u8 *buf, u16 len)
{
        MB_CS_L;
        SPIx_ReadWriteByte(MB85RS256A_WREN_INST);                   /* step 1 .  WEL = 1            */
        MB_CS_H;
//         delay(1000);
        MB_CS_L;
        SPIx_ReadWriteByte(MB85RS256A_WRITE_INST);
    SPIx_ReadWriteByte((u8)(add>>8));
    SPIx_ReadWriteByte((u8)(add));
    for (; len > 0; len--)
        {                                                                            /* step 4 . send out bytes      */
        SPIx_ReadWriteByte(*buf++);
        }
        MB_CS_H;
}

void MB85RS256A_READ(u16 add, u8 *buf, u16 len)
{       
        MB_CS_L;
        SPIx_ReadWriteByte(MB85RS256A_READ_INST);
    SPIx_ReadWriteByte((u8)(add>>8));
    SPIx_ReadWriteByte((u8)(add));
    for (;len > 0; len--)
        {
       *buf++ = (SPIx_ReadWriteByte(0x00));
        }
        MB_CS_H;
}




MB85RS16.zip

3.02 KB, 下载次数: 465

回复 支持 反对

使用道具 举报

1

主题

74

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2017-2-9
在线时间
19 小时
发表于 2017-2-15 09:42:06 | 显示全部楼层
楼上+1
回复 支持 反对

使用道具 举报

27

主题

118

帖子

0

精华

高级会员

Rank: 4

积分
845
金钱
845
注册时间
2015-12-8
在线时间
175 小时
发表于 2018-8-2 15:55:40 | 显示全部楼层
3楼正解,我之前读数据读出的都为0,是因为我写数据没有成功,主要原因是在发送写使能命令后没有将片选信号拉高再拉低
为自己掌握新的知识感到快乐
回复 支持 反对

使用道具 举报

12

主题

45

帖子

0

精华

初级会员

Rank: 2

积分
169
金钱
169
注册时间
2017-8-23
在线时间
45 小时
发表于 2020-11-3 14:12:46 | 显示全部楼层
请问:
                id1[0]=SPIx_ReadWriteByte( 0x9F );        //读ID
                id1[1]=SPIx_ReadWriteByte(0xa5);
                id1[2]=SPIx_ReadWriteByte(0xa5);
                id1[3]=SPIx_ReadWriteByte(0xa5);
                id1[4]=SPIx_ReadWriteByte(0xa5);
                id1[5]=SPIx_ReadWriteByte(0xa5);       
读ID读到的数据都是0,我用示波器看了MISO口是有波形的,是什么原因?
回复 支持 反对

使用道具 举报

0

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
132
金钱
132
注册时间
2020-8-5
在线时间
28 小时
发表于 2021-1-9 20:01:02 | 显示全部楼层
MB85RS用过spi模拟时序驱动过吗?最近在做这个,总是读不出数,求指教
回复 支持 反对

使用道具 举报

5

主题

56

帖子

0

精华

初级会员

Rank: 2

积分
121
金钱
121
注册时间
2018-7-27
在线时间
86 小时
发表于 2021-2-20 11:33:06 | 显示全部楼层
楼主有IIC接口的驱动代码吗
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2020-6-18
在线时间
3 小时
发表于 2021-10-19 14:25:57 | 显示全部楼层
吉双章 发表于 2021-1-9 20:01
MB85RS用过spi模拟时序驱动过吗?最近在做这个,总是读不出数,求指教

我也在做这个,用的模拟spi,总是写不进去
回复 支持 反对

使用道具 举报

4

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2016-1-11
在线时间
12 小时
发表于 2022-12-19 22:08:33 | 显示全部楼层
请问这个主程序应该写什么?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 19:44

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表