CH579的SPI使用问题

SPI0驱动FLASH芯片W25Q64,SPI1驱动TFT屏幕(驱动芯片ST7735),当使用SPI0对FLASH进行擦除、写入等动作时,SPI1引脚也会输出信号,但是使用SPI1对屏幕进行写操作SPI0引脚正常,不会跟随SPI1输出,各位路过的大佬们能否帮忙看下是什么问题。驱动源码如下:

/////////////////////////////////////////////////////////////分界线///////////////////////////////////////////////////////////////

SPI0驱动FLASH程序使用官方例程,将SPI1改为SPI0:

#include "SPIFlash.H"


/********************************* 引脚定义 ************************************

*    PA12  <===========>  SCS

*    PA13  <===========>  SCK

*    PA13  <===========>  DI/MOSI

*    PA15  <===========>  DO/MISO

*******************************************************************************/


#define  SPI0_CS_LOW()        GPIOA_ResetBits( GPIO_Pin_12 )

#define  SPI0_CS_HIGH()       GPIOA_SetBits( GPIO_Pin_12 )


/*******************************************************************************

* Function Name  : ReadExternalFlashStatusReg_SPI

* Description    : 用来读取状态寄存器,并返回状态寄存器的值

* Input          : None

* Output         : None

* Return         : ExFlashRegStatus

*******************************************************************************/

UINT8 ReadExternalFlashStatusReg_SPI( void )

{

    UINT8 ExFlashRegStatus;

    

    

    SPI0_CS_LOW();

    SPI0_MasterSendByte( CMD_STATUS1 );                                          //发送读状态寄存器的命令

    ExFlashRegStatus = SPI0_MasterRecvByte();                                    //读取状态寄存器

    SPI0_CS_HIGH();

    

    return ExFlashRegStatus;

}


/*******************************************************************************

* Function Name  : WaitExternalFlashIfBusy

* Description    : 等待芯片空闲(在执行Byte-Program, Sector-Erase, Block-Erase, Chip-Erase操作后)

* Input          : None

* Output         : None

* Return         : None

*******************************************************************************/

void WaitExternalFlashIfBusy( void )

{

    while ((ReadExternalFlashStatusReg_SPI())&0x01 == 0x01 )

    {

        ;    //等待直到Flash空闲

    }

}

/*******************************************************************************

* Function Name  : WriteExternalFlashEnable_SPI

* Description    : 写使能,同样可以用于使能写状态寄存器

* Input          : None

* Output         : None

* Return         : None

*******************************************************************************/

void WriteExternalFlashEnable_SPI( void )

{

    SPI0_CS_LOW();

    SPI0_MasterSendByte( CMD_WR_ENABLE );                                        //发送写使能命令

    SPI0_CS_HIGH();

}

/*******************************************************************************

* Function Name  : EraseExternal4KFlash_SPI

* Description    : 擦除4K Flash  擦除一个扇区

* Input          : Dst_Addr 0-1 ffff ffff ,清除任意地址所在的扇区。

* Output         : None

* Return         : None

*******************************************************************************/

//擦除一个扇区

//Dst_Addr:扇区地址 0~2047*1024*4 for w25q64

//擦除一个扇区的最少时间:150ms

void EraseExternal4KFlash_SPI( UINT32 Dst_Addr )

{

Dst_Addr*=4096;

    WriteExternalFlashEnable_SPI();

    WaitExternalFlashIfBusy();

    

    SPI0_CS_LOW();

    SPI0_MasterSendByte(CMD_ERASE_4KBYTE);                                    //扇区擦除命令

    SPI0_MasterSendByte(((Dst_Addr & 0xFFFFFF) >> 16));                       //发送3字节地址

    SPI0_MasterSendByte(((Dst_Addr & 0xFFFF) >> 8));

    SPI0_MasterSendByte(Dst_Addr & 0xFF);

    SPI0_CS_HIGH();

    

    WaitExternalFlashIfBusy();

}

/*******************************************************************************

* Function Name  : EraseExternalFlash_SPI

* Description    : 擦除32K Flash  擦除一个扇区

* Input          : Dst_Addr 0-1 ffff ffff ,清除任意地址所在的扇区。

* Output         : None

* Return         : None

*******************************************************************************/

void EraseExternal32KFlash_SPI( UINT32 Dst_Addr )

