圣源电子制作

标题: GY-26 电子指南针-C51程序-PIC程序-原理图-制作DIY [打印本页]

作者: sydz    时间: 2011-11-6 00:43
标题: GY-26 电子指南针-C51程序-PIC程序-原理图-制作DIY
一、   概述
  GY-26是一款低成本平面数字罗盘模块。输入电压低,功耗小,体积小。其工作原理是通过磁传感器中两个相互垂直轴同时感应地球磁场的磁分量,从而得出方位角度,此罗盘以RS232协议,及IIC协议与其他设备通信。该产品精度高,稳定性高。并切具有重新标定的功能,能够在任意位置得到准确的方位角,其输出的波特率是9600bps,有连续输出与询问输出两种方式,具有磁偏补偿功能,可适应不同的工作
环境。
(, 下载次数: 52)
二、      产品特点
1)、体积小                          四、技术参数  
2)、高性价比                        
  
名称
  

参数

  
测量范围
  

0°~ 360°

  
分辨率
  

    0.1 °

  
测量精度
  

1 °

  
重复精度
  

     1 °

  
响应频率
  

     25 HZ

  
工作电压
  

     3~5 V

  
工作电流
  

5 V--15mA   3V--8 mA

  
工作温度
  

-20°~ 85°

  
储存温度
  

-40°~ 125°

  
尺寸
  

25.6mm×25.6mm

3)、串口及IIC输出格式                  
   
   
三、产品应用         
1)、手持式仪器仪表      
2)、机器人导航、定位   
3)、航行系统                        
4)、船用自动舵                       
5)、八木天线定位                        
6)、车载GPS导线                    
(7)、航模定向                        

                                      




、串口通信协议
1)、串口通信参数
      波特率:9600 bps   校验位:N   数据位:8   停止位:1
2)、模块输出格式,每帧包含8个字节:
①.Byte0:  0x0D               (ASCII码 回车)
②.Byte1:   0x0A               (ASCII码换行)
③.Byte2:   0x30~0x33角度百位 (ASCII 0~3)
④.Byte3:  0x30~0x39 角度十位 (ASCII 0~9)
⑤.Byte4:  0x30~0x39 角度个位 (ASCII 0~9)
⑥.Byte5:  0x2E               (ASCII码小数点)   
⑦.Byte6:   0x30~0x39角度小数位(ASCII0~9)
⑧.Byte7:   0x00~0xFF校验和    (仅低8bit)        
  注:校验和    Byte7 =Byte0+Byte1+…….Byte6)结果仅取低8bit
  例:一帧数据<0x0D-0x0A-0x33-0x35-0x39-0x2E-0x36-0x1C> = 359.6°
3)、命令字节,由外部控制器发送至模块(十六进制)
     . 0x31:进行一次角度测量--------返回值参考输出格式
     ②.0xC0:校准磁场开始---------返回值参考输出格式(000.0度)         ③.0xC1 :校准磁场结束--------------返回值参考硬铁补偿‘ ②’
④.0xA0-0XAA-0XA5-0XC5 :
恢复出厂设定----------------------返回值参考输出格式(000.0度)
⑤. 0xA0-0XAA-0XA5-IIC_ADDR :
模块的IIC地址修改-------------返回值参考输出格式(000.0度)
IIC地址范围参考“IIC通信协议(3)”
⑥. 0x03 + 磁偏高8位 :
磁偏角设定,正北方向设定--返回值参考输出格式(000.0度)
⑦. 0x04 + 磁偏低8位 :
磁偏角设定,正北方向设定--返回值参考输出格式(000.0度)

例:发送0XC0至模块时,模块应答以下1帧
   <0x0D-0x0A-0x30-0x30-0x30-0x2E-0x30-0x05>表示成功
    Led灯亮起,进入校准

例:发送0x03,0x00,0x04,0x64至模块时,模块应答以下1帧(4次)
   <0x0D-0x0A-0x30-0x30-0x30-0x2E-0x30-0x05>表示成功
    磁偏角被修改为10.0度


