8051
#include
#include
#define uint unsigned int
#define uchar unsigned char
#define delay4us() {_nop_();_nop_();_nop_();_nop_();} //12MHZ 系统频率下,延时 4us
***it DQ = P1^7;
//***it FM=P2^4;
***it LCD_RS = P2^0;
***it LCD_RW = P2^1;
***it LCD_EN = P2^2;
uchar code Temp_Disp_title[]={"HC: LC: " }; //1602 液晶第一行显示内容宽度16个
uchar Current_Temp_Display_Buffer[]={"TEMP: "}; //1602 液晶第二行显示内容
uchar syp1=38;
uchar syp2=50;
uchar code df_Table[]={ 0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9 }; //温度小数位对照表
uchar CurrentT = 0; //当前读取的温度整数部分
uchar Temp_Value[]={0x00,0x00}; //从 DS18B20 读取的温度值
uchar Display_Digit[]={0,0,0,0}; //待显示的各温度数位
bit DS18B20_IS_OK = 1; //DS18B20 正常标志
void DelayXus(uint x) //延时 1
{
uchar i;
while(x--)
{
for(i=0;i<200;i++);
}
}
bit LCD_Busy_Check() //LCD 忙标志,返回值为 1602LCD 的忙标志位,为 1 表示忙--1.1.1.1
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delay4us();
result = (bit)(P0&0x80);
LCD_EN=0;
return result;
}
void Write_LCD_Command(uchar cmd) //1602LCD 写指令函数(位置)--1.1.1
{
while(LCD_Busy_Check());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delay4us();
LCD_EN = 1;
delay4us();
LCD_EN = 0;
}
void Write_LCD_Data(uchar dat) //1602LCD 写数据函数(内容)
{
while(LCD_Busy_Check());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delay4us();
LCD_EN = 1;
delay4us();
LCD_EN = 0;
}
void LCD_Initialise() //1602LCD 初始化--1.1.0
{
Write_LCD_Command(0x01);
DelayXus(5);
Write_LCD_Command(0x38);
DelayXus(5);
Write_LCD_Command(0x0c);
DelayXus(5);
Write_LCD_Command(0x06);
DelayXus(5);
}
void Set_LCD_POS(uchar pos) //1602LCD 设置显示位置
{
Write_LCD_Command(pos|0x80);
}
void Delay(uint x) //延时 2
{
while(x--);
}
//测温装置
uchar Init_DS18B20() //初始化(或者说复位)DS18B20
{
uchar status;
DQ = 1;
Delay(8);
DQ = 0;
Delay(90);
DQ = 1;
Delay(8);
status=DQ;Delay(100);
DQ = 1;
return status;
}
uchar ReadOneByte() //从 DS18B20 读一字节数据
{
uchar i,dat=0;
DQ = 1;
_nop_();
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
_nop_();
_nop_();
if(DQ)
dat |= 0X80;
Delay(30);
DQ = 1;
}
return dat;
}
void WriteOneByte(uchar dat) //从 DS18B20 写一字节数据
{
uchar i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat& 0x01;
Delay(5);
DQ = 1;
dat >>= 1;
}
}
void Read_Temperature() //从 DS18B20 读取温度值
{
if(Init_DS18B20()==1) //DS18B20 故障
DS18B20_IS_OK=0;
else
{
WriteOneByte(0xcc); //跳过序列号命令
WriteOneByte(0x44); //启动温度转换命令
Init_DS18B20(); //复位 DS18B20(每一次读写之前都要对 DS18B20 进行复位操作)
WriteOneByte(0xcc); //跳过序列号命令
WriteOneByte(0xbe); //读取温度寄存器
Temp_Value[0] = ReadOneByte(); //读取温度低 8 位(先读低字节,再读高字节,)
Temp_Value[1] = ReadOneByte();//读取温度高 8 位 (每次只能读一个字节)
DS18B20_IS_OK=1; //DS18B20 正常
}
}
void Display_Temperature() //在 1602LCD 上显示当前温度
{
///////////////////////////////////////////////温度换算
uchar i;
uchar t = 150, ng = 0; //延时值与负数标志
if((Temp_Value[1]&0xf8)==0xf8) //高字节高 5 位如果全为 1,则为负数,为负数时取反
{ //加 1,并设置负数标志为 1
Temp_Value[1] = ~Temp_Value[1];
Temp_Value[0] = ~Temp_Value[0]+1;
if(Temp_Value[0]==0x00) //若低字节进位,则高字节加 1
Temp_Value[1]++;
ng = 1; //设置负数标志为 1
}
Display_Digit[0] = df_Table[Temp_Value[0]&0x0f]; //查表得到温度小数部分
//获取温度整数部分(低字节低 4 位清零,高 4 位右移 4 位)+(高字节高 5 位清零,
//低三位左移 4 位)
CurrentT = ((Temp_Value[0]&0xf0)>>4) | ((Temp_Value[1]&0x07)<<4);
//将温度整数部分分解为 3 位待显示数字
Display_Digit[3] = CurrentT/100;
Display_Digit[2] = CurrentT%100/10;
Display_Digit[1] = CurrentT%10;
//刷新 LCD 缓冲 //加字符 0 是为了将待数字转化为字符显示
Current_Temp_Display_Buffer[11] = Display_Digit[0] + '0';
Current_Temp_Display_Buffer[10] = '.';
Current_Temp_Display_Buffer[9] = Display_Digit[1] + '0';
Current_Temp_Display_Buffer[8] = Display_Digit[2] + '0';
Current_Temp_Display_Buffer[7] = Display_Digit[3] + '0';
if(Display_Digit[3] == 0) //高位为 0 时不显示
Current_Temp_Display_Buffer[7] = ' ';
if(Display_Digit[2] == 0&&Display_Digit[3]==0) //高位为 0,且次高位为 0,则次高位不显示
Current_Temp_Display_Buffer[8] = ' ';
//负号显示在恰当位置
if(ng)
{
if(Current_Temp_Display_Buffer[8] == ' ')
Current_Temp_Display_Buffer[8] = '-';
else if(Current_Temp_Display_Buffer[7] == ' ')
Current_Temp_Display_Buffer[7] = '-';
else
Current_Temp_Display_Buffer[6] = '-';
}
/////////////////////////////////////////1602显示
Set_LCD_POS(0x00); //第一行显示标题,第一列
for(i=0;i<8;i++)
{
Write_LCD_Data(Temp_Disp_Title);
}
Set_LCD_POS(0x00+8); //第一行显示标题,第八列
for(i=8;i<16;i++)
{
Write_LCD_Data(Temp_Disp_Title);
}
Set_LCD_POS(0x04);
Write_LCD_Data(syp1/10+'0');
Set_LCD_POS(0x05);
Write_LCD_Data(syp1%10+'0');
Set_LCD_POS(0x0c);
Write_LCD_Data(syp2/10+'0');
Set_LCD_POS(0x0d);
Write_LCD_Data(syp2%10+'0');
Set_LCD_POS(0x40); //第二行显示当前温度
for(i=0;i<16;i++)
{
Write_LCD_Data(Current_Temp_Display_Buffer);
}
//显示温度符号
Set_LCD_POS(0x4c);
Write_LCD_Data(0x00);
Set_LCD_POS(0x4d);
Write_LCD_Data('C');
}
void large0() interrupt 0
{
syp1++;
if(syp1==99)
syp1=99;
}
void large1() interrupt 1
{
syp1--;
if(syp1==26)
syp1=26;
}
void main(void) //主函数--1.0.0
{
IT0=1;
EX0=1;
EA=1;
IT1=1;
EX1=1;
EA=1;
LCD_Initialise();//初始化1602
Read_Temperature();//从ds18b20 读取温度
Delay(50000);
Delay(50000);
while(1)
{
Read_Temperature();
//FM=0;
if(DS18B20_IS_OK)
Display_Temperature();//显示当前温度
DelayXus(100);
}
}
我想在原程序上加入外部中断来设置HC和LC的数值,但编译出现错位,不知如何修改。
"E:proteus86Proteus 8 ProfessionalToolsMAKERunTool.exe" --good-exits=0,1 --executable=C51.exe "..keshe1.c" ROM(SMALL) BROWSE DEBUG CODE OBJECTEXTEND PREPRINT OBJECT("keshe1.OBJ")
C51 COMPILER V9.00 - SN: Eval Version
COPYRIGHT KEIL ELEKTRONIK GmbH 1987 - 2009
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)
"E:proteus86Proteus 8 ProfessionalToolsMAKERunTool.exe" --good-exits=0,1 --executable=BL51.exe "keshe1.OBJ" TO "Debug.OMF"
BL51 BANKED LINKER/LOCATER V6.22 - SN: Eval Version
COPYRIGHT KEIL ELEKTRONIK GmbH 1987 - 2009
*** ERROR L121: IMPROPER FIXUP
MODULE: KESHE1.OBJ (KESHE1)
SEGMENT: ABSOLUTE
OFFSET: 0003H
*** ERROR L121: IMPROPER FIXUP
MODULE: KESHE1.OBJ (KESHE1)
SEGMENT: ABSOLUTE
make: *** [Debug.OMF] Error 1
OFFSET: 000BH
******************************************************************************
* RESTRICTED VERSION WITH 0800H BYTE CODE SIZE LIMIT; USED: 02EAH BYTE (36%) *
******************************************************************************
Program Size: data=28.2 xdata=0 code=1029
LINK/LOCATE RUN COMPLETE. 0 WARNING(S), 2 ERROR(S)
错误代码2
更多回帖