111 lines
3.4 KiB
C
111 lines
3.4 KiB
C
//
|
||
// Created by cfif on 16.09.22.
|
||
//
|
||
#include <SystemDelayInterface.h>
|
||
#include "SpiPortNation.h"
|
||
|
||
|
||
tSpiPortNation SpiPort_Init(
|
||
SPI_Module *spi,
|
||
uint16_t spiFrameBit,
|
||
tGpioPin *chipSelect
|
||
) {
|
||
SPI_InitType spi_init_struct;
|
||
|
||
spi_init_struct.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
|
||
spi_init_struct.SpiMode = SPI_MODE_MASTER;
|
||
spi_init_struct.DataLen = spiFrameBit;
|
||
spi_init_struct.CLKPOL = SPI_CLKPOL_LOW;
|
||
spi_init_struct.CLKPHA = SPI_CLKPHA_FIRST_EDGE;
|
||
spi_init_struct.NSS = SPI_NSS_SOFT;
|
||
spi_init_struct.BaudRatePres = SPI_BR_PRESCALER_8;
|
||
spi_init_struct.FirstBit = SPI_FB_MSB;
|
||
SPI_Init(spi, &spi_init_struct);
|
||
|
||
SPI_Enable(spi, ENABLE);
|
||
|
||
tSpiPortNation spiPort = {
|
||
.spi = spi,
|
||
.chipSelect = chipSelect
|
||
};
|
||
|
||
return spiPort;
|
||
}
|
||
|
||
|
||
static bool vSpiPortTransmit(tSpiPortNation *env, const uint16_t *data, uint32_t timeout) {
|
||
|
||
uint32_t endMs = SystemGetMs() + timeout;
|
||
|
||
while ((timeout == SystemWaitForever) || (endMs > SystemGetMs())) {
|
||
// Буфер передатчика пуст
|
||
if (SPI_I2S_GetStatus(env->spi, SPI_I2S_TE_FLAG)) {
|
||
SPI_I2S_TransmitData(env->spi, *data);
|
||
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
static bool vSpiPortReceive(tSpiPortNation *env, uint16_t *data, uint32_t timeout) {
|
||
|
||
uint32_t endMs = SystemGetMs() + timeout;
|
||
while ((timeout == SystemWaitForever) || (endMs > SystemGetMs())) {
|
||
// В буфере приемника еcть данные
|
||
if (SPI_I2S_GetStatus(env->spi, SPI_I2S_RNE_FLAG)) {
|
||
*data = SPI_I2S_ReceiveData(env->spi);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
static bool vSpiPortSovTransmit(tSpiPortNation *env, const uint16_t *data, uint32_t timeout) {
|
||
|
||
uint32_t endMs = SystemGetMs() + timeout;
|
||
|
||
while ((timeout == SystemWaitForever) || (endMs > SystemGetMs())) {
|
||
// Буфер передатчика пуст
|
||
if (SPI_I2S_GetStatus(env->spi, SPI_I2S_TE_FLAG)) {
|
||
SPI_I2S_TransmitData(env->spi, *data);vSpiPortReceive (env,data,timeout);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
static bool vSpiPortSovReceive(tSpiPortNation *env, uint16_t *data, uint32_t timeout) {
|
||
uint32_t endMs = SystemGetMs() + timeout;
|
||
vSpiPortTransmit (env,data,timeout);
|
||
while ((timeout == SystemWaitForever) || (endMs > SystemGetMs())) {
|
||
// В буфере приемника еcть данные
|
||
if (SPI_I2S_GetStatus(env->spi, SPI_I2S_RNE_FLAG)) {
|
||
*data = SPI_I2S_ReceiveData(env->spi);
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//простая реализация chipSelect для одного утройства на шине
|
||
static bool vSpiPortChipSelectMono(tSpiPortNation *env, uint32_t timeout) {
|
||
GpioPinEnable(env->chipSelect);
|
||
return true;
|
||
}
|
||
|
||
static bool vSpiPortChipReleaseMono(tSpiPortNation *env, uint32_t timeout) {
|
||
GpioPinDisable(env->chipSelect);
|
||
return true;
|
||
}
|
||
|
||
tSpiPortIO SpiPort_GetIo(tSpiPortNation *env) {
|
||
tSpiPortIO io = {
|
||
.env = env,
|
||
.receive = (SpiPortIOTransaction) vSpiPortSovReceive,
|
||
.transmit = (SpiPortIOTransaction) vSpiPortSovTransmit,
|
||
.chipSelect =(SpiPortChipArbitrage) vSpiPortChipSelectMono,
|
||
.chipRelease =(SpiPortChipArbitrage) vSpiPortChipReleaseMono,
|
||
};
|
||
return io;
|
||
} |