[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*)(®ister_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
反正就當工作日誌吧
如果有高人路過歡迎指教
如果有看不懂或有細項想問也可以留言