打印

STM32F4学习笔记之SPI(使用固件库,非中断方式)

[复制链接]
9064|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
feng_710|  楼主 | 2013-4-27 15:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 feng_710 于 2013-4-27 17:44 编辑

1.使能对应SPI模块时钟

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE) for SPI1
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE) for SPI2
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE) for SPI3.

2.使能对应GPIO的时钟

RCC_AHB1PeriphClockCmd() function. (SCK, MOSI, MISO and NSS ).

3.配置对应引脚的复用功能

        GPIO_PinAFConfig(GPIOx, GPIO_PinSourcex, GPIO_AF_SPIx); //引脚映射
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                    // 设置为推挽输出
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                       //复用模式
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x ;                              //引脚选择
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_xxMHz;                 //速度选择
        GPIO_Init(GPIOx, &GPIO_InitStructure);                                        //写入配置信息


4.配置SPI信息

        SPI_InitStructure.SPI_Direction = xxx;//工作模式SPI_Direction_2Lines_FullDuplex,SPI_Direction_2Lines_RxOnly等
        SPI_InitStructure.SPI_Mode = xxx; //主从模式选择SPI_Mode_Master,SPI_Mode_Slave
        SPI_InitStructure.SPI_DataSize = xxx;//数据位选择SPI_DataSize_8b,SPI_DataSize_16b
        SPI_InitStructure.SPI_CPOL = xxx;//时钟空闲电平选择SPI_CPOL_High,SPI_CPOL_Low
        SPI_InitStructure.SPI_CPHA = xxx;//数据捕捉跳变沿选择SPI_CPHA_2Edge,SPI_CPHA_1Edge
        SPI_InitStructure.SPI_NSS = xxx;//NSS信号由硬件还是软件控制SPI_NSS_Soft,SPI_NSS_Hard
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_x;//时钟分频选择
        SPI_InitStructure.SPI_FirstBit = xxx;//数据大小端选择SPI_FirstBit_MSB,SPI_FirstBit_LSB
        SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC值计算的多项式
        SPI_Init(SPI1, &SPI_InitStructure);//写入配置信息

5.发送

           while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
         SPI_I2S_SendData(SPI1,u8 xxx);

6.接收

          while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
              SPI_I2S_ReceiveData(SPI1);

程序举例:

本例是对交换机芯片KSZ8873的配置

宏定义:
#define KSZ8873_SPI                           SPI1
#define KSZ8873_SPI_CLK                       RCC_APB2Periph_SPI1
#define KSZ8873_SPI_SCK_PIN                   GPIO_Pin_3                  
#define KSZ8873_SPI_SCK_GPIO_PORT             GPIOB                     
#define KSZ8873_SPI_SCK_GPIO_CLK              RCC_AHB1Periph_GPIOB
#define KSZ8873_SPI_SCK_SOURCE                GPIO_PinSource3

#define KSZ8873_SPI_MISO_PIN                  GPIO_Pin_4                  
#define KSZ8873_SPI_MISO_GPIO_PORT            GPIOB                       
#define KSZ8873_SPI_MISO_GPIO_CLK             RCC_AHB1Periph_GPIOB
#define KSZ8873_SPI_MISO_SOURCE               GPIO_PinSource4

#define KSZ8873_SPI_MOSI_PIN                  GPIO_Pin_5                 
#define KSZ8873_SPI_MOSI_GPIO_PORT            GPIOB                       
#define KSZ8873_SPI_MOSI_GPIO_CLK             RCC_AHB1Periph_GPIOB
#define KSZ8873_SPI_MOSI_SOURCE               GPIO_PinSource5

#define KSZ8873_CS_PIN                        GPIO_Pin_15                 
#define KSZ8873_CS_GPIO_PORT                  GPIOA                     
#define KSZ8873_CS_GPIO_CLK                   RCC_AHB1Periph_GPIOA