IIC通信协议
1)、进行IIC通信时,模块相当于24C04EEPROM存储器,通信非常简单。
      模块内部对应地址的数据(相当EEPROM各地址的数据),映射各参数
      请参考下表
  
模块内部地址
  

地址的数据含义

  
0x00
  

未用到

  
0x01
  

角度值高8

  
0x02
  

角度值低8

  
0x03
  

磁偏角高8

  
0x04
  

磁偏角低8

  
0x05
  

未用到

  
0x06
  

未用到

  
0x07
  

校准等级值

       实际当前角度值为上表“角度值高8位”与“角度值低8位”合成的16位数据,数据范围0-3599(因为分辨率为0.1°)
       实际当前磁偏角值为“磁偏角高8位”与“磁偏角低8位”合成的16位数据,数据范围0-3599(因为分辨率为0.1°)

(2)、模块的命令表, 经IIC总线写入模块中

  
命令值
  

作用

  
0x00+ 0x31
  

角度测量

  
0x00+ 0xC0
  

校准

  
0x00+ 0xC1
  

停止校准

  
0x00+0xA0+0XAA+0XA5+0XC5
  

恢复出厂设置

  
0x00+0xA0+0XAA+0XA5+IIC_ADDR
  

IIC地址修改

  
0x03 + 磁偏高8位值
  

磁偏角修改

  
0x04 + 磁偏低8位值
  

磁偏角修改

      磁偏角的值,范围0-3599(因为分辨率为0.1°),是由2个8位的数据组成,当修改模块磁偏角时,分为高8位值,低8位值,写入模块。
(3)、模块的IIC地址可修改,出厂默认是0xe0。模块上电时led对应IIC地址闪动,闪动的次数由模块上电led亮起,led灭掉开始记。若模块上电立即向模块发送命令,则led不闪动。向模块写入地址时,模块只接收以下16个数据地址,其他无效

  
模块地址
  

Led闪动次数

  
0xe0
  

0

  
0xe2
  

1

  
0xe4
  

2

  
0xe6
  

3

  
0xe8
  

4

  
0xea
  

5

  
0xec
  

6

  
0xee
  

7

  
0xf0
  

8

  
0xf2
  

9

  
0xf4
  

10

  
0xf6
  

11

  
0xf8
  

12

  
0xfa
  

13

  
0xfc
  

14

  
0xfe
  

15

六、术语说明
(1)、磁偏角
磁北线与真北线之间的夹角(如图),地球表面任一点的磁子午圈同地理子午圈的夹角。不同的地点磁偏角不同,同一地点不同的时间磁偏角也不同。模块的磁偏角=原始角度+设定磁偏角度,即顺时针加上。例如:磁偏角为0的100度,此时更改磁偏角为10度,那么模块输出为100+10=110度。
file:///C:/Users/FSY/AppData/Local/Temp/msohtml1/02/clip_image004.jpg


2)、硬铁补偿,磁场校准
      当电子指南针使用的环境发生改变时,由于受到周围磁场的影响,输出的角度也将会受到干扰,为了消除干扰,需要进行环境磁场校准。本模块的校准方法有三种种 如下:

①.               在模块的第9(CAL)引脚,接一按键至电源负极(GND),当第一次按下按键时,进入校准状态,LED常亮起。保持模块水平,缓慢旋转1周(旋转1周时间大约1分钟)。再次按下按键LED灭,校准结束。
②.               控制器串口发送数据0XC0至模块后LED常亮起,模块应答成功数据。保持模块水平,缓慢旋转1周(旋转1周时间大约1分钟)。发送数据0XC1至模块,LED灭,校准结束。此时模块模块应答本次校准的等级(0级~9级,级数越大说明校准越好),应答一帧格式为:
Byte0:   0x0D               (ASCII码回车)
Byte1:   0x0A               (ASCII码换行)
Byte2:  0x30                (ASCII码0 )
Byte3:  0x30                (ASCII码0 )
Byte4:  0x30                (ASCII码0 )
Byte5:   0x2E                (ASCII码小数点)   
Byte6:   0x30~0x39 校准等级  (ASCII 0~9)
Byte7:  0x00~0xFF校验和    (仅低8bit)
        注:校验和    Byte7 =Byte0+Byte1+…….Byte6)结果仅取低8bit
    例:发送0XC1至模块时,模块应答以下1帧
  <0x0D-0x0A-0x30-0x30-0x30-0x2E-0x39-0x0E>表示成功校准等级9

