#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 }