Урок 49. HAL. Магнитометр LSM303DLHC
Часть 1
Сегодня мы продолжим тему датчиков с использованием технологии MEMS и вернёмся к датчику, который мы уже частично рассматривали 10 уроков назад – LSM303DLHC.
Повторюсь, что данный датчик установлен на плате STM32F3Discovery. И изучим мы сегодня его вторую часть – магнитометр. Магнитометр – это такой датчик, который способен реагировать и измерять такую величину, как магнитная индукция, которая измеряется в Гауссах (система СГС). Также в официальной таблице СИ магнитная индукция измеряется в Теслах. 1 Гаусс равен 100 мкТл или 1 Тесла равна 10000 Гауссов.
Технические характеристики данного описаны в даташите на него, ссылку на который я повторю в конце статьи. Основные характеристики, которые нам понадобятся – это те, что он также 16-битный, правда для показаний биты используются не все – только 12 бит и измерения свои он интерпретирует в регистрах в диапазоне от -2048 до +2047
Также нам нужны следующие характеристики:
интерфейс для снятия показаний – I2C;
Диапазон показаний ±1.3 / ±1.9 / ±2.5 / ±4.0 / ±4.7 / ±5.6 / ±8.1 gauss;
Дискретность 1 Гаусса или количество градаций в 1 Гауссе зависит от установленного диапазона показаний, а также от осей и находится в пределах от 205 до 1100
С остальными характеристиками, тонкостями, магнитометра мы познакомимся в ходе его программирования.
Проект мы создадим из предыдущего проекта для этого датчики – из проекта Accel и назовём его Mag
Запустим проект в Cube MX.
Внесём изменение следующее – прибавим скорость шины USART2
Сгенерируем код, откроем проект, настроим программатор на авторезет, как обычно. Подключим файл lsm303dlhc.c. Скомпилируем проект.
В файле main.c в бесконечном цикле пока закомментируем вызов функции
//Accel_ReadAcc();
В файле lsm303dlhc.h удалим полностью всё и вставим готовый подготовленный код с новыми макросами для магнитометра и с исправленными прототипами функций
#ifndef LSM303DLHC_H_
#define LSM303DLHC_H_
#include «stm32f3xx_hal.h»
#include <string.h>
//————————————————
#define ABS(x) (x < 0) ? (-x) : x
//————————————————
#define LD_PORT GPIOE
#define LD3 GPIO_PIN_9 //RED1
#define LD4 GPIO_PIN_8 //BLUE1
#define LD5 GPIO_PIN_10 //ORANGE1
#define LD6 GPIO_PIN_15 //GREEN1
#define LD7 GPIO_PIN_11 //GREEN2
#define LD8 GPIO_PIN_14 //ORANGE2
#define LD9 GPIO_PIN_12 //BLUE2
#define LD10 GPIO_PIN_13 //RED2
//————————————————-
#define ACC_I2C_ADDRESS 0x32
#define MAG_I2C_ADDRESS 0x3C
//————————————————
//————————————————-
#define LSM303DLHC_CTRL_REG1_A 0x20 /* Control register 1 acceleration */
#define LSM303DLHC_CTRL_REG2_A 0x21 /* Control register 2 acceleration */
#define LSM303DLHC_CTRL_REG3_A 0x22 /* Control register 3 acceleration */
#define LSM303DLHC_CTRL_REG4_A 0x23 /* Control register 4 acceleration */
#define LSM303DLHC_CTRL_REG5_A 0x24 /* Control register 5 acceleration */
#define LSM303DLHC_CRA_REG_M 0x00 /* Control register A magnetic field */
#define LSM303DLHC_CRB_REG_M 0x01 /* Control register B magnetic field */
#define LSM303DLHC_MR_REG_M 0x02 /* Control register MR magnetic field */
//————————————————
#define LD3_ON HAL_GPIO_WritePin(LD_PORT, LD3, GPIO_PIN_SET) //RED1
#define LD4_ON HAL_GPIO_WritePin(LD_PORT, LD4, GPIO_PIN_SET) //BLUE1
#define LD5_ON HAL_GPIO_WritePin(LD_PORT, LD5, GPIO_PIN_SET) //ORANGE1
#define LD6_ON HAL_GPIO_WritePin(LD_PORT, LD6, GPIO_PIN_SET) //GREEN1
#define LD7_ON HAL_GPIO_WritePin(LD_PORT, LD7, GPIO_PIN_SET) //GREEN2
#define LD8_ON HAL_GPIO_WritePin(LD_PORT, LD8, GPIO_PIN_SET) //ORANGE2
#define LD9_ON HAL_GPIO_WritePin(LD_PORT, LD9, GPIO_PIN_SET) //BLUE2
#define LD10_ON HAL_GPIO_WritePin(LD_PORT, LD10, GPIO_PIN_SET) //RED2
#define LD3_OFF HAL_GPIO_WritePin(LD_PORT, LD3, GPIO_PIN_RESET) //RED1
#define LD4_OFF HAL_GPIO_WritePin(LD_PORT, LD4, GPIO_PIN_RESET) //BLUE1
#define LD5_OFF HAL_GPIO_WritePin(LD_PORT, LD5, GPIO_PIN_RESET) //ORANGE1
#define LD6_OFF HAL_GPIO_WritePin(LD_PORT, LD6, GPIO_PIN_RESET) //GREEN1
#define LD7_OFF HAL_GPIO_WritePin(LD_PORT, LD7, GPIO_PIN_RESET) //GREEN2
#define LD8_OFF HAL_GPIO_WritePin(LD_PORT, LD8, GPIO_PIN_RESET) //ORANGE2
#define LD9_OFF HAL_GPIO_WritePin(LD_PORT, LD9, GPIO_PIN_RESET) //BLUE2
#define LD10_OFF HAL_GPIO_WritePin(LD_PORT, LD10, GPIO_PIN_RESET) //RED2
//————————————————
#define LSM303DLHC_NORMAL_MODE ((uint8_t)0x00)
#define LSM303DLHC_LOWPOWER_MODE ((uint8_t)0x08)
//————————————————-
#define LSM303DLHC_ODR_1_HZ ((uint8_t)0x10) /*!< Output Data Rate = 1 Hz */
#define LSM303DLHC_ODR_10_HZ ((uint8_t)0x20) /*!< Output Data Rate = 10 Hz */
#define LSM303DLHC_ODR_25_HZ ((uint8_t)0x30) /*!< Output Data Rate = 25 Hz */
#define LSM303DLHC_ODR_50_HZ ((uint8_t)0x40) /*!< Output Data Rate = 50 Hz */
#define LSM303DLHC_ODR_100_HZ ((uint8_t)0x50) /*!< Output Data Rate = 100 Hz */
#define LSM303DLHC_ODR_200_HZ ((uint8_t)0x60) /*!< Output Data Rate = 200 Hz */
#define LSM303DLHC_ODR_400_HZ ((uint8_t)0x70) /*!< Output Data Rate = 400 Hz */
#define LSM303DLHC_ODR_1620_HZ_LP ((uint8_t)0x80) /*!< Output Data Rate = 1620 Hz only in Low Power Mode */
#define LSM303DLHC_ODR_1344_HZ ((uint8_t)0x90) /*!< Output Data Rate = 1344 Hz in Normal mode and 5376 Hz*/
//————————————————-
#define LSM303DLHC_X_ENABLE ((uint8_t)0x01)
#define LSM303DLHC_Y_ENABLE ((uint8_t)0x02)
#define LSM303DLHC_Z_ENABLE ((uint8_t)0x04)
#define LSM303DLHC_AXES_ENABLE ((uint8_t)0x07)
#define LSM303DLHC_AXES_DISABLE ((uint8_t)0x00)
//————————————————-
#define LSM303DLHC_HR_ENABLE ((uint8_t)0x08)
#define LSM303DLHC_HR_DISABLE ((uint8_t)0x00)
//————————————————-
#define LSM303DLHC_FULLSCALE_2G ((uint8_t)0x00) /*!< ±2 g */
#define LSM303DLHC_FULLSCALE_4G ((uint8_t)0x10) /*!< ±4 g */
#define LSM303DLHC_FULLSCALE_8G ((uint8_t)0x20) /*!< ±8 g */
#define LSM303DLHC_FULLSCALE_16G ((uint8_t)0x30) /*!< ±16 g */
//————————————————-
#define LSM303DLHC_BlockUpdate_Continous ((uint8_t)0x00) /*!< Continuos Update */
#define LSM303DLHC_BlockUpdate_Single ((uint8_t)0x80) /*!< Single Update: output registers not updated until MSB and LSB reading */
//————————————————-
#define LSM303DLHC_BLE_LSB ((uint8_t)0x00) /*!< Little Endian: data LSB @ lower address */
#define LSM303DLHC_BLE_MSB ((uint8_t)0x40) /*!< Big Endian: data MSB @ lower address */
//————————————————-
#define LSM303DLHC_HPM_NORMAL_MODE_RES ((uint8_t)0x00)
#define LSM303DLHC_HPM_REF_SIGNAL ((uint8_t)0x40)
#define LSM303DLHC_HPM_NORMAL_MODE ((uint8_t)0x80)
#define LSM303DLHC_HPM_AUTORESET_INT ((uint8_t)0xC0)
//————————————————-
#define LSM303DLHC_HPFCF_8 ((uint8_t)0x00)
#define LSM303DLHC_HPFCF_16 ((uint8_t)0x10)
#define LSM303DLHC_HPFCF_32 ((uint8_t)0x20)
#define LSM303DLHC_HPFCF_64 ((uint8_t)0x30)
//————————————————-
#define LSM303DLHC_HPF_AOI1_DISABLE ((uint8_t)0x00)
#define LSM303DLHC_HPF_AOI1_ENABLE ((uint8_t)0x01)
//————————————————-
#define LSM303DLHC_HPF_AOI2_DISABLE ((uint8_t)0x00)
#define LSM303DLHC_HPF_AOI2_ENABLE ((uint8_t)0x02)
//————————————————-
#define LSM303DLHC_ACC_SENSITIVITY_2G ((uint8_t)1) /*!< accelerometer sensitivity with 2 g full scale [mg/LSB] */
#define LSM303DLHC_ACC_SENSITIVITY_4G ((uint8_t)2) /*!< accelerometer sensitivity with 4 g full scale [mg/LSB] */
#define LSM303DLHC_ACC_SENSITIVITY_8G ((uint8_t)4) /*!< accelerometer sensitivity with 8 g full scale [mg/LSB] */
#define LSM303DLHC_ACC_SENSITIVITY_16G ((uint8_t)12) /*!< accelerometer sensitivity with 12 g full scale [mg/LSB] */
//————————————————
#define LSM303DLHC_OUT_X_L_A 0x28 /* Output Register X acceleration */
#define LSM303DLHC_OUT_X_H_A 0x29 /* Output Register X acceleration */
#define LSM303DLHC_OUT_Y_L_A 0x2A /* Output Register Y acceleration */
#define LSM303DLHC_OUT_Y_H_A 0x2B /* Output Register Y acceleration */
#define LSM303DLHC_OUT_Z_L_A 0x2C /* Output Register Z acceleration */
#define LSM303DLHC_OUT_Z_H_A 0x2D /* Output Register Z acceleration */
//————————————————
#define LSM303DLHC_OUT_X_H_M 0x03 /* Output Register X magnetic field */
#define LSM303DLHC_OUT_X_L_M 0x04 /* Output Register X magnetic field */
#define LSM303DLHC_OUT_Z_H_M 0x05 /* Output Register Z magnetic field */
#define LSM303DLHC_OUT_Z_L_M 0x06 /* Output Register Z magnetic field */
#define LSM303DLHC_OUT_Y_H_M 0x07 /* Output Register Y magnetic field */
#define LSM303DLHC_OUT_Y_L_M 0x08 /* Output Register Y magnetic field */
//————————————————
#define LSM303DLHC_TEMPSENSOR_ENABLE ((uint8_t) 0x80) /*!< Temp sensor Enable */
#define LSM303DLHC_TEMPSENSOR_DISABLE ((uint8_t) 0x00) /*!< Temp sensor Disable */
//————————————————
#define LSM303DLHC_ODR_0_75_HZ ((uint8_t) 0x00) /*!< Output Data Rate = 0.75 Hz */
#define LSM303DLHC_ODR_1_5_HZ ((uint8_t) 0x04) /*!< Output Data Rate = 1.5 Hz */
#define LSM303DLHC_ODR_3_0_HZ ((uint8_t) 0x08) /*!< Output Data Rate = 3 Hz */
#define LSM303DLHC_ODR_7_5_HZ ((uint8_t) 0x0C) /*!< Output Data Rate = 7.5 Hz */
#define LSM303DLHC_ODR_15_HZ ((uint8_t) 0x10) /*!< Output Data Rate = 15 Hz */
#define LSM303DLHC_ODR_30_HZ ((uint8_t) 0x14) /*!< Output Data Rate = 30 Hz */
#define LSM303DLHC_ODR_75_HZ ((uint8_t) 0x18) /*!< Output Data Rate = 75 Hz */
#define LSM303DLHC_ODR_220_HZ ((uint8_t) 0x1C) /*!< Output Data Rate = 220 Hz */
//————————————————
#define LSM303DLHC_FS_1_3_GA ((uint8_t) 0x20) /*!< Full scale = ±1.3 Gauss */
#define LSM303DLHC_FS_1_9_GA ((uint8_t) 0x40) /*!< Full scale = ±1.9 Gauss */
#define LSM303DLHC_FS_2_5_GA ((uint8_t) 0x60) /*!< Full scale = ±2.5 Gauss */
#define LSM303DLHC_FS_4_0_GA ((uint8_t) 0x80) /*!< Full scale = ±4.0 Gauss */
#define LSM303DLHC_FS_4_7_GA ((uint8_t) 0xA0) /*!< Full scale = ±4.7 Gauss */
#define LSM303DLHC_FS_5_6_GA ((uint8_t) 0xC0) /*!< Full scale = ±5.6 Gauss */
#define LSM303DLHC_FS_8_1_GA ((uint8_t) 0xE0) /*!< Full scale = ±8.1 Gauss */
//————————————————
#define LSM303DLHC_CONTINUOS_CONVERSION ((uint8_t) 0x00) /*!< Continuous-Conversion Mode */
#define LSM303DLHC_SINGLE_CONVERSION ((uint8_t) 0x01) /*!< Single-Conversion Mode */
#define LSM303DLHC_SLEEP ((uint8_t) 0x02) /*!< Sleep Mode */
//————————————————
void AccelMag_Ini(void);
void AccelMag_Read(void);
//————————————————
#endif /* LSM303DLHC_H_ */
Исправим имя функции инициализации датчика на более универсальное также в файлах main.c и lsm303dlhc.c
/* USER CODE BEGIN 2 */
AccelMag_Ini();
/* USER CODE END 2 */
//———————————————
void AccelMag_Ini(void)
{
Закомментируем в коде реализации данной функции строки, связанные с инициализацией акселерометра кроме считывания идентификатора, ибо данная опция у датчика универсальна
else Error();
// ctrl|=(LSM303DLHC_NORMAL_MODE|LSM303DLHC_ODR_50_HZ|LSM303DLHC_AXES_ENABLE);
// ctrl|=((LSM303DLHC_BlockUpdate_Continous|LSM303DLHC_BLE_LSB|LSM303DLHC_HR_ENABLE)<<8);
// AccInit(ctrl);
// ctrl=(uint8_t)(LSM303DLHC_HPM_NORMAL_MODE|LSM303DLHC_HPFCF_16|\
// LSM303DLHC_HPF_AOI1_DISABLE|LSM303DLHC_HPF_AOI2_DISABLE);
// Accel_AccFilter(ctrl);
LD7_ON;
Добавим функцию MagInit, скопировав полностью и исправив подобную функцию для акселерометра (AccInit). Входящий аргумент будет уже 32-битный, т.к. использовать будем 3 разных регистра и 16-битного нам не хватит
//———————————————
void MagInit(uint32_t InitStruct)
{
uint8_t ctrl = 0x00;
ctrl = (uint8_t) InitStruct;
Accel_IO_Write(MAG_I2C_ADDRESS,LSM303DLHC_CRA_REG_M,ctrl);
ctrl = (uint8_t)(InitStruct>>8);
Accel_IO_Write(MAG_I2C_ADDRESS, LSM303DLHC_CRB_REG_M,ctrl);
ctrl = (uint8_t)(InitStruct>>16);
Accel_IO_Write(MAG_I2C_ADDRESS, LSM303DLHC_MR_REG_M,ctrl);
}
//———————————————
О регистрах и настройках их битов мы узнаем несколько позже, когда будем заносить в них значения перед вызовом данной функции. Если Вы заметили, то адрес I2C для общения с магнитометром у нас уже будет другой
Добавим код настройки регистров инициализации в общую функцию инициализации, для этого вначале добавим ещё одну переменную для возможности передачи 32-битного значения настроек
uint16_t ctrl = 0x0000;
uint32_t ctrl32 = 0x00000000;
—
// Accel_AccFilter(ctrl);
ctrl32|=(LSM303DLHC_TEMPSENSOR_DISABLE|LSM303DLHC_ODR_220_HZ);
ctrl32|=LSM303DLHC_FS_4_0_GA<<8;
ctrl32|=LSM303DLHC_CONTINUOS_CONVERSION<<16;
MagInit(ctrl32);
LD7_ON;
А вот теперь и познакомимся вкратце, что у нас творится с настройками битов регистров управления.
В регистре CRA_REG_M (00h) мы отключим датчик температуры и настроим частоту считывания данных с осей магнитометра
В регистре CRB_REG_M (01h) настроим предел измерений магнитометра
В регистре MR_REG_M (02h) включим непрерывный режим преобразования
В следующей части нашего занятия мы напишем функцию чтения данных датчика и попытаемся увидеть показания на ПК сначала в терминальной программе, а затем в двух программах визуализации.
Предыдущий урок Программирование МК STM32 Следующая часть
Техническая документация на датчик
Купить отладочную плату можно здесь STM32F3-DISCOVERY
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Добавить комментарий