野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 20962|回复: 4

SPI FLASH例程,无法发送数据

[复制链接]
发表于 2021-8-8 16:21:28 | 显示全部楼层 |阅读模式
我用的板子是原子的,用的是SPI2口,FLASH是W25Q128。按照视频的代码写了读取JEDEC ID的程序,但是结果是总是出现ERROR0,那应该是发送数据时没有收到SPI2的TXE的信号。看了一天的程序了,也没找出原因,程序如下,请大神帮我看看

bsp_spi.h
#ifndef __SPI_FLASH_H
#define        __SPI_FLASH_H

#include "stm32f10x.h"
#include "stm32f10x_spi.h"

/********************SPI参数定义********************/
#define        FLASH_SPIx                                                                                SPI2
#define FLASH_SPI_APBxClock_Cmd                                RCC_APB1PeriphClockCmd
#define FLASH_SPI_CLK                                                                        RCC_APB1Periph_SPI2
#define FLASH_SPI_GPIO_APBxCLock_Cmd        RCC_APB2PeriphClockCmd
#define FLASH_SPI_GPIO_CLK                                                RCC_APB2Periph_GPIOB

#define FLASH_SPI_MISO_PORT                                                GPIOB
#define FLASH_SPI_MISO_PIN                                                GPIO_Pin_14
#define FLASH_SPI_MOSI_PORT                                                GPIOB
#define FLASH_SPI_MOSI_PIN                                                GPIO_Pin_15
#define FLASH_SPI_SCK_PORT                                                GPIOB
#define FLASH_SPI_SCK_PIN                                                        GPIO_Pin_13
#define FLASH_SPI_CS_PORT                                                        GPIOB
#define FLASH_SPI_CS_PIN                                                        GPIO_Pin_12

/* SPI分频因子 */
#define FLASH_SPI_BaudRatePrescaler   SPI_BaudRatePrescaler_2
/* SPI模式3,时钟极性1,时钟相位1 */
#define FLASH_SPI_Clock_Phase                                        SPI_CPHA_2Edge
#define FLASH_SPI_Clock_Polarity                        SPI_CPOL_High
/* 不适用CRC校验 */
#define FLASH_SPI_CRCPolynomial                                0
#define FLASH_SPI_DataSize                                                SPI_DataSize_8b
#define FLASH_SPI_data_direction_mode        SPI_Direction_2Lines_FullDuplex
#define FLASH_SPI_MSB_LSB_transmission         SPI_FirstBit_MSB
#define FLASH_SPI_master_slave_mode                SPI_Mode_Master
#define FLASH_SPI_Slave_Select_management        SPI_NSS_Soft

/* 定义超时时间 */
#define SPI_FLAG_TIMEOUT                               ((uint32_t)0x1000)
#define SPI_LONG_TIMEOUT                               ((uint32_t)(10*SPI_FLAG_TIMEOUT))

#define DUMMY                                                                                                0x00
#define READ_JEDEC_ID                                                                0x9f

/* SPI片选信号CS控制 */
#define FLASH_SPI_CS_HIGH()                                        GPIO_SetBits(FLASH_SPI_CS_PORT,FLASH_SPI_CS_PIN)
#define FLASH_SPI_CS_LOW()                                        GPIO_ResetBits(FLASH_SPI_CS_PORT,FLASH_SPI_CS_PIN)

/* 信息输出 */
#define SPI_FLASH_DEBUG_ON                                               0

#define SPI_FLASH_INFO(fmt,arg...)       printf("<<-SPI_FLASH-INFO->>"fmt"\n",##arg)       
#define SPI_FLASH_ERROR(fmt,arg...)      printf("<<-SPI_FLASH-ERROR->>"fmt"\n",##arg)       
#define SPI_FLASH_DEBUG(fmt,arg...)      do{\
                                                                                                                                                if(EEPROM_DEBUG_ON)\
                                                                                                                                                printf("<<-SPI_FLASH-DEBUG->>[%d]"fmt"\n",__LINE__,##arg);\
                                                                                                                                                }while(0)

