STM32 SPI学习笔记!

A.SPI特性
1.SPI一共有四根线,一根片选线CS,一根时钟线SCK,两根信号线MOSI或者是MISO
2.SPI的通信速率很快,不同舍设备可以达到10M+
3.通信方式
最大的特点使用主从模式,在总线上移动存在主设备和从设备,主设备发送数据,从设备接收数据。主从设备的通信信号,NSS,当主设备要发送数据时,将设一个引脚的电平拉低,从设备的对应NSS引脚接收低电平信号将会进入从设备接收模式。如果不通过硬件相连接NSS,也可以在使用软件方式来内部驱动NSS进入对应主从模式。
注意SPI的两个信号引脚MISO和MOSI,M代表Main,S代表Slave,在主从模式同一引脚并不都为输入获都为输出而是对应交换的。
主设备的SCK输出同步时钟到从设备上面,作为外部时钟驱动。
4.一些关键的设置:
第一、CPOL位设置,在SPI_CR1寄存器中,它决定了在空闲状态下SCK的电平状态。CPOL=1 表示空闲状态下是高电平。
第二、CPHA设置,时钟相位设置,设置在在SCK时钟的第几个时钟边沿进行采样,当CPHA=1时在第二个边沿进行数据采样。
第三、数据帧的格式,SPI_CR1的LSBFIRST设置MSB还是LSB在前;DFF位设置数据时16位还是8位的,SPI的数据寄存器是16位的根据设置自动无额定使用8位或16位。
第四、波特率设置,SPI_CR1中BR[2:0]设置对挂载的时候输入的分频
第五、主从模式设置,设置设置SPI_CR1寄存器的SSM位和SSI位设置SPI的NSS是工作的软件模式或是硬件模式
第六、设置工作模式,有全双工模式、单向只接收获只发送模式。设置SPI_CR1寄存器中的BIDIMODE等。
5.发送方式与中断
a.发送前应该先等待TXE 标志( 发送缓冲器空),表名上一帧数据 已经发送完毕;SPI_CR2寄存器中设置了TXEIE 位是对应的外设中断使能位,如果在打开了NVIC中的CPU中断通道,将会将进入中断,可以采用这种终端的发送方式
b.与上面类似,读数据前应该先等待RXNE 标志置位,表示接收缓冲器非空,可以读取数据,硬件自动清除标志位,如果使能对应RXNEIE,及打SPI开接收中断,如果在使能CPU级别的中断将会进入中断服务程序。
当然也可采用查询的方式来发送或接收。
另外如果需要尖山哦CPU开销,同时提高SPI的发送速率,还可以采用DMA来接管SPI的数据发送和接收,保证总线上通信的连续性。
6.CRC错误校验,CRCEN位启用校验,它会在数据发送完成之后,自动发送一个CRC校验值,从机检查与自己的SPI_TXCRCR数值是否匹配来判断是否有发送错误。
主模式失效事件  MODF ,溢出错误  OVR ,CRC错误标志  CRCERR,对应了一个错误中断ERRIE 通道。
7.软件配置:
第一步开启GPIO的复用:
SPI3的复用引脚:
SPI2的引脚复用:
先挂载GPIO时钟,使能SPI时钟,配置GPIO复用,将输出引荐NSS,SCK,MOSI,MISO,这厮个引脚在SPI通信中都可能出现双向的信号,应该配置成推挽输出。
 
初始化和读写函数如下:
void Init_SPI()
{
  GPIO_InitTypeDef GPIO_InitStructure; 
  SPI_InitTypeDef    SPI_InitStructure; 
 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );         
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,    ENABLE );         
 
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                  
  GPIO_Init(GPIOB, &GPIO_InitStructure);                             
 
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                      
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;         
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                         
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     
  SPI_InitStructure.SPI_CPOL =  SPI_CPOL_High;                        
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                     
  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);                                        
}
 u8 read_data()
{
	u8 ch;
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)	//查询发送器是否为空						{
		ch = SPI_I2S_ReceiveData(SPI2); 
	}
	return ch;
}

void send_data(u8 ch)
{
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)	//查询接收器是否非空			
	{
		SPI_I2S_SendData(SPI2,ch);
	}
}

 
上面的发送方式是采用查询的方式,在想要发送数据的时候调用。
如果想要周期性的发送,或者采用中断发送,可以在想要发送的时候设置使能TXE的中断,变回当TXE位置位以后进入发送中断。
也可以打开接收中断使能,这样当外部有数据到达时,便会自动进入到中断,这是可以对接收到的数据进行处理。
总的来看,SPI通信的使用方法跟SCI是非常像的,所以通信协议的制定可以参考一起拿使用SCI时的方式,一般来讲多用SPI于外部器件如Flash,EEPROM,AD等通信,SPI的速度快,简单易操作,非常常用。
 
 
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值