你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
alangxl 提问时间:2018-6-22 15:06 /
求助各位大神,小弟在用STM32F4 进行SPI通讯,SPI 动作时,软件片选信号被拉高,IO口程序逻辑失控,请问是为啥?

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

上图中绿色为CLK,蓝色为MOSI,红色为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就被拉高了。波形如下:
483850115169619986.jpg

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

这个问题困扰我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);

}

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

哎,真实苦了我了,求老师啊,我企鹅475437231,求大家批评啊。

收藏 1 评论16 发布时间:2018-6-22 15:06

举报

16个回答
alangxl 回答时间:2018-6-22 15:07:38
帖子啥时候通过啊?
CC4 回答时间:2018-6-22 18:28:20
return (u8)(u16Temp);
我记得这个是数据类型转换。

SPI 的时候,CS一直是拉低的,按说不应该出现 波动的。难道是因为F4的原因吗?

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

alangxl 回答时间:2018-6-24 11:51:22
select326 发表于 2018-6-22 18:28
return (u8)(u16Temp);
我记得这个是数据类型转换。

我的这个CS是软件模拟的,所以我是刻意先拉低后再在1个byte后拉高的,可是就是不清楚为啥像图1一样SPI一动作就给拉高了。。。
CC4 回答时间:2018-6-24 21:21:28
alangxl 发表于 2018-6-24 11:51
我的这个CS是软件模拟的,所以我是刻意先拉低后再在1个byte后拉高的,可是就是不清楚为啥像图1一样SPI一 ...

我意思是,按照SPI协议来说,CS拉高后就停止通信了。所以,你这个刻意拉高 我就理解 不了了
alangxl 回答时间:2018-6-26 10:58:46
select326 发表于 2018-6-24 21:21
我意思是,按照SPI协议来说,CS拉高后就停止通信了。所以,你这个刻意拉高 我就理解 不了了 ...

嗯嗯,我现在是比较纠结像我图1抓的波形那样,SPI一动作,我本来拉低的GPIO pin ,居然瞬间被拉高,但我换了另一个函数后就变好,很是奇怪。
alangxl 回答时间:2018-6-26 14:41:01
沉下去了,自己顶一个!
子曰好人 回答时间:2018-6-28 09:14:26
“return (u8)(u16Temp);” 的意思是只取变量u16Temp的低8位。
在程序运行中需要这个变量的高八位做存储之类的运算,但是最后需要的结果是这个变量的低八位,所以定义了一个个16位的变量,最后返回的时候只取了低八位。
希望能帮到楼主理解

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

x5y4z3 回答时间:2018-6-28 09:22:53
咱咋多 SPI 的问题啊?,我自备板凳旁边来看热闹!
STM1024 回答时间:2018-6-28 10:30:52
你的示波器成功滴引起了我的注意

点评

哈哈~  发表于 2018-6-29 10:13
STM1024 回答时间:2018-6-28 10:56:34
我一开始在想,是不是你的外设有什么特别的地方,就是每次CS一拉低之后,出现了短路的现象?但是根据后面换代码就能解决问题,似乎并不是硬件的原因。
然后想问问,SPI1_Init里面,
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);
最后到底启用RCC没有呢?

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

zhongfg 回答时间:2018-6-28 12:43:40
这个问题因该是类型转换出了问题了,读2个字节数据变成读1个字节而编译器又把1字节的数据编译成2个字节的数据调用时第2个字节刚好又对IO操作的。所以出现IO电平的改变。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

果粽子 回答时间:2018-6-28 13:55:25
我觉得应该是类型转换的问题和你CS初始化的问题

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

alangxl 回答时间:2018-6-28 16:42:38
stm1024 发表于 2018-6-28 10:56
我一开始在想,是不是你的外设有什么特别的地方,就是每次CS一拉低之后,出现了短路的现象?但是根据后面换 ...

RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);是复位SPI1
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);是停止复位SPI1
我这样理解没错吧,
确实是换了读写函数就好了,是不是第一次用的读写函数没有先收SPI 导致某个标志位溢出导致的异常呢?
STM1024 回答时间:2018-6-28 18:09:43
你在使用这些前,先把CS强制拉高一下试试?

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

12下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版