QMC5883L芯片的参数要求

1.QMC5883l(以下简称5883)他需要传感器每次传一位的时间是5us左右,我这么说的原因是我用示波器测量过传出一位的时间。
2. 最开始的时候,需要给5883传输起始信号,这个和停止信号没有时间要求,但是SCL和SDA的时序要对的上,什么意思呢? 简单点来说就是,当起始信号的时候,你要确保SDA被拉低的时候,SCL为高点平,可以多次循环,但是可以不管时间。

void IIC_Start(void)
{       uchar i = 0;SDA_H;SCL_H;for (i=0; i<5; i++){Delay(4);SDA_L;Delay(4);Delay(4);SCL_L;        //after end of start condition both SDA and SCL will be low}}

3.有些时候,我们无法确定延时函数的时间是否准确,因为一个工作周期的时间是由你所选择的时钟所确定的,而你选择的时钟与哪个晶振或者内部的振荡器是有直接的关系的,因为我用的开发板是32768的外部晶振,不能提供足够的时钟周期,于是我的老师建议我采用内部的时钟源–DCO,DCO也分很多种8M、12M,都有的,选8M就够了,有的6M好像也够用,但是内部的DCO有点小问题,不准,并不是他会跳变,而是你选择的是5M,但是他有可能是6M左右,这就出现了一个问题,你的延时函数不够准确。但是这并不致命。
最致命的问题:当你使用RS-232或者485把数据传出来的时候,就完了,你不确定时钟的频率,你就不能确定串口通信的数值该多大,再这卡的时间几乎和调IIC的时间是一样的了。而且你换一块芯片,只要你采用内部的振荡器,就要调很久,这几乎让我调到怀疑人生。Oh,My God。

void ModBus_Init()
{       P4SEL|= BIT0 + BIT1;                //设置IO口为第二功能模式,启用UART功能P4DIR|= BIT0;                       //设置TXD0口方向为输出U1CTL|= CHAR;                //SWRST=1,CHAR=1,8位数据模式ME2|= UTXE1 + URXE1;         //UTXE0=1,串口0发送允许,UART0发送使能U1TCTL |= SSEL1 + SSEL0 + URXSE;          // UCLK = SMCLK, start edge detectU1BR0 = 0x8a;                             // 6MHz 9600U1BR1 = 0x02;                             // 6MHz 9600U1MCTL = 0x00;                            // 6MHz 9600modulationU1CTL &= ~SWRST;                          // Initialize USART state machineIE2 |= URXIE1;                            // Enable USART1 RX interrupt}

4.当你把IIC调通,485或者232也调通,把程序当中的地址寄存器也都也好以后,记得保留你在接收ACK时的设置,例如当接受ACK时,点亮一个小灯,这么做是为了日后设备出现问题时,可以确定是哪里的问题。嗯,好吧,这也是一个痛。痛彻心扉。

话不多数上程序

IIC通讯程序

#include <math.h>#define CPU_F ((double)8000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) #define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long#define HMC5883L_DIR   P10DIR
#define HMC5883L_IN    P10IN
#define HMC5883L_OUT   P10OUT
#define SCL  BIT5     //IIC??????????
#define SDA  BIT4     //IIC???????????   //DRDY ????
#define SCL_H  (HMC5883L_DIR|=SCL,HMC5883L_OUT|=SCL)
#define SCL_L  (HMC5883L_DIR|=SCL,HMC5883L_OUT&=~SCL)
#define SDA_H  (HMC5883L_DIR|=SDA,HMC5883L_OUT|=SDA)
#define SDA_L  (HMC5883L_DIR|=SDA,HMC5883L_OUT&=~SDA)
#define SlaveAddress  0x1a         //??????????IIC?????е????
uchar Rec_Data[6];
int x,y,z;
double Angle;
uint Acr;
uint qian=0,bai=0,shi=0,ge=0;                //???????????
uchar Buf[6];
/*???????*/
void Delay(uint t)
{t=t/4;
while(t--);
}/*??????*/
void IIC_Start(void)
{       uchar i = 0;SDA_H;SCL_H;for (i=0; i<5; i++){Delay(4);SDA_L;Delay(4);Delay(4);SCL_L;        //after end of start condition both SDA and SCL will be low}}/*?????*/
void IIC_Stop(void)
{       uchar i = 0;SDA_L;Delay(4);SCL_H;    for(i=0;i<8;i++){Delay(4);}SDA_H;Delay(4);i=0;//ensure bus is in default condition ( freed by slave)while(!(HMC5883L_IN&SDA)) // i is just a variable to control the while loop run time.{SCL_H;Delay(4);SCL_L;Delay(4);Delay(4);i++;if( i > 25){break;}}SCL_H;//After generating stop condition SCL and SDA are both high. Default condition for I2C bus.}/*??????????*/
void IIC_SendAck(char Ack)
{   if(Ack)      //ack (0:ACK 1:NACK)SDA_H;else SDA_L;SCL_H;Delay(4);SCL_L;Delay(4);
}/*??????????*/
char IIC_RecAck(void)
{   char CY;HMC5883L_DIR&=~SDA;SCL_H; Delay(4);if(HMC5883L_IN&SDA)CY=1;else CY=0;    SCL_L;Delay(4);if(!CY){P7DIR = 0x00; }return CY;
}/*??IIC?????????????????*/
void HMC5883_Send_Byte(uchar Dat)
{uchar i;SCL_L;for(i=0;i<8;i++){if(Dat&BIT7)SDA_H;else SDA_L;  Delay(2);SCL_H; Dat<<=1;Delay(4);SCL_L;Delay(4);if(i == 7){SDA_H;}}Delay(2);IIC_RecAck();
}/*??IIC?????????????????*/
uchar HMC5883_Rec_Byte(void)
{uchar i,Dat=0;SDA_H;Delay(4);HMC5883L_DIR&=~SDA;for(i=0;i<8;i++){Dat<<=1;SCL_H;Delay(4);if((HMC5883L_IN&SDA)==SDA)Dat|=BIT0;SCL_L;Delay(4);}return Dat;
}/*?????дHMC5883*/
void Single_Write_HMC5883(uchar Address,uchar Dat)
{IIC_Start();HMC5883_Send_Byte(SlaveAddress);HMC5883_Send_Byte(Address);HMC5883_Send_Byte(Dat);IIC_Stop();
}/*??????HMC5883*/
uchar Single_Read_HMC5883(uchar Addr)
{uchar Value;IIC_Start();
//    HMC5883_Send_Byte(SlaveAddress);HMC5883_Send_Byte(Addr);IIC_Start();
//    HMC5883_Send_Byte(SlaveAddress+1);Value=HMC5883_Rec_Byte();IIC_SendAck(1);IIC_Stop();return Value;
}/*??????HMC5883*/
void Multiple_Read_HMC5883(void)
{uchar i;  //????????HMC5883????????????????Χ0x3~0x5IIC_Start();HMC5883_Send_Byte(SlaveAddress);HMC5883_Send_Byte(0x00);//????洢??????????0x03??? IIC_Start();HMC5883_Send_Byte(SlaveAddress+1);for(i=0;i<6;i++) //???????6???????????洢??Rec_Data{Rec_Data[i]=HMC5883_Rec_Byte();if(i==5)IIC_SendAck(1); //???????????????NOACKelseIIC_SendAck(0); //???ACK}IIC_Stop();Delay(100);
}//初始化QMC5883,根据需要请参考pdf进行修改****
void Init_QMC5883()
{Single_Write_HMC5883(0x09,0x0d);  //控制寄存器配置Single_Write_HMC5883(0x0b,0x01);  //设置清除时间寄存器Single_Write_HMC5883(0x20,0x40);  //Single_Write_HMC5883(0x21,0x01);  //
}/********************??????????????*******************/
/********************0?? x??????************************/
void get_angle()
{       Init_QMC5883();Multiple_Read_HMC5883();//??????????????洢??Rec_Data[]??x=Rec_Data[0]<<8 | Rec_Data[1];//Combine MSB and LSB of X Data output registerz=Rec_Data[2]<<8 | Rec_Data[3];//Combine MSB and LSB of Z Data output registery=Rec_Data[4]<<8 | Rec_Data[5];//Combine MSB and LSB of Y Data output registerAngle= atan2((double)y,(double)x)*(180/3.14159265)+180;//??λ????? (0~360)  //Angle*=10; Delay(50000);
}void QMC5883_IIC(void)
{    get_angle();qian=(int)Angle/1000;bai=((int)Angle%1000)/100;shi=((int)Angle%100)/10;ge=(int)Angle%10;Buf[0] = qian;Buf[1] = bai;Buf[2] = shi;Buf[3] = ge;}

msp430FG4618 --切记不同的芯片选择的时钟也是不一样的

这里面还包含了jt808的一些通讯协议,这个不重要。

#include <msp430xG46x.h>
#include "IICComunication.c"
#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long
#define CPU_F ((double)8000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
#define baud           9600                                            //设置波特率的大小
#define baud_setting   (uint)((ulong)CPU_F/((ulong)baud))               //波特率计算公式
#define baud_h         (uchar)(baud_setting>>8)                         //提取高位
#define baud_l         (uchar)(baud_setting)                              //低位
uchar Adress0=0x30,Adress1=0x30,Adress2=0x30;                              //可更改初始ID号
const uchar ucAdress0=0x30,ucAdress1=0x30,ucAdress2=0x30;//不可更改地址
uchar TxBuffer[255];
uchar TxLen;
uchar RxBuffer[50];
uchar RxLen = 0;
uchar crctemp0,crctemp1,crcresult0,crcresult1;//校验码
uchar hex[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
uint Buffer[4];
unsigned char buffer[255];
uchar Com= 0x00;//校验位
uint time=0,data0,data1,data2;
uint temp_d0=0,temp_d1=0,temp_d2=0;
int a1[5],a2[5],a3[5];
int m1=0,m2=0,n1=0,n2=0,n3=0;
int temp0[100],temp1[100],temp2[100];
uint TEMP0,TEMP1,TEMP2;
int k=0;
//关闭内部看门狗
void WDT_Init()
{WDTCTL = WDTPW + WDTHOLD;
}
//时钟配置函数
void Clock_Init_XT1()
{//  FLL_CTL0 |= XCAP18PF;                     // Set load capacitance
//  FLL_CTL1 &= ~XT2OFF;                      // Turn on XT2
FLL_CTL0 |= DCOPLUS;           // DCO+ set, freq = xtal x D x N+1
SCFI0 |= FN_8;
}
//IO口初始化
void Port_Init()
{//RS485P3DIR|=BIT6;P3DIR|=BIT7;P3OUT|=BIT6;P3OUT|=BIT7;//LEDP7DIR = 0XFF;P7OUT = 0X00;//P10DIR = 0xFF;
}/****************************************************************************
* 函数名称:modBus_Init()
* 函数功能:初始化ModBus通讯所需模块
* 参数:uiBaudRate:9600 波特率 ucDataBits:8 数据位 ucPrity:无校验 奇偶校验
****************************************************************************/
void ModBus_Init()
{       P4SEL|= BIT0 + BIT1;                //设置IO口为第二功能模式,启用UART功能P4DIR|= BIT0;                       //设置TXD0口方向为输出U1CTL|= CHAR;                //SWRST=1,CHAR=1,8位数据模式ME2|= UTXE1 + URXE1;         //UTXE0=1,串口0发送允许,UART0发送使能U1TCTL |= SSEL1 + SSEL0 + URXSE;          // UCLK = SMCLK, start edge detectU1BR0 = 0x8a;                             // 12MHz 9600U1BR1 = 0x02;                             // 12MHz 9600U1MCTL = 0x00;                            // 12MHz 9600modulationU1CTL &= ~SWRST;                          // Initialize USART state machineIE2 |= URXIE1;                            // Enable USART1 RX interrupt}//     串口发送数据函数
void UartPutChar(uchar data)
{while(!(IFG2&UTXIFG1));          //等待数据发送完毕,发送寄存器空的时候发送数据TXBUF1=data;  //串口发送缓冲寄存器
}
//      串口发送字符串函数
void UartPutStr(uchar str[],uchar strlen)
{uchar i;for(i=0;i<strlen;i++){while(!(IFG2&UTXIFG1)); delay_us(1000);//必要的延时,否则低波特率发送会出现误码U1TXBUF = str[i]; delay_ms(1);//必要的延时,否则低波特率发送会出现误码}
}
void NumToHex(int num)
{int i=0,yushu;for(i=0;i<4;i++){yushu=num%16;if((yushu>=0)&&(yushu <=9))Buffer[i]=yushu;elseBuffer[i]=yushu-10+0x0a;num=num/10; }
}
unsigned char CheckNum(unsigned char* pucMsg){int i = 0;Com = pucMsg[1];for(i=2;i<=20;i++){Com ^= pucMsg[i];    }return Com;
}
//      TIMERA初始化
void TIMERA_Init(void)
{TACCTL0 = CCIE;                           // TACCR0 interrupt enabledTACCR0 = 5000;   //50msTACTL = TASSEL_1 + MC_1;                  // ACLK, up mode
}
void Send_Byte(uchar data)
{while(!(IFG2&UTXIFG1));          //等待数据发送完毕,发送寄存器空的时候发送数据TXBUF1=data;  //串口发送缓冲寄存器
}//函数功能:数据接受处理
void ModbusHandle()
{   TxBuffer[0] = 0x7E;TxBuffer[1] = 0x09;TxBuffer[2] = 0x00;//  消息体属性TxBuffer[3] = 0x00;TxBuffer[4] = 0x08;//手机号  TxBuffer[5] = 0x01;TxBuffer[6] = 0x30;TxBuffer[7] = 0x81;TxBuffer[8] = 0x85;TxBuffer[9] = 0x77;TxBuffer[10] = 0x97;//传感器id、TxBuffer[11] = 0x00;TxBuffer[12] = 0x07;//传感器测重值TxBuffer[13] = Rec_Data[5];//z轴的高八位TxBuffer[14] = Rec_Data[4];//z轴的低八位TxBuffer[15] = Rec_Data[3];//y轴的高八位TxBuffer[16] = Rec_Data[2];//y轴的低八位//传感器测量温度TxBuffer[17] = 0x00;TxBuffer[18] = 0x00;TxBuffer[19] = 0x00;TxBuffer[20] = 0x01;//数据校验TxBuffer[21] = CheckNum(TxBuffer);//截至位rTxBuffer[22] = 0x09;TxLen=23; UartPutStr(TxBuffer,TxLen);
//  UartPutChar(0x30);TxLen = 0;//清除发送缓冲  }
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{   QMC5883_IIC();ModbusHandle();
    while(!(IFG2&UTXIFG1));
    delay_us(100);//必要的延时,否则低波特率发送会出现误码
    U1TXBUF = 0x32;
  delay_ms(1000);//必要的延时,否则低波特率发送会出现误码
//  buffer[0]=Rec_Data[0];
//  buffer[1]=Rec_Data[1];
//  buffer[2]=Rec_Data[2];
//  buffer[3]=Rec_Data[3];
//  buffer[4]=Rec_Data[4];
//  buffer[5]=Rec_Data[5];
//  UartPutStr(buffer,6);//这里调了22次,我也是醉了
//
}//主函数
void main(void)
{WDT_Init();Clock_Init_XT1();Port_Init();
//  ADC_Init();ModBus_Init();TIMERA_Init();ADC12CTL0 |= ADC12SC;                   // Start conversionswhile(1){//
//      P7OUT = 0x00;
//      delay_ms(10);
//      P7OUT = 0xff;
//       delay_ms(10);  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
//    IIC_Start();
//    HMC5883_Send_Byte(SlaveAddress);}}

最后上数据

这个数据是Z方向的数据

|
这玩意是弱磁传感器,磁铁离得太近就完犊子了。

再来一个程序,画图的

import matplotlib.pyplot as plt#约定俗成的写法plt
#首先定义两个函数(正弦&余弦)
import numpy as np
fig,ax = plt.subplots()
plt.xlabel('distance')
plt.ylabel("Magnetic intensity")
X=[29,25,21,18,14,11,9,8,7,6,5,4]
C=[0x56,0x55,0x53,0x4f,0x46,0x34,0x06,0x03,0xce,0x86,0x80,0x1d]
plt.plot(X,C)#在ipython的交互环境中需要这句话才能显示出来
plt.show()

QMC5883L与msp430FG4618--IIC通信相关推荐

  1. PIC单片机 IIC通信及实现

    IIC通信   IIC是一种只需要2根数据线就可以实现数据通信的总线式结构.IIC采用主从式通信方式,通信过程完全由主设备决定.完整的通信流程是主设备发送起始信号给从设备,再发送地址来选中从设备,然后 ...

  2. 16F877A和24C02通信汇编语言,pic单片机IIC通信读24C02程序例 16F877A 主频4M

    #define _iic_h_//pic单片机IIC通信初始化函数声明 void iiccsh(void); //pic单片机IIC通信读外围设备函数声明 //功能:传送一个8位地址,返回一个8位数据 ...

  3. i2c通信 msp430g2553_msp430g2553的IIC通信

    SCCB_Stop(); if(!SCCB_Start()) { //return 0; } SCCB_SendByte( DEV_ADR + 1 );               /* 器件地址 * ...

  4. 树莓派3B 之IIC通信

    上一篇我们将了树莓派的uart通信. 本篇幅我们来讲一下,树莓派IIC通信. 读取slave 的数据. 依然我们用wirningPi库,驱动IIC 的引脚编号8/9,分别用作SDA/SCL. 我们用来 ...

  5. 华大单片机HC32L130/HC32L136从机IIC通信

    从机IIC理论知识 主机IIC的做法比较多,从机IIC的就相对比较难一点. 先补充一下从机IIC的思路: 先看IIC时序图,然后根据时序图理清IIC从机需要做哪些判断: 从机发送: ·判断IIC ST ...

  6. LPC1768 IIC通信示——PCF8563

    PCF8563与AT24C02一样,是典型的IIC通信器件,这里就以它为例,编写基于LPC1768硬件IIC的通信代码: 上图是PCF8563各个寄存器地址,PCF8563的IIC地址是0xA2 #i ...

  7. STM32 IIC通信简介+PCF8563时钟芯片示例

    IIC总线是嵌入式设备最常用的接口之一,包括51单片机在内的MCU一般都可以进行IIC通信. IIC通信有3种类型的信号:开始信号,结束信号,和应答信号. 开始信号:SCL为高电平,SDA由高电平向低 ...

  8. ICM20602六轴传感器-IIC通信模式

    ICM20602六轴传感器 ICM20602 通过IIC协议与MCU通信 ICM20602 初始化配置 ICM20602 相关配置函数 ICM20602 内部寄存器 注意事项 (一)ICM20602 ...

  9. 中微SC8F5771模拟IIC通信——指令运行速度的探索(附编译软件与烧录软件)

    文章目录 一.中微单片机烧录与使用 编译软件 烧录软件 下载地址 烧录软件 二.模拟IIC 三.逻辑分析仪下的时序 一.中微单片机烧录与使用 编译软件 中微所使用编译软件为SCMCU_IDE,不过个人 ...

  10. 51单片机常用通信方式之IIC通信(二)

    IIC通信是一种同步通信方式,同步通信是采用一个同步时钟线,连到收发双方,使收发双方达到完全同步.则IIC通信硬件连接就有四根线VCC.GND.SDA.SCL,SDA是传送数据的,SCL是控制时序的, ...

最新文章

  1. 独家 | 国内AI专业高考报考指南
  2. SSG140 web、telnet、ssh无法访问,仅支持console
  3. Mysql学习总结(14)——Mysql主从复制配置
  4. mxnet METRIC自定义评估验证函数
  5. idea提示 cannot resolve symbol “println
  6. C++ STL 数据结构与算法 —— 排序
  7. Vue传递方法给页面调用
  8. 有什么可以测试耳机性能的软件吗,测试耳机性能好坏的简单方法
  9. wps表格宏被禁用如何解禁_怎么解除宏禁用_win7系统取消宏已被禁用提示的方法...
  10. 小提琴1234567位置图解_1秒找到小提琴上的每个调音阶
  11. 什么是云服务举例说明_云服务器与云服务有什么区别
  12. 程序员选什么方向好?前端还是后端?
  13. CodeForces #379(734A|734B|734C|734D|734E|734F)|二分查找|模拟|树的半径|位运算
  14. 【苹果推iMessage送】摆设overrideUserInterfaceStyle属性以使该视图及其子视图具备特定的UIUserInterfaceStyle
  15. 百慕大三角新奇神秘事件
  16. 科技爱好者周刊(第 159 期):游戏开发者的年薪
  17. MQTT协议(1)介绍
  18. Haplotype-aware genotyping from noisy long reads 单倍型识别的基因分型来自嘈杂的长读
  19. 剖析 TCP - SO_REUSEPORT 使用
  20. 计算机应用基础大作业0483,西南大学2020年春季计算机应用基础【0483】课程考试大作业参考答案.pdf...

热门文章

  1. 吹爆系列:教科书级别的Android音视频入门进阶学习手册,学完我成功“挤进”了抖音音视频开发岗
  2. 加州大学圣克鲁兹分校计算机科学,加州大学圣克鲁兹分校专业设置详细介绍!...
  3. 王学岗Kotlin协程(三)---协程的上下文与协程的异常处理
  4. [poj1797] Heavy Transportation
  5. c++ 泛型 之 TypeTraints
  6. 上下左右键的ASCII
  7. cmd 查看端口占用并且结束进程【建议收藏】
  8. 一个故事,讲懂什么是区块链
  9. cpu 占用过高排查
  10. 谷歌浏览器打开后是360导航界面解决办法