|
HMC5883L電子指南針
完整的單片機源程序下載:
2014年6月7日 指南針 1602.rar
(45.92 KB, 下載次數: 187)
2016-12-19 21:17 上傳
點擊文件名下載附件
HMC5883L 下載積分: 黑幣 -5
預覽:
- #include <reg52.h> //調用單片機頭文件
- #define uchar unsigned char //無符號字符型 宏定義 變量范圍0~255
- #define uint unsigned int //無符號整型 宏定義 變量范圍0~65535
- #include <math.h> //Keil library
- #include <stdio.h> //Keil library
- #include <INTRINS.H>
- sbit rs=P2^3; //寄存器選擇信號 H:數據寄存器 L:指令寄存器
- sbit rw=P2^4; //寄存器選擇信號 H:數據寄存器 L:指令寄存器
- sbit e =P2^5; //片選信號 下降沿觸發
- sbit SCL=P1^1; //IIC時鐘引腳定義
- sbit SDA=P1^0; //IIC數據引腳定義
- #define SlaveAddress 0x3C //定義器件在IIC總線中的從地址
- uchar BUF[8]; //接收數據緩存區
- uchar ge,shi,bai,qian,wan; //顯示變量
- int dis_data; //變量
- /******************1ms 延時函數*******************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<120;j++);
- }
- /***********************延時函數************************/
- void delay_uint(uint q)
- {
- while(q--);
- }
- /**************************************
- 延時5微秒(STC90C52RC@12M)
- 不同的工作環境,需要調整此函數,注意時鐘過快時需要修改
- 當改用1T的MCU時,請調整此延時函數
- **************************************/
- void Delay5us()
- {
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- }
- /***********************lcd1602寫命令函數************************/
- void write_com(uchar com)
- {
- e=0;
- rs=0;
- rw=0;
- P0=com;
- delay_uint(3);
- e=1;
- delay_uint(25);
- e=0;
- }
- /***********************lcd1602寫數據函數************************/
- void write_data(uchar dat)
- {
- e=0;
- rs=1;
- rw=0;
- P0=dat;
- delay_uint(3);
- e=1;
- delay_uint(25);
- e=0;
- }
- /***********************lcd1602上顯示特定的字符************************/
- void write_zifu(uchar hang,uchar add,uchar date)
- {
- if(hang==1)
- write_com(0x80+add);
- else
- write_com(0x80+0x40+add);
- write_data(date);
- }
- /***********************lcd1602上顯示這字符函數************************/
- void write_string(uchar hang,uchar add,uchar *p)
- {
- if(hang==1)
- write_com(0x80+add);
- else
- write_com(0x80+0x40+add);
- while(1)
- {
- if(*p == '\0') break;
- write_data(*p);
- p++;
- }
- }
- /***********************lcd1602初始化設置************************/
- void init_1602() //lcd1602初始化設置
- {
- write_com(0x38); //
- write_com(0x0c);
- write_com(0x06);
- delay_uint(1000);
- write_string(1,0," zhi nan zhen ");
- write_string(2,0," ");
- write_zifu(2,11,0xdf); //顯示度
- }
- /***********************lcd1602上顯示兩位十進制數************************/
- void write_jiaodu(uchar hang,uchar add,uint date)
- {
- if(hang==1)
- write_com(0x80+add);
- else
- write_com(0x80+0x40+add);
- write_data(0x30+date/1000%10);
- write_data(0x30+date/100%10);
- write_data(0x30+date/10%10);
- write_data('.');
- write_data(0x30+date%10);
- }
- /**************************************
- 起始信號
- **************************************/
- void HMC5883_Start()
- {
- SDA = 1; //拉高數據線
- Delay5us(); //延時
- SDA = 0; //產生下降沿
- Delay5us(); //延時
- SCL = 0; //拉低時鐘線
- }
- /**************************************
- 停止信號
- **************************************/
- void HMC5883_Stop()
- {
- SDA = 0; //拉低數據線
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- SDA = 1; //產生上升沿
- Delay5us(); //延時
- }
- /**************************************
- 發送應答信號
- 入口參數:ack (0:ACK 1:NAK)
- **************************************/
- void HMC5883_SendACK(bit ack)
- {
- SDA = ack; //寫應答信號
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- }
- /**************************************
- 接收應答信號
- **************************************/
- bit HMC5883_RecvACK()
- {
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- CY = SDA; //讀應答信號
- SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- return CY;
- }
- /**************************************
- 向IIC總線發送一個字節數據
- **************************************/
- void HMC5883_SendByte(uchar dat)
- {
- uchar i;
- for (i=0; i<8; i++) //8位計數器
- {
- dat <<= 1; //移出數據的最高位
- SDA = CY; //送數據口
- SCL = 0; //拉高時鐘線
- Delay5us(); //延時
- SCL = 1; //拉低時鐘線
- Delay5us(); //延時
- }
- HMC5883_RecvACK();
- }
- /**************************************
- 從IIC總線接收一個字節數據
- **************************************/
- uchar HMC5883_RecvByte()
- {
- uchar i;
- uchar dat = 0;
- SDA = 1; //使能內部上拉,準備讀取數據,
- for (i=0; i<8; i++) //8位計數器
- {
- dat <<= 1;
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- dat |= SDA; //讀數據
- SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- }
- return dat;
- }
- //***************************************************
- void Single_Write_HMC5883(uchar REG_Address,uchar REG_data)
- {
- HMC5883_SendByte(SlaveAddress); //發送設備地址+寫信號
- HMC5883_SendByte(REG_Address); //內部寄存器地址,請參考中文pdf
- HMC5883_SendByte(REG_data); //內部寄存器數據,請參考中文pdf
- }
- //******************************************************
- //
- //連續讀出HMC5883內部角度數據,地址范圍0x3~0x8
- //
- //******************************************************
- void Multiple_read_HMC5883(void)
- { uchar i;
- HMC5883_Start(); //起始信號
- HMC5883_SendByte(SlaveAddress); //發送設備地址+寫信號
- HMC5883_SendByte(0x03); //發送存儲單元地址,從0x3開始
- HMC5883_Start(); //起始信號
- HMC5883_SendByte(SlaveAddress+1); //發送設備地址+讀信號
- for (i=0; i<6; i++) //連續讀取6個地址數據,存儲中BUF
- {
- BUF[i] = HMC5883_RecvByte(); //BUF[0]存儲數據
- if (i == 5)
- {
- HMC5883_SendACK(0); //最后一個數據需要回NOACK
- }
- else
- {
- HMC5883_SendACK(1); //回應ACK
- }
- }
- delay_1ms(5);
- }
- //初始化HMC5883,根據需要請參考pdf進行修改****
- void Init_HMC5883()
- {
- Single_Write_HMC5883(0x02,0x00); //
- }
- /*****************主函數********************/
- void main()
- {
- int x,y,z,jiadu;
- double angle;
- P0 = P1 = P2 = P3 = 0xff; //單片機IO口初始化為1
- Init_HMC5883();
- init_1602(); //lcd1602初始化
- while(1)
- {
- Multiple_read_HMC5883(); //連續讀出數據,存儲在BUF中
- //---------顯示X軸
- x=BUF[0] << 8 | BUF[2]; //Combine MSB and LSB of X Data output register
- z=BUF[2] << 8 | BUF[4]; //Combine MSB and LSB of Z Data output register
-
- 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);
- }
- }
復制代碼
|
|