找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5249|回复: 6
收起左侧

想HMC5883L做个电子指南针,大神帮帮,求教怎么用

[复制链接]
ID:223438 发表于 2017-8-8 12:35 | 显示全部楼层 |阅读模式
  1. #include <reg52.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <intrins.h>

  5. typedef unsigned char uchar;
  6. typedef unsigned int uint;

  7. /*12864液晶引脚定义*/      
  8. sbit CS=P3^3;
  9. sbit SID=P3^4;
  10. sbit SCLK=P3^5;

  11. sbit SCL=P1^0;      //IIC时钟引脚定义
  12. sbit SDA=P1^1;      //IIC数据引脚定义

  13. #define SlaveAddress 0x3c   //定义器件在IIC总线中的从地址
  14. uchar Rec_Data[6];
  15. void Send_byte(unsigned char bbyte);
  16. void Delaynms(unsigned int di);


  17. /*延时函数*/
  18. void Delay(uint t)
  19. {
  20.     while(t--)
  21.     {}
  22. }
  23. /********************************************
  24. **LCD显示函数
  25. ********************************************/
  26. /*写入一个数据或指令*/
  27. void Send_DATA(uchar ddata,uchar start)
  28. {

  29.         unsigned char start_data,Hdata,Ldata;
  30.           if(start==0)
  31.                 start_data=0xf8;//写指令
  32.     else   
  33.             start_data=0xfa; //写数据

  34.     SCLK=0;
  35.     CS=1;

  36.         Hdata=ddata&0xf0;                  //取高四位
  37.           Ldata=(ddata<<4)&0xf0;  //取低四位
  38.           Send_byte(start_data);          //发送起始信号
  39.           Delaynms(5); //延时是必须的
  40.           Send_byte(Hdata);              //发送高四位
  41.           Delaynms(1);  //延时是必须的
  42.           Send_byte(Ldata);                  //发送低四位
  43.           Delaynms(1);  //延时是必须的
  44.     CS=0;
  45.     Delay(20);  
  46. }

  47. void Delaynms(unsigned int di) //??
  48. {
  49.         unsigned int da,db;
  50.         for(da=0;da<di;da++)
  51.                    for(db=0;db<10;db++);
  52. }

  53. void Send_byte(unsigned char bbyte) //发送一个字节
  54. {
  55.         unsigned char i;
  56.         for(i=0;i<8;i++)
  57.            {
  58.                    SID=bbyte&0x80; //取出最高位
  59.                 SCLK=1;
  60.                    SCLK=0;
  61.                    bbyte<<=1; //左移
  62.            }  
  63. }
  64. void LCD_set_xy( unsigned char x, unsigned char y )
  65. {        //设置LCD显示的起始位置,X为行,Y为列
  66.     unsigned char address;
  67.         switch(x)
  68.         {
  69.                 case 0: address = 0x80 + y; break;   
  70.             case 1: address = 0x80 + y; break;
  71.                 case 2: address = 0x90 + y; break;
  72.                     case 3: address = 0x88 + y; break;
  73.                 case 4: address = 0x98 + y; break;
  74.                 default:address = 0x80 + y; break;
  75.         }
  76.         Send_DATA(address,0);
  77. }

  78. /*12864液晶初始化*/
  79. void LCD_Init(void)
  80. {
  81.     Delay(60000);
  82.     Send_DATA(0x30,0);
  83.     Send_DATA(0x04,0);
  84.     Send_DATA(0x0c,0);
  85.     Send_DATA(0x01,0);
  86.     Delay(3000);
  87. }
  88. /*显示字符串*/
  89. void Dis_str(uchar Addr,uchar *str)
  90. {

  91.     Send_DATA(Addr,0);
  92.     Delay(10);
  93.     while(*str!='\0')
  94.     {
  95.         Send_DATA(*str,1);
  96.         str++;
  97.         Delay(10);
  98.     }
  99. }
  100. /*起始信号*/
  101. void IIC_Start(void)
  102. {
  103.     SDA=1;
  104.     SCL=1;
  105.     Delay(5);
  106.     SDA=0;
  107.     Delay(5);
  108.     SCL=0;
  109. }
  110. /*停止信号*/
  111. void IIC_Stop(void)
  112. {
  113.     SDA=0;
  114.     SCL=1;
  115.     Delay(5);
  116.     SDA=1;
  117.     Delay(5);
  118. }
  119. /*发送应答信号*/
  120. void IIC_SendAck(bit Ack)
  121. {
  122.     SDA=Ack;//ack (0:ACK 1:NACK)
  123.     SCL=1;
  124.     Delay(5);
  125.     SCL=0;
  126.     Delay(5);
  127. }
  128. /*接收应答信号*/
  129. bit IIC_RecAck(void)
  130. {
  131.     SCL=1;
  132.     Delay(5);
  133.     CY=SDA;
  134.     SCL=0;
  135.     Delay(5);
  136.     return CY;
  137. }
  138. /*向IIC总线发送一个字节数据*/
  139. void HMC5883_Send_Byte(uchar Dat)
  140. {
  141.     uchar i;
  142.     for(i=0;i<8;i++)
  143.     {
  144.         Dat<<=1;
  145.         SDA=CY;
  146.         SCL=1;
  147.         Delay(5);
  148.         SCL=0;
  149.         Delay(5);
  150.     }
  151.     IIC_RecAck();
  152. }
  153. /*从IIC总线接收一个字节数据*/
  154. uchar HMC5883_Rec_Byte(void)
  155. {
  156.     uchar i,Dat=0;
  157.     SDA=1;
  158.     for(i=0;i<8;i++)
  159.     {
  160.         Dat<<=1;
  161.         SCL=1;
  162.         Delay(5);
  163.         Dat |=SDA;
  164.         SCL=0;
  165.         Delay(5);
  166.     }
  167.     return Dat;
  168. }
  169. /*单字节写HMC5833*/
  170. void Single_Write_HMC5883(uchar Address,uchar Dat)
  171. {
  172.     IIC_Start();
  173.     HMC5883_Send_Byte(SlaveAddress);
  174.     HMC5883_Send_Byte(Address);
  175.     HMC5883_Send_Byte(Dat);
  176.     IIC_Stop();
  177. }
  178. /*单字节读HMC5833*/
  179. /*uchar Single_Read_HMC5883(uchar Addr)
  180. {
  181.     uchar Value;
  182.     IIC_Start();
  183.     HMC5883_Send_Byte(SlaveAddress);
  184.     HMC5883_Send_Byte(Addr);
  185.     IIC_Start();
  186.     HMC5883_Send_Byte(SlaveAddress+1);
  187.     Value=HMC5883_Rec_Byte();
  188.     IIC_SendAck(1);
  189.     IIC_Stop();
  190.     return Value;
  191. }*/
  192. /*多字节读HMC5833*/
  193. void Multiple_Read_HMC5883(void)
  194. {
  195.     uchar i;  //连续读出HMC5883内部角度数据,地址范围0x3~0x5
  196.     IIC_Start();
  197.     HMC5883_Send_Byte(SlaveAddress);
  198.     HMC5883_Send_Byte(0x03);//发送存储单元地址,从0x03开始
  199.     IIC_Start();
  200.     HMC5883_Send_Byte(SlaveAddress+1);
  201.     for(i=0;i<6;i++) //连续读取6个地址数据,存储在Rec_Data
  202.     {
  203.         Rec_Data[i]=HMC5883_Rec_Byte();
  204.         if(i==5)
  205.             IIC_SendAck(1); //最后一个数据需要回NOACK
  206.         else
  207.             IIC_SendAck(0); //回应ACK
  208.     }
  209.     IIC_Stop();
  210.     Delay(100);
  211. }
  212. //初始化HMC5883,根据需要请参考pdf进行修改****
  213. void HMC5883_Init(void)
  214. {
  215.      Single_Write_HMC5883(0x02,0x00);
  216. }
  217. /*主函数*/
  218. void main(void)
  219. {
  220.     int X,Y,Z;
  221.     double Angle;
  222.     uint Acr;

  223.     LCD_Init();//LCD12864液晶初始化
  224.     HMC5883_Init();//HMC5883初始化

  225.      while(1)
  226.     {
  227.         Multiple_Read_HMC5883();//连续读出数据,存储在Rec_Data[]中
  228.         X=Rec_Data[0]<<8 | Rec_Data[1];//Combine MSB and LSB of X Data output register
  229.         Z=Rec_Data[2]<<8 | Rec_Data[3];//Combine MSB and LSB of Z Data output register
  230.         Y=Rec_Data[4]<<8 | Rec_Data[5];//Combine MSB and LSB of Y Data output register
  231.         Angle= atan2((double)Y,(double)X)*(180/3.14159265)+180;//单位:角度 (0~360)
  232.         Angle*=10;
  233.         Acr=(uint)Angle;
  234.                         LCD_set_xy(2,0);
  235.         Send_DATA(Acr%10000/1000+0x30,1);
  236.         Send_DATA(Acr%1000/100+0x30,1);
  237.         Send_DATA(Acr%100/10+0x30,1);
  238.         Send_DATA('.',1);
  239.         Send_DATA(Acr%10+0x30,1);

  240.         Delay(50000);
  241.     }
  242. }
