STM32标准库SPI的初始化

发布者:平安幸福最新更新时间:2018-09-22 来源: eefocus关键字:STM32  标准库SPI  初始化 手机看文章 扫描二维码
随时随地手机看文章

SPI的初始化比较简单,但是能明白原理是最好的,毕竟出了问题以后好排除。

SPI的初始化过程:

1、初始化GPIO

2、初始化SPI_InitStructure结构体

3、使能SPI外设

SPI的初始化结构体如下图所示:

typedef struct

{

  uint16_t SPI_Direction;          

  uint16_t SPI_Mode;                

  uint16_t SPI_Daize;            

  uint16_t SPI_CPOL;                

  uint16_t SPI_A;                

  uint16_t SPI_NSS;                

 

  uint16_t SPI_BaudRatePrescaler;  

  uint16_t SPI_FirstBit;            

  uint16_t SPI_CRCPolynomial;      

}SPI_InitTypeDef;

SPI_Direction为SPI的传输方向有如下选项:

#define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000)     //2线全双工

#define SPI_Direction_2Lines_RxOnly     ((uint16_t)0x0400)      //2线只接收

#define SPI_Direction_1Line_Rx          ((uint16_t)0x8000)          //1线只接收

#define SPI_Direction_1Line_Tx          ((uint16_t)0xC000)          //1线只发送

#define IS_SPI_DIRECTION_MODE(MODE) (((MODE) == SPI_Direction_2Lines_FullDuplex) || \

                                     ((MODE) == SPI_Direction_2Lines_RxOnly) || \

                                     ((MODE) == SPI_Direction_1Line_Rx) || \

                                     ((MODE) == SPI_Direction_1Line_Tx))

SPI_Mode指定SPI的模式的可选择参数如下:

SPI主机模式下,主机输出SCK,从机时候接收SCK,当配置为主机模式接收数据的时候必须发送数据来启动SCK


#define SPI_Mode_ter                 ((uint16_t)0x0104)                       //主机模式

#define SPI_Mode_Slave                  ((uint16_t)0x0000)                        //从机模式

#define IS_SPI_MODE(MODE) (((MODE) == SPI_Mode_ter) || \

                           ((MODE) == SPI_Mode_Slave))

SPI_Daize为一帧数据的长度,可选参数为:


#define SPI_Daize_16b                ((uint16_t)0x0800)       //8位

#define SPI_Daize_8b                 ((uint16_t)0x0000)         //16位

#define IS_SPI_DAIZE(DAIZE) (((DAIZE) == SPI_Daize_16b) || \

                                   ((DAIZE) == SPI_Daize_8b))

一般选择为8位

SPI_CPOL和SPI_A是比较重要的参数,他们决定了触发信号和采样信号的时刻,

SPI_CPOL=0,SCK空闲状态为低电平

SPI_CPOL=1,SCK空闲状态为高电平

SPI_A=0,表示在第一个边沿跳变时采样

SPI_A=1,表示在第二个边沿跳变时采样

当SPI_CPOL=0,SPI_A=0时,SCK空闲状态为低电平,表示在第一个边沿跳变时采样,说明采样状态为上升沿采样,下降沿触发,

当SPI_CPOL=1,SPI_A=0时,SCK空闲状态为高电平,表示在第一个边沿跳变时采样,说明采样状态为下降沿采样,上升沿触发。

当SPI_CPOL=0,SPI_A=1时,SCK空闲状态为高电平,表示在第二个边沿跳变时采样,说明采样状态为下降沿,上升沿触发

当SPI_CPOL=1,SPI_A=1时,SCK空闲状态为高电平,表示在第二个边沿跳变时采样,说明采样状态为上升沿降沿,下降沿触发

特别提醒:这两个位必须和外设支持的传输方式一致

SPI_CPOL的可选择参数如下:

#define SPI_CPOL_Low                    ((uint16_t)0x0000)

#define SPI_CPOL_High                   ((uint16_t)0x0002)

#define IS_SPI_CPOL(CPOL) (((CPOL) == SPI_CPOL_Low) || \

                           ((CPOL) == SPI_CPOL_High))

SPI_A的可选择参数如下:

#define SPI_A_1Edge                  ((uint16_t)0x0000)

#define SPI_A_2Edge                  ((uint16_t)0x0001)

#define IS_SPI_A(A) (((A) == SPI_A_1Edge) || \

                           ((A) == SPI_A_2Edge))

SPI_NSS为CS信号线,该位表示CS信号是由软件模拟还是由硬件自动产生。官方推荐CS信号由软件模拟,毕竟CS信号比较简单。可选择的参数如下:

#define SPI_NSS_Soft                    ((uint16_t)0x0200)

