STM32 cube工程建立和I2C, SPI, UART的簡單介紹

STM32 cube工程建立和I2C, SPI, UART的簡單介紹

linux 平臺下stm32串口燒錄方法

  • Rx, Tx 的跳線帽需要連接, 因爲使用了板載的串口模塊。
  • 另外,燒錄時 BOOT 的B0 需要置高, 本機所用版本(stm32f103rct6)

stm32flash

stm32flash -w filename -v -g 0x0 /dev/ttyS0

爲命令加點包裝

  • 創建文件 flashstm32.sh
#!/bin/sh
# author:combofish
# email:[email protected] 
# Filename: flash_stm32.sh

port="/dev/ttyUSB0"

stm32flash -w $1 -v -g 0x0 $port
  • 之後默認以命令加 xx.hex 文件燒錄
flash_stm32 f1rrct6.hex

STM32cubeIDE setting

添加hex output

你先得在工程屬性裏配置輸出hex文件,才能在Debug/Release文件夾下找到對應工程名的hex文件 右擊工程名,屬性->C/C++ Build->IAR Linker for ARM->Output Converter->勾選Generate additional output,並在output format下拉框裏選擇Intel extended

project setting

  • Add necessary library files as reference in the toolchain project configuration file.
  • Generate peripheral initialization as a pair of ‘.c/ .h’ files per peripheral.

參考鏈接

https://www.cnblogs.com/ChurF-Lin/p/10793111.html

usart

  • 通用異步收發傳輸器 (Universal Asynchronous Receiver/Transmitter)
  • USART(Universal Synchronous Asynchronous Receiver and Transmitter通用同步異步收發器) USART相當於UART的升級版,USART支持同步模式, 因此USART 需要同步始終信號USARTCK(如STM32 單片機),通常情況同步信號很少使用, 因此一般的單片機UART和USART使用方式是一樣的,都使用異步模式。因爲USART的使用方法上跟UART基本相同,所以在此就以UART來講該通信協議了。

uart 直接發送

int main() {
  unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45};    //數組內十六進制代表“ABCDE”
  //
  while (1)  {
    //
    HAL_UART_Transmit($huart2, uTx_Data, sizeof(uTx_Data), 0xffff);
  }
}
  • uart 發送字符串

  • 在頭文件添加聲明

    void USER_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char* uData);
    
  • 在對應的 .c 文件添加 函數

    void USER_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char* uData){
            while (*uData){
                    HAL_UART_Transmit(uartHandle, uData, 1, 1000);
                    uData++;
            }
    }
    
  • 在 main() 函數的主循環中調用

    USER_UART_SendString(&huart2, uTx_Data2);
    USER_UART_SendString(&huart3, uTx_Data2);
    HAL_Delay(500);
    

uart 接收後就發送

  • 接受字符串

  • 接受後就發送

  • 這種接收方式是直接在main函數裏的while循環裏不斷接收,會嚴重佔用程序的進程,且接收較長的數據時,會發生接收錯誤

    int main() {
      unsigned char uRx_Data = 0;
      //
      if(HAL_UART_Receive(&huart2, &uRx_Data, 1, 1000) == HAL_OK){
        HAL_UART_Transmit(&huart2, &uRx_Data, 1, 1000);
      }
    }
    

接收中斷併發送

  • 在 HALUARTMspInit() 中使能中斷

    
    void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      if(uartHandle->Instance==USART2)
        {
          /* USER CODE BEGIN USART2_MspInit 0 */
    
          /* USER CODE END USART2_MspInit 0 */
          /* USART2 clock enable */
          __HAL_RCC_USART2_CLK_ENABLE();
    
          __HAL_RCC_GPIOA_CLK_ENABLE();
          /**USART2 GPIO Configuration    
             PA2     ------> USART2_TX
             PA3     ------> USART2_RX 
          */
          GPIO_InitStruct.Pin = GPIO_PIN_2;
          GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
          GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
          HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
          GPIO_InitStruct.Pin = GPIO_PIN_3;
          GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
          GPIO_InitStruct.Pull = GPIO_NOPULL;
          HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
          /* USART2 interrupt Init */
          HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
          HAL_NVIC_EnableIRQ(USART2_IRQn);
          /* USER CODE BEGIN USART2_MspInit 1 */
          //HAL_UART_Receive_IT(&huart2, rData, 1);
          __HAL_UART_ENABLE_IT(uartHandle, UART_IT_RXNE);
    
          /* USER CODE END USART2_MspInit 1 */
        }
    }
    
  • 在 USART1IRQHandler() 中處理數據

    void USART2_IRQHandler(void)
    {
      /* USER CODE BEGIN USART2_IRQn 0 */
            unsigned char uRx_Data = 0;
            HAL_UART_Receive(&huart2, &uRx_Data, 1, 1000);
            HAL_UART_Transmit(&huart2, &uRx_Data, 1, 0xffff);
    
      /* USER CODE END USART2_IRQn 0 */
      HAL_UART_IRQHandler(&huart2);
      /* USER CODE BEGIN USART2_IRQn 1 */
    
      /* USER CODE END USART2_IRQn 1 */
    }
    

