sdfan2002 发表于 2025-7-9 23:59:20

8G1K08的SPI读写串口psram

<p>采用软件或硬件SPI方式读写串口psram,最近想用串口psram当显示屏的缓存,买了乐鑫psram64h和来扬LY68L6400芯片进行测试,用SPI方式读写成功,代码如下:</p>
<p>主代码文件:main.c</p>
//
//PSRAM演示程序,采用普通SPI功能读写芯片,编译时定义 HARDWARE_SPI,则使用硬件SPI功能
//否则使用软件模拟SPI,读写芯片
//    # psram id:0x0D5D-46A02A547A67--PSRAM64H,SPI模式2、模式3测试能成功
//    # psram id:0x0D5D-5312A4D13899--LY68L6400SLI,SPI模式0、模式3测试能成功
#include "sysdef.h"
#define BUFSIZE 256
unsigned char Device_ID = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char xdata test_buf;
u32 systick = 0;
sbit LED = P5^4;
void Print_Drive_ID(void);
void Timer0_Init(void);
// 主函数
void main(void)
{   
    unsigned int i;
    unsigned long addr = 0;
   
    P1M1 = 0x00;   P1M0 = 0x00;
    P2M1 = 0x00;   P2M0 = 0x00;
    P3M0 = 0x80;   P3M1 = 0x00; //P3.7设置为推挽输出,用于PSRAM启动供电
    P4M1 = 0x00;   P4M0 = 0x00;
    P5M1 = 0x00;   P5M0 = 0x00;

    P1PU = 0xff;   P3PU = 0xff;

    Uart1_Init();
    Timer0_Init();
    EA = 1;
    printf("uart init.\r\n");
    Delay_ms(50);
    printf("[%ldms]:Psram Init.\r\n",systick);
    PSRAM_Init();
    PSRAM_ReadID(Device_ID,8);
    Delay_ms(1);
    PSRAM_ReadID(Device_ID,8);
    Delay_ms(1);
    printf("[%ldms]:Psram Init OK.\r\n",systick);

    while(1)
    {      
#if defined(HARDWARE_SPI)
      printf("<<<<***********   USING HARDWARE SPI   *************>>>>\r\n");
      printf("SPI PIN--CS(P1.0), MOSI(P3.4), MISO(P3.3), SCLK(P3.2)\r\n");
#else
      printf("<<<<***************   USING SOFT SPI    ************>>>>\r\n");
      printf("SOFT-SPI PIN--CS(P1.0), MOSI(P3.6), MISO(P1.1), SCLK(P3.5)\r\n");
#endif
      PSRAM_ReadID(Device_ID,8);
      printf("PSRAM64H ID: ");
      Print_Drive_ID();      
      for(i = 0; i < 8;i++)
            Device_ID = 0;
      printf("\r\n");
      printf("[ %ld ms]:Write Data to psram. Addr:%#lx.\r\n",systick,addr);
      for(i = 0; i < sizeof(test_buf); i++)
            test_buf = i;
      PSRAM_Write(addr,test_buf,sizeof(test_buf));
      printf("[ %ld ms]:Write Psram finish.\r\n",systick);
      Delay_ms(1);
      printf("[ %ld ms]:Clear cache.\r\n",systick);
      for(i = 0; i < sizeof(test_buf); i++)
            test_buf = 0;
      printf("[ %ld ms]:Start Read Psram Data.\r\n",systick);
      PSRAM_Read(addr,test_buf,sizeof(test_buf));      

      
      printf("<<<<*****************   READ DATA   *****************>>>>\r\n");
      for(i = 0; i < sizeof(test_buf); i++){
            PrintLong2Str(addr);
            PrintHex2Str(test_buf);PrintHex2Str(test_buf);PrintHex2Str(test_buf);PrintHex2Str(test_buf);
            PrintHex2Str(test_buf);PrintHex2Str(test_buf);PrintHex2Str(test_buf);PrintHex2Str(test_buf);
            PrintHex2Str(test_buf);PrintHex2Str(test_buf);PrintHex2Str(test_buf);PrintHex2Str(test_buf);
            PrintHex2Str(test_buf);PrintHex2Str(test_buf);PrintHex2Str(test_buf);PrintHex2Str(test_buf);
            addr+= 16;
            printf("\r\n");
      }
      printf("[ %ld ms]:Read Psram finish.\r\n",systick);
      Delay_ms(1000);
    }
}
void Print_Drive_ID(void){
    PrintHex2Str(Device_ID);
    PrintHex2Str(Device_ID);
    PrintHex2Str(Device_ID);
    PrintHex2Str(Device_ID);
    PrintHex2Str(Device_ID);
    PrintHex2Str(Device_ID);
    PrintHex2Str(Device_ID);
    PrintHex2Str(Device_ID);
}

void Timer0_Isr(void) interrupt 1
{
    systick++;
    if(systick % 500 == 0)
      LED = !LED;
}

