找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 9344|回復(fù): 10
收起左側(cè)

HMC5883L電子指南針單片機(jī)程序

  [復(fù)制鏈接]
ID:127035 發(fā)表于 2016-12-19 21:19 | 顯示全部樓層 |閱讀模式
HMC5883L電子指南針
完整的單片機(jī)源程序下載:
2014年6月7日 指南針 1602.rar (45.92 KB, 下載次數(shù): 187)

預(yù)覽:
  1. #include <reg52.h>                 //調(diào)用單片機(jī)頭文件
  2. #define uchar unsigned char  //無(wú)符號(hào)字符型 宏定義        變量范圍0~255
  3. #define uint  unsigned int         //無(wú)符號(hào)整型 宏定義        變量范圍0~65535
  4. #include  <math.h>    //Keil library  
  5. #include  <stdio.h>   //Keil library        
  6. #include  <INTRINS.H>

  7. sbit rs=P2^3;         //寄存器選擇信號(hào) H:數(shù)據(jù)寄存器          L:指令寄存器
  8. sbit rw=P2^4;         //寄存器選擇信號(hào) H:數(shù)據(jù)寄存器          L:指令寄存器
  9. sbit e =P2^5;         //片選信號(hào)   下降沿觸發(fā)

  10. sbit SCL=P1^1;      //IIC時(shí)鐘引腳定義
  11. sbit SDA=P1^0;      //IIC數(shù)據(jù)引腳定義

  12. #define        SlaveAddress   0x3C                 //定義器件在IIC總線中的從地址
  13. uchar BUF[8];                        //接收數(shù)據(jù)緩存區(qū)              
  14. uchar ge,shi,bai,qian,wan;           //顯示變量
  15. int  dis_data;                       //變量

  16. /******************1ms 延時(shí)函數(shù)*******************/
  17. void delay_1ms(uint q)
  18. {
  19.         uint i,j;
  20.         for(i=0;i<q;i++)
  21.                 for(j=0;j<120;j++);
  22. }


  23. /***********************延時(shí)函數(shù)************************/
  24. void delay_uint(uint q)
  25. {
  26.         while(q--);
  27. }

  28. /**************************************
  29. 延時(shí)5微秒(STC90C52RC@12M)
  30. 不同的工作環(huán)境,需要調(diào)整此函數(shù),注意時(shí)鐘過(guò)快時(shí)需要修改
  31. 當(dāng)改用1T的MCU時(shí),請(qǐng)調(diào)整此延時(shí)函數(shù)
  32. **************************************/
  33. void Delay5us()
  34. {
  35.              _nop_();_nop_();_nop_();_nop_();
  36.              _nop_();_nop_();_nop_();_nop_();
  37.         _nop_();_nop_();_nop_();_nop_();
  38.         _nop_();_nop_();_nop_();_nop_();
  39.               _nop_();_nop_();_nop_();_nop_();
  40.         _nop_();_nop_();_nop_();_nop_();
  41.         _nop_();_nop_();_nop_();_nop_();
  42.              _nop_();_nop_();_nop_();_nop_();

  43. }

  44. /***********************lcd1602寫(xiě)命令函數(shù)************************/
  45. void write_com(uchar com)
  46. {
  47.         e=0;
  48.         rs=0;
  49.         rw=0;
  50.         P0=com;
  51.         delay_uint(3);
  52.         e=1;
  53.         delay_uint(25);
  54.         e=0;
  55. }

  56. /***********************lcd1602寫(xiě)數(shù)據(jù)函數(shù)************************/
  57. void write_data(uchar dat)
  58. {
  59.         e=0;
  60.         rs=1;
  61.         rw=0;
  62.         P0=dat;
  63.         delay_uint(3);
  64.         e=1;
  65.         delay_uint(25);
  66.         e=0;        
  67. }

  68. /***********************lcd1602上顯示特定的字符************************/
  69. void write_zifu(uchar hang,uchar add,uchar date)
  70. {
  71.         if(hang==1)   
  72.                 write_com(0x80+add);
  73.         else
  74.                 write_com(0x80+0x40+add);
  75.         write_data(date);        
  76. }

  77. /***********************lcd1602上顯示這字符函數(shù)************************/
  78. void write_string(uchar hang,uchar add,uchar *p)
  79. {
  80.         if(hang==1)   
  81.                 write_com(0x80+add);
  82.         else
  83.                 write_com(0x80+0x40+add);
  84.         while(1)                                                                                                                 
  85.         {
  86.                 if(*p == '\0')  break;
  87.                 write_data(*p);
  88.                 p++;
  89.         }        
  90. }


  91. /***********************lcd1602初始化設(shè)置************************/
  92. void init_1602()         //lcd1602初始化設(shè)置
  93. {
  94.         write_com(0x38);        //
  95.         write_com(0x0c);
  96.         write_com(0x06);
  97.         delay_uint(1000);
  98.         write_string(1,0,"  zhi nan zhen ");               
  99.         write_string(2,0,"               ");        
  100.         write_zifu(2,11,0xdf);  //顯示度        
  101. }

  102. /***********************lcd1602上顯示兩位十進(jìn)制數(shù)************************/
  103. void write_jiaodu(uchar hang,uchar add,uint date)
  104. {
  105.         if(hang==1)   
  106.                 write_com(0x80+add);
  107.         else
  108.                 write_com(0x80+0x40+add);
  109.         write_data(0x30+date/1000%10);
  110.         write_data(0x30+date/100%10);
  111.         write_data(0x30+date/10%10);
  112.         write_data('.');
  113.         write_data(0x30+date%10);        
  114. }

  115. /**************************************
  116. 起始信號(hào)
  117. **************************************/
  118. void HMC5883_Start()
  119. {
  120.     SDA = 1;                    //拉高數(shù)據(jù)線
  121.     Delay5us();                 //延時(shí)
  122.     SDA = 0;                    //產(chǎn)生下降沿
  123.     Delay5us();                 //延時(shí)
  124.     SCL = 0;                    //拉低時(shí)鐘線
  125. }

  126. /**************************************
  127. 停止信號(hào)
  128. **************************************/
  129. void HMC5883_Stop()
  130. {
  131.     SDA = 0;                    //拉低數(shù)據(jù)線
  132.     SCL = 1;                    //拉高時(shí)鐘線
  133.     Delay5us();                 //延時(shí)
  134.     SDA = 1;                    //產(chǎn)生上升沿
  135.     Delay5us();                 //延時(shí)
  136. }

  137. /**************************************
  138. 發(fā)送應(yīng)答信號(hào)
  139. 入口參數(shù):ack (0:ACK 1:NAK)
  140. **************************************/
  141. void HMC5883_SendACK(bit ack)
  142. {
  143.     SDA = ack;                  //寫(xiě)應(yīng)答信號(hào)
  144.     SCL = 1;                    //拉高時(shí)鐘線
  145.     Delay5us();                 //延時(shí)
  146.     SCL = 0;                    //拉低時(shí)鐘線
  147.     Delay5us();                 //延時(shí)
  148. }

  149. /**************************************
  150. 接收應(yīng)答信號(hào)
  151. **************************************/
  152. bit HMC5883_RecvACK()
  153. {
  154.     SCL = 1;                    //拉高時(shí)鐘線
  155.     Delay5us();                 //延時(shí)
  156.     CY = SDA;                   //讀應(yīng)答信號(hào)
  157.     SCL = 0;                    //拉低時(shí)鐘線
  158.     Delay5us();                 //延時(shí)

  159.     return CY;
  160. }

  161. /**************************************
  162. 向IIC總線發(fā)送一個(gè)字節(jié)數(shù)據(jù)
  163. **************************************/
  164. void HMC5883_SendByte(uchar dat)
  165. {
  166.     uchar i;

  167.     for (i=0; i<8; i++)         //8位計(jì)數(shù)器
  168.     {
  169.         dat <<= 1;              //移出數(shù)據(jù)的最高位
  170.         SDA = CY;               //送數(shù)據(jù)口
  171.         SCL = 0;                //拉高時(shí)鐘線
  172.         Delay5us();             //延時(shí)
  173.         SCL = 1;                //拉低時(shí)鐘線
  174.         Delay5us();             //延時(shí)
  175.     }
  176.     HMC5883_RecvACK();
  177. }

  178. /**************************************
  179. 從IIC總線接收一個(gè)字節(jié)數(shù)據(jù)
  180. **************************************/
  181. uchar HMC5883_RecvByte()
  182. {
  183.     uchar i;
  184.     uchar dat = 0;

  185.     SDA = 1;                    //使能內(nèi)部上拉,準(zhǔn)備讀取數(shù)據(jù),
  186.     for (i=0; i<8; i++)         //8位計(jì)數(shù)器
  187.     {
  188.         dat <<= 1;
  189.         SCL = 1;                //拉高時(shí)鐘線
  190.         Delay5us();             //延時(shí)
  191.         dat |= SDA;             //讀數(shù)據(jù)               
  192.         SCL = 0;                //拉低時(shí)鐘線
  193.         Delay5us();             //延時(shí)
  194.     }
  195.     return dat;
  196. }

  197. //***************************************************

  198. void Single_Write_HMC5883(uchar REG_Address,uchar REG_data)
  199. {
  200.     HMC5883_SendByte(SlaveAddress);   //發(fā)送設(shè)備地址+寫(xiě)信號(hào)
  201.     HMC5883_SendByte(REG_Address);    //內(nèi)部寄存器地址,請(qǐng)參考中文pdf
  202.     HMC5883_SendByte(REG_data);       //內(nèi)部寄存器數(shù)據(jù),請(qǐng)參考中文pdf
  203. }

  204. //******************************************************
  205. //
  206. //連續(xù)讀出HMC5883內(nèi)部角度數(shù)據(jù),地址范圍0x3~0x8
  207. //
  208. //******************************************************
  209. void Multiple_read_HMC5883(void)
  210. {   uchar i;
  211.     HMC5883_Start();                          //起始信號(hào)
  212.     HMC5883_SendByte(SlaveAddress);           //發(fā)送設(shè)備地址+寫(xiě)信號(hào)
  213.     HMC5883_SendByte(0x03);                   //發(fā)送存儲(chǔ)單元地址,從0x3開(kāi)始        
  214.     HMC5883_Start();                          //起始信號(hào)
  215.     HMC5883_SendByte(SlaveAddress+1);         //發(fā)送設(shè)備地址+讀信號(hào)
  216.         for (i=0; i<6; i++)                      //連續(xù)讀取6個(gè)地址數(shù)據(jù),存儲(chǔ)中BUF
  217.     {
  218.         BUF[i] = HMC5883_RecvByte();          //BUF[0]存儲(chǔ)數(shù)據(jù)
  219.         if (i == 5)
  220.         {
  221.            HMC5883_SendACK(0);                //最后一個(gè)數(shù)據(jù)需要回NOACK
  222.         }
  223.         else
  224.         {
  225.           HMC5883_SendACK(1);                //回應(yīng)ACK
  226.        }
  227.    }
  228.     delay_1ms(5);
  229. }

  230. //初始化HMC5883,根據(jù)需要請(qǐng)參考pdf進(jìn)行修改****
  231. void Init_HMC5883()
  232. {
  233.      Single_Write_HMC5883(0x02,0x00);  //
  234. }


  235. /*****************主函數(shù)********************/
  236. void main()
  237. {        
  238.     int x,y,z,jiadu;
  239.     double angle;
  240.         P0 = P1 = P2 = P3 = 0xff;                //單片機(jī)IO口初始化為1
  241.     Init_HMC5883();
  242.         init_1602();                 //lcd1602初始化
  243.         while(1)
  244.         {   
  245.             Multiple_read_HMC5883();      //連續(xù)讀出數(shù)據(jù),存儲(chǔ)在BUF中
  246.         //---------顯示X軸
  247.             x=BUF[0] << 8 | BUF[2]; //Combine MSB and LSB of X Data output register
  248.             z=BUF[2] << 8 | BUF[4]; //Combine MSB and LSB of Z Data output register
  249.         
  250.             angle= atan2((double)y,(double)x) * (180 / 3.14); // angle in degrees
  251.                 jiadu = angle;
  252.                 write_jiaodu(2,6,angle);        //顯示角度
  253.                 if((angle >= 3380) || (angle <= 220))          //北 N
  254.                         write_string(2,0,"  N  ");        
  255.                 if((angle >= 230) && (angle <= 670))          //東 北
  256.                         write_string(2,0," E N ");        
  257.                 if((angle >= 680) && (angle <= 1120))          //東 E
  258.                         write_string(2,0,"  E  ");        
  259.                 if((angle >= 1130) && (angle <= 1570))          //東 南
  260.                         write_string(2,0," E S ");        
  261.                 if((angle >= 1580) && (angle <= 2010))          //南  S
  262.                         write_string(2,0,"  S  ");        
  263.                 if((angle >= 2020) && (angle <= 2460))          //西 南  
  264.                         write_string(2,0," W S ");        
  265.                 if((angle >= 2470) && (angle <= 2910))          //西  W  
  266.                         write_string(2,0,"  W  ");        
  267.                 if((angle >= 2920) && (angle <= 3360))          //西  北  
  268.                         write_string(2,0," W N  ");        
  269.                 delay_1ms(300);

  270.         }
  271. }
