神农鼎 发表于 2024-4-8 09:06:04

SPI从机,你用
STC32/STC8H/STC8G/STC8C/STC8A/STC12H1K16
我们有完善的从机演示程序






晓飛飛 发表于 2024-4-8 13:44:25

SPI有四种时序,看看是不是前后沿问题,导致多出一位

虹涛犹珷 发表于 2024-4-8 13:44:46

神农鼎 发表于 2024-4-8 09:06
SPI从机,你用
STC32/STC8H/STC8G/STC8C/STC8A/STC12H1K16
我们有完善的从机演示程序


您好,我移植ISP软件上面的SPI程序,丛机终于可以返回正确的数据了,但是还有个问题,如果丛机的中断里面的操作稍微有延时,就会导致SPI丢失数据,按道理这个现象可以避免的,一时不知道如何操作了。


这是丛机的程序:

//**************************主函数**********************//
data uint8_t Flag = 0;
data uint16_t Addr = 0;
void main(void)
{       
    /***********************************************************/ //SPI初始化
    SPDAT= 0x00;
    SPCTL= 0x43;//使能SPI从机模式
    SPSTAT = 0xc0;//清中断标志
        /***********************************************************/ //设置中断
        EADC_SPI=1;
    AUXR |= 0x08;
    EA = 1;
        while (1)
    {
      if(P22==0)
      {
            while(P22==0);
            HAL_SystemReset(); //免断电下载
      }
    }
}
//**************************中断函数**********************//
void ADC_SPI_ISR() interrupt 5
{
    SPSTAT = 0xc0; //清中断标志
    if(Flag == 0)
    {
      if (SPDAT == 0x03)
      {
            Flag++;
            Addr = 0;
      }
    }
    else
    {
      Flag++;
      Addr <<= 8;
      Addr |= SPDAT;
      if (Flag >= 3)
      {
            Flag = 0;
            if (Addr < 0x1000) //4K EEPROM
            {
                //SPDAT = HAL_FLASH_ReadByte(Addr); //加入读取EEPROM的操作就会返回0x00,就算不使用读取EEPROM的函数,加个100us的延时,也会导致丢数据
                SPDAT = 0xCC;
                P27 = !P27;
                return;
            }
      }
    }
    SPDAT = 0x00;
}

当注释掉SPDAT = HAL_FLASH_ReadByte(Addr);时,可以正确返回数据:



下面是主机的程序,比较简单,也是移植ISP软件上面的,就发送了4个数据过去,0x03,0x40,0x00,0xFF:

//**************************主函数**********************//
void main(void)
{       
    uint8_t Byte;
   
    P10=1;
    SPCTL = 0x53;   //使能SPI主机模式
    SPSTAT = 0xc0;//清中断标志
    MyUart_Init();
        while (1)
    {
      if(P22==0)
      {
            while(P22==0);
            //发送数据
            P10 = 0;                  //拉低从机SS管脚
            
            SPDAT = 0x03;               //发送测试数据
            while (!(SPSTAT & 0x80));   //查询完成标志
            SPSTAT = 0xc0;            //清中断标志
            Byte = SPDAT;
            
            SPDAT = 0x04;               //发送测试数据
            while (!(SPSTAT & 0x80));   //查询完成标志
            SPSTAT = 0xc0;            //清中断标志
            Byte = SPDAT;
            
            SPDAT = 0x00;               //发送测试数据
            while (!(SPSTAT & 0x80));   //查询完成标志
            SPSTAT = 0xc0;            //清中断标志
            Byte = SPDAT;
            
            SPDAT = 0xFF;               //发送测试数据
            while (!(SPSTAT & 0x80));   //查询完成标志
            SPSTAT = 0xc0;            //清中断标志
            Byte = SPDAT;
            HAL_UART1_TransmitByte(SPDAT);

            P10 = 1;                  //拉高从机的SS管脚
      }
    }
}

虹涛犹珷 发表于 2024-4-8 13:47:20

晓飛飛 发表于 2024-4-8 13:44
SPI有四种时序,看看是不是前后沿问题,导致多出一位

