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使用FATFSW读写SD出现错误2的原因
下一篇:STM32 ADC多通道DMA传输
推荐阅读最新更新时间:2024-03-16 16:14