電子羅盤源碼


/***************************************************************************************************    
工程名稱:  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);

       }
}

Ċ
Kim Chen,
2012年5月26日 上午5:46
ċ
完整源碼.c
(8k)
Kim Chen,
2012年6月6日 下午9:30
Comments