③.    控制器经IIC总线发送数据0x00+ 0xC0至模块后LED常亮起保持模块水平,缓慢旋转1周(旋转1周时间大约1分钟)。发送数据0x00+0XC1至模块,LED灭,校准结束。

七、结束
1)、模块参数都是基于一个标准5V状态下测试的。建议使用纹波较小的电源供给。

2)、模块测量时LED的闪动对应测量的频率。校准时LED常亮。
3)、模块测量时和校准时,保持水平,将获得最好的准确度,测量时应远离磁体尽量30厘米以上。
4)、模块内部有记忆功能,可掉电记忆校准系数及磁偏角。

5)、恢复出厂设定,即恢复出厂时的校准系数及磁偏角度,并不会修改模块当前的IIC地址。
  
6)、模块输入输出的高低电平3-5V,可以直接与单片机串口,单片机IO连接,可以直接与PL2303CH340FT232等芯片连接,但不能与电脑串口直接连接
原理图:

(, 下载次数: 82)
C程序
  1. //  GY-26电子指南针模块测试程序
  2. //  使用单片机:STC89C52
  3. //  晶振:  11.0592 M
  4. //  液晶屏:LCD1602
  5. #include<REG52.H>        
  6. #include<math.h>       //Keil library  
  7. #include<stdio.h>      //Keil library        
  8. #include<INTRINS.H>
  9. #define uchar unsigned char
  10. #define uint  unsigned int        
  11. #define DataPort P0           //LCD1602 数据端口        
  12. sbit    LCM_RS=P2^0;   //LCD1602 控制端口               
  13. sbit    LCM_RW=P2^1;   //LCD1602 控制端口        
  14. sbit    LCM_EN=P2^2;   //LCD1602 控制端口
  15. sbit    KEY_1 =P2^3;
  16. sbit    KEY_2 =P2^4;
  17. sbit    KEY_3 =P2^5;
  18. sbit    KEY_4 =P2^6;        
  19. //********定义变量*****************************
  20. uchar   BUF[8];        //数据缓存区
  21. uchar   cnt;           //接收数据的累计值
  22. //********定义函数*****************************
  23. void    delay(unsigned int k);
  24. void    InitLcd();
  25. void    WriteDataLCM(uchar dataW);
  26. void    WriteCommandLCM(uchar CMD,uchar Attribc);
  27. void    DisplayOneChar(uchar X,uchar Y,uchar DData);
  28. void    SeriPushSend(uchar send_data);
  29. void    ReadKey(void);
  30. void         display(void);
  31. //*********************************************
  32. //串口中断
  33. void serial_serve(void) interrupt 4        
  34. {
  35.   if(RI==1){
  36.     RI=0;
  37.     BUF[cnt]=SBUF;
  38.         cnt++;
  39. //        if(cnt==7)flag=1;
  40.   }
  41. }
  42. //*********************************************
  43. //串口初始化
  44. //9600 bps @ 11.059 MHz
  45. void init_uart()
  46. {
  47.         TMOD=0x21;                                
  48.         TH1=0xfd;                                
  49.         TL1=0xfd;                                
  50.         SCON=0x50;
  51.         PS=1;      //串口中断设为高优先级别
  52.         TR0=1;           //启动定时器                        
  53.         TR1=1;
  54.         ET0=1;     //打开定时器0中断                        
  55.         ES=1;        
  56. }
  57. //*********LCD1602初始化**********************
  58. void InitLcd()                                
  59. {                        
  60.         WriteCommandLCM(0x38,1);        
  61.         WriteCommandLCM(0x08,1);        
  62.         WriteCommandLCM(0x01,1);
  63.         WriteCommandLCM(0x06,1);        
  64.         WriteCommandLCM(0x0c,1);
  65. }
  66. //**********检测忙信号************************
  67. void WaitForEnable(void)        
  68. {                                       
  69.         DataPort=0xff;               
  70.         LCM_RS=0;LCM_RW=1;_nop_();
  71.         LCM_EN=1;_nop_();_nop_();
  72.         while(DataPort&0x80);        
  73.         LCM_EN=0;                                
  74. }                                       
  75. //**********写命令至LCD***********************
  76. void WriteCommandLCM(uchar CMD,uchar Attribc)
  77. {                                       
  78.         if(Attribc)WaitForEnable();        
  79.         LCM_RS=0;LCM_RW=0;_nop_();
  80.         DataPort=CMD;_nop_();        
  81.         LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  82. }                                       
  83. //**********写数据至LCD************************
  84. void WriteDataLCM(uchar dataW)
  85. {                                       
  86.         WaitForEnable();               
  87.         LCM_RS=1;LCM_RW=0;_nop_();
  88.         DataPort=dataW;_nop_();        
  89.         LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  90. }                                       
  91. //*********写一个字符数据到指定的目标***********
  92. void DisplayOneChar(uchar X,uchar Y,uchar DData)
  93. {                                                
  94.         Y&=1;                                                
  95.         X&=15;                                                
  96.         if(Y)X|=0x40;                                       
  97.         X|=0x80;                        
  98.         WriteCommandLCM(X,0);               
  99.         WriteDataLCM(DData);               
  100. }
  101. //**********延时函数***************
  102. void delay(unsigned int k)        
  103. {                                                
  104.         unsigned int i,j;                                
  105.         for(i=0;i<k;i++)
  106.         {                        
  107.         for(j=0;j<121;j++)                        
  108.         {;}
  109.         }                                                
  110. }                                                            
  111. //*********串口数据发送******************
  112. void  SeriPushSend(uchar send_data)
  113. {
  114.     SBUF=send_data;  
  115.         while(!TI);TI=0;         
  116. }
  117. //*********按键检测**********************
  118. void ReadKey(void)
  119. {

  120.     EA=0;
  121.     if(KEY_1==0){
  122.        delay(50);
  123.        if(KEY_1==0){
  124.        SeriPushSend(0XC0);                                    //发送校准命令。
  125.            display();
  126.        while(KEY_1==0);                                       //等待按键放开
  127.        }
  128.     }
  129.     if(KEY_2==0){
  130.        delay(50);
  131.        if(KEY_2==0){
  132.        SeriPushSend(0XC1);                                    //发送停止校准命令。
  133.            display();
  134.        while(KEY_2==0);                                       //等待按键放开
  135.        }
  136.     }
  137.     if(KEY_3==0){
  138.        delay(50);
  139.        if(KEY_3==0){
  140.        SeriPushSend(0XA0);                                    //发送恢复出厂命令。
  141.            display();
  142.        SeriPushSend(0XAA);                                    //发送恢复出厂命令。
  143.            display();
  144.        SeriPushSend(0XA5);                                    //发送恢复出厂命令。
  145.            display();
  146.        SeriPushSend(0XC5);                                    //发送恢复出厂命令。
  147.            display();
  148.        while(KEY_3==0);                                       //等待按键放开
  149.        }
  150.     }

  151.     if(KEY_4==0){
  152.        delay(50);
  153.        if(KEY_4==0){
  154.        SeriPushSend(0X3);                                    //发送设定磁偏角高8位命令。
  155.            display();
  156.        SeriPushSend(0X0);                                    //发送磁偏角高8位的数据。
  157.            display();
  158.        SeriPushSend(0X4);                                    //发送设定磁偏角低8位命令
  159.            display();
  160.        SeriPushSend(0X64);                                   //发送磁偏角低8位的数据。此时磁偏角被设定为10.0度
  161.            display();
  162.        while(KEY_4==0);                                       //等待按键放开
  163.        }
  164.     }
  165. /*
  166.     if(KEY_5==0){
  167.        delay(50);
  168.        if(KEY_4==0){
  169.        SeriPushSend(0XAE);                                    //发送当前角度为0度命令。
  170.            display();
  171.        while(KEY_4==0);                                       //等待按键放开
  172.        }
  173.     }
  174. */

  175.     EA=1;

  176. }
  177. //*******************数据接收并显示**********************
  178. void display(void)
  179. {
  180.     uchar SUM;
  181.     uint   i ;
  182.    for (i=0;i<3000;i++);                                      //传送数据延时
  183.           if(BUF[0]==0X0D&&BUF[1]==0X0A){                         //帧头判断
  184.         SUM=BUF[6]+BUF[5]+BUF[4]+BUF[3]+BUF[2]+BUF[1]+BUF[0]; //校验和
  185.                if (BUF[7]==SUM){                                     //校验和判断
  186.           DisplayOneChar(0,0,BUF[2]);                         //角度百位值 写入LCD,因为是字符类型,所以不用转换,直接显示
  187.           DisplayOneChar(1,0,BUF[3]);                         //角度十位值 写入LCD
  188.           DisplayOneChar(2,0,BUF[4]);                         //角度个位值 写入LCD
  189.           DisplayOneChar(3,0,BUF[5]);                         //小数点
  190.                DisplayOneChar(4,0,BUF[6]);                         //角度小数位值 写入LCD
  191.             }                                                     //end if        
  192.       }
  193. }  
  194. //***************************************
  195. //主程序
  196. void main()
  197. {  uint   i ;
  198.    delay(500);                                                      //延时               
  199.    InitLcd();                                                 //初始化LCD
  200.    init_uart();                                               //初始化串口
  201.    EA=1;                                                      //开总中断
  202.   while(1){                                                   //循环
  203.     cnt=0;                                                    //接收数据的累计值
  204.     SeriPushSend(0X31);                                       //发送1帧读取命令。
  205.     display();                                          
  206.     ReadKey();                                                //按键检测        
  207.     for (i=0;i<12000;i++);                                    //一定时间的延时        
  208.    }                                                          //end while
  209. }

