打印

【连载】STM8L051F3_13_SPI应用

[复制链接]
1478|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
caijie001|  楼主 | 2018-5-24 18:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本文介绍STM8L051F3的SPI相关知识。内容分为以下几部分:
  • SPI简介
  • OLED显示
1、SPI简介SPI(Serial peripheral interface):串行外围接口。SPI可以与外部设备进行半/全双工、同步、串行通讯,它可以作为主设备来为外部设备提供通讯时钟,同时还可以配置为多主机模式运行。SPI的主要特点如下:
  • 全双工同步传输(3线)
  • 在2线或没有双向传输的数据线的情况下的单工同步传输
  • 主机或从机运行模式
  • 主模式频率(最大fSYSCLK/2)
  • 从模式频率(最大fSYSCLK/2)
  • 快速通讯最大SPI速度:8MHz
  • 在主模式或从模式都可以硬件或软件管理NSS(片选引脚)
  • 可编程时钟极性和相位
  • 可编程数据顺序是高位或低位先发送
  • 在中断功能中有独立的发送和接收标志位
  • SPI总线忙状态标志
  • 具备中断功能的主模式下故障和溢出标志
  • 具备DMA功能(发送和接收请求)的1字节发送和接收缓存器
  • 具备可靠通讯的硬件CRC:
    • CRC值在发送模式作为最后一个字节发送
    • 可对最后接收的字节进行CRC错误检测
  • 唤醒功能:
    • 只有在全双工或半双工的发送模式下可以将MCU从低功耗模式下唤醒


SPI经过4个引脚连接外部设备:
  • MISO:主输入/从输出数据;在主模式用于接收数据,在从模式用于发送数据
  • MOSI:主输出/从输入数据;在主模式用于输出数据,在从模式用于接收数据
  • SCK:主模式下时钟输出,从模式下时钟输入
  • NSS:从机选择;这是一个用于选择从设备的引脚,相当于‘片选’,让主设备与从设备独立通讯,避免数据线的占用。从机的NSS可以由主机的标准IO口输入,SPI进入主机模式失败的状态:MSTR位重置,设备被配置为从模式
从机选择(NSS)引脚管理。通过配置SPI_CR2寄存器的SSM位可以设置使用硬件或软件管理NSS引脚:
  • 软件NSS管理(SSM=1):在这个配置下,从机选择的信息是有内部SPI_CR2寄存器SSI为决定的,外部NSS引脚可以用作其他用途
  • 硬件NSS管理(SSM=0):作为主机,该设备可以允许多主机功能;作为从机,NSS引脚作为输入,当NSS被拉低时说明从机被选中,否则NSS引脚为高电平
时钟相位与时钟极性。通过CPOL和CPHA位可以选择四种不同的时钟关系。CPOL(时钟极性)位控制在没有数据发送时时钟线的状态值,该位收主机和从机模式影响。如果CPOL位被重置,时钟引脚在空闲时是低电平,如果CPOL位被置位,时钟引脚在空闲状态时高电平。
如果CPHA(时钟相位)位被置位,第二个时钟引脚的边沿(如果CPOL位是重置的就是下降沿,如果CPOL为是置位的就是上升沿)采样最高位,在第一个时钟状态改变的期间数据被锁存。如果CPHA(时钟相位)位被重置,第一个时钟引脚的边沿(如果CPOL位是置位的就是下降沿,如果CPOL为是重置的就是上升沿)采样最高位,在第二个时钟状态改变的期间数据被锁存。如下图:


