├── DS18B20 ├── README.md ├── ds18b20.c └── ds18b20.h ├── LICENSE ├── MPU6500 ├── README.md ├── mpu6500.c └── mpu6500.h ├── MPU9250 ├── README.md ├── mpu9250.c └── mpu9250.h ├── OLED ├── README.md ├── oled_spi.c └── oled_spi.h ├── README.md ├── Tamagawa ├── README.md ├── tamagawa.c └── tamagawa.h └── soft_i2c ├── READMEmd ├── soft_i2c.c └── soft_i2c.h /DS18B20/README.md: -------------------------------------------------------------------------------- 1 | # 原理讲解 2 | [DS18B20温度传感器数据读取](https://imuncle.github.io/content.html?id=46) 3 | 4 | # 函数接口 5 | function_name|brief 6 | :--:|:--: 7 | DS18B20_Delay|基于TIM7的微秒延时函数,其中TIM7预分频之后频率为1MHz 8 | DS18B20_Init|初始化函数,传入引脚号 9 | DS18B20_MatchRom|匹配 DS18B20 ROM 10 | DS18B20_GetTemp_SkipRom|在跳过匹配 ROM 情况下获取 DS18B20 温度值 11 | DS18B20_GetTemp_MatchRom|在匹配 ROM 情况下获取 DS18B20 温度值 12 | DS18B20_ReadId|在匹配 ROM 情况下获取 DS18B20 温度值 13 | 14 | # 调用示例代码 15 | ```c 16 | while(1) 17 | { 18 | DS18B20_Init(GPIOA, GPIO_PIN_6); 19 | tempareture1 = DS18B20_GetTemp_SkipRom(GPIOA, GPIO_PIN_6); 20 | } 21 | ``` -------------------------------------------------------------------------------- /DS18B20/ds18b20.c: -------------------------------------------------------------------------------- 1 | #include "ds18b20.h" 2 | #include "tim.h" 3 | /** 4 | * 函数功能: 5 | * 输入参数: 无 6 | * 返 回 值: 无 7 | * 说 明:无 8 | */ 9 | static void DS18B20_Delay(uint16_t time) 10 | { 11 | uint16_t differ = 0xffff-time-5; 12 | __HAL_TIM_SET_COUNTER(&htim7, differ); 13 | HAL_TIM_Base_Start(&htim7); 14 | while(__HAL_TIM_GET_COUNTER(&htim7) < 0xffff-6){} 15 | HAL_TIM_Base_Stop(&htim7); 16 | } 17 | 18 | /** 19 | * 函数功能: 使DS18B20-DATA引脚变为上拉输入模式 20 | * 输入参数: 无 21 | * 返 回 值: 无 22 | * 说 明:无 23 | */ 24 | static void DS18B20_Mode_IPU(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 25 | { 26 | GPIO_InitTypeDef GPIO_InitStruct; 27 | 28 | /* 串口外设功能GPIO配置 */ 29 | GPIO_InitStruct.Pin = GPIO_Pin; 30 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 31 | GPIO_InitStruct.Pull = GPIO_PULLUP; 32 | HAL_GPIO_Init(GPIOx, &GPIO_InitStruct); 33 | 34 | } 35 | 36 | /** 37 | * 函数功能: 使DS18B20-DATA引脚变为推挽输出模式 38 | * 输入参数: 无 39 | * 返 回 值: 无 40 | * 说 明:无 41 | */ 42 | static void DS18B20_Mode_Out_PP(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 43 | { 44 | GPIO_InitTypeDef GPIO_InitStruct; 45 | 46 | /* 串口外设功能GPIO配置 */ 47 | GPIO_InitStruct.Pin = GPIO_Pin; 48 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 49 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 50 | HAL_GPIO_Init(GPIOx, &GPIO_InitStruct); 51 | } 52 | 53 | /** 54 | * 函数功能: 主机给从机发送复位脉冲 55 | * 输入参数: 无 56 | * 返 回 值: 无 57 | * 说 明:无 58 | */ 59 | static void DS18B20_Rst(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 60 | { 61 | /* 主机设置为推挽输出 */ 62 | DS18B20_Mode_Out_PP(GPIOx, GPIO_Pin); 63 | 64 | HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_RESET); 65 | 66 | /* 主机至少产生480us的低电平复位信号 */ 67 | DS18B20_Delay(750); 68 | 69 | /* 主机在产生复位信号后,需将总线拉高 */ 70 | HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_SET); 71 | 72 | /*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/ 73 | DS18B20_Delay(15); 74 | } 75 | 76 | /** 77 | * 函数功能: 检测从机给主机返回的存在脉冲 78 | * 输入参数: 无 79 | * 返 回 值: 0:成功,1:失败 80 | * 说 明:无 81 | */ 82 | static uint8_t DS18B20_Presence(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 83 | { 84 | uint8_t pulse_time = 0; 85 | 86 | /* 主机设置为上拉输入 */ 87 | DS18B20_Mode_IPU(GPIOx, GPIO_Pin); 88 | 89 | /* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号 90 | * 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲 91 | */ 92 | while( HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) && pulse_time<100 ) 93 | { 94 | pulse_time++; 95 | DS18B20_Delay(1); 96 | } 97 | /* 经过100us后,存在脉冲都还没有到来*/ 98 | if( pulse_time >=100 ) 99 | return 1; 100 | else 101 | pulse_time = 0; 102 | 103 | /* 存在脉冲到来,且存在的时间不能超过240us */ 104 | while( !HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) && pulse_time<240 ) 105 | { 106 | pulse_time++; 107 | DS18B20_Delay(1); 108 | } 109 | if( pulse_time >=240 ) 110 | return 1; 111 | else 112 | return 0; 113 | } 114 | 115 | /** 116 | * 函数功能: DS18B20 初始化函数 117 | * 输入参数: 无 118 | * 返 回 值: 无 119 | * 说 明:无 120 | */ 121 | uint8_t DS18B20_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 122 | { 123 | __HAL_RCC_GPIOA_CLK_ENABLE(); 124 | DS18B20_Mode_Out_PP(GPIOx, GPIO_Pin); 125 | HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_SET); 126 | 127 | DS18B20_Rst(GPIOx, GPIO_Pin); 128 | 129 | return DS18B20_Presence (GPIOx, GPIO_Pin); 130 | } 131 | 132 | /** 133 | * 函数功能: 从DS18B20读取一个bit 134 | * 输入参数: 无 135 | * 返 回 值: 读取到的数据 136 | * 说 明:无 137 | */ 138 | static uint8_t DS18B20_ReadBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 139 | { 140 | uint8_t dat; 141 | 142 | /* 读0和读1的时间至少要大于60us */ 143 | DS18B20_Mode_Out_PP(GPIOx, GPIO_Pin); 144 | /* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */ 145 | HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_RESET); 146 | DS18B20_Delay(10); 147 | 148 | /* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */ 149 | DS18B20_Mode_IPU(GPIOx, GPIO_Pin); 150 | 151 | if( HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) == SET ) 152 | dat = 1; 153 | else 154 | dat = 0; 155 | 156 | /* 这个延时参数请参考时序图 */ 157 | DS18B20_Delay(45); 158 | 159 | return dat; 160 | } 161 | 162 | /** 163 | * 函数功能: 从DS18B20读一个字节,低位先行 164 | * 输入参数: 无 165 | * 返 回 值: 读到的数据 166 | * 说 明:无 167 | */ 168 | static uint8_t DS18B20_ReadByte(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 169 | { 170 | uint8_t i, j, dat = 0; 171 | 172 | for(i=0; i<8; i++) 173 | { 174 | j = DS18B20_ReadBit(GPIOx, GPIO_Pin); 175 | dat = (dat) | (j<>1; 196 | /* 写0和写1的时间至少要大于60us */ 197 | if (testb) 198 | { 199 | HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_RESET); 200 | /* 1us < 这个延时 < 15us */ 201 | DS18B20_Delay(8); 202 | 203 | HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_SET); 204 | DS18B20_Delay(58); 205 | } 206 | else 207 | { 208 | HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_RESET); 209 | /* 60us < Tx 0 < 120us */ 210 | DS18B20_Delay(70); 211 | 212 | HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_SET); 213 | /* 1us < Trec(恢复时间) < 无穷大*/ 214 | DS18B20_Delay(2); 215 | } 216 | } 217 | } 218 | 219 | /** 220 | * 函数功能: 跳过匹配 DS18B20 ROM 221 | * 输入参数: 无 222 | * 返 回 值: 无 223 | * 说 明:无 224 | */ 225 | static void DS18B20_SkipRom (GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 226 | { 227 | DS18B20_Rst(GPIOx, GPIO_Pin); 228 | DS18B20_Presence(GPIOx, GPIO_Pin); 229 | DS18B20_WriteByte(0XCC, GPIOx, GPIO_Pin); /* 跳过 ROM */ 230 | } 231 | 232 | /** 233 | * 函数功能: 执行匹配 DS18B20 ROM 234 | * 输入参数: 无 235 | * 返 回 值: 无 236 | * 说 明:无 237 | */ 238 | static void DS18B20_MatchRom (GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 239 | { 240 | DS18B20_Rst(GPIOx, GPIO_Pin); 241 | DS18B20_Presence(GPIOx, GPIO_Pin); 242 | DS18B20_WriteByte(0X55, GPIOx, GPIO_Pin); /* 匹配 ROM */ 243 | } 244 | 245 | 246 | /* 247 | * 存储的温度是16 位的带符号扩展的二进制补码形式 248 | * 当工作在12位分辨率时,其中5个符号位,7个整数位,4个小数位 249 | * 250 | * |---------整数----------|-----小数 分辨率 1/(2^4)=0.0625----| 251 | * 低字节 | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) | 252 | * 253 | * 254 | * |-----符号位:0->正 1->负-------|-----------整数-----------| 255 | * 高字节 | s | s | s | s | s | 2^6 | 2^5 | 2^4 | 256 | * 257 | * 258 | * 温度 = 符号位 + 整数 + 小数*0.0625 259 | */ 260 | /** 261 | * 函数功能: 在跳过匹配 ROM 情况下获取 DS18B20 温度值 262 | * 输入参数: 无 263 | * 返 回 值: 温度值 264 | * 说 明:无 265 | */ 266 | float DS18B20_GetTemp_SkipRom (GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 267 | { 268 | uint8_t tpmsb, tplsb; 269 | short s_tem; 270 | float f_tem; 271 | 272 | 273 | DS18B20_SkipRom (GPIOx, GPIO_Pin); 274 | DS18B20_WriteByte(0X44, GPIOx, GPIO_Pin); /* 开始转换 */ 275 | 276 | 277 | DS18B20_SkipRom (GPIOx, GPIO_Pin); 278 | DS18B20_WriteByte(0XBE, GPIOx, GPIO_Pin); /* 读温度值 */ 279 | 280 | tplsb = DS18B20_ReadByte(GPIOx, GPIO_Pin); 281 | tpmsb = DS18B20_ReadByte(GPIOx, GPIO_Pin); 282 | 283 | 284 | s_tem = tpmsb<<8; 285 | s_tem = s_tem | tplsb; 286 | 287 | if( s_tem < 0 ) /* 负温度 */ 288 | f_tem = (~s_tem+1) * 0.0625; 289 | else 290 | f_tem = s_tem * 0.0625; 291 | 292 | return f_tem; 293 | } 294 | 295 | /** 296 | * 函数功能: 在匹配 ROM 情况下获取 DS18B20 温度值 297 | * 输入参数: ds18b20_id:用于存放 DS18B20 序列号的数组的首地址 298 | * 返 回 值: 无 299 | * 说 明:无 300 | */ 301 | void DS18B20_ReadId (uint8_t * ds18b20_id ,GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 302 | { 303 | uint8_t uc; 304 | 305 | DS18B20_WriteByte(0x33, GPIOx, GPIO_Pin); //读取序列号 306 | 307 | for ( uc = 0; uc < 8; uc ++ ) 308 | ds18b20_id [ uc ] = DS18B20_ReadByte(GPIOx, GPIO_Pin); 309 | } 310 | 311 | /** 312 | * 函数功能: 在匹配 ROM 情况下获取 DS18B20 温度值 313 | * 输入参数: ds18b20_id:存放 DS18B20 序列号的数组的首地址 314 | * 返 回 值: 温度值 315 | * 说 明:无 316 | */ 317 | float DS18B20_GetTemp_MatchRom ( uint8_t * ds18b20_id,GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 318 | { 319 | uint8_t tpmsb, tplsb, i; 320 | short s_tem; 321 | float f_tem; 322 | 323 | 324 | DS18B20_MatchRom (GPIOx, GPIO_Pin); //匹配ROM 325 | 326 | for(i=0;i<8;i++) 327 | DS18B20_WriteByte ( ds18b20_id [ i ] ,GPIOx, GPIO_Pin); 328 | 329 | DS18B20_WriteByte(0X44,GPIOx, GPIO_Pin); /* 开始转换 */ 330 | 331 | 332 | DS18B20_MatchRom (GPIOx, GPIO_Pin); //匹配ROM 333 | 334 | for(i=0;i<8;i++) 335 | DS18B20_WriteByte ( ds18b20_id [ i ] ,GPIOx, GPIO_Pin); 336 | 337 | DS18B20_WriteByte(0XBE,GPIOx, GPIO_Pin); /* 读温度值 */ 338 | 339 | tplsb = DS18B20_ReadByte(GPIOx, GPIO_Pin); 340 | tpmsb = DS18B20_ReadByte(GPIOx, GPIO_Pin); 341 | 342 | 343 | s_tem = tpmsb<<8; 344 | s_tem = s_tem | tplsb; 345 | 346 | if( s_tem < 0 ) /* 负温度 */ 347 | f_tem = (~s_tem+1) * 0.0625; 348 | else 349 | f_tem = s_tem * 0.0625; 350 | 351 | return f_tem; 352 | } 353 | 354 | -------------------------------------------------------------------------------- /DS18B20/ds18b20.h: -------------------------------------------------------------------------------- 1 | #ifndef DS18B20_H 2 | #define DS18B20_H 3 | 4 | #include "stm32f4xx.h" 5 | 6 | uint8_t DS18B20_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 7 | void DS18B20_ReadId(uint8_t * ds18b20_id, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 8 | float DS18B20_GetTemp_SkipRom(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 9 | float DS18B20_GetTemp_MatchRom(uint8_t *ds18b20_id,GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 big_uncle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MPU6500/README.md: -------------------------------------------------------------------------------- 1 | # 原理讲解 2 | [MPU9250姿态解析](https://imuncle.github.io/content.html?id=44) 3 | 4 | # 注意事项 5 | 代码中使用的是STM32的**硬件I2C2**,如果你使用的I2C方式不一样,请注意修改。 6 | 7 | 这里使用的是MPU9250中的MPU6500,该代码也适用于MPU6650。 8 | 9 | # 函数接口 10 | function_name|brief 11 | :--:|:--: 12 | MPU6500_Init|MPU6500初始化 13 | GetImuData|获取IMU的陀螺仪数据和加速度数据 14 | imuDataHandle|IMU原始数据的处理,包括滤波,消除静差等 15 | imuUpdate|IMU姿态解析函数,使用AHRS融合算法 16 | 17 | # 调用示例 18 | ```c 19 | MPU6500_Init(); 20 | while(1) 21 | { 22 | GetImuData(); 23 | imuDataHandle(); 24 | imuUpdate(); 25 | } 26 | ``` -------------------------------------------------------------------------------- /MPU6500/mpu6500.c: -------------------------------------------------------------------------------- 1 | #include "mpu6500.h" 2 | #include "i2c.h" 3 | #include 4 | 5 | #define DEG2RAD 0.017453293f /*度转弧度*/ 6 | #define RAD2DEG 57.29578f /*弧度转度*/ 7 | 8 | struct MPU6500_t mpu6500; 9 | 10 | BiasObj gyroBiasRunning; 11 | int gyroBiasFound = 0; 12 | float accScaleSum = 0; 13 | float accScale = 1; 14 | 15 | float Kp = 2.0f; /*比例增益*/ 16 | float Ki = 0.1f; /*积分增益*/ 17 | float exInt = 0.0f; 18 | float eyInt = 0.0f; 19 | float ezInt = 0.0f; /*积分误差累计*/ 20 | 21 | static float q0 = 1.0f; /*四元数*/ 22 | static float q1 = 0.0f; 23 | static float q2 = 0.0f; 24 | static float q3 = 0.0f; 25 | 26 | uint8_t imu_data[14]={0}; 27 | 28 | float faccx,faccy,faccz; 29 | 30 | struct Axisf gyroBias; 31 | 32 | volatile uint32_t last_update, now_update; 33 | 34 | int MPU6500_Init(void) 35 | { 36 | unsigned char pdata; 37 | //检查设备是否准备好 38 | HAL_I2C_IsDeviceReady(&hi2c2, MPU6500_ADDRESS, 10, 10); 39 | 40 | pdata=0x80; //复位MPU 41 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_PWR_MGMT1_REG, 1, &pdata, 1, 10); 42 | 43 | HAL_Delay(500); //复位后需要等待一段时间,等待芯片复位完成 44 | 45 | pdata=0x00; //唤醒MPU 46 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_PWR_MGMT1_REG, 1, &pdata, 1, 10); 47 | 48 | HAL_I2C_Mem_Read(&hi2c2, MPU6500_ADDRESS, MPU_WHO_I_AM, 1, &pdata, 1, 10); 49 | if(pdata != 0x71) return 1; 50 | 51 | pdata=0x18; //设置量程为2000 52 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_GYRO_CFG_REG, 1, &pdata, 1, 10); 53 | 54 | pdata=0x08; //设置加速度传感器量程±4g 55 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_ACCEL_CFG_REG, 1, &pdata, 1, 10); 56 | 57 | pdata=0; //陀螺仪采样分频设置 58 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_SAMPLE_RATE_REG, 1, &pdata, 1, 10); 59 | 60 | pdata=0; //关闭所有中断 61 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_INT_EN_REG, 1, &pdata, 1, 10); 62 | 63 | pdata=0; //关闭FIFO 64 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_FIFO_EN_REG, 1, &pdata, 1, 10); 65 | 66 | pdata = 6; //设置mpu6500的数字低通滤波器 67 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_CFG_REG, 1, &pdata, 1, 10); 68 | 69 | pdata = 0x0C; 70 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_ACCEL_DLPF_DERG, 1, &pdata, 1, 10); 71 | 72 | pdata=0; //使能陀螺仪和加速度工作 73 | HAL_I2C_Mem_Write(&hi2c2, MPU6500_ADDRESS, MPU_PWR_MGMT2_REG, 1, &pdata, 1, 10); 74 | 75 | return 0; 76 | } 77 | 78 | /*计算方差和平均值*/ 79 | static void sensorsCalculateVarianceAndMean(BiasObj* bias, struct Axisf* varOut, struct Axisf* meanOut) 80 | { 81 | uint32_t i; 82 | int64_t sum[3] = {0}; 83 | int64_t sumsq[3] = {0}; 84 | 85 | for (i = 0; i < SENSORS_NBR_OF_BIAS_SAMPLES; i++) 86 | { 87 | sum[0] += bias->buffer[i].x; 88 | sum[1] += bias->buffer[i].y; 89 | sum[2] += bias->buffer[i].z; 90 | sumsq[0] += bias->buffer[i].x * bias->buffer[i].x; 91 | sumsq[1] += bias->buffer[i].y * bias->buffer[i].y; 92 | sumsq[2] += bias->buffer[i].z * bias->buffer[i].z; 93 | } 94 | 95 | varOut->x = (sumsq[0] - ((int64_t)sum[0] * sum[0]) / SENSORS_NBR_OF_BIAS_SAMPLES); 96 | varOut->y = (sumsq[1] - ((int64_t)sum[1] * sum[1]) / SENSORS_NBR_OF_BIAS_SAMPLES); 97 | varOut->z = (sumsq[2] - ((int64_t)sum[2] * sum[2]) / SENSORS_NBR_OF_BIAS_SAMPLES); 98 | 99 | meanOut->x = (float)sum[0] / SENSORS_NBR_OF_BIAS_SAMPLES; 100 | meanOut->y = (float)sum[1] / SENSORS_NBR_OF_BIAS_SAMPLES; 101 | meanOut->z = (float)sum[2] / SENSORS_NBR_OF_BIAS_SAMPLES; 102 | } 103 | /*传感器查找偏置值*/ 104 | static int sensorsFindBiasValue(BiasObj* bias) 105 | { 106 | int foundbias = 0; 107 | 108 | if (bias->isBufferFilled) 109 | { 110 | 111 | struct Axisf mean; 112 | struct Axisf variance; 113 | sensorsCalculateVarianceAndMean(bias, &variance, &mean); 114 | 115 | if (variance.x < GYRO_VARIANCE_BASE && variance.y < GYRO_VARIANCE_BASE && variance.z < GYRO_VARIANCE_BASE) 116 | { 117 | bias->bias.x = mean.x; 118 | bias->bias.y = mean.y; 119 | bias->bias.z = mean.z; 120 | foundbias = 1; 121 | bias->isBiasValueFound= 1; 122 | }else 123 | bias->isBufferFilled=0; 124 | } 125 | return foundbias; 126 | } 127 | 128 | /** 129 | * 计算陀螺方差 130 | */ 131 | int processGyroBias(int16_t gx, int16_t gy, int16_t gz, struct Axisf *gyroBiasOut) 132 | { 133 | static int count = 0; 134 | gyroBiasRunning.buffer[count].x = gx; 135 | gyroBiasRunning.buffer[count].y = gy; 136 | gyroBiasRunning.buffer[count].z = gz; 137 | count++; 138 | if(count == 1024) 139 | { 140 | count = 0; 141 | gyroBiasRunning.isBufferFilled = 1; 142 | } 143 | 144 | if (!gyroBiasRunning.isBiasValueFound) 145 | { 146 | sensorsFindBiasValue(&gyroBiasRunning); 147 | } 148 | 149 | gyroBiasOut->x = gyroBiasRunning.bias.x; 150 | gyroBiasOut->y = gyroBiasRunning.bias.y; 151 | gyroBiasOut->z = gyroBiasRunning.bias.z; 152 | 153 | return gyroBiasRunning.isBiasValueFound; 154 | } 155 | 156 | /** 157 | * 根据样本计算重力加速度缩放因子 158 | */ 159 | int processAccScale(int16_t ax, int16_t ay, int16_t az) 160 | { 161 | static int accBiasFound = 0; 162 | static uint32_t accScaleSumCount = 0; 163 | 164 | if (!accBiasFound) 165 | { 166 | accScaleSum += sqrtf(powf((float)ax/8192, 2) + powf((float)ay/8192, 2) + powf((float)az/8192, 2)); 167 | accScaleSumCount++; 168 | 169 | if (accScaleSumCount == SENSORS_ACC_SCALE_SAMPLES) 170 | { 171 | accScale = accScaleSum / SENSORS_ACC_SCALE_SAMPLES; 172 | accBiasFound = 1; 173 | } 174 | } 175 | 176 | return accBiasFound; 177 | } 178 | 179 | int GetImuData(void) 180 | { 181 | if(HAL_I2C_Mem_Read(&hi2c2, MPU6500_ADDRESS, MPU_ACCEL_XOUTH_REG, 1, imu_data, 14, 10) == HAL_OK) //读取陀螺仪和加速度计的数据 182 | { 183 | return 1; 184 | } 185 | else 186 | { 187 | return 0; 188 | } 189 | } 190 | 191 | void imuDataHandle(void) 192 | { 193 | short accx,accy,accz; 194 | short gyrox,gyroy,gyroz; 195 | float fgyrox, fgyroy, fgyroz; 196 | 197 | float gyro_sensitivity = 16.384f; 198 | int acc_sensitivity = 8192; 199 | 200 | accx = (imu_data[0]<<8)|imu_data[1]; 201 | accy = (imu_data[2]<<8)|imu_data[3]; 202 | accz = (imu_data[4]<<8)|imu_data[5]; 203 | gyrox = (imu_data[8]<<8)|imu_data[9]; 204 | gyroy = (imu_data[10]<<8)|imu_data[11]; 205 | gyroz = (imu_data[12]<<8)|imu_data[13]; 206 | 207 | gyroBiasFound = processGyroBias(gyrox, gyroy, gyroz, &gyroBias); 208 | 209 | if (gyroBiasFound) 210 | { 211 | processAccScale(accx, accy, accz); /*计算accScale*/ 212 | } 213 | 214 | fgyrox = -(float)(gyrox-gyroBias.x)/gyro_sensitivity; 215 | fgyroy = (float)(gyroy-gyroBias.y)/gyro_sensitivity; 216 | fgyroz = (float)(gyroz-gyroBias.z)/gyro_sensitivity; 217 | 218 | mpu6500.gyro.x = 0.8f*fgyrox + 0.2f*mpu6500.gyro.x; 219 | mpu6500.gyro.y = 0.8f*fgyroy + 0.2f*mpu6500.gyro.y; 220 | mpu6500.gyro.z = 0.8f*fgyroz + 0.2f*mpu6500.gyro.z; 221 | 222 | faccx = -(float)(accx)/acc_sensitivity/accScale; 223 | faccy = (float)(accy)/acc_sensitivity/accScale; 224 | faccz = (float)(accz)/acc_sensitivity/accScale; 225 | 226 | mpu6500.acc.x = 0.2f*faccx + 0.8f*mpu6500.acc.x; 227 | mpu6500.acc.y = 0.2f*faccy + 0.8f*mpu6500.acc.y; 228 | mpu6500.acc.z = 0.2f*faccz + 0.8f*mpu6500.acc.z; 229 | } 230 | 231 | void imuUpdate(struct Axisf acc, struct Axisf gyro) 232 | { 233 | float q0q0 = q0 * q0; 234 | float q1q1 = q1 * q1; 235 | float q2q2 = q2 * q2; 236 | float q3q3 = q3 * q3; 237 | 238 | float q0q1 = q0 * q1; 239 | float q0q2 = q0 * q2; 240 | float q0q3 = q0 * q3; 241 | float q1q2 = q1 * q2; 242 | float q1q3 = q1 * q3; 243 | float q2q3 = q2 * q3; 244 | 245 | float normalise; 246 | float ex, ey, ez; 247 | float halfT; 248 | float vx, vy, vz; 249 | 250 | now_update = HAL_GetTick(); //单位ms 251 | halfT = ((float)(now_update - last_update) / 2000.0f); 252 | last_update = now_update; 253 | 254 | gyro.x *= DEG2RAD; /*度转弧度*/ 255 | gyro.y *= DEG2RAD; 256 | gyro.z *= DEG2RAD; 257 | 258 | /* 对加速度计数据进行归一化处理 */ 259 | if(acc.x != 0 || acc.y != 0 || acc.z != 0) 260 | { 261 | normalise = sqrt(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z); 262 | acc.x /= normalise; 263 | acc.y /= normalise; 264 | acc.z /= normalise; 265 | } 266 | 267 | /* 计算加速度计投影到物体坐标上的各个分量 */ 268 | vx = 2.0f*(q1q3 - q0q2); 269 | vy = 2.0f*(q0q1 + q2q3); 270 | vz = q0q0 - q1q1 - q2q2 + q3q3; 271 | 272 | /* 叉积误差累计,用以修正陀螺仪数据 */ 273 | ex = (acc.y*vz - acc.z*vy); 274 | ey = (acc.z*vx - acc.x*vz); 275 | ez = (acc.x*vy - acc.y*vx); 276 | 277 | /* 互补滤波 PI */ 278 | exInt += ex * Ki * halfT; 279 | eyInt += ey * Ki * halfT; 280 | ezInt += ez * Ki * halfT; 281 | gyro.x += Kp*ex + exInt; 282 | gyro.y += Kp*ey + eyInt; 283 | gyro.z += Kp*ez + ezInt; 284 | 285 | /* 使用一阶龙格库塔更新四元数 */ 286 | q0 += (-q1 * gyro.x - q2 * gyro.y - q3 * gyro.z) * halfT; 287 | q1 += ( q0 * gyro.x + q2 * gyro.z - q3 * gyro.y) * halfT; 288 | q2 += ( q0 * gyro.y - q1 * gyro.z + q3 * gyro.x) * halfT; 289 | q3 += ( q0 * gyro.z + q1 * gyro.y - q2 * gyro.x) * halfT; 290 | 291 | /* 对四元数进行归一化处理 */ 292 | normalise = sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3); 293 | q0 /= normalise; 294 | q1 /= normalise; 295 | q2 /= normalise; 296 | q3 /= normalise; 297 | 298 | /* 由四元数求解欧拉角 */ 299 | mpu6500.attitude.x = -asinf(-2*q1*q3 + 2*q0*q2) * RAD2DEG; //pitch 300 | mpu6500.attitude.y = atan2f(2*q2*q3 + 2*q0*q1, -2*q1*q1 - 2*q2*q2 + 1) * RAD2DEG; //roll 301 | mpu6500.attitude.z = atan2f(2*q1*q2 + 2*q0*q3, -2*q2*q2 - 2*q3*q3 + 1) * RAD2DEG; //yaw 302 | } 303 | -------------------------------------------------------------------------------- /MPU6500/mpu6500.h: -------------------------------------------------------------------------------- 1 | #ifndef MPU9250_H 2 | #define MPU9250_H 3 | 4 | #define MPU6500_ADDRESS 0xD0 //AD0接GND时地址为0x68,接VCC时地址为0x69 5 | #define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1 6 | #define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器 7 | #define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器 8 | #define MPU_ACCEL_DLPF_DERG 0x1D //加速度低通寄存器 9 | #define MPU_SAMPLE_RATE_REG 0X19 //陀螺仪采样频率分频器 10 | #define MPU_INT_EN_REG 0X38 //中断使能寄存器 11 | #define MPU_USER_CTRL_REG 0X6A //用户控制寄存器 12 | #define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器 13 | #define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器 14 | #define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器 15 | #define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2 16 | #define MPU_CFG_REG 0X1A //配置寄存器 低通滤波器配置寄存器 17 | 18 | #define MPU_TEMP_OUTH_REG 0X41 //温度值高8位寄存器 19 | #define MPU_TEMP_OUTL_REG 0X42 //温度值低8位寄存器 20 | 21 | #define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器 22 | #define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器 23 | #define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器 24 | #define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器 25 | #define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器 26 | #define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器 27 | 28 | #define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器 29 | #define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器 30 | #define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器 31 | #define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器 32 | #define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器 33 | #define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器 34 | 35 | #define MPU_WHO_I_AM 0x75 //陀螺仪ID 36 | 37 | #define AK8963_ADDRESS 0x18 //磁力计地址0x0C 38 | #define AK8963_CNTL1 0x0A //磁力计读取寄存器 39 | #define AK8963_HXL 0x03 //磁力计X轴低8位寄存器 40 | #define AK8963_HXH 0x04 //磁力计X轴高8位寄存器 41 | #define AK8963_HYL 0x05 //磁力计Y轴低8位寄存器 42 | #define AK8963_HYH 0x06 //磁力计Y轴高8位寄存器 43 | #define AK8963_HZL 0x07 //磁力计Z轴低8位寄存器 44 | #define AK8963_HZH 0x08 //磁力计Z轴高8位寄存器 45 | #define AK8963_WHO_I_AM 0x00 //磁力计ID 46 | 47 | #define SENSORS_NBR_OF_BIAS_SAMPLES 1024 /*计算方差的采样样本个数 */ 48 | #define GYRO_VARIANCE_BASE 4000 /* 陀螺仪零偏方差阈值 */ 49 | #define SENSORS_ACC_SCALE_SAMPLES 200 /* 加速度采样个数 */ 50 | 51 | struct Axisf 52 | { 53 | float x; 54 | float y; 55 | float z; 56 | }; 57 | 58 | struct Axisi 59 | { 60 | int x; 61 | int y; 62 | int z; 63 | }; 64 | 65 | struct MPU6500_t 66 | { 67 | struct Axisf gyro; 68 | struct Axisf acc; 69 | struct Axisf attitude; 70 | }; 71 | 72 | typedef struct 73 | { 74 | struct Axisf bias; 75 | int isBiasValueFound; 76 | int isBufferFilled; 77 | struct Axisi buffer[SENSORS_NBR_OF_BIAS_SAMPLES]; 78 | }BiasObj; 79 | 80 | extern BiasObj gyroBiasRunning;; 81 | extern struct MPU6500_t mpu6500; 82 | 83 | int MPU6500_Init(void); 84 | int GetImuData(void); 85 | void imuDataHandle(void); 86 | void imuUpdate(struct Axisf acc, struct Axisf gyro); 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /MPU9250/README.md: -------------------------------------------------------------------------------- 1 | # 原理讲解 2 | [MPU9250姿态解析](https://imuncle.github.io/content.html?id=39) 3 | 4 | # 注意事项 5 | 代码中使用的是STM32的**硬件I2C2**,如果你使用的I2C方式不一样,请注意修改。 6 | 7 | # 函数接口 8 | function_name|brief 9 | :--:|:--: 10 | MPU6500_Init|MPU6500初始化 11 | GetImuData|获取IMU的陀螺仪数据和加速度数据 12 | imuUpdate|IMU姿态解析函数,使用AHRS融合算法 13 | 14 | # 调用示例 15 | ```c 16 | MPU6500_Init(); 17 | while(1) 18 | { 19 | GetImuData(); 20 | imuUpdate(); 21 | } 22 | ``` -------------------------------------------------------------------------------- /MPU9250/mpu9250.c: -------------------------------------------------------------------------------- 1 | #include "mpu9250.h" 2 | #include "i2c.h" 3 | #include 4 | 5 | #define DEG2RAD 0.017453293f /*度转弧度*/ 6 | #define RAD2DEG 57.29578f /*弧度转度*/ 7 | 8 | struct MPU9250_t mpu9250; 9 | 10 | float Kp = 2.0f; /*比例增益*/ 11 | float Ki = 0.1f; /*积分增益*/ 12 | float exInt = 0.0f; 13 | float eyInt = 0.0f; 14 | float ezInt = 0.0f; /*积分误差累计*/ 15 | 16 | static float q0 = 1.0f; /*四元数*/ 17 | static float q1 = 0.0f; 18 | static float q2 = 0.0f; 19 | static float q3 = 0.0f; 20 | 21 | int yaw,pitch,roll; 22 | 23 | volatile uint32_t last_update, now_update; 24 | 25 | void MPU9250_Init(void) 26 | { 27 | unsigned char pdata; 28 | //检查设备是否准备好 29 | HAL_I2C_IsDeviceReady(&hi2c1, MPU9250_ADDRESS, 10, HAL_MAX_DELAY); 30 | //检查总线是否准备好 31 | HAL_I2C_GetState(&hi2c1); 32 | 33 | pdata=0x80; //复位MPU 34 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_PWR_MGMT1_REG, 1, &pdata, 1, HAL_MAX_DELAY); 35 | HAL_I2C_IsDeviceReady(&hi2c1, MPU9250_ADDRESS, 10, HAL_MAX_DELAY); 36 | 37 | HAL_Delay(500); //复位后需要等待一段时间,等待芯片复位完成 38 | 39 | pdata=0x01; //唤醒MPU 40 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_PWR_MGMT1_REG, 1, &pdata, 1, HAL_MAX_DELAY); 41 | 42 | pdata=3<<3; //设置量程为2000 43 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_GYRO_CFG_REG, 1, &pdata, 1, HAL_MAX_DELAY); 44 | 45 | pdata=01; //设置加速度传感器量程±4g 46 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_ACCEL_CFG_REG, 1, &pdata, 1, HAL_MAX_DELAY); 47 | 48 | pdata=0; //陀螺仪采样分频设置 49 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_SAMPLE_RATE_REG, 1, &pdata, 1, HAL_MAX_DELAY); 50 | 51 | pdata=0; //关闭所有中断 52 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_INT_EN_REG, 1, &pdata, 1, HAL_MAX_DELAY); 53 | 54 | pdata=0; //关闭FIFO 55 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_FIFO_EN_REG, 1, &pdata, 1, HAL_MAX_DELAY); 56 | 57 | pdata=0X02; //设置旁路模式,直接读取AK8963磁力计数据 58 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_INTBP_CFG_REG, 1, &pdata, 1, HAL_MAX_DELAY); 59 | HAL_Delay(10); //需要一段延时让磁力计工作 60 | 61 | pdata = 4; //设置MPU9250的数字低通滤波器 62 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_CFG_REG, 1, &pdata, 1, HAL_MAX_DELAY); 63 | 64 | pdata=0; //使能陀螺仪和加速度工作 65 | HAL_I2C_Mem_Write(&hi2c1, MPU9250_ADDRESS, MPU_PWR_MGMT2_REG, 1, &pdata, 1, HAL_MAX_DELAY); 66 | 67 | pdata = 0x01; 68 | HAL_I2C_Mem_Write(&hi2c1, AK8963_ADDRESS, AK8963_CNTL1, 1, &pdata, 1, HAL_MAX_DELAY); 69 | HAL_Delay(10); 70 | } 71 | 72 | void GetImuData(void) 73 | { 74 | uint8_t imu_data[14]={0}; 75 | uint8_t mag_data[6] = {0}; 76 | uint8_t pdata; 77 | short accx,accy,accz; 78 | short gyrox,gyroy,gyroz; 79 | short magx,magy,magz; 80 | 81 | float gyro_sensitivity = 16.384f; 82 | int acc_sensitivity = 8192; 83 | 84 | static short mag_count = 0; 85 | 86 | HAL_I2C_Mem_Read(&hi2c1, MPU9250_ADDRESS, MPU_ACCEL_XOUTH_REG, 1, imu_data, 14, HAL_MAX_DELAY); //读取陀螺仪和加速度计的数据 87 | accx = (imu_data[0]<<8)|imu_data[1]; 88 | accy = (imu_data[2]<<8)|imu_data[3]; 89 | accz = (imu_data[4]<<8)|imu_data[5]; 90 | gyrox = (imu_data[8]<<8)|imu_data[9]; 91 | gyroy = (imu_data[10]<<8)|imu_data[11]; 92 | gyroz = (imu_data[12]<<8)|imu_data[13]; 93 | 94 | mpu9250.gyro.x = (float)(gyrox-GYROX_BIAS)/gyro_sensitivity; 95 | mpu9250.gyro.y = (float)(gyroy-GYROY_BIAS)/gyro_sensitivity; 96 | mpu9250.gyro.z = (float)(gyroz-GYROZ_BIAS)/gyro_sensitivity; 97 | 98 | mpu9250.acc.x = (float)(accx-ACCX_BIAS)/acc_sensitivity; 99 | mpu9250.acc.y = (float)(accy-ACCY_BIAS)/acc_sensitivity; 100 | mpu9250.acc.z = (float)(accz-ACCZ_BIAS)/acc_sensitivity; 101 | 102 | mag_count++; 103 | if(mag_count == 10) //磁力计不能读取太频繁 104 | { 105 | HAL_I2C_Mem_Read(&hi2c1, AK8963_ADDRESS, AK8963_HXL, 1, mag_data, 6, HAL_MAX_DELAY); //读取磁力计数据 106 | magx = (mag_data[0]<<8)|mag_data[1]; 107 | magy = (mag_data[2]<<8)|mag_data[3]; 108 | magz = (mag_data[4]<<8)|mag_data[5]; 109 | mpu9250.mag.x = (float)magy/1000.0f; //磁力计的坐标方位不同 110 | mpu9250.mag.y = (float)magx/1000.0f; 111 | mpu9250.mag.z = -(float)magz/1000.0f; 112 | pdata = 1; 113 | HAL_I2C_Mem_Write(&hi2c1, AK8963_ADDRESS, AK8963_CNTL1, 1, &pdata, 1, HAL_MAX_DELAY); //为下一次读取磁力计数据做准备 114 | mag_count = 0; 115 | } 116 | } 117 | 118 | void imuUpdate(struct Axisf acc, struct Axisf gyro, struct Axisf mag) 119 | { 120 | float q0q0 = q0 * q0; 121 | float q1q1 = q1 * q1; 122 | float q2q2 = q2 * q2; 123 | float q3q3 = q3 * q3; 124 | 125 | float q0q1 = q0 * q1; 126 | float q0q2 = q0 * q2; 127 | float q0q3 = q0 * q3; 128 | float q1q2 = q1 * q2; 129 | float q1q3 = q1 * q3; 130 | float q2q3 = q2 * q3; 131 | 132 | float normalise; 133 | float ex, ey, ez; 134 | float halfT; 135 | float hx, hy, hz, bx, bz; 136 | float vx, vy, vz, wx, wy, wz; 137 | 138 | now_update = HAL_GetTick(); //单位ms 139 | halfT = ((float)(now_update - last_update) / 2000.0f); 140 | last_update = now_update; 141 | 142 | gyro.x *= DEG2RAD; /*度转弧度*/ 143 | gyro.y *= DEG2RAD; 144 | gyro.z *= DEG2RAD; 145 | 146 | /* 对加速度计数据进行归一化处理 */ 147 | if(acc.x != 0 || acc.y != 0 || acc.z != 0) 148 | { 149 | normalise = sqrt(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z); 150 | acc.x /= normalise; 151 | acc.y /= normalise; 152 | acc.z /= normalise; 153 | } 154 | 155 | /* 对磁力计数据进行归一化处理 */ 156 | if(mag.x != 0 || mag.y != 0 || mag.z != 0) 157 | { 158 | normalise = sqrt(mag.x * mag.x + mag.y * mag.y + mag.z * mag.z); 159 | mag.x /= normalise; 160 | mag.y /= normalise; 161 | mag.z /= normalise; 162 | } 163 | 164 | /* 计算磁力计投影到物体坐标上的各个分量 */ 165 | hx = 2.0f*mag.x*(0.5f - q2q2 - q3q3) + 2.0f*mag.y*(q1q2 - q0q3) + 2.0f*mag.z*(q1q3 + q0q2); 166 | hy = 2.0f*mag.x*(q1q2 + q0q3) + 2.0f*mag.y*(0.5f - q1q1 - q3q3) + 2.0f*mag.z*(q2q3 - q0q1); 167 | hz = 2.0f*mag.x*(q1q3 - q0q2) + 2.0f*mag.y*(q2q3 + q0q1) + 2.0f*mag.z*(0.5f - q1q1 - q2q2); 168 | bx = sqrt((hx*hx) + (hy*hy)); 169 | bz = hz; 170 | 171 | /* 计算加速度计投影到物体坐标上的各个分量 */ 172 | vx = 2.0f*(q1q3 - q0q2); 173 | vy = 2.0f*(q0q1 + q2q3); 174 | vz = q0q0 - q1q1 - q2q2 + q3q3; 175 | 176 | /* 处理过后的磁力计新分量 */ 177 | wx = 2.0f*bx*(0.5f - q2q2 - q3q3) + 2.0f*bz*(q1q3 - q0q2); 178 | wy = 2.0f*bx*(q1q2 - q0q3) + 2.0f*bz*(q0q1 + q2q3); 179 | wz = 2.0f*bx*(q0q2 + q1q3) + 2.0f*bz*(0.5f - q1q1 - q2q2); 180 | 181 | /* 叉积误差累计,用以修正陀螺仪数据 */ 182 | ex = (acc.y*vz - acc.z*vy) + (mag.y*wz - mag.z*wy); 183 | ey = (acc.z*vx - acc.x*vz) + (mag.z*wx - mag.x*wz); 184 | ez = (acc.x*vy - acc.y*vx) + (mag.x*wy - mag.y*wx); 185 | 186 | /* 互补滤波 PI */ 187 | exInt += ex * Ki * halfT; 188 | eyInt += ey * Ki * halfT; 189 | ezInt += ez * Ki * halfT; 190 | gyro.x += Kp*ex + exInt; 191 | gyro.y += Kp*ey + eyInt; 192 | gyro.z += Kp*ez + ezInt; 193 | 194 | /* 使用一阶龙格库塔更新四元数 */ 195 | q0 += (-q1 * gyro.x - q2 * gyro.y - q3 * gyro.z) * halfT; 196 | q1 += ( q0 * gyro.x + q2 * gyro.z - q3 * gyro.y) * halfT; 197 | q2 += ( q0 * gyro.y - q1 * gyro.z + q3 * gyro.x) * halfT; 198 | q3 += ( q0 * gyro.z + q1 * gyro.y - q2 * gyro.x) * halfT; 199 | 200 | /* 对四元数进行归一化处理 */ 201 | normalise = sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3); 202 | q0 /= normalise; 203 | q1 /= normalise; 204 | q2 /= normalise; 205 | q3 /= normalise; 206 | 207 | /* 由四元数求解欧拉角 */ 208 | mpu9250.attitude.x = -asinf(-2*q1*q3 + 2*q0*q2) * RAD2DEG; //pitch 209 | mpu9250.attitude.y = atan2f(2*q2*q3 + 2*q0*q1, -2*q1*q1 - 2*q2*q2 + 1) * RAD2DEG; //roll 210 | mpu9250.attitude.z = atan2f(2*q1*q2 + 2*q0*q3, -2*q2*q2 - 2*q3*q3 + 1) * RAD2DEG; //yaw 211 | 212 | yaw = mpu9250.attitude.z*100; //用于J-Scope读取 213 | pitch = mpu9250.attitude.x*100; 214 | roll = mpu9250.attitude.y*100; 215 | } 216 | -------------------------------------------------------------------------------- /MPU9250/mpu9250.h: -------------------------------------------------------------------------------- 1 | #ifndef MPU9250_H 2 | #define MPU9250_H 3 | 4 | //在读取时,注意需要人工将地址左移1位(I2C读写为左对齐,第8位要存读写标志位) 5 | #define MPU9250_ADDRESS 0xD0 //AD0接GND时地址为0x68,接VCC时地址为0x69 6 | #define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1 7 | #define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器 8 | #define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器 9 | #define MPU_SAMPLE_RATE_REG 0X19 //陀螺仪采样频率分频器 10 | #define MPU_INT_EN_REG 0X38 //中断使能寄存器 11 | #define MPU_USER_CTRL_REG 0X6A //用户控制寄存器 12 | #define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器 13 | #define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器 14 | #define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器 15 | #define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2 16 | #define MPU_CFG_REG 0X1A //配置寄存器 低通滤波器配置寄存器 17 | 18 | #define MPU_TEMP_OUTH_REG 0X41 //温度值高8位寄存器 19 | #define MPU_TEMP_OUTL_REG 0X42 //温度值低8位寄存器 20 | 21 | #define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器 22 | #define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器 23 | #define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器 24 | #define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器 25 | #define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器 26 | #define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器 27 | 28 | #define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器 29 | #define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器 30 | #define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器 31 | #define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器 32 | #define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器 33 | #define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器 34 | 35 | #define AK8963_ADDRESS 0x18 //磁力计地址0x0C 36 | #define AK8963_CNTL1 0x0A //磁力计读取寄存器 37 | #define AK8963_HXL 0x03 //磁力计X轴低8位寄存器 38 | #define AK8963_HXH 0x04 //磁力计X轴高8位寄存器 39 | #define AK8963_HYL 0x05 //磁力计Y轴低8位寄存器 40 | #define AK8963_HYH 0x06 //磁力计Y轴高8位寄存器 41 | #define AK8963_HZL 0x07 //磁力计Z轴低8位寄存器 42 | #define AK8963_HZH 0x08 //磁力计Z轴高8位寄存器 43 | 44 | #define GYROX_BIAS -2.62451148f //静止时陀螺仪读数(陀螺仪静差) 45 | #define GYROY_BIAS 0.305175781 46 | #define GYROZ_BIAS -0.91552784 47 | 48 | #define ACCX_BIAS 0.0f //静止时加速度计读数(加速度计静差,此处未读取) 49 | #define ACCY_BIAS 0.0f 50 | #define ACCZ_BIAS 0.0f 51 | 52 | struct Axisf 53 | { 54 | float x; 55 | float y; 56 | float z; 57 | }; 58 | 59 | struct MPU9250_t 60 | { 61 | struct Axisf gyro; 62 | struct Axisf acc; 63 | struct Axisf mag; 64 | struct Axisf attitude; 65 | }; 66 | 67 | extern struct MPU9250_t mpu9250; 68 | 69 | void MPU9250_Init(void); 70 | void GetImuData(void); 71 | void imuUpdate(struct Axisf acc, struct Axisf gyro, struct Axisf mag); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /OLED/README.md: -------------------------------------------------------------------------------- 1 | # 注意事项 2 | 本份代码使用的是STM32的SPI1接口,如果你的使用方式不一样,请注意修改。 3 | 4 | # 函数接口 5 | function_name|brief 6 | :--:|:--: 7 | OLED_Init|OLED屏幕初始化,清屏 8 | OLED_ShowString|显示字符串 9 | OLED_ShowNum|显示数字 10 | 11 | # 调用示例 12 | ```c 13 | OLED_Init(); 14 | OLED_ShowString(0,0,(uint8_t *)"OLED TEST", 12); 15 | OLED_ShowNum(103,6,123,3,12); 16 | ``` -------------------------------------------------------------------------------- /OLED/oled_spi.c: -------------------------------------------------------------------------------- 1 | #include "oled.h" 2 | #include "spi.h" 3 | 4 | //OLED模式设置 5 | //0:4线串行模式 6 | //1:并行8080模式 7 | #define OLED_MODE 0 8 | 9 | #define SIZE 16 10 | #define XLevelL 0x00 11 | #define XLevelH 0x10 12 | #define Max_Column 128 13 | #define Max_Row 64 14 | #define Brightness 0xFF 15 | #define X_WIDTH 128 16 | #define Y_WIDTH 64 17 | 18 | /************************************6*8点阵************************************/ 19 | const unsigned char F6x8[][6] = 20 | { 21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp 22 | 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// ! 23 | 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// " 24 | 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// # 25 | 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $ 26 | 0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// % 27 | 0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// & 28 | 0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// ' 29 | 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// ( 30 | 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// ) 31 | 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// * 32 | 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// + 33 | 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// , 34 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// - 35 | 0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// . 36 | 0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// / 37 | 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0 38 | 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1 39 | 0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2 40 | 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3 41 | 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4 42 | 0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5 43 | 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6 44 | 0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7 45 | 0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8 46 | 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9 47 | 0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// : 48 | 0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ; 49 | 0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// < 50 | 0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// = 51 | 0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// > 52 | 0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ? 53 | 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @ 54 | 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A 55 | 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B 56 | 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C 57 | 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D 58 | 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E 59 | 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F 60 | 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G 61 | 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H 62 | 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I 63 | 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J 64 | 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K 65 | 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L 66 | 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M 67 | 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N 68 | 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O 69 | 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P 70 | 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q 71 | 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R 72 | 0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S 73 | 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T 74 | 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U 75 | 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V 76 | 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W 77 | 0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X 78 | 0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y 79 | 0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z 80 | 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [ 81 | 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55 82 | 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ] 83 | 0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^ 84 | 0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _ 85 | 0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// ' 86 | 0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a 87 | 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b 88 | 0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c 89 | 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d 90 | 0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e 91 | 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f 92 | 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g 93 | 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h 94 | 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i 95 | 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j 96 | 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k 97 | 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l 98 | 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m 99 | 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n 100 | 0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o 101 | 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p 102 | 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q 103 | 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r 104 | 0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s 105 | 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t 106 | 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u 107 | 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v 108 | 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w 109 | 0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x 110 | 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y 111 | 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z 112 | 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines 113 | }; 114 | /****************************************8*16点阵************************************/ 115 | const unsigned char F8X16[]= 116 | { 117 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0 118 | 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1 119 | 0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2 120 | 0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3 121 | 0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4 122 | 0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5 123 | 0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6 124 | 0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7 125 | 0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8 126 | 0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9 127 | 0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10 128 | 0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11 129 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12 130 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13 131 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14 132 | 0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15 133 | 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16 134 | 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17 135 | 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18 136 | 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19 137 | 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20 138 | 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21 139 | 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22 140 | 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23 141 | 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24 142 | 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25 143 | 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26 144 | 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27 145 | 0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28 146 | 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29 147 | 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30 148 | 0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31 149 | 0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32 150 | 0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33 151 | 0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34 152 | 0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35 153 | 0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36 154 | 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37 155 | 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38 156 | 0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39 157 | 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40 158 | 0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41 159 | 0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42 160 | 0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43 161 | 0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44 162 | 0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45 163 | 0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46 164 | 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47 165 | 0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48 166 | 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49 167 | 0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50 168 | 0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51 169 | 0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52 170 | 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53 171 | 0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54 172 | 0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55 173 | 0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56 174 | 0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57 175 | 0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58 176 | 0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59 177 | 0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60 178 | 0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61 179 | 0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62 180 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63 181 | 0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64 182 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65 183 | 0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66 184 | 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67 185 | 0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68 186 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69 187 | 0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70 188 | 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71 189 | 0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72 190 | 0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73 191 | 0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74 192 | 0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75 193 | 0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76 194 | 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77 195 | 0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78 196 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79 197 | 0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80 198 | 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81 199 | 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82 200 | 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83 201 | 0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84 202 | 0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85 203 | 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86 204 | 0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87 205 | 0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88 206 | 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89 207 | 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90 208 | 0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91 209 | 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92 210 | 0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93 211 | 0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94 212 | }; 213 | 214 | void OLED_Write_Data(uint8_t data) 215 | { 216 | HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); 217 | HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET); 218 | HAL_SPI_Transmit(&hspi1, &data, sizeof(data), HAL_MAX_DELAY); 219 | } 220 | 221 | void OLED_Write_Cmd(uint8_t data) 222 | { 223 | HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); 224 | HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); 225 | HAL_SPI_Transmit(&hspi1, &data, sizeof(data), HAL_MAX_DELAY); 226 | } 227 | 228 | void OLED_Clear(void) 229 | { 230 | uint8_t i,n; 231 | for(i=0;i<8;i++) 232 | { 233 | OLED_Write_Cmd(0xB0+i); 234 | OLED_Write_Cmd(0x00); 235 | OLED_Write_Cmd(0x10); 236 | for(n=0;n<128;n++) OLED_Write_Data(0); 237 | } 238 | } 239 | 240 | void OLED_Set_Pos(uint8_t x, uint8_t y) 241 | { 242 | OLED_Write_Cmd(0xB0+y); 243 | OLED_Write_Cmd(((x&0xf0)>>4)|0x10); 244 | OLED_Write_Cmd((x&0x0f)|0x01); 245 | } 246 | 247 | //在指定位置显示一个字符,包括部分字符 248 | //x:0~127 249 | //y:0~63 250 | //size:选择字体 16/12 251 | void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size) 252 | { 253 | uint8_t c=0,i=0; 254 | c = chr-' '; 255 | if(x>Max_Column-1){x=0;y+=2;} 256 | if(size == 16) 257 | { 258 | OLED_Set_Pos(x,y); 259 | for(i=0;i<8;i++) 260 | OLED_Write_Data(F8X16[c*16+i]); 261 | OLED_Set_Pos(x,y+1); 262 | for(i=0;i<8;i++) 263 | OLED_Write_Data(F8X16[c*16+i+8]); 264 | } 265 | else { 266 | OLED_Set_Pos(x,y+1); 267 | for(i=0;i<6;i++) 268 | OLED_Write_Data(F6x8[c][i]); 269 | } 270 | } 271 | 272 | void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t size) 273 | { 274 | uint8_t j = 0; 275 | while(chr[j]!='\0') 276 | { 277 | OLED_ShowChar(x,y,chr[j], size); 278 | x+=8; 279 | if(x>120){x=0;y+=2;} 280 | j++; 281 | } 282 | } 283 | 284 | //m^n函数 285 | uint32_t oled_pow(uint8_t m,uint8_t n) 286 | { 287 | uint32_t result=1; 288 | while(n--)result*=m; 289 | return result; 290 | } 291 | 292 | //显示2个数字 293 | //x,y :起点坐标 294 | //len :数字的位数 295 | //size:字体大小 296 | //mode:模式 0,填充模式;1,叠加模式 297 | //num:数值(0~4294967295) 298 | void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size) 299 | { 300 | uint8_t t,temp; 301 | uint8_t enshow=0; 302 | for(t=0;t> 7) ^ (crc >> 7); 177 | 178 | crc <<= 1; 179 | data[i] <<= 1; 180 | crc |= val; 181 | } 182 | 183 | return crc; 184 | } 185 | 186 | void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 187 | { 188 | HAL_UART_Receive_DMA(&huart6, &usart_data, 1); 189 | if(tamagawa_rx_cnt < rx_size) 190 | { 191 | USART6_RX_Buff[tamagawa_rx_cnt] = usart_data; 192 | tamagawa_rx_cnt++; 193 | } 194 | if(tamagawa_rx_cnt == rx_size) 195 | { 196 | rx_parse(USART6_RX_Buff); 197 | tamagawa_read(DATA_ID_3); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /Tamagawa/tamagawa.h: -------------------------------------------------------------------------------- 1 | #ifndef TAMAGAWA_H 2 | #define TAMAGAWA_H 3 | 4 | #include "stm32f4xx.h" 5 | 6 | /** 7 | * @brief Data ID codes 8 | */ 9 | enum DATA_ID 10 | { 11 | DATA_ID_0, /**< Data readout data in one revolution */ 12 | DATA_ID_1, /**< Data readout multi-turn data */ 13 | DATA_ID_2, /**< Data readout encoder ID */ 14 | DATA_ID_3, /**< Data readout data in one revolution, encoder ID, multi-turn, encoder error */ 15 | DATA_ID_6, /**< EEPROM write */ 16 | DATA_ID_7, /**< Reset */ 17 | DATA_ID_8, /**< Reset */ 18 | DATA_ID_C, /**< Reset */ 19 | DATA_ID_D, /**< EEPROM read */ 20 | DATA_ID_NUM /**< Number of Data ID codes */ 21 | }; 22 | 23 | /** 24 | * @brief Tamagawa Interface Transmit data 25 | */ 26 | struct tx 27 | { 28 | uint8_t adf; /**< EEPROM address */ 29 | uint8_t edf; /**< EEPROM data */ 30 | }; 31 | 32 | /** 33 | * @brief Tamagawa Interface Received data 34 | */ 35 | struct rx 36 | { 37 | uint32_t abs; /**< Data in one revolution */ 38 | short abm; /**< Multi-turn Data */ 39 | uint8_t cf; /**< Control Frame */ 40 | uint8_t sf; /**< Status Frame */ 41 | uint8_t enid; /**< Encoder ID */ 42 | uint8_t almc; /**< Encoder error */ 43 | uint8_t adf; /**< EEPROM address */ 44 | uint8_t edf; /**< EEPROM data */ 45 | uint8_t crc; /**< CRC */ 46 | }; 47 | 48 | /** 49 | * @brief Tamagawa Interface 50 | */ 51 | struct TamagawaInterface 52 | { 53 | uint32_t version; /**< Firmware version */ 54 | uint8_t config; /**< Configuration */ 55 | uint8_t data_id; /**< Data ID code */ 56 | struct tx tx; /**< Transmit data */ 57 | struct rx rx; /**< Received data */ 58 | }; 59 | 60 | extern uint8_t usart_data; 61 | extern struct TamagawaInterface ti; 62 | 63 | void tamagawa_read(uint8_t data_id); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /soft_i2c/READMEmd: -------------------------------------------------------------------------------- 1 | # 注意事项 2 | 本份代码使用的是软件模拟的IIC通信,使用的接口如下: 3 | ```c 4 | #define IIC_GPIO GPIOB 5 | #define SDA GPIO_PIN_11 6 | #define SCL GPIO_PIN_10 7 | ``` 8 | 请注意修在`soft_i2c.h`中改为自己使用的接口。 9 | 10 | # 函数接口 11 | function_name|brief 12 | :--:|:--: 13 | IIC_ReadData|IIC读取数据函数 14 | IIC_WriteData|IIC写入函数 15 | 16 | 上述两个函数返回`0`表示操作成功,返回`0xff`表示操作失败。 17 | 18 | # 调用示例 19 | ```c 20 | if(IIC_ReadData(MPU6050_ADDRESS, MPU_WHO_I_AM, &temp_data, 1) == 0) 21 | { 22 | if(temp_data != 0x68) 23 | { 24 | return 0xff; 25 | } 26 | } 27 | 28 | if(IIC_WriteData(MPU6050_ADDRESS,MPU_CFG_REG,6) == 0xff) 29 | { 30 | return 0xff; 31 | } 32 | ``` -------------------------------------------------------------------------------- /soft_i2c/soft_i2c.c: -------------------------------------------------------------------------------- 1 | #include "soft_i2c.h" 2 | #include "tim.h" 3 | 4 | #define IIC_SDA_H() HAL_GPIO_WritePin(IIC_GPIO, SDA, GPIO_PIN_SET) 5 | #define IIC_SDA_L() HAL_GPIO_WritePin(IIC_GPIO, SDA, GPIO_PIN_RESET) 6 | #define IIC_SCL_H() HAL_GPIO_WritePin(IIC_GPIO, SCL, GPIO_PIN_SET) 7 | #define IIC_SCL_L() HAL_GPIO_WritePin(IIC_GPIO, SCL, GPIO_PIN_RESET) 8 | #define IIC_SDA_Read() HAL_GPIO_ReadPin(IIC_GPIO, SDA) 9 | 10 | void IIC_Delay(uint16_t time) 11 | { 12 | uint16_t count; 13 | count = time * 6; 14 | while(count --); 15 | } 16 | 17 | void IIC_SDA_Out(void) 18 | { 19 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 20 | GPIO_InitStruct.Pin = SDA; 21 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 22 | GPIO_InitStruct.Pull = GPIO_NOPULL; 23 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 24 | HAL_GPIO_Init(IIC_GPIO, &GPIO_InitStruct); 25 | } 26 | 27 | void IIC_SDA_In(void) 28 | { 29 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 30 | GPIO_InitStruct.Pin = SDA; 31 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 32 | GPIO_InitStruct.Pull = GPIO_NOPULL; 33 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 34 | HAL_GPIO_Init(IIC_GPIO, &GPIO_InitStruct); 35 | } 36 | 37 | void IIC_Start(void) 38 | { 39 | IIC_SDA_Out(); 40 | IIC_SDA_H(); 41 | IIC_SCL_H(); 42 | IIC_Delay(1); 43 | IIC_SDA_L(); 44 | IIC_Delay(1); 45 | IIC_SCL_L(); 46 | } 47 | 48 | void IIC_Stop(void) 49 | { 50 | IIC_SDA_Out(); 51 | IIC_SCL_L(); 52 | IIC_SDA_L(); 53 | IIC_Delay(1); 54 | IIC_SCL_H(); 55 | IIC_SDA_H(); 56 | IIC_Delay(1); 57 | } 58 | 59 | void IIC_Ack(uint8_t re) 60 | { 61 | IIC_SDA_Out(); 62 | if(re) 63 | IIC_SDA_H(); 64 | else 65 | IIC_SDA_L(); 66 | IIC_SCL_H(); 67 | IIC_Delay(1); 68 | IIC_SCL_L(); 69 | IIC_Delay(1); 70 | } 71 | 72 | int IIC_WaitAck(void) 73 | { 74 | uint16_t Out_Time=1000; 75 | 76 | IIC_SDA_H(); 77 | IIC_SDA_In(); 78 | IIC_Delay(1); 79 | IIC_SCL_H(); 80 | IIC_Delay(1); 81 | while(IIC_SDA_Read()) 82 | { 83 | if(--Out_Time) 84 | { 85 | IIC_Stop(); 86 | return 0xff; 87 | } 88 | } 89 | IIC_SCL_L(); 90 | return 0; 91 | } 92 | 93 | void IIC_WriteBit(uint8_t Temp) 94 | { 95 | uint8_t i; 96 | IIC_SDA_Out(); 97 | IIC_SCL_L(); 98 | for(i=0;i<8;i++) 99 | { 100 | if(Temp&0x80) 101 | { 102 | IIC_SDA_H(); 103 | } 104 | else 105 | { 106 | IIC_SDA_L(); 107 | } 108 | Temp<<=1; 109 | IIC_Delay(1); 110 | IIC_SCL_H(); 111 | IIC_Delay(1); 112 | IIC_SCL_L(); 113 | } 114 | } 115 | 116 | uint8_t IIC_ReadBit(void) 117 | { 118 | uint8_t i,Temp=0; 119 | IIC_SDA_In(); 120 | for(i=0;i<8;i++) 121 | { 122 | IIC_SCL_L(); 123 | IIC_Delay(1); 124 | IIC_SCL_H(); 125 | Temp<<=1; 126 | if(IIC_SDA_Read()) 127 | Temp++; 128 | IIC_Delay(1); 129 | } 130 | IIC_SCL_L(); 131 | return Temp; 132 | } 133 | 134 | int IIC_WriteData(uint8_t dev_addr,uint8_t reg_addr,uint8_t data) 135 | { 136 | IIC_Start(); 137 | 138 | IIC_WriteBit(dev_addr); 139 | if(IIC_WaitAck() == 0xff) 140 | { 141 | return 0xff; 142 | } 143 | 144 | IIC_WriteBit(reg_addr); 145 | if(IIC_WaitAck() == 0xff) 146 | { 147 | return 0xff; 148 | } 149 | 150 | IIC_WriteBit(data); 151 | if(IIC_WaitAck() == 0xff) 152 | { 153 | return 0xff; 154 | } 155 | 156 | IIC_Stop(); 157 | return 0; 158 | } 159 | 160 | int IIC_ReadData(uint8_t dev_addr, uint8_t reg_addr, uint8_t * pdata, uint8_t count) 161 | { 162 | uint8_t i; 163 | IIC_Start(); 164 | 165 | IIC_WriteBit(dev_addr); 166 | if(IIC_WaitAck() == 0xff) 167 | { 168 | return 0xff; 169 | } 170 | 171 | IIC_WriteBit(reg_addr); 172 | if(IIC_WaitAck() == 0xff) 173 | { 174 | return 0xff; 175 | } 176 | 177 | IIC_Start(); 178 | 179 | IIC_WriteBit(dev_addr+1); 180 | if(IIC_WaitAck() == 0xff) 181 | { 182 | return 0xff; 183 | } 184 | 185 | for(i=0;i<(count-1);i++) 186 | { 187 | *pdata=IIC_ReadBit(); 188 | IIC_Ack(0); 189 | pdata++; 190 | } 191 | 192 | *pdata=IIC_ReadBit(); 193 | IIC_Ack(1); 194 | 195 | IIC_Stop(); 196 | 197 | return 0; 198 | } 199 | -------------------------------------------------------------------------------- /soft_i2c/soft_i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef SOFT_I2C_H 2 | #define SOFT_I2C_H 3 | 4 | #include "stm32f4xx.h" 5 | 6 | #define IIC_GPIO GPIOB 7 | #define SDA GPIO_PIN_11 8 | #define SCL GPIO_PIN_10 9 | 10 | int IIC_ReadData(uint8_t dev_addr, uint8_t reg_addr, uint8_t * pdata, uint8_t count); 11 | int IIC_WriteData(uint8_t dev_addr,uint8_t reg_addr,uint8_t data); 12 | 13 | #endif 14 | --------------------------------------------------------------------------------