電子羅盤源碼

/***************************************************************************************************

工程名稱: 1602 + GY-26

功能描述: 實現1602液晶顯示,液晶第一行顯示"角度",第二行顯示"模擬輸出電壓"。

硬件連接: 將1602液晶接口對應插接到P4接口,注意1-16腳不要插反(有些廠家的液晶順序是反的)。

維護記錄: 2012-06-07

***************************************************************************************************/

#include <pic.h> //頭文件在HI-TECH安裝目錄下\HI-TECH Software\PICC\std\9.60\include

#include <stdio.h>

#define uchar unsigned char

#define uint unsigned int

#define GY_26_ADDR 0xE0 //定義電子指南針器件地址(出廠默認為0XE0)

#define rs RD5 //命令/數據選擇

#define rw RD4 //讀寫口

#define e RD3 //鎖存控制

#define Dataport PORTB //數據口定義

void delay_20us(uint nus);

void mcu_init(void);

void nms_delay(uint nms);

uint get_GY_26(uchar read_begin_address,uchar GY_26_cmd);

void conversion(uint i);

//iic使用函數********************************

void iic_Start(void){SEN=1;while(SEN);} //啟動iic

void iic_Stop (void){PEN=1;while(PEN);} //停止iic

void iic_rest (void){RSEN=1;while(RSEN);} //重啟iic

void iic_Write8Bit(uchar x){SSPIF=0;SSPBUF=x;while(!SSPIF);SSPIF=0;}//向iic總線寫8bit數據

uchar iic_read8Bit(void){RCEN=1;while(!BF);ACKEN=1;while(ACKEN);return SSPBUF;}//向iic總線讀8bit數據

uchar dis1[16]={"Compass : 000.0 "}; //顯示兩行

uchar dis2[16]={"RC2 Out : ???? "};

/*********************************************

數據轉換,十六進制數據轉換成10進制

輸入十六進制範圍:0x0000-0x270f(0-9999)

結果分成個十百千位,以ascii存入顯示區

**********************************************/

void conversion(unsigned int i)

{

unsigned int j;

j=i;

PR2 = 0b10111110 ;

T2CON = 0b00000100 ;

CCP1CON = 0b00111100 ;

CCPR1L =(j/19)+1;

j=(((j/19)+1)*100)/38;

dis2[10]=j/100+0x30 ; // 電壓

j=j%100; //取餘數運算

dis2[11]=0x2E; //.(小數點)

dis2[12]=j/10+0x30 ;

j=j%10; //取餘數運算

dis2[13]=j+0x30;

dis2[15]=0x56; // V

dis1[10]=i/1000+0x30 ; // 角度

i=i%1000; //取餘數運算

dis1[11]=i/100+0x30 ;

i=i%100; //取餘數運算

dis1[12]=i/10+0x30 ;

i=i%10; //取餘數運算

dis1[13]=0x2E; //.(小數點)

dis1[14]=i+0x30;

dis1[15]=0xDF; //(度)

}

//****************************************************/

//**********************

//單片機初始化

//**************

void mcu_init(void)

{

TRISC=0xFF; //IIC通信引腳設為輸入

SSPSTAT = 0x80; //IIC設置

SSPCON = 0x38; //IIC設置

SSPCON2 = 0x00; //IIC設置

SSPADD = 50; //IIC設置

}

//延時大約20us***************************************

void delay_20us(uint nus)

{ uchar i;

while(--nus){

for(i=2;i>0;i--);

}

}

//延時大約1ms***************************************

void nms_delay(uint nms)

{

while(nms--)

delay_20us(50);

}

//********************

//從IIC總線獲得電子指南針GY-26數據********************

//從開始地址連續讀出兩個8bit的值,併合成16bit數據

//********************

uint get_GY_26(uchar read_begin_address,uchar GY_26_cmd)