#define SPI_NSS_Hard                    ((uint16_t)0x0000)

#define IS_SPI_NSS(NSS) (((NSS) == SPI_NSS_Soft) || \

                         ((NSS) == SPI_NSS_Hard))

/**

SPI_BaudRatePrescaler SPI的分频系数设置,可选参数如下

#define SPI_BaudRatePrescaler_2         ((uint16_t)0x0000)

#define SPI_BaudRatePrescaler_4         ((uint16_t)0x0008)

#define SPI_BaudRatePrescaler_8         ((uint16_t)0x0010)

#define SPI_BaudRatePrescaler_16        ((uint16_t)0x0018)

#define SPI_BaudRatePrescaler_32        ((uint16_t)0x0020)

#define SPI_BaudRatePrescaler_64        ((uint16_t)0x0028)

#define SPI_BaudRatePrescaler_128       ((uint16_t)0x0030)

#define SPI_BaudRatePrescaler_256       ((uint16_t)0x0038)

#define IS_SPI_BAUDRATE_PRESCALER(PRESCALER) (((PRESCALER) == SPI_BaudRatePrescaler_2) || \

                                              ((PRESCALER) == SPI_BaudRatePrescaler_4) || \

                                              ((PRESCALER) == SPI_BaudRatePrescaler_8) || \

                                              ((PRESCALER) == SPI_BaudRatePrescaler_16) || \

                                              ((PRESCALER) == SPI_BaudRatePrescaler_32) || \

                                              ((PRESCALER) == SPI_BaudRatePrescaler_64) || \

                                              ((PRESCALER) == SPI_BaudRatePrescaler_128) || \

                                              ((PRESCALER) == SPI_BaudRatePrescaler_256))

具体SPI的时钟可根据时钟树来设置。

SPI_FirstBit 表示先发送高位还是先发送低位

#define SPI_FirstBit_MSB                ((uint16_t)0x0000)

#define SPI_FirstBit_LSB                ((uint16_t)0x0080)

#define IS_SPI_FIRST_BIT(BIT) (((BIT) == SPI_FirstBit_MSB) || \

                               ((BIT) == SPI_FirstBit_LSB))

SPI_CRCPolynomial  为CRC值计算的多项式,参数可设置为任意数字

下面为SPI的初始化实例:

void SPI2_Init(void)

{

       GPIO_InitTypeDef GPIO_InitStructure;

       SPI_InitTypeDef  SPI_InitStructure;

RCC_APB2PerClockCmd( RCC_APB2Per_GPIOB, ENABLE );

RCC_APB1PerClockCmd( RCC_APB1Per_SPI2,  ENABLE );

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15ÉÏÀ­

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  

SPI_InitStructure.SPI_Mode = SPI_Mode_ter;

SPI_InitStructure.SPI_Daize = SPI_Daize_8b;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

SPI_InitStructure.SPI_A = SPI_A_2Edge;

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

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); 

SPI2_ReadWriteByte(0xff);

}


关键字:STM32  标准库SPI  初始化 引用地址:STM32标准库SPI的初始化

上一篇:STM32使用FATFSW读写SD出现错误2的原因
下一篇:STM32 ADC多通道DMA传输

推荐阅读最新更新时间:2024-03-16 16:14

STM32学习笔记(1) GPIO初始化及点亮LED
一、led.h头文件分析 #ifndef __LED_H #define __LED_H #include sys.h #define LED0 PAout(8) // PA8 #define LED1 PDout(2) // PD2 void LED_Init(void);//初始化 #endif 问:ifndef,endif有什么用? 在这一段代码中,假设同时有A.h和B.h同时包含了这个头文件,在编译器编译A时,会先判断LED.H有没有被定义(这里肯定是未被定义的),那么就定义(define __LED_H),然后再(endif),在编译器编译B时,同样会判断LED.H有没有被定义(这里经过A的编译,肯定是被定义的),那么
[单片机]
<font color='red'>STM32</font>学习笔记(1) GPIO<font color='red'>初始化</font>及点亮LED
STM32内部RAM在线调试配置方法及详细说明
Ⅰ、 写在前面 本文主要讲述的内容:基于Keil开发工具下,STM32内部RAM在线调试配置方法,以及每一项配置的详细说明。如需要了解更多相关的文章,可以到我博客,或微信公众号查看。 让程序运行在RAM中调试代码有两优点:1.速度快;2.减少对芯片FLASH读写次数,增加芯片寿命。 本文牵涉的知识比较多,如果弄明白所有细节问题,对自己这方面的技能是一种很大的提升。 本文基于ST公司Cortex-M内核的STM32来讲述其配置方法,其实也适用于其他公司(如:TI、NXP等)的Cortex-M芯片,原理都是一样的。 本文内容已经整理成PDF文件,提供给大家下载: http://pan.baidu.com/s/1d
[单片机]
<font color='red'>STM32</font>内部RAM在线调试配置方法及详细说明
STM32之JTAG、SWD模式
说在前面的话 最近YKY项目做了新的硬件设计,其中键盘接口采用矩阵式键盘(4*4),有两个接口使用了STM32 (PB3、PB4), 调试中发现,这两个接口对应的两行均不能正常扫描到按键值,查看数据手册才知道这是系统接口,需要进行设置才可以 作为普通IO口使用。如图是数据手册对这两个接口的介绍: 解决方法 寄存器版本: 1 //JTAG模式设置,用于设置JTAG的模式 2 //mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭; 3 //#define JTAG_SWD_DISABLE 0X02 4 //#define SWD_ENABLE 0X01
[单片机]
stm32学习笔记(八)中断服务函数与函数调用的区别
在《微机原理》和《计算机组成》等课程 教学中(本文以MCS-51单片机为例),中断过程既是教学难点又是教学重点,它与主程序调用子程序过程有一定相似性,但又有很大区别,调用子程序过程相对比较容易掌握,通过把两过程结合起来,采用比较教学方法,能收到了很好的教学效果。 1、两过程定义与作用 子程序是微机基本程序结构中的1种,基本程序结构包括顺序(简单)、分支(判断)、循环、子程序和查表等5种。 子程序是一组可以公用的指令序列,只要给出子程序的入口地址就能从主程序转入子程序。子程序在功能上具有相对的独立性,在执行主程序的过程中往往被多次调用,甚至被不同的程序所调用。一般微机首先执行主程序,碰到调用指令就转去执行子程序,
[单片机]
步进电机的常用驱动方式
步进电机的驱动 stm32为例,使用ULN2003,TB6600电机驱动板,介绍步进电机的常用驱动方式。 步进电机 我使用的是一个教学用的小步进电机,驱动电压只有5V,所有的步进电机驱动原理都是类似的,电机详情如图。 产品参数 该模块为5线4相步进电机,可以使用普通的uln2003芯片驱动。 驱动要求:能够提供较快的电流上升和下降速度,使电流波形经量接近矩形。提供具有戒指期间释放电流流通的贿赂,以前降低绕组两端的反电动势,加快电流衰减。具有较高的功率及效率,步进电机的转速与脉冲信号的频率姐可以对单机进行调速。 内部结构图 四拍驱动方式 在四线驱动方式中,每次仅有一个线圈通电,对磁铁具有吸引作用,从而使电机进行转
[单片机]
步进电机的常用驱动方式
STM32与上位机串口通讯的学习笔记(简明的数据帧设计方法)
最近因为项目需要,需要做一个STM32和Windows的串口通讯协议来交换数据,本着追求极致的心态,来讨论一下简明的数据帧的设计方法。 ##数据的传输方式 对于很多单片机初学者而言,可能他们接触到串口 首先想到的就是通过串口打印字符串,然后就会很理所当然的想到了用“打印”的方式来传输数据。 比如我们需要传输一个float型的数据value,可能小白们首先会想到的方式就是串口重定向printf然后像下面这样把数据传输过去 printf( %f ,&value); 但是实际上,对于程序之间的交流,使用字符串打印这样的方式是非常浪费传输数据的,因为假设这个浮点数据为1234.567占了8个字符(小数点也占一位) 所以用字
[单片机]
STM32之ADC库函数的介绍
ADC的基本概念希望各位网友查阅相应的手册,上面对ADC有比较详尽的介绍,包括误差的分析和消除。这里主要介绍ADC的基本库函数的定义和使用。 1.ADC_DeInit函数的功能是将外设ADCx的全部寄存器重设为默认值。 ADC_DeInit(ADC2); 2.ADC_Init函数的功能是根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器。其中ADC_InitTypeDef定义在stm32f10x_adc.h中。其结构体如下所示: typedef struct { u32 ADC_Mode;//可以设置ADC_Mode FunctionalState ADC_ScanConvMode;//规定了模数转换工作在扫描
[单片机]
STM32 RTC问题
STM32的RTC用纽扣电池供电,本来考虑将电池正极接到一个AD端口,采集电压值,但发现电池很快消耗殆尽,测量电流得到电流竟然高达20mA,而且单片机是工作的,还能驱动外围电路。 下图是设计的电路图: 下面是出现这种问题的原因:I/O接二极管到VCC。 RTC
[单片机]
<font color='red'>STM32</font> RTC问题
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved