41. SPI Dice Roll

Back To All Submissions
Previous Submission
Next Submission

Solving Approach

How do you plan to solve it?

 

 

Code

/*Paste your code here*/

void SPI_Init(SPI_Handle_t *pSPIHandle){

	//let's enable the clock here since it needs to be done everytime we initialise a peripheral
	SPI_PeriClockControl(pSPIHandle->pSPIx, ENABLE);

	//lets configure the SPI_CR1 register

	uint32_t tempReg = 0;

	//1. Configure the device mode
	tempReg |= pSPIHandle->SPIConfig.SPI_DeviceMode << SPI_CR1_MSTR;

	//2. Configure the bus config
	if(pSPIHandle->SPIConfig.SPI_BusConfig == SPI_BUS_CONFIG_FD){
		//clear the  bidi mode bit
		tempReg &= ~(1 << SPI_CR1_BIDIMODE);
	}
	else if(pSPIHandle->SPIConfig.SPI_BusConfig == SPI_BUS_CONFIG_HD)
	{
		//set the bidi mode bit
		tempReg |= (1 << SPI_CR1_BIDIMODE);
	}
	else if(pSPIHandle->SPIConfig.SPI_BusConfig == SPI_BUS_CONFIG_SIMPLEX_RXONLY){

		//clear the bidi mode bit
		tempReg &= ~(1 << SPI_CR1_BIDIMODE);

		//set the rxonly bit
		tempReg |= (1 << SPI_CR1_RXONLY);

	}

	//3. Configure the SPI SCLK speed
	tempReg |= (pSPIHandle->SPIConfig.SPI_SclkSpeed << SPI_CR1_BR);

	//4. Configure the DFF
	tempReg |= (pSPIHandle->SPIConfig.SPI_DFF << SPI_CR1_DFF);

	//5. Configure the CPOL
	tempReg |= (pSPIHandle->SPIConfig.SPI_CPOL << SPI_CR1_CPOL);

	//6. Configure the CPHA
	tempReg |= (pSPIHandle->SPIConfig.SPI_CPHA << SPI_CR1_CPHA);

	//7. Configure SSM
	tempReg |= (pSPIHandle->SPIConfig.SPI_SSM << SPI_CR1_SSM);

	pSPIHandle->pSPIx->CR1 = tempReg;


}

//This function is used to initialise the GPIO pins to behave as SPI2 pins
void SPI_GPIOInit()
{
	GPIO_Handle_t SPI2Pins;
	SPI2Pins.GPIO_PinConfig.GPIO_PinMode = GPIO_MODE_ALTFN;
	SPI2Pins.GPIO_PinConfig.GPIO_PinAltFundMode = 5;
	SPI2Pins.GPIO_PinConfig.GPIO_PinOPType = GPIO_OP_TYPE_PP; // based on SPI specification
	SPI2Pins.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_NO_PUPD;
	SPI2Pins.GPIO_PinConfig.GPIO_PinSpeed = GPIO_SPEED_HIGH;
	
	//SCLK
	SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_13;
	GPIO_Init(&SPI2Pins);

	//MOSI
	SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_15;
	GPIO_Init(&SPI2Pins);

	//MISO
	SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_14;
	GPIO_Init(&SPI2Pins);

	//NSS
	SPI2Pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NUM_12;
	GPIO_Init(&SPI2Pins);
	
}

//This function initialises the SPI config structure and also initialises the SPI peripheral
void SPI2_Init(void){
	SPI_Handle_t SPI2handle;
	//fill out the SPI configuration structure and pass it to SPI init to initialise the SPI peripheral
	SPI2handle.pSPIx = SPI2;
	SPI2handle.SPIConfig.SPI_BusConfig = SPI_BUS_CONFIG_FD;
	SPI2handle.SPIConfig.SPI_DeviceMode = SPI_DEVICE_MODE_MASTER;
	SPI2handle.SPIConfig.SPI_SclkSpeed = SPI_SCLK_SPEED_DIV2; //gives sclk of 8MHz
	SPI2handle.SPIConfig.SPI_DFF = SPI_DFF_8BITS;
	SPI2handle.SPIConfig.SPI_CPOL = SPI_CPOL_LOW;
	SPI2handle.SPIConfig.SPI_CPHA = SPI_CPHA_LOW;
	SPI2handle.SPIConfig.SPI_SSM = SPI_SSM_EN; //Software Slave Management enabled for NSS pin. NSS pin is ignored.

	SPI_Init(&SPI2handle);
}



int main()
{
	char user_data[] = "Hello world";
	SPI_GPIOInit(); //initialise the gpio pins for SPIx (maybe SPI1, SPI2, etc)
	GPIO_ButtonInit();
	SPI2_Init(); //initialise the SPI2 peripheral handle structure
	/*
	 * Note:
	 * For master: NSS output will be enabled when SSOE = 1. When SSOE = 1, SPE = 1, NSS = 0 (NSS is pulled to low when you enable the peripheral). NSS = 1 when SPE = 0
	*/
	SPI_SSOEConfig(SPI2, ENABLE);
	
	while(1)
	{
		while(GPIO_ReadFromInputPin(GPIOC, GPIO_PIN_NUM_13));

		delay();
		
		//enable the SPI peripheral
		SPI_PeripheralControl(SPI2, ENABLE);

		
		//SPI send data blocking call, send some data to trigger MODE2 on slave side for interrupt
		uint8_t request = 0x01;
        SPI_SendData(SPI2, &request, 1);

		/*
		 * Confirm if SPI is busy.
		 * Note: This is important otherwise the peripheral will get disabled immediately after sending data
		 */
		while(SPI_GetFlagStatus(SPI2, SPI_BUSY_FLAG));
		
		
//Send dummy to clock in slave response
		SPI_SendData(SPI2, &dummy_tx, 1);
		while (SPI_GetFlagStatus(SPI2, SPI_BUSY_FLAG));  // wait after dummy send
		
		 //3. Read the received byte
		SPI_ReceiveData(SPI2, &dice_value, 1);
		while (SPI_GetFlagStatus(SPI2, SPI_BUSY_FLAG));  // wait after receive


		//disable the SPI peripheral so we can see MOSI and CLK lines switch to idler on the analyser
		SPI_PeripheralControl(SPI2, DISABLE);
		
		// 5. Print result on serial terminal
        UART_PrintDiceValue(dice_value);
		
	}
	
}

 

Output

Video

Add a video of the output (know more)

 

 

 

 

 

Photo of Output

Add a photo of your hardware showing the output.

 

 

 

 

 

Screenshot of Serial Terminal 

Add a Screenshot of the serial terminal showing the output.


 

Was this helpful?
Upvote
Downvote