{

unsigned int temp;

iic_Start(); //iic啟動時序

iic_Write8Bit(GY_26_ADDR); //寫指南針器件地址

iic_Write8Bit(0); //寫命令

iic_Write8Bit(GY_26_cmd); //寫指南針命令

iic_Stop(); //iic寫停止時序

nms_delay(55); //延時,可執行其他程序

iic_Start(); //iic啟動時序

ACKDT = 0; //允許應答ACK

iic_Write8Bit(GY_26_ADDR); //寫指南針器件地址

iic_Write8Bit(read_begin_address); //寫指南針內部數據地址

iic_rest(); //iic重啟時序

iic_Write8Bit(GY_26_ADDR+1); //指南針器件地址+1=讀

temp=iic_read8Bit(); //讀出8位數據

temp<<=8; //保存數據

ACKDT = 1; //允許應答NO_ACK

temp+=iic_read8Bit(); //讀出8位數據

iic_Stop(); //發送停止時序

return temp; //返回本次測量數值

}

//***********************************************************************************

//延時

//***********************************************************************************

void delay(uint time)

{

uint i,j;

for(i = 0;i < time; i++);

{

for(j = 0;j <30; j++);

}

}

//***********************************************************************************

//IO初始化操作

//***********************************************************************************

void IO_init(void)

{


TRISA=0xfC; //設置RA0與RA1輸出

PORTA=0xff; //設置RA0與RA1初始化數據為高電平

TRISC=0x00; //RC設置為輸入

PORTC=0xff; //初始化為高

TRISB=0x00; //RB設置為輸出 LCD IO

PORTB=0xff; //初始化為高 LCD IO

TRISD=0x00; //RD設置為輸出 LCD command

PORTD=0xff; //初始化為高 LCD command

}

//**************************************************************************************************

//向LCD寫一命令

//**************************************************************************************************

wcode(uchar t)

{

rs=0; // 寫的是命令

rw=0; // 寫狀態

e=1; //使能

Dataport=t; //寫入命令

delay(40); //等待寫入,如果時間太短,會導致液晶無法顯示

e=0; //數據的鎖定

}

//**************************************************************************************************

//向LCD寫一數據

//**************************************************************************************************

wdata(uchar t)

{

rs=1; // 寫的是數據

rw=0; // 寫狀態

e=1; //使能

Dataport=t; //寫入數據

delay(40); //等待寫入,如果時間太短,會導致液晶無法顯示

e=0; //數據的鎖定

}

//**************************************************************************************************

//LCD顯示第一行

//**************************************************************************************************

xian1()

{

uchar i;

wcode(0x80); //設置第一行顯示地址

for(i=0;i<16;i++) //循環16次,寫完1行

{

wdata(dis1[i]); //寫入該行數據

}

}

//**************************************************************************************************

//LCD顯示第二行

//**************************************************************************************************

xian2()

{

uchar i;

wcode(0xc0); //設置第二行顯示地址

for(i=0;i<16;i++) //循環16次,寫完1行

{

wdata(dis2[i]); //寫入該行數據

}

}

//**************************************************************************************************

//LCD 初始化

//**************************************************************************************************

InitLCD()

{

wcode(0x01); //清屏

wcode(0x06); //輸入方式控制,增量光標不移位

wcode(0x0e); //顯示開關控制

wcode(0x38); //功能設定:設置16x2顯示,5x7顯示,8位數據接口

}

//**************************************************************************************************

//主函數

//**************************************************************************************************

main()

{

//uchar i;

__CONFIG(XT&WDTDIS&LVPDIS);//配置,設置為晶振XT方式振蕩,禁看門狗,禁低電壓編程

mcu_init(); //晶片初始化

IO_init(); //IO初始化

InitLCD(); //初始化1602

while(1) //進入while死循環

{

unsigned int CMP_DATA;

CMP_DATA=get_GY_26(1,0x31); //讀取角度

conversion(CMP_DATA); //數據轉換出個,十,百,千 位

xian1(); //顯示 第1行刷新

xian2(); //顯示 第2行刷新

delay(1000);

}

}