中斷接收,先接收完再去處理

  • 在 HALUARTMspInit() 中使能中斷

    
    void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      if(uartHandle->Instance==USART2)
        {
          /* USER CODE BEGIN USART2_MspInit 0 */
    
          /* USER CODE END USART2_MspInit 0 */
          /* USART2 clock enable */
          __HAL_RCC_USART2_CLK_ENABLE();
    
          __HAL_RCC_GPIOA_CLK_ENABLE();
          /**USART2 GPIO Configuration    
             PA2     ------> USART2_TX
             PA3     ------> USART2_RX 
          */
          GPIO_InitStruct.Pin = GPIO_PIN_2;
          GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
          GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
          HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
          GPIO_InitStruct.Pin = GPIO_PIN_3;
          GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
          GPIO_InitStruct.Pull = GPIO_NOPULL;
          HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
          /* USART2 interrupt Init */
          HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
          HAL_NVIC_EnableIRQ(USART2_IRQn);
          /* USER CODE BEGIN USART2_MspInit 1 */
          //HAL_UART_Receive_IT(&huart2, rData, 1);
          __HAL_UART_ENABLE_IT(uartHandle, UART_IT_RXNE);
    
          /* USER CODE END USART2_MspInit 1 */
        }
    }
    
  • 在 USART1IRQHandler() 中處理數據

    void USART2_IRQHandler(void)
    {
      /* USER CODE BEGIN USART2_IRQn 0 */
    
      // 中斷接收和發送
      /*	unsigned char uRx_Data = 0;
            HAL_UART_Receive(&huart2, &uRx_Data, 1, 1000);
            HAL_UART_Transmit(&huart2, &uRx_Data, 1, 0xffff);*/
    
      // 中斷接收完再發送
      static unsigned char uRx_Data[1024] = {0};
      static unsigned char* pRx_Data = uRx_Data;
      static unsigned char uLength = 0;
    
      HAL_UART_Receive(&huart2, pRx_Data, 1, 1000);
    
      if (*pRx_Data == '\n'){
        HAL_UART_Transmit(&huart2, uRx_Data, uLength, 0xffff);
      }else {
        uLength++;
        pRx_Data++;
      }
    
      /* USER CODE END USART2_IRQn 0 */
      HAL_UART_IRQHandler(&huart2);
      /* USER CODE BEGIN USART2_IRQn 1 */
    
      /* USER CODE END USART2_IRQn 1 */
    }
    

參考連接

https://www.cnblogs.com/ChurF-Lin/p/10809000.html https://www.cnblogs.com/ChurF-Lin/p/10809000.html https://www.cnblogs.com/ChurF-Lin/category/1457221.html

spi

SPI 協議 Serial Peripheral Interface 串行外圍設備接口,是一種高速全雙工的通信總線。主要用在MCU與FLASH\ADC\LCD等模塊之間的通信。

4 條總線

  • SS Slave Select

片選信號線,當有多個SPI 設備與 MCU 相連時,每個設備的這個片選信號線是與 MCU 單獨的引腳相連的, 而其他的 SCK、MOSI、MISO 線則爲多個設備並聯到相同的 SPI 總線上,低電平有效。

  • SCK Serial Clock

時鐘信號線,由主通信設備產生,不同的設備支持的時鐘頻率不一樣,如 STM32 的 SPI 時鐘頻率最大爲 f PCLK /2。

  • MOSI Master Output Slave Input

設備輸出 / 從設備輸入引腳。主機的數據從這條信號線輸出,從機由這條信號線讀入數據,即這條線上數據的方向爲主機到從機。

  • MISO Maste Input Slave Output

主設備輸入 / 從設備輸出引腳。主機從這條信號線讀入數據,從機的數據則由這條信號線輸出,即在這條線上數據的方向爲從機到主機。

特性

  • 單次傳輸可選擇爲 8 或 16 位。
  • 波特率預分頻係數(最大爲 fPCLK/2) 。
  • 時鐘極性(CPOL)和相位(CPHA)可編程設置。
  • 數據順序的傳輸順序可進行編程選擇,MSB 在前或 LSB 在前。 注:MSB(Most Significant Bit)是“最高有效位”,LSB(Least Significant Bit)是“最低有效位”。
  • 可觸發中斷的專用發送和接收標誌。
  • 可以使用 DMA 進行數據傳輸操作。

