STM8使用SPI通信需要注意的几个问题

概述:

     在使用STM8L101F3单片机,SPI通信读取三轴传感器ADXL362数据时,出现了一系列的问题,在这里做个笔记,也希望可以给大家一个小的参考。

问题一:

      在SPI初始化过程中,没有初始化MISO,MOSI,SCLK三个引脚,导致在通信过程中写数据读数据出现问题。所以在这里贴出测试后可以正常运行的SPI初始化代码。(STM8L101F3,使用官方标准库)

#include "stm8l10x.h"
#include "stm8l10x_spi.h"
#include "stm8l10x_gpio.h"

/***************************SPI相关定义**************************/
#define SPI_GPIO_PORT           GPIOB
#define SPI_CS_PIN              GPIO_Pin_4
#define SPI_SCLK_PIN            GPIO_Pin_5
#define SPI_MOSI_PIN            GPIO_Pin_6
#define SPI_MISO_PIN            GPIO_Pin_7

/*以下设置为符合我三轴传感器对应配置*/
#define SPI_FIRSTBIT_TYPE       SPI_FirstBit_MSB
#define SPI_SPEED_PRESC         SPI_BaudRatePrescaler_4
#define SPI_MODE                SPI_Mode_Master
#define SPI_CPOL                SPI_CPOL_Low
#define SPI_CPHA                SPI_CPHA_1Edge
#define SPI_DATA_MODE           SPI_Direction_2Lines_FullDuplex
#define SPI_CS_CTRL             SPI_NSS_Soft


/*SPI初始化*/
void spi_init(void)
{
  //开启SPI外设时钟
  CLK_PeripheralClockConfig(CLK_Peripheral_SPI, ENABLE);
  //SPI重置
  SPI_DeInit();
  //SPI相关GPIO初始化
  GPIO_Init(SPI_GPIO_PORT, SPI_CS_PIN, GPIO_Mode_Out_PP_High_Fast);
  GPIO_Init(SPI_GPIO_PORT, SPI_SCLK_PIN, GPIO_Mode_Out_PP_High_Fast);
  GPIO_Init(SPI_GPIO_PORT, SPI_MOSI_PIN, GPIO_Mode_Out_PP_High_Fast);
  //此设置很关键,作为主设备一定要将其设置为输入
  GPIO_Init(SPI_GPIO_PORT, SPI_MISO_PIN, GPIO_Mode_In_PU_No_IT);
  //SPI初始化
  SPI_Init(SPI_FIRSTBIT_TYPE, SPI_SPEED_PRESC, SPI_MODE, SPI_CPOL, SPI_CPHA,           
  SPI_DATA_MODE, SPI_CS_CTRL);
  //SPI启动
  SPI_Cmd(ENABLE);
}

问题二:

     数据写入与数据读取问题,我在使用过程中,官方库提供了两个函数,一个是写入数据一个是接收数据。因为在我的应用中是需要先写两个字节命令及地址数据,然后再去读后面的数据。故在使用中即先使用SPI_SendData()函数写入数据就并未去读取对应的接收数据。(其实SPI通信读取数据,就是要先写入才能读取,只有写入从设备才有时钟。)然后开始读取数据,发现读取到的数据总是不对,后来通过仪器分析,发现回应的数据中有我需要的数据,但我读到的第一个数据其实是我写入时第一个字节回应的数据,也就是说在写入数据时,如果我们不把对应的数据读出,后面写入数据后再去读取数据,其实还是读取到的第一个字节写入时返回的数据,后面的数据并不会覆盖更新。这里贴一下,更改过后的代码。

/*此部分为写入读取数据部分代码,在读取写入数据前后要记得打开及关闭片选信号*/

void spi_write(uint8_t data)
{
    while(SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
    SPI_SendData(data);
    //一定不可省略不写,若不接收对应数据,马上去读数据就会造成读到的数据不对。
    while (SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET);
    u8 dd = SPI_ReceiveData();
}

uint8_t spi_read()
{
    //选择一个无效数据发送(自定义,只是为了给从设备提供时钟),然后读取到对应数据
    uint8_t data = 0xff;
    while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);
    SPI_SendData(data);
    while (SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET);
    uint8_t rxdata  = SPI_ReceiveData();
    return rxdata;
}

//写入数据并读取需要的数据
void spi_write2read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata, uint8_t rlen)
{
    uint8_t i;
    if (wdata == NULL || rdata == NULL) {
        return;
    }
    //写数据
    for (i = 0; i < wlen; i++) {
        spi_write(wdata[i]);
    }
    //读数据
    for (i = 0; i < rlen; i++) {
        rdata[i] = spi_read();
    }
}

     总结:

              对于单片机上使用SPI又多了一点认识,哈哈。

猜你喜欢

转载自blog.csdn.net/Dancer__Sky/article/details/82148560