复制代码
上面是参考网上程序改的,好像不行,显示屏一直显示045.0,显示屏用的是12864.不知道是程序问题还是模块的问题。主控用的是AT89S52。模块是GY271-HMC5883L.
回复

使用道具 举报

ID:82765 发表于 2017-8-8 15:44 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

ID:223438 发表于 2017-8-8 21:53 | 显示全部楼层
cjjcjj1 发表于 2017-8-8 15:44
你好!
1、检查一下模块引脚是不是和程序对应
2、开发板的晶振是多少的

GY-271-SCH.jpg GY-271.JPG 用的是最小系统,晶振11.0592M
回复

使用道具 举报

ID:241616 发表于 2017-10-21 17:00 | 显示全部楼层
我也是是参考网上程序改的,好像不行,显示屏也一直显示045.0。现在解决了么?
回复

使用道具 举报

ID:229445 发表于 2018-2-25 10:41 | 显示全部楼层
原来做跷跷板小车,用到GY271,不小心烧毁了,淘宝买回来一直不能用,细看datasheet发现,一种是hm5883,一种是gm5883
回复

使用道具 举报

ID:285379 发表于 2018-3-1 21:17 | 显示全部楼层
我也是显示450.。。
什么原因我也搞不懂
回复

使用道具 举报

ID:306174 发表于 2018-4-12 01:17 | 显示全部楼层
现实不变化,到底怎么办呀,来个人回答呀
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表