cube 配置

  • 配好時鐘源
  • SPI mode Full-Duplex Master
    • Hardware NSS Signal Disable
  • PA4 gpiooutput Label SPICS

主要函數

HAL_StatusTypeDef  HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);//發送數據
HAL_StatusTypeDef  HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);//接收數據

參考鏈接

http://news.eeworld.com.cn/mcu/2019/ic-news021243150.html https://blog.csdn.net/u014470361/article/details/79015712

I2C

介紹

  • I2C最少只需要兩根線,和異步串口類似,但可以支持多個slave設備。
  • 和SPI不同的是,I2C可以支持mul-master系統,允許有多個master並且每個master都可以與所有的slaves通信

(master之間不可通過I2C通信,並且每個master只能輪流使用I2C總線)。

  • I2C的數據傳輸速率位於串口和SPI之間,大部分I2C設備支持100KHz和400KHz模式。
  • 使用I2C傳輸數據會有一些額外消耗:每發送8bits數據,就需要額外1bit的元數據(ACK或NACK)。
  • I2C支持雙向數據交換,由於僅有一根數據線,故通信是半雙工的。
  1. 地址

    • I2C 總線上的每個設備都有自己的獨立地址,主機發起通訊時,通過 SDA 信號線發送設備地址(SLAVEADDRESS)來查找從機。
    • I2C 協議規定設備地址可以是7 位或10 位,實際中7 位的地址應用比較廣泛。
    • 數據方向
      • 數據方向位在設備地址後一位
      • “1”——讀,“0”——寫
  2. 參考鏈接

    https://blog.csdn.net/la_fe_/article/details/100315073

    #include <stdio.h>
    #include <string.h>
    
    int main(){
      unsigned char a[12] = {0};
      printf("%s", sizeof(a));
    
      return 0;
    }
    

常用函數

/* 第1個參數爲I2C操作句柄
   第2個參數爲從機設備地址
   第3個參數爲從機寄存器地址
   第4個參數爲從機寄存器地址長度
   第5個參數爲發送的數據的起始地址
   第6個參數爲傳輸數據的大小
   第7個參數爲操作超時時間 */
HAL_I2C_Mem_Write(&hi2c2,salve_add,0,0,PA_BUFF,sizeof(PA_BUFF),0x10);
HAL_I2C_Mem_Write_IT()HAL_I2C_Mem_Read();
HAL_I2C_Mem_Read_IT();
HAL_I2C_Mem_Read_DMA();
HAL_I2C_Mem_Write_DMA();

HAL_I2C_Master_Receive();// STM32 主機接收,不需要用到寄存器地址
HAL_I2C_Master_Receive_IT();//中斷IIC接收
HAL_I2C_Master_Receive_DMA();// DMA 方式的IIC接收
HAL_I2C_Master_Transmit_IT();  //中斷IIC發送
HAL_I2C_Master_Transmit_DMA();   // DMA 方式的IIC發送
HAL_I2C_Master_Transmit(&hi2c2,salve_add,PA_BUFF,sizeof(PA_BUFF),0x10); //STM32 主機發送

HAL_I2C_Slave_Receive();// STM32 從機機接收,不需要用到寄存器地址
HAL_I2C_Slave_Transmit();// STM32 從機機發送,不需要用到寄存器地址
HAL_I2C_Slave_Receive_IT();
HAL_I2C_Slave_Receive_DMA();
HAL_I2C_Slave_Transmit_IT();
HAL_I2C_Slave_Transmit_DMA();

//舉個調用 HAL_I2C_Mem_Write()函數讀取16個字節的使用例子
HAL_I2C_Mem_Read(&hi2c2,U9_Save_Read_Add,ADC_Result_Add,I2C_MEMADD_SIZE_8BIT,Read_buff,2,0xff);

//再舉一個 HAL_I2C_Mem_Read( ) 函數寫16個字節的使用例子
uint8_t  Configuration_config[2]={0x09,0xc0};

//設置U9的Configuration寄存器爲 0x09 0xc0
HAL_I2C_Mem_Write(&hi2c2,U9_Save_Write_Add,ADC_Configuration_Add,I2C_MEMADD_SIZE_8BIT,Configuration_config,2,0xff); 
  • 參考鏈接

https://www.cnblogs.com/xingboy/p/9566247.html

參考鏈接

http://www.eemaker.com/stm32-hal-i2c-24c02.html

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