stm32f4discovery的SPI问题

[复制链接]
4035|6
 楼主| fengyao 发表于 2013-11-17 22:24 | 显示全部楼层 |阅读模式
  如题,lz在配置stm32f4的SPI通信时,发现配置SPI后程序一直停留在发送函数的while处。
  板子是discovery,时钟配置是systeminit中默认的配置,GPIO什么的使用正常,代码也是参考网上一些成功的例子写的,难道SPI的配置真的有什么玄机,导致lz没有配置成功?
  已经纠结了一下午了……求救论坛里的大神看看有什么问题可能是lz忽略的……感激不尽~
  1. void SPI_GPIOConfig(void)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);  //开启时钟
  5.    
  6.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  //引脚初始化
  7.     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  8.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  9.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  10.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11.     GPIO_Init(GPIOB,&GPIO_InitStructure);
  12.    
  13.     GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);  //打开引脚的复用功能
  14.     GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
  15.     GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
  16. }

  17. SPI2功能初始化:

  18. void SPI_Config(void)
  19. {
  20.     SPI_GPIOConfig();
  21.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);  //时钟
  22.    
  23.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //全双工模式
  24.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;   //作为主机使用
  25.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;   //数据长度8
  26.     SPI_InitStructure.SPI_CPOL  = SPI_CPOL_High;
  27.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  28.     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;   //软件设置NSS功能
  29.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  30.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  31.     SPI_InitStructure.SPI_CRCPolynomial = 7;
  32.     SPI_Init(SPI2,&SPI_InitStructure);
  33.     SPI_Cmd(SPI2,ENABLE);
  34. }
  35. void MySPI_SendData(char da)
  36. {
  37.     while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET);
  38.     SPI_SendData(SPI2,da);
  39. }

  40. uint8_t MySPI_ReceiveData(void)
  41. {
  42.     while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET);
  43.     return SPI_ReceiveData(SPI2);
  44. }
wangzhihai1986 发表于 2013-11-18 09:20 | 显示全部楼层
37.void MySPI_SendData(char da)

38.{

39.    while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET);

40.    SPI_SendData(SPI2,da);

41.}

42.

43.uint8_t MySPI_ReceiveData(void)

44.{

45.    while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET);

46.    return SPI_ReceiveData(SPI2);

47.}
建议把他们合在一块,SPI是双工的,写的时候也读了
另外,你的时钟可能太慢了,你看下吧。
戈卫东 发表于 2013-11-18 10:21 | 显示全部楼层
NSS可能需要注意一下. MASTER模式下需要保持这个信号是无效状态(103是这样,4XX没试过)
chenyu988 发表于 2013-11-18 14:45 | 显示全部楼层
可能是CS管脚配置问题,配置成GPIO_PuPd_NOPULL试试
 楼主| fengyao 发表于 2013-11-19 22:40 | 显示全部楼层