void SPI_FLASH_Init(void);
void SPI2_Init(void);
uint32_t SPI_Read_Device_ID(void);
                                                                                                                                               
#endif /* __SPI_FLASH_H */


bsp_spi.c

#include "bsp_spi.h"
#include "bsp_usart.h"

static uint32_t SPI_Timeout;
static uint32_t SPI_FLASH_TIMEOUT_UserCallback(uint8_t errorCode);

/*
* 函数名:SPI_FLASH_GPIO_Config
* 描述  :SPI1 I/O配置
* 输入  :无
* 输出  :无
* 调用  :内部调用
*/

static void SPI_FLASH_GPIO_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

        /* 使能与SPI2有关的时钟 */
        FLASH_SPI_GPIO_APBxCLock_Cmd(FLASH_SPI_GPIO_CLK,ENABLE);
  FLASH_SPI_APBxClock_Cmd(FLASH_SPI_CLK,ENABLE);  

  /* PB15-SPI_MOSI*/
  GPIO_InitStructure.GPIO_Pin =  FLASH_SPI_MOSI_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;               // 复用推挽输出
  GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStructure);
       
          /* PB13-SPI_SCK*/
  GPIO_InitStructure.GPIO_Pin =  FLASH_SPI_SCK_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;               // 复用推挽输出
  GPIO_Init(FLASH_SPI_SCK_PORT, &GPIO_InitStructure);
       
         /* PB14-SPI_MIS0*/
  GPIO_InitStructure.GPIO_Pin =  FLASH_SPI_MISO_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;         // 浮空输入
  GPIO_Init(FLASH_SPI_MISO_PORT, &GPIO_InitStructure);
       
         /* PB12-SPI_CS*/
  GPIO_InitStructure.GPIO_Pin =  FLASH_SPI_CS_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;             // 通用推挽输出
  GPIO_Init(FLASH_SPI_CS_PORT, &GPIO_InitStructure);
       
        FLASH_SPI_CS_HIGH();
}

/*
* 函数名:SPI_Configuration
* 描述  :SPI 工作模式配置
* 输入  :无
* 输出  :无
* 调用  :内部调用
*/
static void SPI_Mode_Config(void)
{
  SPI_InitTypeDef  SPI_InitStructure;

  /* SPI 配置 */
  SPI_InitStructure.SPI_BaudRatePrescaler = FLASH_SPI_BaudRatePrescaler;
  SPI_InitStructure.SPI_CPHA                                                        = FLASH_SPI_Clock_Phase;
        SPI_InitStructure.SPI_CPOL                                                        = FLASH_SPI_Clock_Polarity;
        SPI_InitStructure.SPI_CRCPolynomial                        = FLASH_SPI_CRCPolynomial;
        SPI_InitStructure.SPI_DataSize                                        = FLASH_SPI_DataSize;
        SPI_InitStructure.SPI_Direction                                        = FLASH_SPI_data_direction_mode;
        SPI_InitStructure.SPI_FirstBit                                        = FLASH_SPI_MSB_LSB_transmission;
        SPI_InitStructure.SPI_Mode                                                        = FLASH_SPI_master_slave_mode;
        SPI_InitStructure.SPI_NSS                                                                = FLASH_SPI_Slave_Select_management;
       
  /* SPI2 初始化 */
  SPI_Init(FLASH_SPIx, &SPI_InitStructure);
       
  /* 使能 SPI */
  SPI_Cmd(FLASH_SPIx, ENABLE);
}

/*
* 函数名:SPI_FLASH_Init
* 描述  :SPI外设FLASH初始化
* 输入  :无
* 输出  :无
* 调用  :外部调用
*/

void SPI_FLASH_Init(void)
{
  SPI_FLASH_GPIO_Config();
  SPI_Mode_Config();
}