復(fù)制代碼


回復(fù)

使用道具 舉報(bào)

ID:1 發(fā)表于 2017-1-3 00:01 | 顯示全部樓層
51黑有你更精彩。。
回復(fù)

使用道具 舉報(bào)

ID:198094 發(fā)表于 2017-5-8 14:58 | 顯示全部樓層
大神您好,能幫忙解釋一下如下程序中,角度值為什么這樣設(shè)置嗎?

angle= atan2((double)y,(double)x) * (180 / 3.14); // angle in degrees
                jiadu = angle;
                write_jiaodu(2,6,angle);        //顯示角度
                if((angle >= 3380) || (angle <= 220))          //北 N
                        write_string(2,0,"  N  ");        
                if((angle >= 230) && (angle <= 670))          //東 北
                        write_string(2,0," E N ");        
                if((angle >= 680) && (angle <= 1120))          //東 E
                        write_string(2,0,"  E  ");        
                if((angle >= 1130) && (angle <= 1570))          //東 南
                        write_string(2,0," E S ");        
                if((angle >= 1580) && (angle <= 2010))          //南  S
                        write_string(2,0,"  S  ");        
                if((angle >= 2020) && (angle <= 2460))          //西 南  
                        write_string(2,0," W S ");        
                if((angle >= 2470) && (angle <= 2910))          //西  W  
                        write_string(2,0,"  W  ");        
                if((angle >= 2920) && (angle <= 3360))          //西  北  
                        write_string(2,0," W N  ");        
                delay_1ms(300);
