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