cancel
Showing results for 
Search instead for 
Did you mean: 

Help implementing SPI using just registers

LLope.31
Associate III

Hello everyone,

I am having trouble communicating with CC1101 radio SPI slave. With HAL, the transfers work well and I am able to read every register, but because I am using stm32f042 MCU, I'm low on flash memory because I'm also using USB CDC. So I'm trying to control the SPI1 peripheral using it's registers. Here is the code for the transfer and the init:

void SPI1_Init(void) {
/* full duplex master, 8 bit transfer, default phase and polarity */
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_SPE | SPI_CR1_SSM | SPI_CR1_SSI;
/* Disable receive FIFO*/
SPI1->CR2 = SPI_CR2_FRXTH;
}

void SPI1_Transfer(uint8_t *outp, uint8_t *inp, int count) {
while(count--) {
while(!(SPI1->SR & SPI_SR_TXE))
;
*(volatile uint8_t *)&SPI1->DR = *outp++;
while(!(SPI1->SR & SPI_SR_RXNE))
;
*inp++ = *(volatile uint8_t *)&SPI1->DR;
}
}

 The problem is that it gets stuck on the while(!(SPI1->SR & SPI_SR_TXE)) loop. It seems the TXE flag is never set. I also have initialized MISO, MOSI and SCK in .ioc as what they are (they are now orange in color in the pinout diagram). Can someone help me figure out what I am missing? Also, here is the read register function which I haven't been able to test due to the issue:

uint8_t readReg(uint8_t addr){
uint8_t value;
uint8_t address = addr | 0x80;
uint8_t zero = 0x00;
HAL_GPIO_WritePin(GPIOA, NSS_Pin, GPIO_PIN_RESET);
SPI1_Transfer(&address, &value, 1);
SPI1_Transfer(&zero, &value, 1);
HAL_GPIO_WritePin(GPIOA, NSS_Pin, GPIO_PIN_SET);
return value;
}

 And also, because I am very tight on flash, if someone could help me setting up the hardware NSS using the registers would be awesome, as I am not sure how to do so, I know it evolves setting the SSM register but I am not sure If I need to set anything else.

Thank you

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

Is the SPI1 clock enabled?

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

4 REPLIES 4
TDK
Guru

Is the SPI1 clock enabled?

If you feel a post has answered your question, please click "Accept as Solution".

Thanks, I did not realize that. i called __HAL_RCC_SPI1_CLK_ENABLE(); and it fixed the issue.

Can you also help me with using the hardware NSS? I have modified the function to get the SSOE bit to 1:

void SPI1_Init(void) {
/* full duplex master, 8 bit transfer, default phase and polarity */
//SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_SPE | SPI_CR1_SSM | SPI_CR1_SSI;
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_SPE | SPI_CR1_SSI;
/* Disable receive FIFO */
SPI1->CR2 = SPI_CR2_FRXTH | SPI_CR2_SSOE;
//SPI1->CR2 = SPI_CR2_FRXTH;
}

 After running it now gets stuck on

while(!(SPI1->SR & SPI_SR_RXNE))

Do I need to do some special initialization to the NSS GPIO pin? All I did was leave it as an output on the .ioc

TDK
Guru

If you're controlling the CS pin manually as a GPIO output pin, you want software NSS. Why do you want to change it from what is currently working?

Just a few notes: You generally shouldn't enable the peripheral (SPE bit) before you finish setting it up.

Writing over CR2 clobbers the current contents. It's not killing you here, but only because the hardware handles it correctly and fixes the error.

If you feel a post has answered your question, please click "Accept as Solution".

Ok thanks, it was actually to save some flash memory, but because on another post you solved that problem for me I will actually just use HAL for SPI since I got more flash now, thank you for the help