找回密码
 立即注册
楼主: 虹涛***

STC单片机做为丛机,在SPI通信下第一个数据会丢失?

[复制链接]

该用户从未签到

551

主题

9238

回帖

1万

积分

管理员

积分
13957
发表于 2024-4-8 09:06:04 | 显示全部楼层
SPI从机,你用
STC32/STC8H/STC8G/STC8C/STC8A/STC12H1K16
我们有完善的从机演示程序

截图202404080903552906.jpg

截图202404080906009160.jpg


回复 支持 反对 送花

使用道具 举报

  • TA的每日心情
    开心
    12 小时前
  • 签到天数: 83 天

    [LV.6]常住居民II

    13

    主题

    323

    回帖

    728

    积分

    荣誉版主

    热心市民

    积分
    728
    发表于 2024-4-8 13:44:25 | 显示全部楼层
    SPI有四种时序,看看是不是前后沿问题,导致多出一位
    睁开眼睛做场梦~~~
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    4 小时前
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    6

    主题

    33

    回帖

    368

    积分

    中级会员

    积分
    368
     楼主| 发表于 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);时,可以正确返回数据:

    1.png

    下面是主机的程序,比较简单,也是移植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管脚
            }
        }
    }

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    4 小时前
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    6

    主题

    33

    回帖

    368

    积分

    中级会员

    积分
    368
     楼主| 发表于 2024-4-8 13:47:20 | 显示全部楼层
    晓飛飛 发表于 2024-4-8 13:44
    SPI有四种时序,看看是不是前后沿问题,导致多出一位

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

    使用道具 举报

  • TA的每日心情
    无聊
    4 小时前
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    6

    主题

    33

    回帖

    368

    积分

    中级会员

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

    这是使用读取的FLASH后:

    2.png

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    4 小时前
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    6

    主题

    33

    回帖

    368

    积分

    中级会员

    积分
    368
     楼主| 发表于 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]; //直接读取数组就不会丢数据
            Addr++;
            return;
        }
        SPDAT = 0x00;
    }

    这是主机发送的数据:


    2.png 微信截图_20240408181417.png




    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    3 小时前
  • 签到天数: 128 天

    [LV.7]常住居民III

    26

    主题

    1284

    回帖

    3995

    积分

    论坛元老

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

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

    使用道具 举报

  • TA的每日心情
    无聊
    4 小时前
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    6

    主题

    33

    回帖

    368

    积分

    中级会员

    积分
    368
     楼主| 发表于 2024-4-9 09:15:25 | 显示全部楼层
    乘风飞扬 发表于 2024-4-8 18:51
    中断里面接收完数据,设置必要标志后就退出,不要执行太多功能。
    在主循环里面判定标志再执行后续操作。 ...

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

    使用道具 举报

  • TA的每日心情
    奋斗
    3 小时前
  • 签到天数: 128 天

    [LV.7]常住居民III

    26

    主题

    1284

    回帖

    3995

    积分

    论坛元老

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

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

    使用道具 举报

  • TA的每日心情
    无聊
    4 小时前
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    6

    主题

    33

    回帖

    368

    积分

    中级会员

    积分
    368
     楼主| 发表于 2024-4-9 15:21:44 | 显示全部楼层
    乘风飞扬 发表于 2024-4-9 09:19
    如果回传的数据是存放在EEPROM里面的话,在芯片上电初始化时就可以读取出来放到RAM里面,回传时从RAM里面 ...

    RAM没这么大吧?有4K的EEPROM,而且丛机开始不知道主机需要读取哪里的数据,需要接收到主机的命令和地址才知道读取哪些数据。如果读取几个数据,倒是可以放RAM。
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-4-30 12:40 , Processed in 0.069555 second(s), 65 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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