//发送一个字节
uint8_t SPI_FLASH_Write_Read_Byte(uint8_t data)
{
        //超时设置为1000
        SPI_Timeout = SPI_FLAG_TIMEOUT;
        //等待检查TXE发送寄存器为空
        while(SPI_I2S_GetITStatus(FLASH_SPIx, SPI_I2S_IT_TXE)==RESET)
        {
                if((SPI_Timeout--)==0)        return SPI_FLASH_TIMEOUT_UserCallback(0);
        }
       
        //发送数据
        SPI_I2S_SendData(FLASH_SPIx, data);

        //超时设置为1000
        SPI_Timeout = SPI_FLAG_TIMEOUT;
        //等待检查TXE接收寄存器为非空
        while(SPI_I2S_GetITStatus(FLASH_SPIx, SPI_I2S_IT_RXNE)==RESET)
        {
                if((SPI_Timeout--)==0)        return SPI_FLASH_TIMEOUT_UserCallback(1);
        }
       
        //返回接收的数据
        return SPI_I2S_ReceiveData(FLASH_SPIx);
}

//接收一个字节
uint8_t SPI_FLASH_ReadByte(void)
{
return SPI_FLASH_Write_Read_Byte(DUMMY);
}

//读取FLASH的Manufacturer/Device ID
uint32_t SPI_Read_Device_ID(void)
{
        uint32_t JEDEC_ID=0;
       
        //选中FLASH片选信号
        FLASH_SPI_CS_LOW();
       
        SPI_FLASH_Write_Read_Byte(READ_JEDEC_ID);
       
        JEDEC_ID = SPI_FLASH_Write_Read_Byte(DUMMY);
       
        JEDEC_ID <<= 8;
       
        JEDEC_ID |= SPI_FLASH_Write_Read_Byte(DUMMY);
       
        JEDEC_ID <<= 8;
       
        JEDEC_ID |= SPI_FLASH_Write_Read_Byte(DUMMY);
       
        FLASH_SPI_CS_HIGH();
       
        return JEDEC_ID;
}

/*
* 函数名:SPI_FLASH_TIMEOUT_UserCallback
* 描述  :basic management of timeout situation
* 输入  :errorCode:错误代码可以用来定位是哪个环节出错
* 输出  :无
* 返回  :返回0表示SPI_FLASH读取失败
* 调用  :
*/
static uint32_t SPI_FLASH_TIMEOUT_UserCallback(uint8_t errorCode)
{
        SPI_FLASH_ERROR("SPI等待超时!errorCode=%d",errorCode);
       
        return 0;
}
/******************** (C) COPYRIGHT 2011 迷你嵌入式开发工作室 ********************/

main.c

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "core_cm3.h"
#include "stdint.h"
#include "system_stm32f10x.h"
#include "bsp_key.h"
#include "bsp_led.h"
#include "bsp_led.h"
#include "bsp_rccclkconfig.h"
#include "bsp_exti.h"
#include "bsp_systick.h"
#include "bsp_usart.h"
#include "bsp_spi.h"

int main(void)
{
        uint32_t FlashID;
       
        //时钟配置为72M
        HSE_SetSysClk(RCC_PLLMul_9);
       
        //串口初始化
        USART_Config();       

        //SPI_FLASH_Init();
       
        printf("这是一个SPI_FLASH试验\n");
       
        FlashID = SPI_Read_Device_ID();
       
        printf("\nFlash device ID=0x%x\n",FlashID);
       
        while(1)
        {
        }
}       


回复

使用道具 举报

发表于 2021-8-9 16:40:02 | 显示全部楼层
最好先用逻辑分析仪看一下波形哪里不对。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-13 22:00:13 | 显示全部楼层
hansome 发表于 2021-8-9 16:40
最好先用逻辑分析仪看一下波形哪里不对。

没有这么高级的工具呀,我就在家自学的,只有一个开发版
回复 支持 反对

使用道具 举报

发表于 2021-8-14 09:00:04 | 显示全部楼层
mecca7aa 发表于 2021-8-13 22:00
没有这么高级的工具呀,我就在家自学的,只有一个开发版

现在网上的逻辑分析仪也就两百多。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-15 12:40:21 | 显示全部楼层
已解决
回复

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-28 06:10 , Processed in 0.039185 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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