打印

stm32f4discovery的SPI问题

[复制链接]
3680|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
fengyao|  楼主 | 2013-11-17 22:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  如题,lz在配置stm32f4的SPI通信时,发现配置SPI后程序一直停留在发送函数的while处。
  板子是discovery,时钟配置是systeminit中默认的配置,GPIO什么的使用正常,代码也是参考网上一些成功的例子写的,难道SPI的配置真的有什么玄机,导致lz没有配置成功?
  已经纠结了一下午了……求救论坛里的大神看看有什么问题可能是lz忽略的……感激不尽~
void SPI_GPIOConfig(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);  //开启时钟
   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  //引脚初始化
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
   
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);  //打开引脚的复用功能
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
}

SPI2功能初始化:

void SPI_Config(void)
{
    SPI_GPIOConfig();
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);  //时钟
   
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //全双工模式
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;   //作为主机使用
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;   //数据长度8
    SPI_InitStructure.SPI_CPOL  = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;   //软件设置NSS功能
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI2,&SPI_InitStructure);
    SPI_Cmd(SPI2,ENABLE);
}
void MySPI_SendData(char da)
{
    while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET);
    SPI_SendData(SPI2,da);
}

uint8_t MySPI_ReceiveData(void)
{
    while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET);
    return SPI_ReceiveData(SPI2);
}
沙发
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试试

使用特权

评论回复
5
fengyao|  楼主 | 2013-11-19 22:40 | 只看该作者
问题解决了,这几天没顾上回帖子……
先贴代码
void spi2_init(void)
{
        GPIO_InitTypeDef GPIO_conf;
        SPI_InitTypeDef  SPI_conf;
        //////////////////////////////////////////////////////////////clock
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
        ////////////////////////////////////////////////////////////// I/O Init
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_SPI2);
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
        GPIO_conf.GPIO_Mode=GPIO_Mode_AF;
        GPIO_conf.GPIO_OType=GPIO_OType_PP ;
        GPIO_conf.GPIO_Pin=GPIO_Pin_15 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_12;
        GPIO_conf.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_conf.GPIO_Speed=GPIO_Speed_100MHz;
        GPIO_Init(GPIOB , &GPIO_conf);

        GPIO_conf.GPIO_Mode=GPIO_Mode_OUT;
        GPIO_conf.GPIO_OType=GPIO_OType_PP ;
        GPIO_conf.GPIO_Pin=GPIO_Pin_3 | GPIO_Pin_2;
        GPIO_conf.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_conf.GPIO_Speed=GPIO_Speed_100MHz;
        GPIO_Init(GPIOA , &GPIO_conf);
        GPIO_conf.GPIO_Mode=GPIO_Mode_OUT;
        GPIO_conf.GPIO_OType=GPIO_OType_PP ;
        GPIO_conf.GPIO_Pin=GPIO_Pin_4;
        GPIO_conf.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_conf.GPIO_Speed=GPIO_Speed_100MHz;
        GPIO_Init(GPIOC , &GPIO_conf);
/////////////////////////////////////////////////////////////////////////SPI _init
          SPI_I2S_DeInit(SPI2);        //
          //GPIO_SetBits(GPIOB,GPIO_Pin_12);
        SPI_conf.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_conf.SPI_DataSize = SPI_DataSize_8b;
        SPI_conf.SPI_Mode = SPI_Mode_Master;          //主机模式
        SPI_conf.SPI_CPOL = SPI_CPOL_High;
        SPI_conf.SPI_CPHA = SPI_CPHA_2Edge;
        SPI_conf.SPI_NSS = SPI_NSS_Soft;
        SPI_conf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
        SPI_conf.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_conf.SPI_CRCPolynomial = 7;
        //SPI_SSOutputCmd(SPI2,ENABLE);
        SPI_Init(SPI2, &SPI_conf);
        //SPI_NSSInternalSoftwareConfig(SPI2,SPI_NSSInternalSoft_Set);
        SPI_Cmd(SPI2, ENABLE);
}

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

}
主要问题有两个:
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来使用。

使用特权

评论回复
6
xinwen666| | 2014-8-20 10:50 | 只看该作者
本帖最后由 xinwen666 于 2014-8-20 10:51 编辑

请问方便给我一下你调试SPI的project吗?我在调试SPI遇到一下问题,不知道怎么处理了。我邮箱297080674@qq.com,谢谢。

使用特权

评论回复
7
yinhaix| | 2015-5-27 17:07 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

15

帖子

0

粉丝