STM Урок 51. Подключаем магнитометр LIS3MDL. Часть 2



Урок 51.

 

Часть 2

 

Магнитометр LIS3MDL

 

В прошлой части нашего урока мы добавили все макросы, которые вносят удобства в чтение и написание кода, начали писать функцию инициализации и проверили код на практике.

Продолжим инициализацию датчика.

Переименуем функцию GyroInit в MagInit, а функцию AccelInit удалим со всем содержимым, чтобы не мешалась

 

//———————————————

void MagInit(uint16_t InitStruct)

{

 

Также исправим и раскомментируем вызов данной функции в главной функции инициализации датчика, а вызов функции инициализации акселерометра также и здесь удалим

 

        LD2_OFF;

        MagInit(ctrl);

        LD2_ON;

 

Продолжаем писать инициализацию, постепенно раскомментировывая и подправляя код в функции

 

        uint8_t value = 0;

        //пока выключим датчик (MD = 0x02)

        value = Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG3);

        value&=~LIS3MDL_MAG_MD_MASK;

        value|=LIS3MDL_MAG_MD_POWER_DOWN;

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG3,value);

        /*

 

Здесь мы используем регистр CTRL_REG3 (22h) и устанавливаем определённым образом его биты MD1 и MD0 с целью пока выключить датчик

 

image15

image14

 

Пишем дальше код

 

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG3,value);

        //Enable BDU

        value = Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG5);

        value&=~LIS3MDL_MAG_BDU_MASK;

        value|=LIS3MDL_MAG_BDU_ENABLE;

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG5,value);  

 

 

Здесь мы работаем уже с другим управляющим регистром – с CTRL_REG5 (24h) и включим в нём бит BDU, смысл которого мы уже изучили в предыдущих занятиях

 

image18

 

Дальше устанавливаем частоту считывания показаний с осей

 

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG5,value);

        //Включим Data Rate 80 Гц

        value = Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG1);

        value&=~LIS3MDL_MAG_DO_MASK;

        value|=LIS3MDL_MAG_DO_80Hz;

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG1,value);

 

Здесь мы используем регистр CTRL_REG1 (20h) и устанавливаем там биты, отвечающие за частоту считывания показаний

 

 image16

image17

 

Пишем код инициализации дальше

 

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG1,value);

        //Full scale selection 4 gauss

        value = Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG2);

        value&=~LIS3MDL_MAG_FS_MASK;

        value|=LIS3MDL_MAG_FS_4Ga;

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG2,value);

 

Здесь мы программируем следующий регистр – CTRL_REG2 (21h), включая в нём биты, отвечающие за диапазон показаний магнитометра

 

image19

image20

 

 

Пишем дальше

 

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG2,value);

        //Включим режим высокой производительности по осям X и Y

        value = Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG1);

        value&=~LIS3MDL_MAG_OM_MASK;

        value|=LIS3MDL_MAG_OM_HIGH;

Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG1,value);

 

Здесь мы работаем также с регистром первым, который мы уже изучили, только работаем с другими битами, отвечающими за производительность датчика по осям X и Y

 

 image21

 

Отключим температурный датчик

 

        //Отключим температурный датчик

        value = Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG1);

        value&=~LIS3MDL_MAG_TEMP_EN_DISABLE;

        value|=LIS3MDL_MAG_OM_HIGH;

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG1,value);

 

Здесь мы также работаем с другим битом того же регистра

 

image22

 

Осталось только включить датчик. Для этого в инициализацию добавим следующий код

 

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG1,value);

        //включим датчик (MD = 0x00)

        value = Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG3);

        value&=~LIS3MDL_MAG_MD_MASK;

        value|=LIS3MDL_MAG_MD_CONTINUOUS;

        Mag_IO_Write(MAG_I2C_ADDRESS,LIS3MDL_MAG_CTRL_REG3,value);

 

Здесь мы просто отключили оба бита MD, тем самым включили режим автоматического преобразования

 

 

image23

Инициализация на этом, в принципе, завершена.

Соберём код, прошьём контроллер и проверим, не погаснет ли у нас светодиод.

Если всё нормально, то начнём писать код считывания показаний с осей магнитометра.

Функцию Gyro_GetXYZ переименуем в Mag_GetXYZ, а функцию Accel_GetXYZ удалим со всем содержимым

 

//———————————————

void Mag_GetXYZ(int16_t* pData)

{

 

Для считывания показаний с осей магнитометра используем регистры с адресами 0x28 – 0x2D

 

image24

 

Раскомментируем код и внесём изменения в функцию считывания показаний

 

//———————————————

void Mag_GetXYZ(int16_t* pData)

{

        uint8_t buffer[6];

        uint8_t i=0;

        buffer[0]=Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_OUTX_L);

        buffer[1]=Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_OUTX_H);

        buffer[2]=Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_OUTY_L);

        buffer[3]=Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_OUTY_H);

        buffer[4]=Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_OUTZ_L);

        buffer[5]=Mag_IO_Read(MAG_I2C_ADDRESS,LIS3MDL_MAG_OUTZ_H);

        for(i=0;i<3;i++)

        {

                pData[i] = ((int16_t)((uint16_t)buffer[2*i+1]<<8)+buffer[2*i]);

        }

}

//———————————————

 

Функцию AccelGyro_Read также переименуем в Mag_Read

 

//———————————————

void Mag_Read(void)

{

 

Команду на считывание данных мы будем уже давать не в бесконечном цикле, а в обработчике прерывания от таймера, причем не просто так, а при определённых условиях.

Во-первых, нам надо сначала этот таймер запустить в функции main(). Также запустим там и считывание данных с USART

 

  /* USER CODE BEGIN 2 */

        HAL_UART_Receive_IT(&huart2, (uint8_t*) str, 8);

        HAL_TIM_Base_Start_IT(&htim1);

        Mag_Ini();

  /* USER CODE END 2 */

 

Теперь создадим обработчик прерывания по флагу окончания счёта таймера и вызовем там команду чтения и обработки данных осей магнитометра в зависимости от сложившихся условий. Условия таковы: должно быть прерывание именно от первого таймера и буфер чтения USART должен быть заполнен. После вызова функции чтения осей опять вызываем функцию чтения по прерывания из порта USART

 

/* USER CODE BEGIN 4 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

        if(htim->Instance==TIM1) //если будет несколько таймеров, чтобы попасть именно в нужный

        {

                        if(huart2.RxXferCount==0)

                        {

                                Mag_Read();

                                HAL_UART_Receive_IT(&huart2, (uint8_t*) str, 8);

                        }

                }

}

/* USER CODE END 4 */

 

В следующей части занятия мы закончим писать функции чтения и обработки показаний датчика с его трёх осей и посмотрим их с помощью нескольких программ на ПК.

 

 

Предыдущая часть Программирование МК STM32 Следующая часть

 

Техническая документация на датчик

Программа Hyper Terminal

Программа NS Port Monitor

Программа NS Mag Visual

 

 

Отладочную плату можно приобрести здесь Nucleo STM32F401RE

Оценочную плату можно приобрести здесь STM32 X-NUCLEO-IKS01A1

 

 

Смотреть ВИДЕОУРОК

 

STM32 Подключаем магнитометр LIS3MDL

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*