He escrito el siguiente código de inicialización SPI para SPI1 en mi microcontrolador STM32F030C8.
Aquí está la función que inicializa SPI1:
void fnSPI_Init()
{
SPI_InitTypeDef SPI1_Config;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);
/*****************MOSI, MISO SCLK GPIO Config********************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_0);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_0);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_0);
/******************Chip Select GPIO Config**********************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_15);
/******************SPI1 Config for RC522************************/
SPI1_Config.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI1_Config.SPI_Mode = SPI_Mode_Master;
SPI1_Config.SPI_DataSize = SPI_DataSize_8b;
SPI1_Config.SPI_CPOL = SPI_CPOL_Low;
SPI1_Config.SPI_CPHA = SPI_CPHA_1Edge;
SPI1_Config.SPI_NSS = SPI_NSS_Hard;
SPI1_Config.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI1_Config.SPI_FirstBit = SPI_FirstBit_MSB;
SPI1_Config.SPI_CRCPolynomial = 7;
SPI_Init(SPI1 , &SPI1_Config);
SPI_SSOutputCmd(SPI1, ENABLE);
SPI_Cmd(SPI1 , ENABLE);
}
Aquí, según la hoja de datos, estoy usando PB3, PB4 y PB5 en el modo de función alternativa 0.
Función principal:
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f0xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f0xx.c file
*/
fnSPI_Init();
while (1)
{
fnSPI_Send_data(0x2A);
Delay(100000); // This is running proper as intended
}
}
El cuerpo de la función para fnSPI_Send_data()
es el siguiente:
void fnSPI_Send_data(uint8_t addr)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_15); // Chip select low
printf("\n\r Send spi data");
SPI_SendData8(SPI1,addr); // standard perip lib fn for stm32f0xx
printf("\n\r Data sent");
GPIO_SetBits(GPIOA,GPIO_Pin_15); // Chip select high
}
Cuerpo de la función para la función SPI_SendData8()
:
void SPI_SendData8(SPI_TypeDef* SPIx, uint8_t Data)
{
uint32_t spixbase = 0x00;
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
spixbase = (uint32_t)SPIx;
spixbase += 0x0C;
*(__IO uint8_t *) spixbase = Data;
}
Ahora, el comportamiento observado es que los niveles de voltaje de GPIO están cambiando entre alto y bajo en el pin de selección de chip, que se verifica utilizando el DSO. Esto significa que la función SPI_SendData8()
se está ejecutando. También la función printf()
verifica que el código no se quede atascado en ninguna parte.
Pero cuando controlo los pines SCK o MOSI, el DSO muestra que no hay pulsos. Entonces mi pregunta es: ¿es correcta mi inicialización de SPI? ¿Necesito cambiar algún otro valor de registro o algo?
Según este código, debe haber datos en la línea MOSI.
Por favor, ayúdame en esto.
Actualización:
Se modificó la función fnSPI_Send_data()
para verificar el contenido de las banderas.
void fnSPI_Send_data(uint8_t addr)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_15);
printf("\n\r Check if FIFO empty");
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
printf("\n\r FIFO empty");
SPI_SendData8(SPI1,addr); // FIFO has space to accept data
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
printf("\n\r Data sent");
GPIO_SetBits(GPIOA,GPIO_Pin_15);
}
La salida observada es que el código se atasca en el primer bucle while()
que verifica si el FIFO está lo suficientemente vacío para aceptar los datos. ¿Cómo puede el FIFO tener datos sobre la inicialización?