配置SPI为从机。在从机模式下,时钟线是由主机设备输入时钟信号,由SPI_CR1寄存器的BR[2:0]位设置,不影响数据传输数率。从机模式的配置步骤如下:
1)配置CPOL和CPHA位来定义数据发送与串行时钟四种关系之一,为了数据正确的传输,主机与 从机的配置应该一致
2)数据结构(取决于SPI_CR1寄存器的LSBFIRST位决定的高位或低位先发送)必须与主机一致
3)在硬件模式,NSS引脚在数据传输期间必须保持低电平;在软件模式通过置位和清除SPI_CR2寄 存器的SSI位实现控制
4)清除MSTR位和设置SPE位来指定引脚作为替换功能
配置SPI为主机。在主机模式下,串行时钟在SCK引脚产生。配置步骤如下:
1)配置SPI_CR1的BR[2:0]位来定义串行时钟的波特率
2)配置CPOL和CPHA位来定义数据发送与串行时钟四种关系之一
3)配置SPI_CR1寄存器的LSBFIRST位来定义数据结构
4)在硬件模式下,在完整的数据传输序列中,NSS引脚连接到一个高电平信号;在软件模式下,设 置SPI_CR2的SSM和SSI位。
5)设置MSTR和SPE位
SPI还有单工通讯功能,数据发送和接收过程、CRC校验等等功能的详细介绍可以参考官方手册RM0031第30章。
2、OLED显示2.1 SPI配置本小节介绍OLED的SPI通讯(默认使用技新的7Pin-0.96寸OLED模块)。实现通过STM8L051F3的硬件SPI与OLED通讯,并让OLED显示:OLED TEST。使用的例程:STM8L051F3_13_SPI。这里需要注意的是,与OLED的SPI通讯实际上是只使用了SPI的MOSI、SCK、NSS引脚,而OLED还需要两个(RES与DC)控制引脚(RES与DC引脚在oled.c与oled.h文件中定义和初始化)。
整体的OLED与STM8L051F3核心板的接线为(电源VCC与GND接V与G):D0--->PB5(SCK)、D1--->PB6(MOSI)、RES--->PB0、DC--->PB3、CS--->PB4(NSS)。其中RES与DC的引脚在oled.h和oled.c文件中定义初始化。
SPI(STM8L051F3是在用的是SPI1)的配置步骤如下:
1)使能SPI1外设时钟
2)配置MISO、MOSI、SCK、NSS引脚
3)拉高NSS引脚
4)初始化SPI1:高位先发送、SPI时钟4分频、SPI主模式、空闲相位高、第二个时钟源发送数据、NSS引脚软件控制、CRC校验0x55
5)使能SPI1
SPI1读写一字节步骤:
1)等待SPI1空闲
2)SPI1发送一字节数据
3)等待SPI1接收一字节数据
4)读取SPI1接收的数据
2.2 例程介绍SPI初始化配置以及读写函数实现在spi.c文件下:
void SPI_Config(void)
{
  /* 使能SPI1时钟 */
  CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
  /* 配置MISO引脚为上拉输入 */
  GPIO_Init(SPI_MISO_GPIO_PORT, SPI_MISO_GPIO_PINS, GPIO_Mode_In_PU_No_IT);
  /* 配置MOSI引脚为推挽输出 */
  GPIO_Init(SPI_MOSI_GPIO_PORT, SPI_MOSI_GPIO_PINS, GPIO_Mode_Out_PP_High_Fast);
  /* 配置SCK引脚为推挽输出 */
  GPIO_Init(SPI_SCK_GPIO_PORT, SPI_SCK_GPIO_PINS, GPIO_Mode_Out_PP_High_Fast);
  /* 配置NSS引脚为推挽输出 */
  GPIO_Init(SPI_NSS_GPIO_PORT, SPI_NSS_GPIO_PINS, GPIO_Mode_Out_PP_High_Fast);
  /* 拉高NSS引脚 */
  SPI_NSS_HIGH();
  /* 初始化SPI1,高位先发送, 时钟8分频,SPI主模式,空闲相位高,
     第二个时钟沿发送数据,NSS引脚软件控制,CRC校验:0x55
*/
  SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_4, SPI_Mode_Master,
           SPI_CPOL_High, SPI_CPHA_2Edge, SPI_Direction_2Lines_FullDuplex, SPI_NSS_Soft, 0x07);
  SPI_Cmd(SPI1, ENABLE);      //使能SPI
}
uint8_t SPI_RW_Byte(uint8_t data)
{
  uint8_t temp;
  /* 等待SPI1空闲 */
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE)== RESET);
  /* SPI1发送数据 */
  SPI_SendData(SPI1, data);
  /* 等待接受一字节数据 */
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE)== RESET);
  /* 读取接收的数据 */
  temp = SPI_ReceiveData(SPI1);
  /* 返回接收的数据 */
return temp;
}
spi.h文件中定义SPI1相关引脚:
/* 定义SPI的IO PORT与PIN */
#define SPI_MISO_GPIO_PORT  (GPIOB)
#define SPI_MISO_GPIO_PINS  (GPIO_Pin_7)

#define SPI_MOSI_GPIO_PORT  (GPIOB)
#define SPI_MOSI_GPIO_PINS  (GPIO_Pin_6)
#define SPI_SCK_GPIO_PORT  (GPIOB)
#define SPI_SCK_GPIO_PINS  (GPIO_Pin_5)
#define SPI_NSS_GPIO_PORT  (GPIOB)
#define SPI_NSS_GPIO_PINS  (GPIO_Pin_4)
#define SPI_NSS_LOW()   GPIO_ResetBits(SPI_NSS_GPIO_PORT, SPI_NSS_GPIO_PINS)
#define SPI_NSS_HIGH()  GPIO_SetBits(SPI_NSS_GPIO_PORT, SPI_NSS_GPIO_PINS)
主函数如下:
void main(void)
{
  LED_Init();   //初始化LED
  SPI_Config();
  OLED_Init(); //OLED初始化
  OLED_Clear();  //OLED清屏
  OLED_ShowString(30,0,"OLED TEST");//OLED显示  OLED TEST
while(1)
{
    delay_ms(300);
    GPIO_ToggleBits(LED1_GPIO_PORT, LED1_GPIO_PINS); //切换LED1状态
}
}
使用ST-LINK把程序下载到开发板,LED1闪烁,OLED显示:OLED TEST。效果如下:



相关帖子

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

本版积分规则

个人签名:21ic公开课专区:http://open.21ic.com/ 21ic资料下载中心:http://dl.21ic.com/ 21ic项目外包中心:http://project.21ic.com/ 杰杰欢迎大家有空常来赛事专区逛逛

131

主题

3790

帖子

63

粉丝