STM32F4 SPI动作时,软件片选信号被拉高,IO口程序逻辑失控

2019-07-14 14:47发布

求助各位大神,小弟在用STM32F4 进行SPI通讯,SPI 动作时,软件片选信号被拉高,IO口程序逻辑失控,请问是为啥?

如下图:CS本来都拉低了,SPI一动作,CS就被拉高了,我用的软件模拟CS信号,单独配置的GPIO口,且配置GPIO的函数与初始化SPI函数独立开了。

上图中绿 {MOD}为CLK,蓝 {MOD}为MOSI,红 {MOD}为CS,我配置希望他前8个clk是要拉低的。

我这段波形运行的代码为:
void SendDatatoSSD(u8 addr,u16 dat)
{        
        u8 a=addr;
        u8 b=((dat >> 8) & 0xFF);
        u8 c=(dat & 0xFF);

        SSD2828_SDC=0;
        delay_ms(20);
        SSD2828_SDC=0;
        
        SPI1_ReadWriteByte(a);
        
        SSD2828_SDC=1;

        SPI1_ReadWriteByte(c);

        SPI1_ReadWriteByte(b);

}

其中SPI读写函数就是特别常用的如下:
u8 SPI1_ReadWriteByte(u8 TxData)
{

        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET);
        
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
        
        SPI_I2S_SendData(SPI1, TxData); //
               
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //

        return SPI_I2S_ReceiveData(SPI1); //

}

SPI 初始化函数和CS GPIO口配置都很常规
void SPI1_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
        
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//
        
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1); //PB3?′ó??a SPI1  PG SPI SCLK
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1); //PB4?′ó??a SPI1  PG SPI MISO
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1); //PB5?′ó??a SPI1  PG SPI MOSI
        
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//
        GPIO_Init(GPIOA, &GPIO_InitStructure);//
               
        //
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);//?′??SPI1
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);//í£?1?′??SPI1

        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //éè??SPIμ¥?ò?ò?????òμ?êy?Y?£ê?:SPIéè???a???????òè???1¤
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //éè??SPI1¤×÷?£ê?:éè???a?÷SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //éè??SPIμ?êy?Y′óD?:SPI·¢?í?óê?8?????á11
        
        //SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                //′?DDí?2?ê±?óμ????D×′ì??a??μ???
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                //′?DDí?2?ê±?óμ????D×′ì??aμíμ???
        //SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //′?DDí?2?ê±?óμ?μú?t??ì?±???£¨é?éy?ò???μ£?êy?Y±?2é?ù
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;        //′?DDí?2?ê±?óμ?μú?t??ì?±???£¨é?éy?ò???μ£?êy?Y±?2é?ù
        
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSSD?o?óéó2?t£¨NSS1ü??£??1ê?èí?t£¨ê1ó?SSI??£?1üàí:?ú2?NSSD?o?óDSSI??????
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;                //?¨ò?2¨ì??ê?¤·??μμ??μ:2¨ì??ê?¤·??μ?μ?a256  ?÷?μ84M??DD·??μ
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //???¨êy?Y′?ê?′óMSB???1ê?LSB???aê?:êy?Y′?ê?′óMSB???aê?
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC?μ????μ??à??ê?
        SPI_Init(SPI1, &SPI_InitStructure);  //?ù?YSPI_InitStruct?D???¨μ?2?êy3?ê??ˉíaéèSPIx??′??÷
        

        
        SPI_Cmd(SPI1, ENABLE);
        
        SPI1_ReadWriteByte(0xff);
}



我后来为了验证是不是SPI动作就把CS拉高,还在CS置0后Delay了一段时间,发现确认SPI移动,CS就被拉高了。波形如下:


这个我就奇了怪了!!!!!

这个问题困扰我3天3夜了,后来我都想不用硬件SPI了,直接用纯软件模拟SPI的各个信号和逻辑。

但来论坛搜了好久,我发现SPI读写函数有好多种,我就换了一种,发现了神奇的事情:
u8 SPI1_ReadWriteByte(u8 TxData)
{

        u16 u16Temp;

  /* Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == SET)
  {
    SPI_I2S_ReceiveData(SPI1);      
  }

  /* Send byte through the SPIx peripheral */
  SPI_I2S_SendData(SPI1, TxData);

  /* Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  u16Temp = SPI_I2S_ReceiveData(SPI1);


  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == SET);


  /* Return the byte read from the SPI bus */
  return (u8)(u16Temp);

}


问题解决了,我刚开始学ARM,用的STM32F4系列,两端代码差别怎么就那么大呢,第一段SPI的读写很常规啊?为啥就出那个问题呢?
我把这个遭遇分享给大家,向大家求教。
最后,经验不足想问问大家:
return (u8)(u16Temp); 这种表述是啥意思?一般不是return (u16Temp);就好了吗?

哎,真实苦了我了,求老师啊,我企鹅475437231,求大家批评啊。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
12条回答
wo97306730
1楼-- · 2019-07-14 23:41
shugan2011 发表于 2019-1-7 15:10
return (u8)(u16Temp);
我记得这个是数据类型转换。

我的这个CS是软件模拟的,所以我是刻意先拉低后再在1个byte后拉高的,可是就是不清楚为啥像图1一样SPI一动作就给拉高了。。。
shugan2011
2楼-- · 2019-07-15 04:00
wo97306730 发表于 2019-1-7 15:29
我的这个CS是软件模拟的,所以我是刻意先拉低后再在1个byte后拉高的,可是就是不清楚为啥像图1一样SPI一动作就给拉高了。。。

我意思是,按照SPI协议来说,CS拉高后就停止通信了。所以,你这个刻意拉高 我就理解 不了了
wo97306730
3楼-- · 2019-07-15 09:38
 精彩回答 2  元偷偷看……
wo97306730
4楼-- · 2019-07-15 12:18
沉下去了,自己顶一个!
nmcxkwqjhd
5楼-- · 2019-07-15 18:08
“return (u8)(u16Temp);” 的意思是只取变量u16Temp的低8位。
在程序运行中需要这个变量的高八位做存储之类的运算,但是最后需要的结果是这个变量的低八位,所以定义了一个个16位的变量,最后返回的时候只取了低八位。
希望能帮到楼主理解
shuqingli
6楼-- · 2019-07-15 22:37
咱咋多 SPI 的问题啊?,我自备板凳旁边来看热闹!

一周热门 更多>