|
|
//-------------------------------------------------------------------------
//存在的問(wèn)題:數(shù)碼管無(wú)法顯示,無(wú)法接收到傳感器的數(shù)據(jù)。
//-------------------------------------------------------------------------
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define Nack_number 10
#define LCD P0
//**************端口定義**************************************************
uchar flag; //LCD控制線接口
sbit RS=P2^6; //RS 端
sbit RW=P2^5; // 讀寫端
sbit LCDE=P2^7; //使能端
//mlx90614 端口定義
sbit SCK=P3^7; // 時(shí)鐘線
sbit SDA=P3^6; // 數(shù)據(jù)線
sbit DPY1 = P2^2; //溫度顯示第 1 個(gè)數(shù)碼管段選
sbit DPY2 = P2^3; //溫度顯示第 2 個(gè)數(shù)碼管段選
sbit DPY3 = P2^4; //溫度顯示第 3 個(gè)數(shù)碼管段選
sbit row1 = P1^7; //矩陣鍵盤第 1 列
sbit row2 = P1^6; //矩陣鍵盤第 2 列
sbit row3 = P1^5; //矩陣鍵盤第 3 列
sbit cow1 = P1^3; //矩陣鍵盤第 1 行
sbit cow2 = P1^2; //矩陣鍵盤第 2 行
sbit cow3 = P1^1; //矩陣鍵盤第 3 行
//************數(shù)據(jù)定義****************************************************
bdata uchar flag1; //可位尋址數(shù)據(jù)
sbit bit_out=flag1^7;
sbit bit_in=flag1^0;
uchar tempH,tempL,err;
void CALTEMP(uint TEMP);
void ReadKey(void);
void initInt();
void delay1(uint z);
void show();
uchar key_num;
uchar mah[5];
/********數(shù)碼管碼值定義*******************************************************/
uchar code LED01[]={ //LED顯示代碼,0-9 共陽(yáng) 不帶小數(shù)點(diǎn)的
0xC0,0xF9,0xA4,0xB0,
0x99,0x92,0x82,0xF8,
0x80,0x90};
uchar code LED02[]={ //LED顯示代碼,0-9 共陽(yáng) 帶小數(shù)點(diǎn)的
0x40,0x79,0x24,0x30,
0x19,0x12,0x02,0x78,
0x00,0x10};
/**********全局變量定義******************************************************/
bit b20ms,b100ms; //定時(shí)標(biāo)志位
uchar c20ms,c100ms; //定時(shí)毫秒數(shù)
//************************** LCD1602 ***********************************
//向 LCD 寫入命令或數(shù)據(jù)*****************************************************
#define LCD_COMMAND 0 //命令
#define LCD_DATA 1 // 數(shù)據(jù)
#define LCD_CLEAR_SCREEN 0x01 // 清屏
#define LCD_HOMING 0x02 // 光標(biāo)返回原點(diǎn)
//設(shè)置顯示模式******* 0x08+ *********************************************
#define LCD_SHOW 0x04 //顯示開(kāi)
#define LCD_HIDE 0x00 //顯示關(guān)
#define LCD_CURSOR 0x02 //顯示光標(biāo)
#define LCD_NO_CURSOR 0x00 //無(wú)光標(biāo)
#define LCD_FLASH 0x01 //光標(biāo)閃動(dòng)
#define LCD_NO_FLASH 0x00 //光標(biāo)不閃動(dòng)
//設(shè)置輸入模式********** 0x04+ ********************************************
#define LCD_AC_UP 0x02 //光標(biāo)右移 AC+
#define LCD_AC_DOWN 0x00 //默認(rèn) 光標(biāo)左移 AC-
#define LCD_MOVE 0x01 //畫面可平移
#define LCD_NO_MOVE 0x00 //默認(rèn) 畫面不移動(dòng)
//************************** mlx90614 ***********************************
//command mode 命令模式
#define RamAccess 0x00 // 對(duì) RAM 操作
#define EepomAccess 0x20 // 對(duì) EEPRAM 操作
#define Mode 0x60 //進(jìn)入命令模式
#define ExitMode 0x61 //退出命令模式
#define ReadFlag 0xf0 //讀標(biāo)志
#define EnterSleep 0xff //進(jìn)入睡眠模式
//ram address read only RAM 地址(只讀)
#define AbmientTempAddr 0x03 //周圍溫度
#define IR1Addr 0x04
#define IR2Addr 0x05
#define LineAbmientTempAddr 0x06 //環(huán)境溫度
/*0x0000 0x4074 16500 0.01/單元
-40 125*/
#define LineObj1TempAddr 0x07 //目標(biāo)溫度,紅外溫度
/*0x27ad-0x7fff 0x3559 22610 0.02/單元
-70.01-382.19 0.01 452.2*/
#define LineObj2TempAddr 0x08
//eepom address EEPROM 地址
#define TObjMaxAddr 0x00 //測(cè)量范圍上限設(shè)定
#define TObjMinAddr 0x01 //測(cè)量范圍下限設(shè)定
#define PWMCtrlAddr 0x02 //PWM 設(shè)定
#define TaRangeAddr 0x03 //環(huán)境溫度設(shè)定
#define KeAddr 0x04 //頻率修正系數(shù)
#define ConfigAddr 0x05 //配置寄存器
#define SMbusAddr 0x0e //器件地址設(shè)定
#define Reserverd1Addr 0x0f //保留
#define Reserverd2Addr 0x19 // 保留
#define ID1Addr 0x1c //ID 地址 1
#define ID2Addr 0x1d //ID 地址 2
#define ID3Addr 0x1e //ID 地址 3
#define ID4Addr 0x1f //ID 地址 4
//************函數(shù)聲明*****************************************************
void start(); //MLX90614 發(fā)起始位子程序
void stop(); //MLX90614 發(fā)結(jié)束位子程序
uchar ReadByte(void); //MLX90614接收字節(jié)子程序
void send_bit(void); //MLX90614 發(fā)送位子程序
void SendByte(uchar number); //MLX90614 接收字節(jié)子程序
void read_bit(void); //MLX90614 接收位子程序
void delay(uint N); //延時(shí)程序
uint readtemp(void); //讀溫度數(shù)據(jù)
void init1602(void); //LCD 初始化子程序
void busy(void); //LCD 判斷忙子程序
void cmd_wrt(uchar cmd); //LCD 寫命令子程序
void dat_wrt(uchar dat); //LCD 寫數(shù)據(jù)子程序
void display(uint Tem); //顯示子程序
void Print(uchar *str); //字符串顯示程序
//*************主函數(shù)*******************************************
void main()
{
uint Tem; //溫度變量
initInt();
SCK=1;
SDA=1;
delay(4);
SCK=0;
delay(1000);
SCK=1;
init1602(); // 初始化 LCD
while(1)
{
while(b100ms) //每 100ms 掃描一次鍵盤
{
b100ms=0;
ReadKey();
}
if(key_num==1) //按下 1 鍵時(shí),進(jìn)行數(shù)碼管顯示
{
Tem=readtemp();
CALTEMP(Tem);
show();
}
if(key_num!=1) //液晶屏顯示
{
Tem=readtemp(); //讀取溫度
cmd_wrt(0x01); // 清屏
Print(" Temperature: "); //顯示字符串 Temperature: 且換行
display(Tem); //顯示溫度
Print(" ^C"); //顯示攝氏度
delay(100000); //延時(shí)再讀取溫度顯示
}
}
}
//------------------字符串顯示程序--------------------------
void Print(uchar *str) //字符串顯示程序
{
while(*str!='\0') //直到字符串結(jié)束
{
dat_wrt(*str); // 轉(zhuǎn)成 ASCII 碼
str++; //指向下一個(gè)字符
}
}
//--------------輸入轉(zhuǎn)換并顯示(用于 LCD1602)--------------------
void display(uint Tem)
{
uint T,a,b;
T=Tem*2;
if(T>=27315) //溫度為正
{
T=T-27315; //
a=T/100; //溫度整數(shù)
b=T-a*100; //溫度小數(shù)
if(a>=100) //溫度超過(guò) 100 度
{
dat_wrt(0x30+a/100); //顯示溫度百位
dat_wrt(0x30+a%100/10); //顯示溫度十位
dat_wrt(0x30+a%10); //顯示溫度個(gè)位
}
else if(a>=10) //溫度超過(guò) 10 度
{
dat_wrt(0x30+a%100/10); //顯示溫度十位
dat_wrt(0x30+a%10); //顯示溫度個(gè)位
}
else //溫度不超過(guò) 10 度
{
dat_wrt(0x30+a); //顯示溫度個(gè)位
}
dat_wrt(0x2e); //顯示小數(shù)點(diǎn)
if(b>=10) //溫度小數(shù)點(diǎn)后第 1 位數(shù)不等于 0
{
dat_wrt(0x30+b/10); //顯示溫度小數(shù)點(diǎn)后第 1 位數(shù)
dat_wrt(0x30+b%10); //顯示溫度小數(shù)點(diǎn)后第 2 位數(shù)
}
else //溫度小數(shù)點(diǎn)后第 1 位數(shù)等于 0
{
dat_wrt(0x30); //顯示溫度小數(shù)點(diǎn)后第 1 位數(shù) 0
dat_wrt(0x30+b); //顯示溫度小數(shù)點(diǎn)后第 2 位數(shù)
}
}
else //溫度為負(fù)
{
T=27315-T;
a=T/100;
b=T-a*100;
dat_wrt(0x2d); //顯示負(fù)號(hào)
if(a>=10) //溫度低于負(fù) 10 度
{
dat_wrt(0x30+a/10); //顯示溫度十位
dat_wrt(0x30+a%10); //顯示溫度個(gè)位
}
else //溫度高于負(fù) 10 度
{
dat_wrt(0x30+a); //顯示溫度個(gè)位
}
dat_wrt(0x2e); //顯示小數(shù)點(diǎn)
if(b>=10) //溫度小數(shù)點(diǎn)后第 1 位數(shù)不等于 0
{
dat_wrt(0x30+b/10); //顯示溫度小數(shù)點(diǎn)后第 1 位數(shù)
dat_wrt(0x30+b%10); //顯示溫度小數(shù)點(diǎn)后第 2 位數(shù)
}
else //溫度小數(shù)點(diǎn)后第 1 位數(shù)等于 0
{
dat_wrt(0x30); //顯示溫度小數(shù)點(diǎn)后第 1 位數(shù) 0
dat_wrt(0x30+b); //顯示溫度小數(shù)點(diǎn)后第 2 位數(shù)
}
}
}
//--------------------根據(jù)十六進(jìn)制計(jì)算溫度------------------------------
void CALTEMP(uint TEMP)
{
uint T;
uint a,b;
uchar A4,A5,A6,A7,A8;
T=TEMP*2;
if(T>=27315)
{
T=T-27315;
a=T/100;
b=T-a*100;
if(a>=100)
{
A4=a/100;
a=a%100;
A5=a/10;
a=a%10;
A6=a;
}
else if(a>=10)
{
A4=0;
A5=a/10;
a=a%10;
A6=a;
}
else
{
A4=0;
A5=0;
A6=a;
}
if(b>=10)
{
A7=b/10;
b=b%10;
A8=b;
}
else
{
A7=0;
A8=b;
}
}
else
{
T=27315-T;
a=T/100;
b=T-a*100;
A4=9;
if(a>=10)
{
A5=a/10;
a=a%10;
A6=a;
}
else
{
A5=0;
A6=a;
}
if(b>=10)
{
A7=b/10;
b=b%10;
A8=b;
}
else
{
A7=0;
A8=b;
}
}
mah[4]=A4;
mah[3]=A5;
mah[2]=A6;
mah[1]=A7;
mah[0]=A8;
}
//------------------------------
void start(void) //開(kāi)始條件是 SCK=1 時(shí),SDA 由 1 到 0
{
SCK=0;
delay(4);
SDA=1;
delay(4);
SCK=1;
delay(4);
SDA=0;
delay(4);
SCK=0;
delay(4);
}
//------------------------------
void stop(void) //停止條件是 SCK=1 時(shí),SDA 由 0 到 1
{
SCK=0;
delay(4);
SDA=0;
delay(4);
SCK=1;
delay(4);
SDA=1;
delay(4);
}
//---------發(fā)送一個(gè)字節(jié)---------
void SendByte(uchar number)
{
uchar i,n,dat;
n=Nack_number; //可以重發(fā)次數(shù)
Send_again:
dat=number;
for(i=0;i<8;i++) //8 位依次發(fā)送
{
if(dat&0x80) //取最高位
{
bit_out=1; // 發(fā) 1
}
else
{
bit_out=0; // 發(fā) 0
}
send_bit(); //發(fā)送一個(gè)位
dat=dat<<1; //左移一位
}
read_bit(); //接收 1 位 應(yīng)答信號(hào)
if(bit_in==1) //無(wú)應(yīng)答時(shí)重發(fā)
{
stop();
if(n!=0)
{
n--; //可以重發(fā) Nack_number=10 次
goto Repeat; // 重發(fā)
}
else
{
goto exit; // 退出
}
}
else
{
goto exit;
}
Repeat:
start(); //重新開(kāi)始
goto Send_again; // 重發(fā)
exit: ; // 退出
}
//-----------發(fā)送一個(gè)位---------
void send_bit(void)
{
if(bit_out==1)
{
SDA=1; // 發(fā) 1
}
else
{
SDA=0; // 發(fā) 0
}
_nop_();
SCK=1; // 上升沿
delay(4);delay(4);
SCK=0;
delay(4);delay(4);
}
//----------接收一個(gè)字節(jié)--------
uchar ReadByte(void)
{
uchar i,dat;
dat=0; // 初值為 0
for(i=0;i<8;i++)
{
dat=dat<<1; // 左移
read_bit(); //接收一位
if(bit_in==1)
{
dat=dat+1; // 為 1 時(shí)對(duì)應(yīng)位加 1
}
}
SDA=0; //發(fā)送應(yīng)答信號(hào) 0
send_bit();
return dat; //帶回接收數(shù)據(jù)
}
//----------接收一個(gè)位----------
void read_bit(void)
{
SDA=1; //數(shù)據(jù)端先置 1
bit_in=1;
SCK=1; // 上升沿
delay(4);delay(4);
bit_in=SDA; // 讀數(shù)據(jù)
_nop_();
SCK=0;
delay(4);delay(4);
}
//------------------------------
uint readtemp(void)
{
SCK=0;
start(); //開(kāi)始條件
SendByte(0x00); //發(fā)送從地址 00
SendByte(0x07); //發(fā)送命令
start(); //開(kāi)始條件
SendByte(0x01); //讀從地址 00
bit_out=0;
tempL=ReadByte(); //讀數(shù)據(jù)低字節(jié)
bit_out=0;
tempH=ReadByte(); //讀數(shù)據(jù)高字節(jié)
bit_out=1;
err=ReadByte(); //讀錯(cuò)誤信息碼
stop(); //停止條件
return(tempH*256+tempL);
}
//******************LCD 顯示子函數(shù)***********************
void init1602(void) //初始化 LCD
{
cmd_wrt(0x01); // 清屏
cmd_wrt(0x0c); //開(kāi)顯示,不顯示光標(biāo),不閃爍
cmd_wrt(0x06); //完成一個(gè)字符碼傳送后,光標(biāo)左移,顯 示不發(fā)生移位
cmd_wrt(0x38); //16 ×2 顯示,5×7 點(diǎn)陣,8 位數(shù)據(jù)接口
}
void busy(void) //LCD忙標(biāo)志判斷
{
flag=0x80; // 賦初值 高位為 1 禁止
while(flag&0x80) //讀寫操作使能位禁止時(shí)等待 繼續(xù)檢測(cè)
{
LCD=0xff;
RS=0; //指向地址計(jì)數(shù)器
RW=1; // 讀
LCDE=1; //信號(hào)下降沿有效
flag=LCD; //讀狀態(tài)位 高位為狀態(tài)
LCDE=0;
}
}
void cmd_wrt(uchar cmd) //寫命令子函數(shù)
{
LCDE=0;
busy(); //檢測(cè) 讀寫操作使能嗎
LCD=cmd; // 命令
RS=0; //指向命令計(jì)數(shù)器
RW=0; // 寫
LCDE=1; //高電平有效
LCDE=0;
}
void dat_wrt(uchar dat) //寫數(shù)據(jù)子函數(shù)
{
busy(); //檢測(cè) 讀寫操作使能嗎
LCDE=0;
if(flag==16)
{
RS=0; //指向指令寄存器
RW=0; // 寫
LCD=0XC0; //指向第二行
LCDE=1; //高電平有效
LCDE=0;
}
RS=1; //指向數(shù)據(jù)寄存器
RW=0; // 寫
LCD=dat; // 寫數(shù)據(jù)
LCDE=1; //高電平有效
LCDE=0;
}
//------------延時(shí)--------------
void delay(uint n)
{
uint j;
for(j=0;j<n;j++)
{
_nop_();
}
}
//------------定時(shí)器初始化函數(shù)----------------
void initInt()
{
TMOD = 0x10; // 定時(shí)器 1 方式 1
TH1=(65536-1000)/256; //定時(shí)器 1 設(shè)置 1ms 定時(shí)
TL1=(65536-1000)%256;
EA=1; //開(kāi)總中斷
ET1 = 1; //開(kāi)定時(shí)器 T1 中斷
TR1 = 1; //啟動(dòng)定時(shí)器 T1
}
//------------定時(shí)器中斷處理函數(shù)-------------------
void timer1handle() interrupt 3 //定時(shí)器 3 1ms 中斷
{
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
c20ms++;
c100ms++;
if(c20ms >= 20) //20ms 計(jì)時(shí)器
{
c20ms = 0;
b20ms = 1;
}
if(c100ms >= 50) //100ms 計(jì)時(shí)器
{
c100ms = 0;
b100ms = 1;
}
}
//--------------------------溫度顯示函數(shù)------------------------
void show()
{
DPY1=0;
LCD=LED01[mah[4]]; //轉(zhuǎn)換 8 位數(shù)顯示,不帶小數(shù)點(diǎn)的
delay1(2);
LCD=0xFF;
DPY1=1;
DPY2=0;
LCD=LED02[mah[3]]; //轉(zhuǎn)換 8 位數(shù)顯示,帶小數(shù)點(diǎn)的
delay1(2);
LCD=0xFF;
DPY1=0;
LCD=LED01[mah[2]]; //轉(zhuǎn)換 8 位數(shù)顯示,不帶小數(shù)點(diǎn)的
delay1(2);
LCD=0xFF;
DPY3=0;
DPY2=1;
DPY1=1;
LCD=LED01[mah[1]]; //轉(zhuǎn)換 8 位數(shù)顯示,不帶小數(shù)點(diǎn)的
delay1(2);
LCD=0xFF;
DPY1=0;
LCD=LED01[mah[0]]; //轉(zhuǎn)換 8 位數(shù)顯示,不帶小數(shù)點(diǎn)的
delay1(2);
LCD=0xFF;
DPY3=1;
DPY1=1;
}
void ReadKey(void)
{
row1=0; //矩陣鍵盤第 1 列,將第一列拉低,掃描是否有按鍵按下,第一列按鍵包 括:1,4,7
row2=1; //矩陣鍵盤第 2 列
row3=1; //矩陣鍵盤第 3 列
cow1=1; //矩陣鍵盤第 1 行
cow2=1; //矩陣鍵盤第 2 行
cow3=1; //矩陣鍵盤第 3 行
_nop_(); //延時(shí)函數(shù)
if(!(cow1&cow2&cow3)) //如果有鍵按下,就返回,且判斷是那個(gè)鍵值,否則繼續(xù)掃描下 一列
{
if(cow1==0)
key_num=1;
if(cow2==0)
key_num=4;
if(cow3==0)
key_num=7;
return;
}
row1=1; //矩陣鍵盤第 1 列,將第一列拉低,掃描是否有按鍵按下,第一列按鍵包 括:2,5,8
row2=0; //矩陣鍵盤第 2 列
row3=1; //矩陣鍵盤第 3 列
cow1=1; //矩陣鍵盤第 1 行
cow2=1; //矩陣鍵盤第 2 行
cow3=1; //矩陣鍵盤第 3 行
_nop_(); //延時(shí)函數(shù)
if(!(cow1&cow2&cow3)) //如果有鍵按下,就返回,且判斷是那個(gè)鍵值,否則繼續(xù)掃描下 一列
{
if(cow1==0)
key_num=2;
if(cow2==0)
key_num=5;
if(cow3==0)
key_num=8;
return;
}
row1=1; //矩陣鍵盤第 1 列,將第一列拉低,掃描是否有按鍵按下,第一列按鍵包 括:3,6
row2=1; //矩陣鍵盤第 2 列
row3=0; //矩陣鍵盤第 3 列
cow1=1; //矩陣鍵盤第 1 行
cow2=1; //矩陣鍵盤第 2 行
_nop_(); //延時(shí)函數(shù)
if(!(cow1&cow2)) //如果有鍵按下,就返回,且判斷是那個(gè)鍵值,否則繼續(xù)掃描下一列
{
if(cow1==0)
key_num=3;
if(cow2==0)
key_num=6;
return;
}
}
//--------------數(shù)碼管顯示延時(shí)函數(shù)-----------------------------------------------------
void delay1(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
|
|