{

    WriteExternalFlashEnable_SPI();

    WaitExternalFlashIfBusy();

    

    SPI0_CS_LOW();

    SPI0_MasterSendByte(CMD_ERASE_32KBYTE);                                    //32K擦除命令

    SPI0_MasterSendByte(((Dst_Addr & 0xFFFFFF) >> 16));                        //发送3字节地址

    SPI0_MasterSendByte(((Dst_Addr & 0xFFFF) >> 8));

    SPI0_MasterSendByte(Dst_Addr & 0xFF);

    SPI0_CS_HIGH();

    

    WaitExternalFlashIfBusy();

}

/*******************************************************************************

* Function Name  : PageWriteExternalFlash_SPI

* Description    : 页写;SPI在一页(0~65535)内写入少于256个字节的数据

* Input          : RcvBuffer:数据存储区

*                  StarAddr:开始写入的地址

*                  Len:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!

* Output         : None

* Return         : None

*******************************************************************************/

void PageWriteExternalFlash_SPI(UINT32 StarAddr,UINT16 Len,PUINT8 RcvBuffer)

{

    UINT16 i;

    

    WriteExternalFlashEnable_SPI();                                            //SET WEL

    

    SPI0_CS_LOW();                                                            

    SPI0_MasterSendByte(CMD_PAGE_PROG);                                        //发送写页命令

    SPI0_MasterSendByte(((StarAddr & 0xFFFFFF) >> 16));                        //发送24bit地址

    SPI0_MasterSendByte(((StarAddr & 0xFFFF) >> 8));

    SPI0_MasterSendByte(StarAddr & 0xFF);

    for(i=0; i!=Len; i++)

    {

        SPI0_MasterSendByte(RcvBuffer[i]);    //循环写数

    }

    SPI0_CS_HIGH();

    

    WaitExternalFlashIfBusy();                                                 //等待写入结束

}

/*******************************************************************************

* Function Name  : BlukWriteExternalFlash_SPI

* Description    : 无检验写SPI FLASH

*                  必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!

*                  具有自动换页功能

*                  在指定地址开始写入指定长度的数据,但是要确保地址不越界!

* Input          : SendBuffer:数据存储区

*                  StarAddr:开始写入的地址

*                  Len:要写入的字节数(最大65535)

* Output         : None

* Return         : None

*******************************************************************************/

void BlukWriteExternalFlash_SPI(UINT32 StarAddr,UINT16 Len,PUINT8 SendBuffer)

{

    UINT16  pageremain;

    

    pageremain = 256-StarAddr%256;                                               //单页剩余的字节数

    if(Len<=pageremain)

    {

        pageremain=Len;    //不大于256个字节

    }

    while(1)

    {

        PageWriteExternalFlash_SPI(StarAddr,pageremain,SendBuffer);

        if(Len==pageremain)

        {

            break;    //写入结束了

        }

        else

        {

            SendBuffer+=pageremain;

            StarAddr+=pageremain;

            Len-=pageremain;                                                   //减去已经写入了的字节数

            if(Len>256)

            {

                pageremain=256;    //一次可以写入256个字节

            }

            else

            {

                pageremain=Len;    //不够256个字节了

            }

        }

    }

}

/*******************************************************************************

* Function Name  : ReadExternalFlash_SPI

* Description    : 读取地址的数据.

*******************************************************************************/

void ReadExternalFlash_SPI( UINT32 StarAddr, UINT16 Len, PUINT8 RcvBuffer )

{    

    SPI0_CS_LOW();                                                      

    SPI0_MasterSendByte(CMD_READ_DATA);                                 //读命令

    SPI0_MasterSendByte(((StarAddr & 0xFFFFFF) >> 16));                 //发送3字节地址

    SPI0_MasterSendByte(((StarAddr & 0xFFFF) >> 8));

    SPI0_MasterSendByte(StarAddr & 0xFF);

    SPI0_MasterRecv( RcvBuffer, Len );

    SPI0_CS_HIGH();

}

/*******************************************************************************

* Function Name  : BlukReadExternalFlash_SPI

* Description    : 读取起始地址(StarAddr)内多个字节(Len)的数据.存入缓冲区RcvBuffer中

* Input          : StarAddr -Destination Address 000000H - 1FFFFFH

                   Len 读取数据长度

                   RcvBuffer 接收缓冲区起始地址

* Output         : None

* Return         : None

*******************************************************************************/

void BlukReadExternalFlash_SPI( UINT32 StarAddr, UINT16 Len, PUINT8 RcvBuffer )

