STM32G031K LL庫的使用 - SPI

SPI在開始配置的時候遇到些問題,這裏也記錄下,我這邊用的是SPI2,其他SPI也可以參考

SPI2 初始化:

void STM32LLSpi2Init(void)
{
  LL_SPI_InitTypeDef SPI_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);            //使能外設時鐘
  
  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);             //GPIO時鐘使能
  /**SPI2 GPIO Configuration  
  PB6   ------> SPI2_MISO
  PB7   ------> SPI2_MOSI
  PB8   ------> SPI2_SCK 
  */
  GPIO_InitStruct.Pin = gpioSPI2_MISO_PIN;                       //MISOPin指定
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;                 //io模式配置爲複用功能
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;               //設置爲高速率
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;          //設置Pin爲輸出模式
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;                        //輸入口設置不帶上拉
  GPIO_InitStruct.Alternate = LL_GPIO_AF_4;                      //當前芯片PB6複用功能AF4爲SPI2的MISO,其他芯片的配置參考相應的芯片手冊
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = gpioSPI2_MOSI_PIN;                       //MOSIPin指定
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;                 //
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;               //
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;          //
  GPIO_InitStruct.Pull = LL_GPIO_PULL_DOWN;                      //輸出口配置爲下拉
  GPIO_InitStruct.Alternate = LL_GPIO_AF_1;                      //io 功能選擇
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = gpioSPI2_SCK_PIN;                        
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_DOWN;                      //輸出口配置爲下拉
  GPIO_InitStruct.Alternate = LL_GPIO_AF_1;                      //io 功能選擇
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* SPI2 interrupt Init */                                 //因爲SPI需要進行不同設備數據讀取,所以這裏不使用中斷模式會更方便
  //NVIC_SetPriority(SPI2_IRQn, 0);
  //NVIC_EnableIRQ(SPI2_IRQn);

  SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;    //spi功能選擇全雙工
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;                 //SPI主設備模式
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;         //數據寬度8位
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;      //Clk空閒時狀態爲高 根據使用的從設備進行配置
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;           //在第二次時鐘跳變開始發送數據
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;                     //片選方式爲軟件設置
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;  //時鐘波特率設置
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;               //字節傳輸方式,從高位開始
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;//不開啓crc校驗
  SPI_InitStruct.CRCPoly = 7;                                //CRC多項式
  LL_SPI_Init(SPI2, &SPI_InitStruct);

  LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);        //使用的SPI協議,可選MT和TI的
  LL_SPI_EnableNSSPulseMgt(SPI2);                            //僅做主設備時可用
    /* Configure the SPI2 FIFO Threshold */
  LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//設置RX非空事件產生的FIFO閾值,根據通信時最小數據的大小設置,我這邊最小爲8位,所以設置爲四分之一
	
  LL_SPI_Enable(SPI2);                                        //最後不要忘記使能SPI2,也可以在其他初始化完了之後的地方使能,爲了防止忘記,這裏先使能了

}

我個人在配置的時候,就是因爲GPIO_InitStruct.Alternate 都設置的默認的AF0,導致一直通信不成功,曾一度懷疑是硬件問題。這裏也提醒大家一下。

SPI數據收發:

//通過SPI在從設備內讀寫一個字節的數據,SPI特性,在MOSI寫數據的時候MISO會獲得應答數據
uint8_t STM32LLSpi2WRByte(uint8_t byte)        //因爲採用的非中斷方式,所以數據直接獲取
{
    uint8_t wait_cnt=0;
 	while(!LL_SPI_IsActiveFlag_TXE(SPI2))        //等待數據發送完成
	{
		if(wait_cnt++ >100)
			break;
	}
	LL_SPI_TransmitData8(SPI2, byte);            //發送8位數據
	wait_cnt = 0;
	while(!LL_SPI_IsActiveFlag_RXNE(SPI2))       //等待接收緩存非空
	{
		if(wait_cnt++ >100)
			break;
	}
	return LL_SPI_ReceiveData8(SPI2);            //返回SPI2接收到的數據
}

SPI的讀寫多個字節的操作,都可以通過循環調用讀寫一個字節的函數去實現,這裏不做說明。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章