问题解决了,这几天没顾上回帖子……
先贴代码
  1. void spi2_init(void)
  2. {
  3.         GPIO_InitTypeDef GPIO_conf;
  4.         SPI_InitTypeDef  SPI_conf;
  5.         //////////////////////////////////////////////////////////////clock
  6.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
  7.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
  8.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
  9.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
  10.         ////////////////////////////////////////////////////////////// I/O Init
  11.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_SPI2);
  12.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);
  13.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
  14.         GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
  15.         GPIO_conf.GPIO_Mode=GPIO_Mode_AF;
  16.         GPIO_conf.GPIO_OType=GPIO_OType_PP ;
  17.         GPIO_conf.GPIO_Pin=GPIO_Pin_15 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_12;
  18.         GPIO_conf.GPIO_PuPd = GPIO_PuPd_NOPULL;
  19.         GPIO_conf.GPIO_Speed=GPIO_Speed_100MHz;
  20.         GPIO_Init(GPIOB , &GPIO_conf);

  21.         GPIO_conf.GPIO_Mode=GPIO_Mode_OUT;
  22.         GPIO_conf.GPIO_OType=GPIO_OType_PP ;
  23.         GPIO_conf.GPIO_Pin=GPIO_Pin_3 | GPIO_Pin_2;
  24.         GPIO_conf.GPIO_PuPd = GPIO_PuPd_NOPULL;
  25.         GPIO_conf.GPIO_Speed=GPIO_Speed_100MHz;
  26.         GPIO_Init(GPIOA , &GPIO_conf);
  27.         GPIO_conf.GPIO_Mode=GPIO_Mode_OUT;
  28.         GPIO_conf.GPIO_OType=GPIO_OType_PP ;
  29.         GPIO_conf.GPIO_Pin=GPIO_Pin_4;
  30.         GPIO_conf.GPIO_PuPd = GPIO_PuPd_NOPULL;
  31.         GPIO_conf.GPIO_Speed=GPIO_Speed_100MHz;
  32.         GPIO_Init(GPIOC , &GPIO_conf);
  33. /////////////////////////////////////////////////////////////////////////SPI _init
  34.           SPI_I2S_DeInit(SPI2);        //
  35.           //GPIO_SetBits(GPIOB,GPIO_Pin_12);
  36.         SPI_conf.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  37.         SPI_conf.SPI_DataSize = SPI_DataSize_8b;
  38.         SPI_conf.SPI_Mode = SPI_Mode_Master;          //主机模式
  39.         SPI_conf.SPI_CPOL = SPI_CPOL_High;
  40.         SPI_conf.SPI_CPHA = SPI_CPHA_2Edge;
  41.         SPI_conf.SPI_NSS = SPI_NSS_Soft;
  42.         SPI_conf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
  43.         SPI_conf.SPI_FirstBit = SPI_FirstBit_MSB;
  44.         SPI_conf.SPI_CRCPolynomial = 7;
  45.         //SPI_SSOutputCmd(SPI2,ENABLE);
  46.         SPI_Init(SPI2, &SPI_conf);
  47.         //SPI_NSSInternalSoftwareConfig(SPI2,SPI_NSSInternalSoft_Set);
  48.         SPI_Cmd(SPI2, ENABLE);
  49. }

  50. u8 spi2_datasend(u8 data)
  51. {
  52.         SPI2->DR = data; // write data to be transmitted to the SPI data register
  53.         while( !(SPI2->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
  54.         while( !(SPI2->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete
  55.         while( SPI2->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
  56.         return SPI2->DR; // return received data from SPI data register

  57. }
主要问题有两个:
1:片内NSS管脚的问题,之前没有仔细研究过后来到网上查了下资料,发现还真是门大学问啊,stm32的NSS有输入,输出两种模式,还可以分别选择软件,硬件控制,具体的使用方法可以参考下面这篇博文:(不知道怎么回事,没有权限发url……自己在前边加http吧……)
hi.baidu.com/kangxuebin/item/9a21b1f96ccaef1ba6298830

2:外部器件的NSS引脚(也就是CS引脚):当只有一个SPI设备时使用的时候可以直接接地,当有多个SPI设备,且公用一个SPI接口时,要控制CS引脚,使用该器件时拉低,不使用时拉高,达到片选的作用。
  还有就是发现stm32的NSS引脚确实是有bug的,虽然st官方并不承认……那就是NSS引脚不管在什么情况下,都不能自动拉高,因此建议在使用时,把NSS引脚当做GPIO来使用。
xinwen666 发表于 2014-8-20 10:50 | 显示全部楼层
本帖最后由 xinwen666 于 2014-8-20 10:51 编辑

请问方便给我一下你调试SPI的project吗?我在调试SPI遇到一下问题,不知道怎么处理了。我邮箱297080674@qq.com,谢谢。
yinhaix 发表于 2015-5-27 17:07 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

15

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部