回復(fù)

使用道具 舉報(bào)

ID:198094 發(fā)表于 2017-5-8 15:02 | 顯示全部樓層
大神麻煩解釋一下如下程序中,東西南北角度值為何這樣設(shè)呢?

angle= atan2((double)y,(double)x) * (180 / 3.14); // angle in degrees
                jiadu = angle;
                write_jiaodu(2,6,angle);        //顯示角度
                if((angle >= 3380) || (angle <= 220))          //北 N
                        write_string(2,0,"  N  ");        
                if((angle >= 230) && (angle <= 670))          //東 北
                        write_string(2,0," E N ");        
                if((angle >= 680) && (angle <= 1120))          //東 E
                        write_string(2,0,"  E  ");        
                if((angle >= 1130) && (angle <= 1570))          //東 南
                        write_string(2,0," E S ");        
                if((angle >= 1580) && (angle <= 2010))          //南  S
                        write_string(2,0,"  S  ");        
                if((angle >= 2020) && (angle <= 2460))          //西 南  
                        write_string(2,0," W S ");        
                if((angle >= 2470) && (angle <= 2910))          //西  W  
                        write_string(2,0,"  W  ");        
                if((angle >= 2920) && (angle <= 3360))          //西  北  
                        write_string(2,0," W N  ");        
                delay_1ms(300);
