STM32F1与STM32CubeIDE编程实例-HMC5883电子罗盘驱动 HMC5883电子罗盘驱动 1、HMC5883介绍 Honeywell的HMC5883L 是一款表面贴装多芯片模块,专为低场磁场感应而设计,具有数字接口,适用于低成本罗盘和磁力测量等应用。 HMC5883L 包括先进的高分辨率 HMC118X 系列磁阻传感器和一个 ASIC,其中包含放大、自动消磁带驱动器、偏移消除和一个 12 位 ADC,可实现 1° 至 2° 罗盘航向 准确性。 I2C 串行总线允许简单的接口。 HMC5883L 是一款 3.0x3.0x0.9mm 表面贴装 16 引脚无引线芯片载体 (LCC)。 HMC5883L 的应用包括移动电话、上网本、消费电子产品、自动导航系统和个人导航设备。
HMC5883L 采用霍尼韦尔的各向异性磁阻 (AMR) 技术,与其他磁传感器技术相比具有优势。 这些各向异性方向传感器具有精确的轴内灵敏度和线性度。 这些传感器的固态结构具有极低的交叉轴灵敏度,旨在测量从毫高斯到 8 高斯的地球磁场的方向和大小。 霍尼韦尔的磁传感器是业内最灵敏、最可靠的低场传感器之一。
2、HMC5883配置 关于STM32CubeIDE工程创建、配置请参考前面文章:
本次HMC5883的配置如下:
3、HMC5883驱动实现 1)HMC5883基本定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 /\* \* hmc2883.h \* \* Created on: Jul 3, 2022 \* Author: jenson \*/ #ifndef HMC5883\_HMC5883\_H\_ #define HMC5883\_HMC5883\_H\_ #include <stm32f1xx\_hal.h> #include <stdbool.h> #define HMC5883\_DEVICE\_ADDR (0x1E) typedef struct { uint16\_t id; uint8\_t addr; I2C_HandleTypeDef\* i2c; int32\_t x,y,z; float angle_xy; // XY平面角度 float angle_xz; // XZ平面角度 float angle_yz; // YZ平面角度 bool inited; }hmc5883\_t; // 判断HMC5883设备是否就绪 bool hmc5883\_is\_ready(hmc5883\_t\* hmc5883); // HMC5883初始化 bool hmc5883\_init(hmc5883\_t\* hmc5883); // HMC5883数据采集及刷新 void hmc5883\_update(hmc5883\_t\* hmc5883); #endif /\* HMC5883\_HMC5883\_H\_ \*/
2)驱动基本定义实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 /\* \* hmc5883.c \* \* Created on: Jul 3, 2022 \* Author: jenson \*/ #include "hmc5883.h" #include <stdio.h> #include <math.h> bool hmc5883\_is\_ready(hmc5883\_t \*hmc5883) { return HAL\_I2C\_IsDeviceReady(hmc5883->i2c, hmc5883->addr, 2, 10); } bool \_\_hmc5883\_write(hmc5883\_t \*hmc5883, uint8\_t mem_addr, uint8\_t \*pData, uint32\_t size) { if (HAL\_I2C\_Mem\_Write(hmc5883->i2c, hmc5883->addr << 1, mem_addr, 1, pData, size, 1000) == HAL_OK) { return true; } printf("write failed\r\n"); return false; } bool \_\_hmc5883\_read(hmc5883\_t \*hmc5883, uint8\_t mem_addr, uint8\_t \*pData, uint32\_t size) { if (HAL\_I2C\_Mem\_Read(hmc5883->i2c, hmc5883->addr << 1, mem_addr, 1, pData, size, 1000) == HAL_OK) { return true; } printf("read failed\r\n"); return false; } bool hmc5883\_init(hmc5883\_t \*hmc5883) { if (!hmc5883\_is\_ready(hmc5883)) { printf("hmc5883\_init:device not found\r\n"); return false; } // 设置传感器采样模式 uint8\_t mem_addr = 0x02; uint8\_t write_data = 0x00; // 连续采样模式 bool res = \_\_hmc5883\_write(hmc5883, mem_addr, &write_data, 1); hmc5883->inited = res; return res; } void hmc5883\_update(hmc5883\_t \*hmc5883) { uint8\_t mem_addr = 0x03; // X MSB 寄存器 uint8\_t data[6] = { 0 }; \_\_hmc5883\_read(hmc5883, mem_addr, data, 6); hmc5883->x = data[0] << 8 | data[1]; hmc5883->y = data[2] << 8 | data[3]; hmc5883->z = data[4] << 8 | data[5]; // 计算XY,XZ,YZ平面角度 //计算XY平面角度 hmc5883->angle_xy = atan2((double) hmc5883->y, (double) hmc5883->x) \* (180 / 3.14159265) + 180.0; //计算XZ平面角度 hmc5883->angle_xz = atan2((double) hmc5883->z, (double) hmc5883->x) \* (180 / 3.14159265) + 180.0; //计算YZ平面角度 hmc5883->angle_yz = atan2((double) hmc5883->z, (double) hmc5883->y) \* (180 / 3.14159265) + 180.0; }
3、驱动测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 /\* Private includes ----------------------------------------------------------\*/ /\* USER CODE BEGIN Includes \*/ #include <stdio.h> #include <hmc5883/hmc5883.h> /\* USER CODE END Includes \*/ /\* Private variables ---------------------------------------------------------\*/ /\* USER CODE BEGIN PV \*/ hmc5883\_t hmc5883; /\* USER CODE END PV \*/ int main(void) { /\* USER CODE BEGIN 1 \*/ /\* USER CODE END 1 \*/ /\* MCU Configuration--------------------------------------------------------\*/ /\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/ HAL\_Init(); /\* USER CODE BEGIN Init \*/ /\* USER CODE END Init \*/ /\* Configure the system clock \*/ SystemClock\_Config(); /\* USER CODE BEGIN SysInit \*/ /\* USER CODE END SysInit \*/ /\* Initialize all configured peripherals \*/ MX\_GPIO\_Init(); MX\_USART1\_UART\_Init(); MX\_I2C1\_Init(); /\* USER CODE BEGIN 2 \*/ hmc5883.id = 0x01; hmc5883.addr = HMC5883_DEVICE_ADDR; hmc5883.i2c = &hi2c1; if (!hmc5883\_init(&hmc5883)) { printf("hmc5883 init failed\r\n"); while (1) ; } /\* USER CODE END 2 \*/ /\* Infinite loop \*/ /\* USER CODE BEGIN WHILE \*/ while (1) { /\* USER CODE END WHILE \*/ /\* USER CODE BEGIN 3 \*/ hmc5883\_update(&hmc5883); printf("x = %d,y = %d,z = %d\r\n", hmc5883.x, hmc5883.y, hmc5883.z); printf("xy = %.2f,xz = %.2f,yz = %.2f\r\n", hmc5883.angle_xy, hmc5883.angle_xz, hmc5883.angle_yz); HAL\_Delay(100); } /\* USER CODE END 3 \*/ } /\*\* \* @brief System Clock Configuration \* @retval None \*/ void SystemClock\_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = { 0 }; RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 }; /\*\* Initializes the RCC Oscillators according to the specified parameters \* in the RCC\_OscInitTypeDef structure. \*/ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL\_RCC\_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error\_Handler(); } /\*\* Initializes the CPU, AHB and APB buses clocks \*/ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL\_RCC\_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error\_Handler(); } }
文章来源: https://iotsmart.blog.csdn.net/article/details/125868203
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!