void Timer0_Init(void)                //1毫秒@24.000MHz
{
      AUXR |= 0x80;                        //定时器时钟1T模式
      TMOD &= 0xF0;                        //设置定时器模式
      TL0 = 0x40;                              //设置定时初始值
      TH0 = 0xA2;                              //设置定时初始值
      TF0 = 0;                              //清除TF0标志
      TR0 = 1;                              //定时器0开始计时
      ET0 = 1;                              //使能定时器0中断
}<p>spi.c文件</p>
#include "spi.h"
#if defined(HARDWARE_SPI)

    #define SPIF 0x80
    #define WCOL 0x40
    #define SSIG 0x80
    #define SPEN 0x40
    #define DORD 0x20
    #define MSTR 0x10

    void SPI_Init(void){      
      P_SW1 |= 0x0c;                //SPI: SS(P3.5), MOSI(P3.4), MISO(P3.3), SCLK(P3.2)
      SPCTL = 0x9C;   //SSIG=1,SPEN=0,DORD=0,MSTR=1,CPOL=0,CPHA=0,SPR=00b
      SPCTL |= SPI_MODE<<2;
      SPSTAT = 0xC0;//SPIF、WCOL写1清空
      SPCTL |= SPEN;//使能硬件SPI
    }
   
    u8 SPI_ReadWrite(u8 dat){
      SPDAT = dat;
      while(!(SPSTAT & SPIF));
      SPSTAT = 0xC0;
      return SPDAT;
    }

#else
    void SPI_Init(void){
      CS = 1;
      MOSI = 1;
      MISO = 1;
      CLK = S_CPOL;
    }

    u8 SPI_ReadWrite(u8 dat){
      u8 rst = 0;
      u8 i;
      for(i = 0; i < 8; i++){
    #if (S_CPHA)      //数据前沿驱动后沿采样
      {
            CLK = !S_CPOL;
            MOSI = (bit)(dat & 0x80);
            dat <<= 1;
            CLK = S_CPOL;
            rst <<= 1;
            rst |= MISO;      
      }
    #else            //数据前沿采样后沿驱动
      {
            MOSI = (bit)(dat & 0x80);
            dat <<= 1;
            CLK = !S_CPOL;
            rst <<= 1;
            rst |= MISO;
            CLK = S_CPOL;
      }
    #endif   
      }
      return rst;
    }
#endif<p>uart.c文件</p>
#include "uart.h"
bit serial_busy;
char wptr;
char rptr;
char buffer;

void Uart1_Isr(void) interrupt 4
{
      if (TI)                              //检测串口1发送中断
      {
                TI = 0;                        //清除串口1发送中断请求位
      serial_busy = 0;
      }
      if (RI)                              //检测串口1接收中断
      {
                RI = 0;                        //清除串口1接收中断请求位
      buffer = SBUF;
      wptr &= 0x0F;
      }
}

void Uart1_Init(void)      //115200bps@24.000MHz
{
      SCON = 0x50;                //8位数据,可变波特率
      AUXR |= 0x01;                //串口1选择定时器2为波特率发生器
      AUXR |= 0x04;                //定时器时钟1T模式
      T2L = 0xCC;                        //设置定时初始值
      T2H = 0xFF;                        //设置定时初始值
      AUXR |= 0x10;                //定时器2开始计时
      ES = 1;                              //使能串口1中断
}

void UartSend(char dat)
{
    while (serial_busy);
    serial_busy = 1;
    SBUF = dat;
}

char putchar(char c){
    UartSend(c);
    return c;
}

void PrintHex2Str(unsigned char dat){
    unsigned char i,j;
    i = (dat & 0xF0)>>4;
    j = dat & 0x0F;
    if(i >= 0 && i <=9)
      i += '0';
    else if(i >= 10 && i <= 15)
      i = i - 10 + 'A';
    if(j >= 0 && j <=9)
      j += '0';
    else if(j >= 10 && j <= 15)
      j = j - 10 + 'A';
    UartSend(i);
    UartSend(j);
    UartSend(' ');
}
void PrintLong2Str(long addr){
    unsigned char dat,i,j;
    dat = (addr >> 16) & 0xFF;
    i = (dat & 0xF0)>>4;
    j = dat & 0x0F;
    if(i >= 0 && i <=9)
      i += '0';
    else if(i >= 10 && i <= 15)
      i = i - 10 + 'A';
    if(j >= 0 && j <=9)
      j += '0';
    else if(j >= 10 && j <= 15)
      j = j - 10 + 'A';
    UartSend(i);
    UartSend(j);
   
    dat = (addr >> 8) & 0xFF;
    i = (dat & 0xF0)>>4;
    j = dat & 0x0F;
    if(i >= 0 && i <=9)
      i += '0';
    else if(i >= 10 && i <= 15)
      i = i - 10 + 'A';
    if(j >= 0 && j <=9)
      j += '0';
    else if(j >= 10 && j <= 15)
      j = j - 10 + 'A';
    UartSend(i);
    UartSend(j);
   
    dat = addr & 0xFF;
    i = (dat & 0xF0)>>4;
    j = dat & 0x0F;
    if(i >= 0 && i <=9)
      i += '0';
    else if(i >= 10 && i <= 15)
      i = i - 10 + 'A';
    if(j >= 0 && j <=9)
      j += '0';
    else if(j >= 10 && j <= 15)
      j = j - 10 + 'A';
    UartSend(i);
    UartSend(j);
    UartSend(' ');UartSend(' ');UartSend(' ');UartSend(' ');
}



页: [1]
查看完整版本: 8G1K08的SPI读写串口psram