复制代码

PIC原理图
(, 下载次数: 68)

GY-26电子指南针PIC代码IIC
  1. /*****************************************
  2. * 基于PIC单片机GY-26模块通信程序                  *
  3. * 功    能:IIC通信读取数据并显示        *
  4. * 时钟频率:4M晶振                                                  *
  5. * 设    计:电应普公司                                         *
  6. * 修改日期:2010年10月26日                                 *
  7. * 编译环境:MPLAB-IDEv8.60+HI-TECHv9.60  *
  8. * 实验环境:PIC16F877A+1602                             *
  9. * 使用端口:RC7,RC6,RC5,RC4,RC3,PORTD          *
  10. * 参    考:网友24c02IIC程序,1602程序   *
  11. *****************************************/
  12. #include <pic.h>    //调用头文件
  13. #include <stdio.h>
  14. __CONFIG(0x3F32);   //芯片配置字                  
  15. #define  uchar unsigned char
  16. #define  uint  unsigned int
  17. #define  ulint unsigned long int        
  18. #define  GY_26_ADDR         0xE0                   //定义电子指南针器件地址(出厂默认为0XE0)                                                                        
  19. #define  LCD_DATA_PORT    PORTD        //定义LCD的D0-D7所在端口
  20. #define  LCD_DATA_POUT    TRISD= 0x00  //定义LCD数据端口为输出
  21. #define  LCD_DATA_PIN     TRISD= 0xFF  //定义LCD数据端口为输入(在读LCD状态时用到)
  22. #define  LCD_Control_OUT  TRISC&=0X1F  //定义LCD控制端口输出
  23. #define  LCD_EN           RC7          //LCD对应端口
  24. #define  LCD_RW           RC6          //LCD对应端口
  25. #define  LCD_RS           RC5          //LCD对应端口
  26. //函数申明**********************************
  27. void        delay_20us(uint nus);
  28. void        nms_delay(uint nms);
  29. void        mcu_init(void);
  30. void         lcd_init(void);
  31. void         LCD_en_write(void);
  32. void         wait_LCD_Ready(void);
  33. void         set_LCD_xy(uchar x, uchar y );
  34. void         LCD_write_onechar(uchar COMM,uchar DAT);
  35. void         LCD_write_string(uchar X,uchar Y,uchar *string);
  36. uint         get_GY_26(uchar read_begin_address,uchar GY_26_cmd);
  37. void         conversion(uint i);
  38. //iic使用函数********************************
  39. void          iic_Start(void){SEN=1;while(SEN);}    //启动iic
  40. void          iic_Stop (void){PEN=1;while(PEN);}          //停止iic
  41. void          iic_rest (void){RSEN=1;while(RSEN);}  //重启iic
  42. void          iic_Write8Bit(uchar x){SSPIF=0;SSPBUF=x;while(!SSPIF);SSPIF=0;}//向iic总线写8bit数据               
  43. uchar         iic_read8Bit(void){RCEN=1;while(!BF);ACKEN=1;while(ACKEN);return SSPBUF;}//向iic总线读8bit数据
  44. //数组****************************************
  45. uchar        START_DISPLAY1[16]={"Compass:       "};//LCD初始化显示数据
  46. uchar         START_DISPLAY2[16]={"  Temp :       "};//LCD初始化显示数据  
  47. uchar         display[7]={0,0,0,'.',0,0Xdf,0};     //显示数据数组
  48. /*********************************************
  49. 数据转换,十六进制数据转换成10进制
  50. 输入十六进制范围:0x0000-0x270f(0-9999)
  51. 结果分成个十百千位,以ascii存入显示区
  52. **********************************************/
  53. void conversion(unsigned int i)  
  54. {  
  55.         display[0]=i/1000+0x30 ;
  56.     i=i%1000;    //取余运算
  57.     display[1]=i/100+0x30 ;
  58.     i=i%100;    //取余运算
  59.     display[2]=i/10+0x30 ;
  60.     i=i%10;     //取余运算
  61.     display[4]=i+0x30;  
  62. }
  63. //单片机初始化**************
  64. void mcu_init(void)
  65. {
  66.         TRISC=0XFF;             //IIC通信引脚设为输入        
  67.         SSPSTAT = 0x80;         //IIC设置
  68.         SSPCON  = 0x38;         //IIC设置
  69.         SSPCON2 = 0x00;         //IIC设置
  70.         SSPADD  = 50;                        //IIC设置                 
  71. }
  72. //LCD初始化***************************
  73. void lcd_init(void)
  74. {
  75.     nms_delay(100);
  76.         LCD_DATA_POUT;             //LCD数据口设为输出
  77.     LCD_Control_OUT;
  78.     LCD_write_onechar(0x38,0);
  79.     LCD_write_onechar(0x08,0);   
  80.     LCD_write_onechar(0x01,0);   
  81.     LCD_write_onechar(0x06,0);   
  82.     LCD_write_onechar(0x0C,0);   
  83. }
  84. //LCD写使能******************************
  85. void LCD_en_write(void)      
  86. {
  87.     LCD_EN=1;
  88.    // delay_20us(1);  //E脉冲周期最小150ns
  89.     LCD_EN=0;
  90. }
  91. //等待LCD空闲****************************
  92. void wait_LCD_Ready(void)
  93. {
  94.     uchar temp1;
  95.     LCD_DATA_PORT=0XFF;
  96.     LCD_DATA_PIN;      //准备判断LCD忙标志
  97.     LCD_RS=0;
  98.     LCD_RW=1;          //读
  99.     LCD_EN=1;
  100.     delay_20us(1);
  101.     while((temp1=PORTD & 0X80));
  102.         LCD_EN=0;
  103.         LCD_RS=1;
  104.         LCD_DATA_POUT;
  105. }
  106. //LCD写一个字符**********************
  107. void LCD_write_onechar(uchar COMM,uchar DAT)
  108. {
  109.         wait_LCD_Ready();         //等待LCD空闲
  110.         LCD_RW=0;                 //写        
  111.          if(COMM==0){              //写数据   
  112.          LCD_RS=1;                //RS高电平向LCD写数据
  113.          LCD_DATA_PORT=DAT;
  114.         }
  115.         else{                     //写命令        
  116.          LCD_RS=0;
  117.          LCD_DATA_PORT=COMM;
  118.         }
  119.          LCD_en_write();
  120.          delay_20us(1);
  121.          LCD_RW=1;
  122.          LCD_RS=1;
  123. }
  124. //LCD写字符到指定坐标******************************
  125. void LCD_write_string(uchar X,uchar Y,uchar *string)
  126. {
  127.     set_LCD_xy( X, Y );        //设置LCD显示坐标
  128.     while (*string)
  129.     {
  130.          LCD_write_onechar(0,*string );
  131.          string ++;                //指向下一显示字符地址
  132.     }
  133. }
  134. //LCD写坐标设置**********************************
  135. void set_LCD_xy(uchar x, uchar y )
  136. {
  137.     uchar DIS_address;
  138.     if (y == 0)
  139.          DIS_address = 0x80 + x;               //第一行X列
  140.     else
  141.          DIS_address = 0xc0 + x;
  142.          LCD_write_onechar( DIS_address, 0 );  //第二行X列
  143. }
  144. //延时大约20us***************************************
  145. void delay_20us(uint nus)
  146. {  uchar i;
  147.    while(--nus){
  148.    for(i=2;i>0;i--);
  149.    }        
  150. }
  151. //延时大约1ms***************************************
  152. void nms_delay(uint nms)
  153. {
  154.         while(nms--)
  155.         delay_20us(50);
  156. }
  157. //从IIC总线获得电子指南针GY-26数据********************
  158. //从开始地址连续读出两个8bit的值,并合成16bit数据
  159. uint get_GY_26(uchar read_begin_address,uchar GY_26_cmd)
  160. { unsigned int temp;
  161.     iic_Start();                        //iic启动时序
  162.     iic_Write8Bit(GY_26_ADDR);          //写指南针器件地址
  163.     iic_Write8Bit(0);                   //写命令
  164.     iic_Write8Bit(GY_26_cmd);                        //写指南针命令
  165.     iic_Stop();                                                        //iic写停止时序
  166.     nms_delay(55);                            //延时,可执行其他程序
  167.     iic_Start();                        //iic启动时序
  168.         ACKDT = 0;                                                        //允许应答ACK
  169.     iic_Write8Bit(GY_26_ADDR);          //写指南针器件地址     
  170.     iic_Write8Bit(read_begin_address);        //写指南针内部数据地址
  171.     iic_rest();                         //iic重启时序
  172.     iic_Write8Bit(GY_26_ADDR+1);                //指南针器件地址+1=读
  173.     temp=iic_read8Bit();                //读出8位数据
  174.     temp<<=8;                           //保存数据
  175.     ACKDT = 1;                          //允许应答NO_ACK
  176.            temp+=iic_read8Bit();                                //读出8位数据                        
  177.     iic_Stop();                         //发送停止时序
  178.         return temp;                        //返回本次测量数值
  179. }
  180. //主程序************************************************
  181. void main(void)
  182. {   unsigned int  CMP_DATA,TEMP_DATA;
  183.         mcu_init();                          //单片机初始化
  184.         lcd_init();                          //lcd1602初始化         
  185.         LCD_write_string(0,0,START_DISPLAY1);//LCD初始化显示数据
  186.         LCD_write_string(0,1,START_DISPLAY2);//LCD初始化显示数据
  187.         while(1)
  188.     {      
  189.           CMP_DATA=get_GY_26(1,0x31);       //读取角度
  190.           conversion(CMP_DATA);             //数据转换出个,十,百,千 位         
  191.           LCD_write_string(9,0,display);    //显示角度,从第0行第9列开始   
  192.           TEMP_DATA=get_GY_26(5,0x35);      //读取温度
  193.           conversion(TEMP_DATA);            //数据转换出个,十,百,千 位  
  194.           LCD_write_string(9,1,display);    //显示角度,从第1行第9列开始   
  195.     }               
  196. }

复制代码









欢迎光临 圣源电子制作 (https://syyyd.com/) Powered by Discuz! X3.4