STM8单片机教程–10 SPI通讯
注意:本文案需要配合无际单片机编程-STM8单片机教程视频学习。
注意:本文案需要配合无际单片机编程-STM8单片机教程视频学习。
SPI通讯
一 本节课的目标
- 学习了解SPI 通讯原理
- 完成STM8单片机的SPI的驱动
- 获取SX1278的软件版本号
二 硬件介绍:
打开“lora门磁&遥控器“的主板原理图,如图所示:
本章节涉及的电路,如下图所示:
通过上图,可以看出射频芯片SX1278和单片机通过SPI接口来通讯的。 本节课就是通过单片机的SPI接口来完成SX1278芯片的SPI接口通讯。
三 SPI通讯原理简单介绍(理解)
典型的连线图:
简单的原理分析:
SCK : 决定数据的速率
数据: 1高电平 0 低电平
SPI的四种通讯模式:
spi协议时序图和四种模式实际应用详解 (qq.com) 大家可以看一下这个资料:
首先我们要了解两个特殊寄存器 分别是 CPOL (Clock POlarity)和 CPHA (Clock PHAse)。
CPOL:配置SPI总线的极性
CPHA: 配置SPI总线的相位
SPI总线极性的概念: 空闲的时候时钟信号是高电平还是低电平
CPOL = 1; SCK 空闲是高电平
CPOL = 0; SCK 空闲是低电平
SPI总线的相位的概念:
一个时钟周期有2个跳变沿,相位决定从那个跳变开始采集数据
CPHA = 0; 表示从第一个跳变 开始采集
CPHA = 1; 表示从第二个跳变 开始采集
SPI的单线 和双线 模式
单线:一般用于OLED屏幕灯单向通讯
双向:一般用于芯片之间的双向通讯
特别说明: 一般情况下,我们不用刻意去学习四种模式的具体细节,一般芯片资料里面都会告诉你芯片支持的模式:
例如:SX1278 收据手册中77页面。
四 官方提供例程(跳过)
五 SPI通信 标准库函数简单介绍(了解)
void SPI_DeInit(void);
void SPI_Init(SPI_FirstBit_TypeDef SPI_FirstBit, SPI_BaudRatePrescaler_TypeDef
SPI_BaudRatePrescaler, SPI_Mode_TypeDef SPI_Mode, SPI_CPOL_TypeDef
SPI_CPOL, SPI_CPHA_TypeDef SPI_CPHA, SPI_DirectionMode_TypeDef
SPI_DirectionMode, SPI_NSS_TypeDef SPI_NSS);
void SPI_Cmd(FunctionalState NewState);
void SPI_ITConfig(SPI_IT_TypeDef SPI_IT, FunctionalState NewState);
void SPI_NSSInternalSoftwareCmd(FunctionalState NewState);
void SPI_BiDirectionalLineConfig(SPI_Direction_TypeDef SPI_Direction);
void SPI_SendData(uint8_t Data);
uint8_t SPI_ReceiveData(void);
FlagStatus SPI_GetFlagStatus(SPI_FLAG_TypeDef SPI_FLAG);
ITStatus SPI_GetITStatus(SPI_IT_TypeDef SPI_IT);
void SPI_ClearFlag(void);
void SPI_ClearITPendingBit(void);
六 驱动代码实现(掌握)
1.驱动代码编辑:
复制标准工程并命名为 “测试例程-SPI通讯“ 如下图所示:
打开工程,修改测试例程中的编辑main.c 函数:
2 main.c 源代码
#include “stm8l10x.h”
#define RF_RST_PORT GPIOC
#define RF_RST_PIN GPIO_Pin_0
#define RF_RST_HIGH GPIO_SetBits(RF_RST_PORT,RF_RST_PIN)
#define RF_RST_LOW GPIO_ResetBits(RF_RST_PORT,RF_RST_PIN)
//输入
#define MISO_PORT GPIOB
#define MISO_PIN GPIO_Pin_7
#define MISO_DATABIT GPIO_ReadInputDataBit(MISO_PORT,MISO_PIN)
//输出
#define MOSI_PORT GPIOB
#define MOSI_PIN GPIO_Pin_6
#define MOSI_HIGH GPIO_SetBits(MOSI_PORT,MOSI_PIN)
#define MOSI_LOW GPIO_ResetBits(MOSI_PORT,MOSI_PIN)
#define SCK_PORT GPIOB
#define SCK_PIN GPIO_Pin_5
#define SCK_HIGH GPIO_SetBits(SCK_PORT,SCK_PIN)
#define SCK_LOW GPIO_ResetBits(SCK_PORT,SCK_PIN)
//CS
#define CS_PORT GPIOB
#define CS_PIN GPIO_Pin_4
#define CS_HIGH GPIO_SetBits(CS_PORT,CS_PIN)
#define CS_LOW GPIO_ResetBits(CS_PORT,CS_PIN)
//输入
#define RF_IRQ_DIO0_PORT GPIOB
#define RF_IRQ_DIO0_PIN GPIO_Pin_0
#define RF_IRQ_DIO0_DATABIT GPIO_ReadInputDataBit(RF_IRQ_DIO0_PORT,RF_IRQ_DIO0_PIN)
unsigned char SpiInOut(unsigned char outData)
{
unsigned char rxData = 0;
while(SPI_GetFlagStatus(SPI_FLAG_TXE ) == RESET );
SPI_SendData(outData);
while(SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET );
rxData=SPI_ReceiveData();
return rxData;
}
void sx1278WriteBuffer(unsigned char addr,unsigned char *buffer,unsigned char size)
{
unsigned char i;
CS_LOW;
SpiInOut(addr | 0x80 );
for( i = 0; i < size; i++ )
{
SpiInOut(buffer[i] );
}
CS_HIGH;
}
///SX1278 写寄存器操作 STM8L101F3 SPI 只有
void sx1278ReadBuffer(unsigned char addr,unsigned char *buffer,unsigned char size)
{
unsigned char i;
CS_LOW;
SpiInOut(addr & 0x7F);
for( i = 0; i < size; i++ )
{
buffer[i] = SpiInOut(0);
}
CS_HIGH;
}
static void hal_Sx1278_GpioInt(void)
{
GPIO_Init(RF_RST_PORT,RF_RST_PIN , GPIO_Mode_Out_PP_Low_Slow);
GPIO_Init(SCK_PORT,SCK_PIN , GPIO_Mode_Out_PP_Low_Fast);
GPIO_Init(MISO_PORT,MISO_PIN , GPIO_Mode_In_PU_No_IT);
GPIO_Init(MOSI_PORT,MOSI_PIN , GPIO_Mode_Out_PP_Low_Fast);
GPIO_Init(CS_PORT,CS_PIN , GPIO_Mode_Out_PP_Low_Fast);
GPIO_Init(RF_IRQ_DIO0_PORT,RF_IRQ_DIO0_PIN,GPIO_Mode_In_PU_No_IT);
CS_HIGH;
RF_RST_HIGH;
}
void hal_spi_Config(void)
{
//SPI 时钟配置
CLK_PeripheralClockConfig(CLK_Peripheral_SPI, ENABLE);
/////SPI 相关的 GPIO 配置
hal_Sx1278_GpioInt();
//SPI参数初始化
SPI_Init(SPI_FirstBit_MSB, SPI_BaudRatePrescaler_2, SPI_Mode_Master,SPI_CPOL_Low, SPI_CPHA_1Edge, SPI_Direction_2Lines_FullDuplex,SPI_NSS_Soft);
//使能SPI
SPI_Cmd(ENABLE);
}
void main(void)
{
static uint8_t versionvalue = 0;
///设置系统时钟 16M
CLK_MasterPrescalerConfig(CLK_MasterPrescaler_HSIDiv1);
//SPI 初始化
hal_spi_Config();
////多读取几次,确保通讯正常
sx1278ReadBuffer(0x42, &versionvalue,1); //读操作
sx1278ReadBuffer(0x42, &versionvalue,1);
sx1278ReadBuffer(0x42, &versionvalue,1);
sx1278ReadBuffer(0x42, &versionvalue,1);
sx1278ReadBuffer(0X01, &versionvalue,1);
versionvalue = 8;
sx1278WriteBuffer(0X01,&versionvalue,1); ////写操作
sx1278ReadBuffer(0X01, &versionvalue,1);
sx1278ReadBuffer(0X01, &versionvalue,1);
sx1278ReadBuffer(0x42, &versionvalue,1);
sx1278ReadBuffer(0x42, &versionvalue,1);
while (1)
{
}
}
七 实验需要的器材和硬件连接方式
1.实验需要的器材:
2.连接图如下:
连接方式:
- ST-LINK 和门磁主板的烧录接口P3的丝印要一一对应。 如上图蓝色所示:
- VCC —- 3.3V
- GND —- GND
- SWIM —- SWIM
- REST —- RST
- 电池供电 3.7V 锂电池插到J1 接口,如上图黄色所示。
- ST LINK 插到电脑USB接口。 如上图红色所示。
- 建议大家都可以自行购买一个USB Hub。 这样测试更加方便,也可以避免电脑的USB插拔次数过多而老化。
八 功能测试
功能测试正常。
本小节结束