{    

    SPI0_CS_LOW();

    SPI0_MasterSendByte(CMD_FAST_READ);                                 //高速度

    SPI0_MasterSendByte(((StarAddr & 0xFFFFFF) >> 16));                 //发送3字节地址

    SPI0_MasterSendByte(((StarAddr & 0xFFFF) >> 8));

    SPI0_MasterSendByte(StarAddr & 0xFF);

    SPI0_MasterSendByte(0x00);    

    SPI0_MasterRecv( RcvBuffer, Len );

    SPI0_CS_HIGH();

}

/*******************************************************************************

* Function Name  : SPIFlash_ReadID

* Description    : SPI Flash读取芯片ID

* Input          : None

* Output         : None

* Return         : 0XEF13,表示芯片型号为W25Q08

*                  0XEF14,表示芯片型号为W25Q16

*                  0XEF15,表示芯片型号为W25Q32

*                  0XEF16,表示芯片型号为W25Q64

*                  0XEF17,表示芯片型号为W25Q128

*******************************************************************************/

UINT16 SPIFlash_ReadID(void)

{

    UINT16  temp = 0;

    

    SPI0_CS_LOW();

    SPI0_MasterSendByte(CMD_DEVICE_ID);                    //读取ID命令

    SPI0_MasterSendByte(0x00);

    SPI0_MasterSendByte(0x00);

    SPI0_MasterSendByte(0x00);

    temp = SPI0_MasterRecvByte();

    temp = temp<<8;

    temp |= SPI0_MasterRecvByte();

    SPI0_CS_HIGH();

    

    return temp;

}

/*******************************************************************************

* Function Name  : SPI0Flash_Init

* Description    : SPI Flash初始化

* Input          : None

* Output         : None

* Return         : None

*******************************************************************************/

void SPIFlash_Init(void)

{

GPIOA_SetBits( GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14 );

GPIOA_ModeCfg( GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14, GPIO_ModeOut_PP_5mA );// MOSI/SCK/CS

GPIOA_SetBits( GPIO_Pin_15 );

GPIOA_ModeCfg( GPIO_Pin_15, GPIO_ModeIN_PU );// MISO

    SPI0_MasterDefInit();

    SPI0_DataMode( Mode3_HighBitINFront );

    SPI0_CLKCfg( 4 );

    printf("id:0x%04x\n", SPIFlash_ReadID() );

}


/////////////////////////////////////////////////////////////分界线///////////////////////////////////////////////////////////////

SPI1是手搓的TFT驱动程序:

#include "ST7735.H"


//RESETPB3

//RSPB5

//SDAPA1

//SCLPA0

//CS        PB6


uint16_t BG_Color=WHITE;


void LCD_GPIO_Init(void)

{

GPIOA_ModeCfg(GPIO_Pin_0|GPIO_Pin_1, GPIO_ModeOut_PP_5mA);

GPIOB_ModeCfg(GPIO_Pin_3|GPIO_Pin_5|GPIO_Pin_6, GPIO_ModeOut_PP_5mA);

}


void LCD_Reset(void)

{

GPIOB_ResetBits(GPIO_Pin_3);//拉低RST

mDelaymS(20);

GPIOB_SetBits(GPIO_Pin_3);//拉高RST

mDelaymS(20);

}


void LCD_Write_REG(uint8_t Com)

{

GPIOB_ResetBits(GPIO_Pin_6);//片选

GPIOB_ResetBits(GPIO_Pin_5);//拉低->命令

SPI1_MasterSendByte(Com);//发送命令

GPIOB_SetBits(GPIO_Pin_6);//取消片选

}


void LCD_Write_Byte(uint8_t Data)

{

GPIOB_ResetBits(GPIO_Pin_6);//片选

GPIOB_SetBits(GPIO_Pin_5);//拉高->数据

SPI1_MasterSendByte(Data);//发送数据

GPIOB_SetBits(GPIO_Pin_6);//取消片选

}


void LCD_Write_Data(uint16_t Data)

{

LCD_Write_Byte(Data>>8);

LCD_Write_Byte(Data);

}


测试SPI0输出时不会影响到SPI1的输出;能够使用逻辑分析仪抓一下波形贴出来看一下。

可以将将程序发送到rzz@wch.cn实测一下。

image.png


已发送程序到大佬你的邮箱了,麻烦有空的时候帮忙看下,谢谢。


只有登录才能回复,可以选择微信账号登录