回復(fù)

使用道具 舉報(bào)

ID:204529 發(fā)表于 2017-5-24 22:37 | 顯示全部樓層
貌似這個(gè)程序不好用!
回復(fù)

使用道具 舉報(bào)

ID:229064 發(fā)表于 2017-9-12 19:55 | 顯示全部樓層
感謝 您對(duì)資源的分享。。。!
回復(fù)

使用道具 舉報(bào)

ID:225984 發(fā)表于 2018-3-31 11:27 | 顯示全部樓層
非常66666,正好用得到
回復(fù)

使用道具 舉報(bào)

ID:316962 發(fā)表于 2018-5-6 17:34 | 顯示全部樓層
為什么那個(gè)顯示的角度不會(huì)變呢
回復(fù)

使用道具 舉報(bào)

ID:326147 發(fā)表于 2018-5-9 18:12 | 顯示全部樓層
有用!
回復(fù)

使用道具 舉報(bào)

ID:63090 發(fā)表于 2020-4-12 13:58 | 顯示全部樓層
角度竟然是固定的18度,怎么轉(zhuǎn)動(dòng)傳感器都不會(huì)變啊,這程序有問(wèn)題啊
回復(fù)

使用道具 舉報(bào)

ID:348295 發(fā)表于 2020-5-11 16:50 | 顯示全部樓層
請(qǐng)問(wèn)我按上面程序載入,只顯示 18度,值不會(huì)變
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表