#include <iom128v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#define DS18B20 PF0
#define RESOLU_9 0X1F //即分别对应config 中的R1 R0=00 01 10 11
#define RESOLU_10 0X3F
#define RESOLU_11 0X5F
#define RESOLU_12 0X7F
#define RD_ROM 0X33 //总线上只有一个设备时才可能使用该命令
#define MATCH_ROM 0X55
#define SKIP_ROM 0XCC
#define SEARCH_ROM 0XF0
#define ALARM_ROM 0XEC
#define TEMP_TRANS 0X44 //启动温度转换
#define RD_SCRATCHPAD 0XBE //从暂存存储器中读字节(9字节)从字节0开始,可由复位中断读
#define WR_SCRATCHPAD 0X4E //写数值到暂存存储器地址2和3(TH,TL温度触发器)
#define COPY_SCRATCHPAD 0X48 //将暂存存储器中数值调入E2中(仅地址2、3:TH,TL高低温触发)
#define RECALL_E2 0XB8 //将非易失性存储器中的数值重新调入暂存存储器
#define RD_POWER 0XB4 //发18B20电源方式的信号到主机
/******************************************************************
- 功能描述:延时函数
- 隶属模块:延时
- 函数属性:外部,供用户使用
- 参数说明:us:us级的延时
- 返回说明:无
- 注:无
******************************************************************/
void delay_us(uint us)
{
uint i;
us = us*5/4; //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值
for(i=0; i<us; i++);
}
/******************************************************************
- 功能描述:延时函数
- 隶属模块:延时
- 函数属性:外部,供用户使用
- 参数说明:ms:ms级的延时
- 返回说明:无
- 注:无
******************************************************************/
void delay(uint ms)
{
uint i,j;
for(i=0; i<ms; i++)
for(j=0; j<1141; j++);
}
/******************************************************************
- 功能描述:18b20的初始化
- 隶属模块:18b20
- 函数属性:内部
- 参数说明:无
- 返回说明:无
- 注:无
******************************************************************/
void _18B20_Init(void)
{
DDRF |= BIT(DS18B20);
PORTF &= ~BIT(DS18B20); //主机(Master Tx)发送复位脉冲
delay_us(600); //拉低至少480us
PORTF |= BIT(DS18B20);
delay_us(40); //18B20等待15-60us再响应主机复位脉冲发存在脉冲
DDRF &= ~BIT(DS18B20); //配置为输入,等待18B20发主机发存在脉冲
while(PINF & BIT(DS18B20)); //等待18B20拉低总线(ds18b20 Tx)
delay_us(150);
while(!(PINF & BIT(DS18B20))); ////等待18B20释放总线
DDRF |= BIT(DS18B20);
}
/******************************************************************
- 功能描述:18b20的写入字节
- 隶属模块:18b20
- 函数属性:内部
- 参数说明:DaCmd为要写入的字节
- 返回说明:无
- 注:无
******************************************************************/
void Write_18B20(uchar DaCmd) //所有写时间片操作至少需要60us
{
uchar i = 0;
for(i=0; i<8; i++)
{
DDRF |= BIT(DS18B20); //配置为输出
PORTF &= ~BIT(DS18B20); //拉低总线,启动写数据位
delay_us(2); //每个独立的写周期都要1us的恢复时间
if(DaCmd & 0x01)
PORTF |= BIT(DS18B20); //DQ线拉低后15-60us,18b20对总线采样
else //总线为高则写1操作,为低则写0操作
PORTF &= ~BIT(DS18B20);
delay_us(60);
PORTF |= BIT(DS18B20); //释放总线
DaCmd >>= 1;
}
delay_us(50);
}
/******************************************************************
- 功能描述:18b20的读出字节
- 隶属模块:18b20
- 函数属性:内部
- 参数说明:无
- 返回说明:返回读出的字节
- 注:无
******************************************************************/
uchar Read_18B20(void)
{
uchar i = 0;
uchar recByte = 0;
for(i=0; i<8; i++)
{
recByte >>= 1;
DDRF |= BIT(DS18B20); //配置为输出
PORTF &= ~BIT(DS18B20); //主机拉低总线,启起读操作
//delay_us(1); //不能有延时
PORTF |= BIT(DS18B20);
delay_us(5);
DDRF &= ~BIT(DS18B20); //配置为输入,开始读取数据位
if(PINF & BIT(DS18B20))
recByte |= 0x80;
delay_us(60);
}
return recByte;
}
/******************************************************************
- 功能描述:18b20的分辨率调整
- 隶属模块:18b20
- 函数属性:外部
- 参数说明:RESOLU_9;RESOLU_10;RESOLU_11;RESOLU_12(对应9--12位分辨率)
- 返回说明:无
- 注:无
******************************************************************/
void Adjust_Resolu(uchar resolu) //调整分辨率resolu:0x1f,0x3f,0x5f,0x7f
{ //分别对应0.5c,0.25,0.125,0.0625
_18B20_Init();
Write_18B20(SKIP_ROM);
Write_18B20(WR_SCRATCHPAD);
Write_18B20(0x44); //设置TH
Write_18B20(0x86); //设置TL
Write_18B20(resolu); //设置配置寄存器R1 R0=01(分辨率10bit)
_18B20_Init();
Write_18B20(SKIP_ROM);
Write_18B20(COPY_SCRATCHPAD);
}
/******************************************************************
- 功能描述:18b20的读出温度
- 隶属模块:18b20
- 函数属性:外部
- 参数说明:无
- 返回说明:Temp_H:返回温度的16进制
- 注:g_TH, g_TL存放返回温度16进制的高低字节
******************************************************************/
uchar g_TH, g_TL; //全局变量
uint Convert_T(void)
{
uint Temp_H = 0; //定义为无符整型(16bit),最后用于存放温度
uchar Temp_L = 0;
uchar inter = 0;
uchar decim =0;
uchar i = 0;
_18B20_Init();
Write_18B20(SKIP_ROM); //单点总线,选择跳过ROM检测
Write_18B20(TEMP_TRANS);
delay(800); //温度转换需要750ms的时间,不然每次读的是上次值
_18B20_Init();
Write_18B20(SKIP_ROM);
Write_18B20(RD_SCRATCHPAD);
Temp_L = Read_18B20(); //该字节的低4位是温度的小数部分
Temp_H = Read_18B20(); //该字节的高5位是符号位,为0是表正温度,为1时为负
g_TH = Read_18B20(); //温度上限和下限,用于报警
g_TL = Read_18B20();
Temp_H =(Temp_H<<8) | (Temp_L); //转化为16位数据
return Temp_H;
}
/******************************************************************
- 功能描述:18b20的扩展性功能模块
- 隶属模块:18b20
- 函数属性:外部
- 参数说明:带入温度的16进制
- 返回说明:neg_flag:为负温度标志位
- 注:可以判断温度正负并转换为ACS码
******************************************************************/
uchar g_temperature[5]; //全局数组,用来存放温度
uchar Split_temp(uint temp_val)
{
uchar inter = 0;
uchar decim = 0;
uchar neg_flag = 0; //负数标记
if((temp_val) & (0xF000))
{
temp_val = ~temp_val+1;
neg_flag = 1; //表明为负温度
}
else
{
neg_flag = 0;
}
inter = (uchar)(temp_val*0.0625); //取整数部分
decim = (uchar)(temp_val & 0xf)*0.625; //10位分辨率bit0,bit1未定义,权值为0
//扩大10倍,后取整,保留一位小数,有强制转换float->char
if(inter >= 100)
inter = 0;
g_temperature[0] = inter/10 +'0';
g_temperature[1] = inter%10 +'0';
g_temperature[2] = '.';
g_temperature[3] = decim +'0';
return neg_flag;
}
/******************************************************************
- 功能描述:向LCD中写入命令
- 隶属模块:LCD模块
- 函数属性:外部,供用户使用
- 参数说明:com:为命令控制字
- 返回说明:实现向LCD中写入控制命令
- 注:无
******************************************************************/
void write_com(uchar com)
{
PORTB&=~BIT(0); //RS
PORTB&=~BIT(1); //RW
PORTD=com;
PORTB|=BIT(2); //EN
delay(1);
PORTB&=~BIT(2); //EN
}
/******************************************************************
- 功能描述:向LCD中写入数据
- 隶属模块:LCD模块
- 函数属性:外部,供用户使用
- 参数说明:dat:为写入的数据
- 返回说明:实现向LCD中写入数据
- 注:无
******************************************************************/
void write_dat(uchar dat)
{
PORTB|=BIT(0); //RS
PORTB&=~BIT(1); //RW
PORTD=dat;
PORTB|=BIT(2); //EN
delay(1);
PORTB&=~BIT(2); //EN
}
/******************************************************************
- 功能描述:LCD初始化
- 隶属模块:LCD模块
- 函数属性:内部
- 参数说明:无
- 返回说明:实现LCD的初始化
- 注:无
******************************************************************/
void lcd_Init() //lcd初始化
{
DDRD=0XFF; //数据端
DDRB|=BIT(0)|BIT(1)|BIT(2); //控制端 RS RW EN
PORTB&=~BIT(2);
write_com(0X30);
delay(1);
write_com(0X01);
delay(1);
write_com(0X0C);
delay(1);
write_com(0X06); //如果为07且write_com(0X18)。。显示为右到左的现实直到消失,如果为06且write_com(0X18)为右到左显示
//07表示右边到左边显示出来。。06为光标处出现
}
void main()
{
uchar i;
uint Temperature,Tem;
lcd_Init(); //液晶初始化
Adjust_Resolu(RESOLU_11);
while(1)
{
Temperature=(Convert_T()); //除以100保留小数点后2位,符合18b20的10位精度
Tem=Temperature*6.25;
g_temperature[4]=Tem/1000+'0';
g_temperature[3]=Tem%1000/100+'0';
g_temperature[2]='.';
g_temperature[1]=Tem%100/10+'0';
g_temperature[0]=Tem%10+'0';
write_com(0X80);
delay(1);
write_dat(g_temperature[4]);
delay(1);
write_dat(g_temperature[3]);
delay(1);
write_dat(g_temperature[2]);
delay(1);
write_dat(g_temperature[1]);
delay(1);
write_dat(g_temperature[0]);
delay(1);
}
}
|