概述:
在使用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又多了一点认识,哈哈。
上一篇:ADC采样频率计算与时钟频率选择
下一篇:FLASH和EEPROM的区别
推荐阅读最新更新时间:2024-11-13 12:38
设计资源 培训 开发板 精华推荐
- 开源SCPI可编程精密电阻仪
- FRDM-HB2000-EVM: FRDM-HB2000-EVM: Freedom Platform for MC33HB2000, HSOP32, 10 A H-Bridge, RDSon 235mOhm max, Programmable Brushed DC Motor Driver
- CH55X_MSP
- NCP81239REFGEVB:USB 供电 4 开关降压升压控制器评估板
- 用于笔记本电脑的 MOSFET 功率驱动器
- LT1170CQ、5V/5A 正向转换器的典型应用
- C2683633_WT588D 语音芯片方案验证板
- R1242S 30V 输入、3A 降压 DC/DC 转换器的典型应用
- STEVAL-MKSBOX1V1,SensorTile.box 无线多传感器开发套件,带有用于物联网和可穿戴传感器应用的用户友好应用程序
- 具有大接地回路电压的 LTC2862ACDD-2 RS485 链路的典型应用