📄 18b20.c
字号:
/***********************************************
**** DS18B20温度采集,LCD1602B显示 ***
**** MCU : Atmeag16 ***
**** 作者: XueTwins ***
**** 时间 20007.02.17 ***
注:DS18B20的数据口接PA0
***********************************************/
#include <iom16v.h>
#include <macros.h>
/*******************************************************************************
定义MCU与LCD的接口
接线:EN-PD3、RS-PD2、DATA-PD4,5,6,7
*******************************************************************************/
#define LCD_EN_PORT PORTD //PD3使能LCD
#define LCD_RS_PORT PORTD //PD2
#define LCD_DATA_PORT PORTD
#define LCD_EN 0x08 //PD3 out
#define LCD_RS 0x02 //PD2 out
#define LCD_DATA 0xF0 //PD4,5,6,7
/*******************************************************************************
函数原型声明
*******************************************************************************/
void LCD_init(void);//LCD初始化
void LCD_en_write(void);//LCD写
void LCD_set_xy(unsigned char x,unsigned char y);//写X,Y地址
void LCD_write_string(unsigned char x,unsigned char y,unsigned char *string);
void LCD_write_char(unsigned command,unsigned data);
void LCD_write_data_variable(unsigned char x,unsigned char y,
unsigned char Z,unsigned long S);
/*******************************************************************************
延时函数
系统时钟:8M
*******************************************************************************/
void delay_1us(void) //1us延时函数
{
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
void delay_nus(unsigned int n) //N us延时函数
{
unsigned int i=0;
for (i=0;i<n;i++)
delay_1us();
}
void delay_1ms(void) //1ms延时函数
{
unsigned int i;
for (i=0;i<1142;i++);
}
void delay(unsigned int n) //N ms延时函数
{
unsigned int i=0;
for (i=0;i<n;i++)
delay_1ms();
}
/*******************************************************************************
上面声明各函数的实现
*******************************************************************************/
void LCD_init(void)
{
LCD_write_char(0x28,0);
LCD_en_write();
delay(15);//延时15ms
LCD_write_char(0x28,0);//四位数据接口,二行显示,5*7点阵字符
LCD_write_char(0x0C,0);//显示开
LCD_write_char(0x01,0);//清屏
delay(2);
LCD_write_char(0x06,0);//显示光标移动设置
}
void LCD_en_write(void)//液晶使能
{
LCD_EN_PORT|=LCD_EN;
delay(1);
LCD_EN_PORT&=~LCD_EN;
}
/*******************************************************************************
写数据
*******************************************************************************/
void LCD_write_char(unsigned command,unsigned data)
{
unsigned command_temp,data_temp;
command_temp=command;
data_temp=data;
delay(16);
if(command==0)
{
LCD_RS_PORT|=LCD_RS; //RS=1
LCD_DATA_PORT&=0X0f;
LCD_DATA_PORT|=data_temp&0xf0; //写高四位
LCD_en_write();
data_temp=data_temp<<4;
LCD_DATA_PORT&=0X0f;
LCD_DATA_PORT|=data_temp&0xf0; //写低四位
LCD_en_write();
}
else
{
LCD_RS_PORT&=~LCD_RS; //RS=0
LCD_DATA_PORT&=0X0f;
LCD_DATA_PORT|=command_temp&0xf0; //写高四位
LCD_en_write();
command_temp=command_temp<<4;
LCD_DATA_PORT&=0x0f;
LCD_DATA_PORT|=command_temp&0xf0; //写低四位
LCD_en_write();
}
}
/*******************************************************************************
写地址
//设置LCD显示的起始位置,显示字符串的位置,X:0-15,Y:0-1
// LCD第一行显示寄存器地址:0X80-0X8F
// LCD第一行显示寄存器地址:0XC0-0XCF
*******************************************************************************/
void LCD_set_xy(unsigned char x,unsigned char y)
{
unsigned char address;
if(y==0)
address=0x80 + x;
else //即y==1
address=0xC0 + x;
LCD_write_char(address,0);
}
/*******************************************************************************
英文字符串显示函数
*******************************************************************************/
void LCD_write_string(unsigned char x,unsigned char y,unsigned char *string)
{
LCD_set_xy(x,y);//写地址
while (*string) // 写显示字符
{
LCD_write_char(0,*string);
string ++;
}
}
/*******************************************************************************
显示数字变量函数
Z为S变量共几位数 //最大变量显示为99999;
*******************************************************************************/
void LCD_write_data_variable(unsigned char x,unsigned char y,
unsigned char Z,unsigned long S)
{
unsigned char k;
unsigned char p[6]="0";
unsigned char i=0;
LCD_set_xy( x, y );
for(i=0;i<Z;i++)
{
p[i]=S%10;
S=S/10;
}
while(!(p[i]))
{
if(i==0)
{
LCD_write_char( 0, 0x30 );
i--;
}
else
{
i--;
LCD_write_char( 0, 0x80 );
}
}
for(;i<255;i--)
{
LCD_write_char( 0, p[i]+0x30 );
}
}
///////////////////////数字温度传感器////////////////////////////////////
////////////////////////DS18B20//////////////////////////////////////////
#define DS18B20_PORT PORTA
#define DS18B20_DDR DDRA
#define DS18B20_PIN PINA
#define DS18B2_IO BIT(0)//0x01
/*******************************************************************************
函数原型声明
*******************************************************************************/
unsigned char DS18B20_reset(void); // 复位程序
unsigned char DS18B20_read(void); //从单总线读1字节
void DS18B20_write(unsigned char CMD); //向单总线写1字节
long count;
/*******************************************************************************
复位程序
检查DS18B20是否存在:不存在返回1,存在返回0
*******************************************************************************/
unsigned char DS18B20_reset(void)
{
unsigned char online;
DS18B20_DDR |= DS18B2_IO; //PORTA.0输出
DS18B20_PORT &=~DS18B2_IO; //PORTA&=0xFE;//输出低电平
delay_nus(500); //480us~960us
DS18B20_PORT |=DS18B2_IO; //输出高电平
DS18B20_DDR &=~DS18B2_IO; //PORTA.0输入
delay_nus(45); //16-60us等待响应
online=DS18B20_PORT & DS18B2_IO;//响应信号,读出online的值
delay_nus(100); //60-240us
return (online);
}
/*******************************************************************************
从DS18B20读1字节数据(从单总线读1字节)
*******************************************************************************/
unsigned char DS18B20_read(void)
{
unsigned char i,temp;
unsigned char byte=0;//byte=0x00;
for(i=0;i<8;i++)
{
DS18B20_DDR|=DS18B2_IO; //PORTA.0输出
DS18B20_PORT&=~DS18B2_IO; //PORTA&=0xFE;//输出低电平,产生读起始信号
delay_nus(3); //延时1us~15us
DS18B20_PORT|=DS18B2_IO; //输出高电平
DS18B20_DDR&=~DS18B2_IO; //PORTA.0输入,接收数据
delay_nus(10); //要在15us内完成读数
temp=(DS18B20_PIN & DS18B2_IO);//读数据,从低位开始
if(temp!=0x00)
byte|=0x80;
if(i<7)
byte=byte>>1;
delay_nus(100); //60~120us
DS18B20_DDR|=DS18B2_IO; //PORTA.0输出
delay_nus(5);
}
return byte;
}
/*******************************************************************************
写ROM或存储器命令到DS18B20(向单总线写1字节)
*******************************************************************************/
void DS18B20_write(unsigned char CMD)
{
unsigned char i,value;
DS18B20_DDR|=DS18B2_IO; //PORTA.0输出
for(i=0;i<8;i++)
{
value=CMD&DS18B2_IO;
if(value==0x01)
{
delay_nus(1); //延时>1us
DS18B20_PORT&=~DS18B2_IO; //产生写起始信号
delay_nus(10); //延时1us~15us
DS18B20_PORT|=DS18B2_IO; //数据线电平拉高
delay_nus(100); //延时60us~120us
}
else
{
delay_nus(1); //延时>1us
DS18B20_PORT&=~DS18B2_IO; //产生写起始信号
delay_nus(100); //18B20采样要60us到120us
DS18B20_PORT|=DS18B2_IO; //数据线电平拉高
delay_nus(10);
}
CMD=CMD>>1; //右移一位
}
}
/*******************************************************************************
主函数
*******************************************************************************/
void main(void)
{
unsigned char i,temh,teml;
unsigned char errortrue;
DDRD|=LCD_EN | LCD_RS | LCD_DATA;//EN方向,RS方向,数据口方向为输出
LCD_EN_PORT &= ~LCD_EN; //EN=0
LCD_init(); //液晶初始化
delay_nus(2000);
OSCCAL=0X9d; //系统时钟校准,不同的芯片和不同的频率,
WDR(); //看门狗计数清零
WDTCR=0x0F;
for(;;)
{
LCD_write_char(0x01,0);//清屏
errortrue=DS18B20_reset(); //复位18b20
if(errortrue==0x01)
{
LCD_write_string(0,1,"wrong"); //初始化失败
}
else
{
LCD_write_string(0,0,"Temperature:");//初始化成功
}
DS18B20_write(0xcc); // 发出转换命令
DS18B20_write(0x44); //启动18B20温度开始转换
delay_nus(400); //每次转换需要延时200ms以上
DS18B20_reset();
WDR();
DS18B20_write(0xcc); //发出读命令 ,搜索ROM
DS18B20_write(0xbe); //读闪存器,读CRC冗余校验
teml=DS18B20_read(); //读低字节数据
temh=DS18B20_read(); //读高字节数据
count=(temh*256+teml)*6.25; //计算具体温度
WDR();
LCD_write_data_variable(0,1,2,count);
LCD_write_string(14,1,"`C");
delay(300);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -