#STM32與sensor開發紀錄


Posted by dav134679 on 2020-04-22

[TOC]


前言

之前寫了一篇關於STM32CubeIDE的開發流程
這次寫一下使用STM32與sensor做應用開發的記錄吧

開發平台使用STM32CubeIDE
MCU是STM32F103C8T6
sensor使用數位光感IC,通訊介面使用I2C


STM32配置

  • UART
  • I2C
  • 一般高低準位輸出
  • Debug
  • 中斷

IO需求視應用而定
像我需要一個簡單的指示LED -> PB13 GPIO_Output
需要PWM輸出 -> TIM3_CH1
等等...

特別提醒一下
I2C配置


Sensor

當初第一次看sensor的Datasheet真的一頭霧水阿==
還記得當初大概看懂一部分後就急著實作
雖然堪用,但常常出現問題卻很難Debug
後來重頭到尾把它看懂後,一切豁然開朗
(我經驗不多,實習一年來讀過的Datasheet 7.8來篇吧)

至於Sensor Datasheet有些重要的資訊可能如下所示:

Slave Address
我碰過的sensor是這樣寫的:
"sensor provides fixed I2C slave address of 0x58 using 7 bit addressing protocol"

Slave Address R/W Command Bit Operation
0x58 0 Write Command to IC
0x58 1 Read Data from IC

這是I2C常見的地址格式
以上例來看,實際上的讀寫地址變為:
Write:0x58 << 1 + 0 = 0XB0
Read:0x58 << 1 + 1 = 0XB1

P.S. 以前用Arduino的I2C讀寫函數好像會自動轉換成讀寫地址,這時輸入地址就一樣是0x58,但STM32 HAL庫就需要輸入加了讀寫位的,也就是0xB0、0xB1

Control Register Map

ADDR REG NAME BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 Default
0x00 STATE EN_B_Mode EN_A_Mode 0x00
0x01 ALSCTRL GAIN IT 0x00
... ... ... ... ... ... ... ... ... ... ...

這是一張sensor的可讀/寫的Reg表
通常會在分別詳細說明各Reg功能,以及其各位元的意義

Application Circuit
我碰到的應用電路不難
大概就是一些上拉電阻、旁路電路、LED驅動電路等等...
就理解後自己Layout玩玩看,做後續開發
以下示意圖:

看懂Datasheet後,準備進行韌體開發
我會先建立一個header file存放Register Map
之後做I2C讀寫操作比較方便,可讀性也較高
除了上述這些東西以外,時序圖狀態圖都很重要
我個人經驗還是要全部看一次啦

P.S. 有些至關重要的訊息也只會用淡淡地用文字描述,建議還是要看仔細


讀寫資料

這邊提供HAL庫的I2C讀寫方法
我是把讀寫操作包在自訂函數裡面

void I2C_reg_W(uint8_t register_pointer, uint16_t register_value)
{
    HAL_StatusTypeDef status = HAL_OK;

    status = HAL_I2C_Mem_Write(&hi2c1, SLAVE_ADDRESS_W, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, (uint8_t*)(&register_value), 1, 100);

    /* Check the communication status */
    if(status != HAL_OK)
    {
        printf("I2C Write error\r\n");
        // Error handling, for example re-initialization of the I2C peripheral
    }
}

uint32_t I2C_reg_R(uint8_t register_pointer,uint16_t length)
{
    //sequential read 4 byte
    HAL_StatusTypeDef status = HAL_OK;
    uint16_t return_value = 0 ;

    status = HAL_I2C_Mem_Read(&hi2c1, SLAVE_ADDRESS_R, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, &return_value, length, 100);

    /* Check the communication status */
    if(status != HAL_OK)
    {
        printf("I2C Read error\r\n");
        //printf(" %X \r\n",status);
    }

    return return_value;
}

實際操作如下:

I2C_reg_W(STATE_Reg,0x00); //STATE Reg設為0x00(0x00有其對應的功能)

串口輸出

網路上有很多文章教學
我也簡單分享一下
STM32 HAL庫的 printf 函數輸出到串口
我是在uart.c文件裡的USER CODE裡添加如下程式

/* USER CODE BEGIN 1 */
#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
  return ch;
}
/* USER CODE END 1 */

然後main.c文件裡

#include <stdio.h>

這樣在main裡printf就可以直接輸出到串口


讀取/輸出 sensor感測值

直接看 main() code 示意:

int main(void)
{
  初始化stm32
  初始化sensor
  while(1) //Infinite loop
  {
    while(1)
    {
      uint8_t FLAG = I2C_reg_R(ADC_FLAG,1);
      if(FLAG) break; //確保sensor ADC轉換完成
    }
    uint8_t Data = I2C_reg_R(Data1,2); //一個Data是16bit,但是reg是8bit,讀兩byte再合併
    printf("data= %u\r\n",Data); //輸出至串口
  }
}

程式碼架構大概長這樣
然後就可以去串口看Data了
至於串口,Microsoft Store裡面有個APP叫串口調適助手或者用puTTY
裡面參數需調整成在配置STM32 Pinout時的UART配置一樣

串口號依個人裝置而異


結語

其實看了自己寫的文章發現真的很淺XD
反正就當工作日誌吧
如果有高人路過歡迎指教
如果有看不懂或有細項想問也可以留言


#STM32 #STM32CubeIDE #sensor







Related Posts

如何使用 Python 進行字串格式化

如何使用 Python 進行字串格式化

Advanced JS  (上)

Advanced JS (上)

兩年過後,我能夠被稱為資深工程師了嗎?

兩年過後,我能夠被稱為資深工程師了嗎?


Comments