原创SPI双机通信,分频系数受限求助

2019-07-21 02:12发布

最近自己写了一个SPI双机通信的工程,遇到了点问题。
需求:两块stm32f4的板子通过SPI进行全双工通信,主机可以向从机写入数据或者读取数据。设计方案:
主机写入从机:发送包含实际数据的完整帧,发送完后等待从机的确认字节,完成任务;
主机读取从机:发送包含所要数据的信息的指令帧,从机接收到后准备好包含实际数据的完整帧,在主机的驱动下返回;
主机采用软件片选,从机采用硬件片选。(这一块花了蛮久时间搞懂)
整个机制建立在中断基础上:主机初始化时仅使能接收中断,从机初始化时使能发送接收中断,所以从机初始化后会立即向发送缓冲区填入一个字节。当主机想要发送一帧时,在准备好实际的数据后,使能发送中断就可以将整个帧数据逐字节的发送出去。
问题描述:
初始化时分频系数最低到16可以正常工作,但4和8均会出现丢失数据导致无法正常通信。
主从机代码采用预编译的方式写在同一个工程中,下面贴代码

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
bleemcs
1楼-- · 2019-07-21 02:34
 精彩回答 2  元偷偷看……
bleemcs
2楼-- · 2019-07-21 06:26
//SPI中断
void SPI1_IRQHandler(void)
{
        //发送中断
  if(SPI_I2S_GetFlagStatus(User_SPI, SPI_I2S_FLAG_TXE) != RESET)
        {
                switch(SPI_Structure.state)
                {
                        case READY:
                                SPI_I2S_SendData(User_SPI, SPI_Structure.response);
                                break;
                        case COMMANDING:
                                #ifdef Master                                               
                                        SPI_SendCmdM();                        //主机逐字节发送指令帧
                                #endif
                                #ifdef Slave
                                        SPI_SendCmdReplyS();        //从机在接收主机指令时发送的无效字节
                                #endif
                                break;
                        case COMMANDED:
                                #ifdef Master
                                        SPI_RecvFrameReplyM();        //主机在读取从机数据时发送的无效字节
                                #endif
                                #ifdef Slave       
                                        SPI_SendFrameS();                //从机逐字节发送数据帧       
                                #endif                       
                                break;
                }
        }
        //接收中断
        if(SPI_I2S_GetFlagStatus(User_SPI, SPI_I2S_FLAG_RXNE) != RESET)
        {
                u8 data = SPI_I2S_ReceiveData(User_SPI);
                #ifdef Master
                        SPI_RecvDataM(data);                //主机接收从机的字节并解包
                #endif
                #ifdef Slave
                        SPI_RecvDataS(data);                //从机接收主机的字节并解包
                #endif
        }
}
bleemcs
3楼-- · 2019-07-21 10:36
主机供外部调用的函数

//供外部调用的主机发送函数
void SPI_MasterSend(u8 ms,SPI_COMState func,u16 base,u8 len)
{
        SPI_ExportData(ms,func,base,len);                //准备实际帧
        SPI_SendStartUp();                        //开始发送
}
//开始发送函数
void SPI_SendStartUp()
{
        if(!SPI_Structure.SPI_SendCmdHolder.valid) return;       
        SPI_Structure.state=COMMANDING;               
        SPI_Structure.com=SPI_Structure.SPI_SendCmdHolder.func;       
        SPI_Structure.sendIndex=0;               
        //以上为更新SPI结构体状态
        SPI_I2S_ITConfig(User_SPI,SPI_I2S_IT_TXE, ENABLE);        //使能发送中断后立即开始发送数据
}
bleemcs
4楼-- · 2019-07-21 11:01
关于片选我也是看了很久才搞明白是什么意思。之前为了让自己印象深一些写了个博客:https://blog.csdn.net/weixin_40185666/article/details/89297107。目前双机通信,主机读写我都已经实现了,问题就在于使用8分频或者4分频会出错,按道理SPI的通信在4分频21Mhz下应当是可以的,请问大家有什么修改的建议么?
bleemcs
5楼-- · 2019-07-21 12:26
这是硬件连接图,会不会和这个也有关系
peng1554
6楼-- · 2019-07-21 14:38
 精彩回答 2  元偷偷看……

一周热门 更多>