主丛机使用的都是SPI1_MODE0,时钟在逻辑 0 处空闲 ,数据会在SCK的上升沿上读取,在下降沿上发送。

虹涛犹珷 发表于 2024-4-8 13:49:32

虹涛犹珷 发表于 2024-4-8 13:44
您好,我移植ISP软件上面的SPI程序,丛机终于可以返回正确的数据了,但是还有个问题,如果丛机的中断里面 ...

这是使用读取的FLASH后:



虹涛犹珷 发表于 2024-4-8 18:20:25

乘风飞扬 发表于 2024-4-8 09:03
从机不知道要发什么数据情况下,可以先发固定数据作为握手信号,主机也可以凭此判定从机是否有正常响应。 ...

现在可以连续读取数据了,就是丛机这里的中断里面不能操作太久,太久会导致丢数据,有没有好办法?
这是丛机主函数:

    while (1)
    {
      if (P14 == 1)
      {
            Step=0;
      }
      if(P22==0)
      {
            while(P22==0);
            HAL_SystemReset(); //免断电下载
      }
    }
这是丛机中断程序:

//**************************中断函数**********************//
void ADC_SPI_ISR() interrupt 5
{
    SPSTAT = 0xc0; //清中断标志
    if(Step == 0)
    {
      if (SPDAT == 0x03)
      {
            Step++;
            Addr = 0;
      }
    }
    else if ((Step == 1)||(Step == 2))
    {
      Step++;
      Addr <<= 8;
      Addr |= SPDAT;
    }
    if (Step == 3)
    {
      if (Addr >= 0x1000) //4K EEPROM
      {
            Addr = 0;
      }
      //使用读取EEPROM的操作就会返回0x00,就算不使用读取EEPROM的函数,加个100us的延时,也会导致丢数据
      //SPDAT = HAL_FLASH_ReadByte(Addr);
      SPDAT = Local_Buf; //直接读取数组就不会丢数据
      Addr++;
      return;
    }
    SPDAT = 0x00;
}

这是主机发送的数据:







乘风飞扬 发表于 2024-4-8 18:51:03

虹涛犹珷 发表于 2024-4-8 18:20
现在可以连续读取数据了,就是丛机这里的中断里面不能操作太久,太久会导致丢数据,有没有好办法?
这是 ...

中断里面接收完数据,设置必要标志后就退出,不要执行太多功能。
在主循环里面判定标志再执行后续操作。

虹涛犹珷 发表于 2024-4-9 09:15:25

乘风飞扬 发表于 2024-4-8 18:51
中断里面接收完数据,设置必要标志后就退出,不要执行太多功能。
在主循环里面判定标志再执行后续操作。 ...

把读取EEPROM的操作放到主函数里面,会不会来不及传输给主机,主机就发送下一个数据过来了。想问下,主机是不是不会等待丛机发送数据?丛机想做到接收到数据,再回传给主机,只能把主机的通信速度放慢,这样估计可行。我再试试。PS:那些FLASH芯片是如何做到快速回传数据的,我感觉单片机做不到快速回传数据。{:dizzy:}

乘风飞扬 发表于 2024-4-9 09:19:33

虹涛犹珷 发表于 2024-4-9 09:15
把读取EEPROM的操作放到主函数里面,会不会来不及传输给主机,主机就发送下一个数据过来了。想问下,主机 ...

如果回传的数据是存放在EEPROM里面的话,在芯片上电初始化时就可以读取出来放到RAM里面,回传时从RAM里面获取。

虹涛犹珷 发表于 2024-4-9 15:21:44

乘风飞扬 发表于 2024-4-9 09:19
如果回传的数据是存放在EEPROM里面的话,在芯片上电初始化时就可以读取出来放到RAM里面,回传时从RAM里面 ...

RAM没这么大吧?有4K的EEPROM,而且丛机开始不知道主机需要读取哪里的数据,需要接收到主机的命令和地址才知道读取哪些数据。如果读取几个数据,倒是可以放RAM。
页: 1 [2] 3
查看完整版本: STC单片机做为丛机,在SPI通信下第一个数据会丢失?