#define KSZ8873_CS_LOW()       GPIO_ResetBits(KSZ8873_CS_GPIO_PORT, KSZ8873_CS_PIN)
#define KSZ8873_CS_HIGH()      GPIO_SetBits(KSZ8873_CS_GPIO_PORT, KSZ8873_CS_PIN)

#define KSZ8873_WRITE_CMD     0x02
#define KSZ8873_READ_CMD      0x03

程序:
void KSZ8873_SPI_Init(void)
{
        SPI_InitTypeDef  SPI_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        
        RCC_AHB1PeriphClockCmd(KSZ8873_CS_GPIO_CLK, ENABLE);
        
        GPIO_InitStructure.GPIO_Pin = KSZ8873_CS_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
        GPIO_Init(KSZ8873_CS_GPIO_PORT, &GPIO_InitStructure);
        
        RCC_AHB1PeriphClockCmd(KSZ8873_SPI_SCK_GPIO_CLK | KSZ8873_SPI_MISO_GPIO_CLK |
                                                                KSZ8873_SPI_MOSI_GPIO_CLK,  ENABLE);
        RCC_APB2PeriphClockCmd(KSZ8873_SPI_CLK, ENABLE);
        
        GPIO_PinAFConfig(KSZ8873_SPI_SCK_GPIO_PORT, KSZ8873_SPI_SCK_SOURCE, GPIO_AF_SPI1);
        GPIO_PinAFConfig(KSZ8873_SPI_MISO_GPIO_PORT, KSZ8873_SPI_MISO_SOURCE, GPIO_AF_SPI1);
        GPIO_PinAFConfig(KSZ8873_SPI_MOSI_GPIO_PORT, KSZ8873_SPI_MOSI_SOURCE, GPIO_AF_SPI1);
        
        GPIO_InitStructure.GPIO_Pin = KSZ8873_SPI_SCK_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
        GPIO_Init(KSZ8873_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
        GPIO_InitStructure.GPIO_Pin = KSZ8873_SPI_MISO_PIN;
        GPIO_Init(KSZ8873_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
        GPIO_InitStructure.GPIO_Pin = KSZ8873_SPI_MOSI_PIN;
        GPIO_Init(KSZ8873_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
        
        KSZ8873_CS_HIGH();
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_CRCPolynomial = 7;
        SPI_Init( KSZ8873_SPI , &SPI_InitStructure);
        
        SPI_Cmd(SPI1, ENABLE);
}


void KSZ8873_SPI_SendByte(u8 addr,u8 byte)
{
                KSZ8873_CS_LOW();
          while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
          SPI_I2S_SendData( KSZ8873_SPI , KSZ8873_WRITE_CMD);
          while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
          SPI_I2S_ReceiveData( KSZ8873_SPI );
          while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
          SPI_I2S_SendData( KSZ8873_SPI , addr);
                 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
          SPI_I2S_ReceiveData( KSZ8873_SPI );
                while (SPI_I2S_GetFlagStatus( KSZ8873_SPI , SPI_I2S_FLAG_TXE) == RESET);
          SPI_I2S_SendData(SPI1, byte);
                 while (SPI_I2S_GetFlagStatus( KSZ8873_SPI , SPI_I2S_FLAG_RXNE) == RESET);
          SPI_I2S_ReceiveData( KSZ8873_SPI );
                KSZ8873_CS_HIGH();
}


u8 KSZ8873_SPI_ReceiveByte(u8 byte)
{
        u8 i;
        KSZ8873_CS_LOW();
          while (SPI_I2S_GetFlagStatus( KSZ8873_SPI , SPI_I2S_FLAG_TXE) == RESET);
          SPI_I2S_SendData(SPI1, KSZ8873_READ_CMD);
                while (SPI_I2S_GetFlagStatus( KSZ8873_SPI , SPI_I2S_FLAG_RXNE) == RESET);
          SPI_I2S_ReceiveData(SPI1);
          while (SPI_I2S_GetFlagStatus( KSZ8873_SPI , SPI_I2S_FLAG_TXE) == RESET);
          SPI_I2S_SendData(SPI1, byte);
                while (SPI_I2S_GetFlagStatus( KSZ8873_SPI , SPI_I2S_FLAG_RXNE) == RESET);
          SPI_I2S_ReceiveData(SPI1);
               
        while (SPI_I2S_GetFlagStatus( KSZ8873_SPI , SPI_I2S_FLAG_TXE) == RESET);
          SPI_I2S_SendData(SPI1, byte);
          while (SPI_I2S_GetFlagStatus( KSZ8873_SPI , SPI_I2S_FLAG_RXNE) == RESET);
          i=SPI_I2S_ReceiveData(SPI1);
                KSZ8873_CS_HIGH();


        return i;
}



























沙发
astudent| | 2014-10-7 20:22 | 只看该作者
是用什么单片机连接KSZ8873?为何不用mii接口?

使用特权

评论回复
板凳
feng_710|  楼主 | 2014-10-11 23:12 | 只看该作者
astudent 发表于 2014-10-7 20:22
是用什么单片机连接KSZ8873?为何不用mii接口?

通信用的就是MII接口,SPI是配置接口

使用特权

评论回复
地板
astudent| | 2014-10-12 20:23 | 只看该作者
本帖最后由 astudent 于 2014-10-12 20:46 编辑
feng_710 发表于 2014-10-11 23:12
通信用的就是MII接口,SPI是配置接口
手册上说MII接口可以访问phy寄存器,spi接口可以访问内部所有寄存器。LZ用spi接口配置哪些寄存器?

使用特权

评论回复
5
astudent| | 2014-10-12 20:58 | 只看该作者
另外,手册上smi接口也可以访问内部所有寄存器,smi接口即mdc和mdio,还有必要使用spi接口么?

使用特权

评论回复
6
astudent| | 2014-10-16 15:52 | 只看该作者
feng_710 发表于 2014-10-11 23:12
通信用的就是MII接口,SPI是配置接口

另外,8873芯片的mii接口中mdio和mdc也是spi接口的spid、spic,即共用sda_mdio、scl_mdc。如何同时使用mii和spi访问?

使用特权

评论回复
7
feng_710|  楼主 | 2014-10-18 20:09 | 只看该作者
本帖最后由 feng_710 于 2014-10-18 20:13 编辑
astudent 发表于 2014-10-16 15:52
另外,8873芯片的mii接口中mdio和mdc也是spi接口的spid、spic,即共用sda_mdio、scl_mdc。如何同时使用mi ...

1.KSZ8873不是个PHY芯片,是个三口的交换机芯片,所以要多一些配置寄存器,需要SPI接口才能访问所有的寄存器
2.MII接口和SMI接口没有包含关系

使用特权

评论回复
8
astudent| | 2014-10-18 20:12 | 只看该作者
本帖最后由 astudent 于 2014-10-18 20:13 编辑
feng_710 发表于 2014-10-18 20:09
1.KSZ8873不是个PHY芯片,是个三口的交换机芯片,所以要多一些配置寄存器,需要SPI接口才能访问所有的寄存 ...

KSZ8873,网上看到只做普通交换机用的话,可以不用配置。上电默认就工作在phy模式,三**换机功能工作。

使用特权

评论回复
9
feng_710|  楼主 | 2014-10-18 20:14 | 只看该作者
astudent 发表于 2014-10-18 20:12
KSZ8873,网上看到只做普通交换机用的话,可以不用配置。

我的需求需要修改这些寄存器

使用特权

评论回复
10
搞IT的| | 2014-10-19 10:06 | 只看该作者
是的,,KSZ8873可以不用配置。。

使用特权

评论回复
11
futureiam123| | 2019-7-12 09:50 | 只看该作者
楼主我想用KSZ8873实现组网功能请问该怎么做

使用特权

评论回复
12
路上的工匠| | 2020-7-15 16:07 | 只看该作者
MARK

使用特权

评论回复
13
zdldcyy| | 2020-7-16 22:18 | 只看该作者
谢谢分享~

使用特权

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

本版积分规则

10

主题

51

帖子

3

粉丝