// // Created by cfif on 16.09.22. // #include #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; }