糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 基于STM32F1的HMC5883L电子罗盘驱动——妈妈从此再也不担心我迷路了

基于STM32F1的HMC5883L电子罗盘驱动——妈妈从此再也不担心我迷路了

时间:2019-04-09 15:45:40

相关推荐

基于STM32F1的HMC5883L电子罗盘驱动——妈妈从此再也不担心我迷路了

HMC5883L是一种IIC通信的电子罗盘芯片,输出与北的角度偏差,数值是0-360度,靠西方向增长,可以理解为逆时针为正。配合GPS模块简直就是四轴飞行器的铁杆标配。驱动分为驱动IIC和转换角度两块。

1.驱动IIC

void IIC_IO_Init(void){ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//ê1?üGPIOBê±?óGPIO_InitStructure.GPIO_Pin = GPIO_SCL|GPIO_SDA;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //í?íìê?3?GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(IIC_PERIPH, &GPIO_InitStructure);GPIO_SetBits(IIC_PERIPH,GPIO_Pin_8|GPIO_Pin_9); //PB6,PB7 ê?3???}void i2c_Start(void) { /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */ SDA_OUT();IIC_SDA = 1; delay_us(10); IIC_SCL = 1; delay_us(10); IIC_SDA = 0; delay_us(10); IIC_SCL = 0; delay_us(10); } void i2c_Stop(void) { /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */ SDA_OUT();IIC_SDA = 0; delay_us(10); IIC_SCL = 1; delay_us(10); IIC_SDA = 1; } void i2c_SendByte(u8 _ucByte) { u8 i; SDA_OUT();/* 先发送字节的高位bit7 */ for (i = 0; i < 8; i++) { if (_ucByte & 0x80) { IIC_SDA = 1; } else { IIC_SDA = 0; } delay_us(10); IIC_SCL = 1; delay_us(10);IIC_SCL = 0; if (i == 7) { IIC_SDA = 1; // 释放总线 } _ucByte <<= 1; /* 左移一个bit */ delay_us(10); } } u8 i2c_ReadByte(void) { u8 i; u8 value; IIC_SDA = 1; SDA_IN();/* 读到第1个bit为数据的bit7 */ value = 0; for (i = 0; i < 8; i++) { value <<= 1; IIC_SCL = 1; delay_us(10); if (READ_SDA) { value++; } IIC_SCL = 0; delay_us(10); } return value; } u8 i2c_WaitAck(void) { u8 re; SDA_IN();IIC_SDA = 1; /* CPU释放SDA总线 */ delay_us(10); IIC_SCL = 1; /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ delay_us(10); if (READ_SDA) /* CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } IIC_SCL = 0; delay_us(10); return re; } void i2c_Ack(void) { SDA_OUT();IIC_SDA = 0; /* CPU驱动SDA = 0 */ delay_us(10); IIC_SCL = 1; /* CPU产生1个时钟 */ delay_us(10); IIC_SCL = 0; delay_us(10); IIC_SDA = 1; /* CPU释放SDA总线 */ } void i2c_NAck(void) { SDA_OUT();IIC_SDA = 1; /* CPU驱动SDA = 1 */ delay_us(10); IIC_SCL = 1; /* CPU产生1个时钟 */ delay_us(10); IIC_SCL = 0; delay_us(10); } void HMC5883L_Init() { IIC_IO_Init();//i2c_CheckDevice(HMC5883L_Write_Address); i2c_Start(); i2c_SendByte(HMC5883L_Write_Address); i2c_WaitAck(); i2c_SendByte(0x00); i2c_WaitAck(); i2c_SendByte(0x70); i2c_WaitAck(); i2c_SendByte(0x01); i2c_WaitAck(); i2c_SendByte(0xe0); i2c_WaitAck(); i2c_SendByte(0x02); i2c_WaitAck(); i2c_SendByte(0x01); i2c_Stop(); }

总结:都是常规的IIC设置,注意延时长短。宏定义了一些东西,参数如下

#define SDA_IN() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=(u32)8<<4;}#define SDA_OUT() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=(u32)3<<4;}#define IIC_SCL PBout(8) //SCL#define IIC_SDA PBout(9) //SDA #define GPIO_SCL GPIO_Pin_8#define GPIO_SDA GPIO_Pin_9#define IIC_PERIPH GPIOB#define READ_SDA PBin(9)

SDA_IN()和SDA_OUT()是直接操作寄存器,IO口地址是0XFFFFFF0F,(u32)8中的8是输入模式,左移4是移到当前IO的寄存器设置地址(1x4)

2.转换角度

int x,y,z,X,Y,Z;float Get_Current_Angle() { u8 i; u8 a[6]; float Curent_Angle; HMC5883L_Init(); i2c_Start(); i2c_SendByte(HMC5883L_Write_Address); i2c_WaitAck(); i2c_SendByte(0x03); i2c_WaitAck(); i2c_Start(); i2c_SendByte(HMC5883L_Read_Address); i2c_WaitAck(); for(i=0;i<6;i++) { a[i] = i2c_ReadByte(); if(i==5) { i2c_NAck(); } else { i2c_Ack(); } } i2c_Stop(); x=a[0]; x=x<<8; x=x|a[1]; y=a[2]; y=y<<8; y=y|a[3]; z=a[4]; z=z<<8; z=z|a[5]; if(x>32768) { x = -(0xFFFF - x + 1); } if(y>32768) { y = -(0xFFFF - y + 1); } if(z>32768) { z = -(0xFFFF - z + 1); } X = (s16)x; //x分量 Y = (s16)y; //y分量 Z = (s16)z; //z分量 Curent_Angle = (atan2(Y,X) * (180 / 3.14159265) + 180); //实际水平角度 return Curent_Angle; }

这个实际上就是数据处理函数,只要IIC初始化OK直接copy过来就能用上。函数返回的直接是和北偏离的度数,指南针就做好了。现在手机上自带罗盘,一般打开地图点位置模式就能看到箭头方向。

如果觉得《基于STM32F1的HMC5883L电子罗盘驱动——妈妈从此再也不担心我迷路了》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。