KED/ked/csl/stm32f042/Src/imp_spi.c

182 lines
4.0 KiB

#include "spi.h"
#include "usart.h"
//#define SPI_BASE ((SPI_TypeDef *)spiBase_Addr_List[spi_hw_ch])
// https://controllerstech.com/spi-using-registers-in-stm32/
/*
void spiInit(spiCH_t spi_hw_ch)
{
spiReset(spi_hw_ch);
// TODO implement bittwiddeling etc. for generic SPI init
RCC->APB2ENR |= (1<<12); // Enable SPI1 CLock
//SPI1->CR1 |= (1<<0)|(1<<1); // CPOL=1, CPHA=1
SPI_BASE->CR1 |= (1<<2) | (1 << 1);
//SPI1->CR1 |= (1<<2); // Master Mode
SPI_BASE->CR1 |= (1 << 2);
//SPI1->CR1 |= (3<<3); // BR[2:0] = 011: fPCLK/16, PCLK2 = 80MHz, SPI clk = 5MHz
SPI_BASE-> CR1 |= (3<<3);
//SPI1->CR1 &= ~(1<<7); // LSBFIRST = 0, MSB first
SPI_BASE->CR1 &= ~(1<<7);
//SPI1->CR1 |= (1<<8) | (1<<9); // SSM=1, SSi=1 -> Software Slave Management
SPI_BASE->CR1 |= (1 << 8) | (1 << 9);
//SPI1->CR1 &= ~(1<<10); // RXONLY = 0, full-duplex
SPI_BASE->CR1 &= ~(1<<10);
//SPI1->CR1 &= ~(1<<11); // DFF=0, 8 bit data
SPI_BASE->CR1 &= ~(1 << 11);
//SPI1->CR2 = 0;
SPI_BASE->CR2 = 0;
}
*/
void spiReset(spiCH_t spi_hw_ch)
{
if(spiBus_No[spi_hw_ch] == 1) {
RCC->APB1RSTR |= (1 << spiBus_Rst_bitPos[spi_hw_ch]);
RCC->APB1RSTR &= ~(1 << spiBus_Rst_bitPos[spi_hw_ch]);
print_Usart(usart2, "BUS 1\n\r");
return;
}
print_Usart(usart2, "BUS 2\n\r");
RCC->APB2RSTR |= (1 << spiBus_Rst_bitPos[spi_hw_ch]);
RCC->APB2RSTR &= ~(1 << spiBus_Rst_bitPos[spi_hw_ch]);
}
void spiEnableBus(spiCH_t spi_hw_ch)
{
if(spiBus_No[spi_hw_ch] == 1) {
print_Usart(usart2,"BUS EN 1\n\r");
RCC->APB1ENR |= (1 << spiBus_En_bitPos[spi_hw_ch]);
return;
}
print_Usart(usart2,"BUS EN 2\n\r");
RCC->APB2ENR |= (1 << spiBus_En_bitPos[spi_hw_ch]);
}
void spiEnable(spiCH_t spi_hw_ch)
{
//SPI1->CR1 |= (1<<8) | (1<<9); // SSM=1, SSi=1 -> Software Slave Management
//SPI_BASE->CR1 |= (1 << 8) | (1 << 9);
SPI_BASE->CR1 |= SPI_CR1_SPE;
}
void spiDissable(spiCH_t spi_hw_ch)
{
SPI_BASE->CR1 &= ~SPI_CR1_SPE;
}
void spiSetMode(spiCH_t spi_hw_ch, spi_mode_t mode)
{
SPI_BASE->CR1 &= ~(mode << SPI_CR1_MSTR_Pos);
SPI_BASE->CR1 |= mode << SPI_CR1_MSTR_Pos;
}
void spiSetPolarity(spiCH_t spi_hw_ch, spi_clkPol_t clkPol)
{
// reset
SPI_BASE->CR1 &= ~SPI_CR1_CPOL;
// set
SPI_BASE->CR1 |= clkPol << SPI_CR1_CPOL_Pos;
}
void spiSetPhase(spiCH_t spi_hw_ch, spi_phase_t phase)
{
// reset
SPI_BASE->CR1 &= ~(phase << SPI_CR1_CPHA_Pos);
// set
SPI_BASE->CR1 |= phase << SPI_CR1_CPHA_Pos;
}
void spiSetFrameFormat(spiCH_t spi_hw_ch, spi_framef_t framef)
{
// reset
SPI_BASE->CR1 &= ~SPI_CR1_LSBFIRST;
// set
SPI_BASE->CR1 |= framef << SPI_CR1_LSBFIRST_Pos;
}
spi_framef_t spiGetFrameFormat(spiCH_t spi_hw_ch)
{
return (spi_framef_t)(SPI_BASE->CR1 & SPI_CR1_LSBFIRST) >> SPI_CR1_LSBFIRST_Pos;
}
void spiSetClockPrescaler(spiCH_t spi_hw_ch, uint32_t clkDiv)
{
// reset
SPI_BASE->CR1 &= ~SPI_CR1_BR;
// set
SPI_BASE->CR1 |= (clkDiv << SPI_CR1_BR_Pos) & SPI_CR1_BR;
}
void spiSetComMode(spiCH_t spi_hw_ch, spi_comMode_t comMode)
{
// reset
SPI_BASE->CR1 &= ~SPI_CR1_RXONLY;
// set
SPI_BASE->CR1 |= comMode << SPI_CR1_RXONLY_Pos;
}
void spiSetSoftwareSlaveManagement(spiCH_t spi_hw_ch, uint8_t logic)
{
SPI_BASE->CR1 &= ~SPI_CR1_SSM;
if(logic){
SPI_BASE->CR1 |= SPI_CR1_SSM;
}
}
void spiSetInternalSlaveSelect(spiCH_t spi_hw_ch, uint8_t logic)
{
SPI_BASE->CR1 &= ~SPI_CR1_SSI;
if(logic) {
SPI_BASE->CR1 |= SPI_CR1_SSI;
}
}
uint8_t spiTrx(spiCH_t spi_hw_ch, uint8_t tx_data)
{
uint8_t data;
// example
// wait for BSY bit to Reset -> This will indicate that SPI is not busy in communication
while (((SPI1->SR)&(1<<7)));
//SPI1->DR = tx_data; // send data
*(uint8_t*)&(SPI_BASE->DR) = tx_data;
// Wait for RXNE to set -> This will indicate that the Rx buffer is not empty
while (!((SPI1->SR) &(1<<0)));
data = SPI1->DR;
return data;
// implementation 2. step
#if 0
// wait for SPY ready
while((SPI_BASE->SR) & (1 << 7));
// load tx data
SPI_BASE->DR = tx_data;
// Wait for RXNE flag to be set which indicates transmit complete
while(!((SPI_BASE->SR) & (1<<0));
return SPI_BASE->DR;
#endif
}