单片机C与汇编混合编程在DS18B20温度采集中的应用
我的51单片机之 温度传感器18B20 的C语言和汇编编程
{
TCZ=TCZ%100;//只显示小于 100 的整数温度
}
TC[1]=TCZ/10;
TC[0]=TCZ%10;
}
Hale Waihona Puke }void main() {
LEDCODE=0xFF; LED1=0; while(1) {
ReadTemp(); Disp(); } }
四、汇编程序: ;********************************************************************
温度传感器 18B20 实验
一、功能: 插上 18B20,上电后,数码管显示相应的环境温度。
二、电路图:
三、C 程序: //******************************************************************** //读取 18B20 输出的温度数据(2 位)并在数码管上显示;made by luqichao //********************************************************************
unsigned char Reset(); unsigned char ReadByte(); void WriteByte(unsigned char Data); void ReadTemp(); //延时 void delay(unsigned char n) {
unsigned char i; for(i=0;i<n;i++) { } }
Data>>=1; CLK=0; NOP();NOP();NOP();NOP();NOP();NOP();//6us CLK=1; NOP();NOP();NOP();NOP();NOP();//4us Temp=CLK; if(Temp) {
单片机中使用DS18B20温度传感器C语言程序文件
单片机中使用DS18B20温度传感器C语言程序(参考1)/********************************************************************************DS18B20 测温程序硬件:AT89S52(1)单线ds18b20接P2.2(2)七段数码管接P0口(3)使用外部电源给ds18b20供电,没有使用寄生电源软件:Kei uVision 3**********************************************************************************/ #include "reg52.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned intsbit ds=P2^2;sbit dula=P2^6;sbit wela=P2^7;uchar flag ;uint temp; //参数temp一定要声明为int 型uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //不带小数点数字编码uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //带小数点数字编码/*延时函数*/void TempDelay (uchar us){while(us--);}void delay(uint count) //延时子函数{uint i;while(count){i=200;while(i>0)i--;count--;}}/*串口初始化,波特率9600,方式1 */void init_com(){TMOD=0x20; //设置定时器1为模式2 TH1=0xfd; //装初值设定波特率TR1=1; //启动定时器SM0=0; //串口通信模式设置SM1=1;// REN=1; //串口允许接收数据PCON=0; //波特率不倍频// SMOD=0; //波特率不倍频// EA=1; //开总中断//ES=1; //开串行中断}/*数码管的显示*/void display(uint temp){uchar bai,shi,ge;bai=temp/100;shi=temp%100/10;ge=temp%100%10;dula=0;P0=table[bai]; //显示百位dula=1; //从0到1,有个上升沿,解除锁存,显示相应段dula=0; //从1到0再次锁存P0=0xfe;wela=1;wela=0;delay(1); //延时约2ms P0=table1[shi]; //显示十位dula=1;dula=0;P0=0xfd;wela=1;wela=0;delay(1);P0=table[ge]; //显示个位dula=1;dula=0;P0=0xfb;wela=1;wela=0;delay(1);}/*****************************************时序:初始化时序、读时序、写时序。
单片机DS18B20温度传感器C语言程序含CRC校验
单片机DS18B20温度传感器C语言程序含CRC校验单片机中使用DS18B20温度传感器C语言程序(参考1)/***************************************************** ***************************DS18B20 测温程序硬件:AT89S52(1)单线ds18b20接P2.2(2)七段数码管接P0口(3)使用外部电源给ds18b20供电,没有使用寄生电源软件:Kei uVision 3***************************************************** *****************************/#include "reg52.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned intsbit ds=P2^2;sbit dula=P2^6;sbit wela=P2^7;uchar flag ;uint temp; //参数temp一定要声明为int 型uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //不带小数点数字编码uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //带小数点数字编码/*延时函数*/void TempDelay (uchar us){ while(us--); }void delay(uint count) //延时子函数{ uint i;while(count){ i=200;while(i>0)i--;count--; } }/*串口初始化,波特率9600,方式1 */void init_com(){ TMOD=0x20; //设置定时器1为模式2 TH1=0xfd; //装初值设定波特率TL1=0xfd;TR1=1; //启动定时器SM0=0; //串口通信模式设置SM1=1;// REN=1; //串口允许接收数据PCON=0; //波特率不倍频// SMOD=0; //波特率不倍频// EA=1; //开总中断//ES=1; //开串行中断}/*数码管的显示*/void display(uint temp){ uchar bai,shi,ge;bai=temp/100;shi=temp%100/10;ge=temp%100%10;dula=0;P0=table[bai]; //显示百位dula=1; //从0到1,有个上升沿,解除锁存,显示相应段dula=0; //从1到0再次锁存wela=0;P0=0xfe;wela=1;wela=0;delay(1); //延时约2msP0=table1[shi]; //显示十位dula=1;dula=0;P0=0xfd;wela=1;wela=0;delay(1);P0=table[ge]; //显示个位dula=1;dula=0;P0=0xfb;wela=1;wela=0;delay(1); }/*****************************************时序:初始化时序、读时序、写时序。
(整理)温度传感器DS18b20介绍和汇编度温度程序
基于proteus的51单片机仿真实例六十七、单总线温度传感器DS18B20读写实例标签: proteus温度传感器单片机单总线实例2010-02-20 01:031、I2C总线器件与单片机之间的通信需要两根线,而单总线器件与单片机间的数据通信只要一根线。
单总线适用于单主机系统,能够控制一个或多个从机设备。
主机通常是单片机,从机可以是单总线器件,他们之间通过一条信号线进行数据交换,单总线上同样允许挂接多个单总线器件,因此,每隔单总线器件必须有各自固定的地址,但总线器件通常需要接一个4.7k左右的上拉电阻,这样,当总线空闲时,状态为高电平。
2、单总线器件的数据操作过程1)初始化单总线上的所有处理均从初始化开始,单片机先发送一个复位脉冲,当单总线其间接收到复位脉冲后,先单片机发出应答信号,以便通知单片机:该器件已经准备好等待下一步操作2)识别单总线器件总线上允许挂接多个但总线器件,为便于单片机识别,每个单总线器件在出厂前都分配好了64为序列号以作为地址序列码。
所以单片机能够根据该序列号来识别和判断对那一个单总线器件进行操作3)数据交换单片机与单总线器件之间的数据交换必须遵循严格的通信协议。
单总线协议定义了复位信号,应答信号,写/读0,写/读1的集中信号类型,所有的单总线命令都是由这些基本的信号类型组成的,除了应答信号外,其余信号都由单片机发出,并且发送的所有命令和数据都是低位在前,高位在后。
3、DS18B20的工作时序1)初始化单片机将数据线拉低480-960us后释放,等待15-60us,单总线器件即可输出一个持续时间为60-240us的低电平(应答信号),单片机受到此应答后即可进行后续操作2)写时序当主机将数据线的电平从高拉到低时,形成写时序,有写0和写1两种时序。
写时序开始后,DS18B20在15-60us期间从数据线上采样,如果采样到低电平,则向DS18B20写0,否则写1,两个独立的时序之间至少需要1us的回复时间按(拉高总线电平)3)读时序当主机从DS18B20读取数据时,产生读时序,此时,主机将数据线的电平从高拉到低使读时序被初始化。
DS18b20温度获取C程序
sbit L2 = P3^3;
sbit L3 = P3^2;
sbit L4 = P3^1; */
sbit L5 = P3^0;
uint tvalue; //温度值
uchar tflag; //温度正负标志
//unsigned char table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80,0x40,0xcc};//0-9数字,后面为". - ℃",共阴
L3 = 0;
Delay_DS18B20(250);
L3 = 1;
D0 = table[10];//小数点
L3 = 0;
Delay_DS18B20(250);
L3 = 1 ;
D0 = table[p];//小数部分
L4 = 0;
Delay_DS18B20(250);
D0 = table[m];//十位数
L2 =0;
Delay_DS18B20(250);
L2 = 1;
}
if(m > 0)
{
D0 = table[m];//十位数
L2 = 0;
Delay_DS18B20(250);
L2 = 1;
}
D0 = table[n];//个位数
//*****延时子程序*****
void Delay_DS18B20(int num)
{
while(num--);
}
//*****初始化DS18B20*****
单片机DS18B20温度计(有程序)
;单片机DS18B20温度计C语言程序; 有程序#include<reg51.h>#include<intrins.h>#include <math.H> //要用到取绝对值函数abs()//通过DS18B20测试当前环境温度, 并通过数码管显示当前温度值, 目前显示范围: -55~ +125度sbit wela = P2^7; //数码管位选sbit dula = P2^6; //数码管段选sbit ds = P2^2;int tempValue;//0-F数码管的编码(共阳极)unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//0-9数码管的编码(共阳极), 带小数点unsigned char code tableWidthDot[]={0x40, 0x79, 0x24, 0x30,0x19, 0x12, 0x02,0x78, 0x00, 0x10};//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms.void delay(unsigned int i){unsigned int j;while(i--){for(j = 0; j < 125; j++);}}//初始化DS18B20//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动 void dsInit(){//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于?us unsigned int i;ds = 0;i = 100; //拉低约800us, 符合协议要求的480us以上while(i>0) i--;ds = 1; //产生一个上升沿, 进入等待应答状态i = 4;while(i>0) i--;}void dsWait(){unsigned int i;while(ds);while(~ds); //检测到应答脉冲i = 4;while(i > 0) i--;}//向DS18B20读取一位数据//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,//之后DS18B20则会输出持续一段时间的一位数据bit readBit(){unsigned int i;bit b;ds = 0;i++; //延时约8us, 符合协议要求至少保持1usds = 1;i++; i++; //延时约16us, 符合协议要求的至少延时15us以上b = ds;i = 8;while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求return b;}//读取一字节数据, 通过调用readBit()来实现unsigned char readByte(){unsigned int i;unsigned char j, dat;dat = 0;for(i=0; i<8; i++){j = readBit();//最先读出的是最低位数据dat = (j << 7) | (dat >> 1);}return dat;}//向DS18B20写入一字节数据void writeByte(unsigned char dat){unsigned int i;unsigned char j;bit b;for(j = 0; j < 8; j++){b = dat & 0x01;dat >>= 1;//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1if(b){ds = 0;i++; i++; //拉低约16us, 符号要求15~60us内ds = 1;i = 8; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求}else //写"0", 将DQ拉低60us~120usds = 0;i = 8; while(i>0) i--; //拉低约64us, 符号要求ds = 1;i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us 了}}//向DS18B20发送温度转换命令void sendChangeCmd(){dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化dsWait(); //等待DS18B20应答delay(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0x44); //写入温度转换命令字Convert T}//向DS18B20发送读取数据命令void sendReadCmd(){dsInit();dsWait();delay(1);writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0xbe); //写入读取数据令字Read Scratchpad}//获取当前温度值int getTmpValue(){unsigned int tmpvalue;int value; //存放温度数值float t;unsigned char low, high;sendReadCmd();//连续读取两个字节数据low = readByte();high = readByte();//将高低两个字节合成一个整形变量//计算机中对于负数是利用补码来表示的//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的valuetmpvalue = high;tmpvalue <<= 8;tmpvalue |= low;value = tmpvalue;//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度t = value * 0.0625;//将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入//如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度//如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5return value;}unsigned char const timeCount = 3; //动态扫描的时间间隔//显示当前温度值, 精确到小数点后一位//若先位选再段选, 由于IO口默认输出高电平, 所以当先位选会使数码管出现乱码void display(int v){unsigned char count;unsigned char datas[] = {0, 0, 0, 0, 0};unsigned int tmp = abs(v);datas[0] = tmp / 10000;datas[1] = tmp % 10000 / 1000;datas[2] = tmp % 1000 / 100;datas[3] = tmp % 100 / 10;datas[4] = tmp % 10;if(v < 0){//关位选, 去除对上一位的影响P0 = 0xff;wela = 0;//段选P0 = 0x40; //显示"-"号dula = 1; //打开锁存, 给它一个下降沿量dula = 0;//位选P0 = 0xfe;wela = 1; //打开锁存, 给它一个下降沿量wela = 0;delay(timeCount);}for(count = 0; count != 5; count++){//关位选, 去除对上一位的影响P0 = 0xff;wela = 1; //打开锁存, 给它一个下降沿量wela = 0;//段选if(count != 2){P0 = table[datas[count]]; //显示数字}else{P0 = tableWidthDot[datas[count]]; //显示带小数点数字}dula = 0;//位选P0 = _crol_(0xfd, count); //选择第(count + 1) 个数码管wela = 1; //打开锁存, 给它一个下降沿量wela = 0;delay(timeCount);}}void main(){unsigned char i;while(1){//启动温度转换sendChangeCmd();//显示5次for(i = 0; i < 40; i++){display(tempValue);}tempValue = getTmpValue();}以下是我编的程序,可用#include <reg52.h>#include <intrins.h>//-----------------------------------------------------------sbit DQ=P1^5;//-----------------------------------------------------------unsigned char number[10]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F};//数字0~9unsigned char wei[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //数码管位循环unsigned char Flag;unsigned char Templ,Temph;unsigned int temp;//-----------------------------------------------------------//函数声明//-----------------------------------------------------------void delay(unsigned char i); //延时程序//----------------------------------void Int18b20(void); //18b20初始化void Write18b20(unsigned char dat); //向18b20写一字节unsigned char Read18b20(void); //从18b20读一字节void Start18b20(void); //开始转换温度void Get18b20(void); //读出温度void chinT(void); //数据转换//----------------------------------void display(void); //显示程序//-----------------------------------------------------------//函数功能:延时//-----------------------------------------------------------/*************精确延时函数*****************/void delay(unsigned char i){while(--i);}/*此延时函数针对的是12Mhz的晶振delay(0); //延时518us 误差:518-2*256=6delay(1); //延时7us (原帖写"5us"是错的)delay(10); //延时25us 误差:25-20=5delay(20); //延时45us 误差:45-40=5delay(100); //延时205us 误差:205-200=5delay(200); //延时405us 误差:405-400=5*///-----------------------------------------------------------//DS18b20的相关程序//-----------------------------------------------------------//初始化//-----------------------------------------------------------void Int18b20(void){DQ=1;_nop_();_nop_();DQ=0; //拉低delay(100); //延时205usdelay(200); //延时405us //等待400~960微秒,最短为480us DQ=1;delay(1); //延时7usdelay(20); //延时45us //等待15~60微秒(等待回复)if(DQ==1) //判断初始化的情况是否成功{Flag=0; //复位失败}else{Flag=1;while(!DQ); //等待回复完成}delay(200); //延时405us //等待完成初始化}//-----------------------------------------------------------//写一字节//-----------------------------------------------------------void Write18b20(unsigned char dat){unsigned char i;for(i=0;i<8;i++){DQ=1;_nop_();DQ=0;delay(1); //延时7us //拉低后延时小于15usif(dat&0x01){DQ=1;}else{DQ=0;}dat=dat>>1;delay(20); //延时45usdelay(10); //延时25us //延时大于60usDQ=1;delay(1); //延时7us //延时大于1us}}//-----------------------------------------------------------//读一字节//-----------------------------------------------------------unsigned char Read18b20(void){unsigned char i,dat=0;for(i=0;i<8;i++){DQ=1;_nop_();DQ=0;delay(1); //延时7usdat=dat>>1;DQ=1;delay(1); //延时7us //确保在15us后60us前读数据if(DQ){dat|=0x80;}delay(20); //延时45us //确保读时续大于60us}return dat;}//-----------------------------------------------------------//开始转换温度//-----------------------------------------------------------void Start18b20(void){Int18b20();Write18b20(0xcc); //跳过ROM指令Write18b20(0x44); //温度转换指令}//-----------------------------------------------------------//读出温度//-----------------------------------------------------------void Get18b20(void){Int18b20();Write18b20(0xcc); //跳过ROM指令Write18b20(0xbe); //读暂存器指令Templ=Read18b20();Temph=Read18b20();}//-----------------------------------------------------------//数据转换//-----------------------------------------------------------void chinT(void){float Tt;temp=Temph; //先把高八位有效数据赋于temptemp=(temp<<8); //将数据从temp低八位移到高八位temp=temp|Templ; //将两字节合成一个整型变量Tt=temp*0.0625; //得到真实十进制温度值(因为DS18B20可以精确到0.0625度) temp=Tt*10+0.5; //放大十倍(将小数点后一位变成个位,个位变成十位,十位变成百位,并四舍五入)}//-----------------------------------------------------------//显示程序//-----------------------------------------------------------void display(void){unsigned int i;unsigned char A1,A2,A3;A1=temp/100; //百位(温度的十位)A2=temp%100/10; //十位(温度的个位)A3=temp%10; //个位(温度的小数点后一位)for(i=0;i<20;i++){P0=0x00;P2=0x00;P0=number[A1];P2=wei[0];delay(220);P0=0x00;P2=0x00;P0=number[A2];P2=wei[1];delay(220);P0=0x00;P2=0x00;P0=number[A3];P2=wei[2];delay(220);P0=0x00;P2=0x00;P0=0x80;P2=wei[1];delay(220);}}//-----------------------------------------------------------//----------------------------------------------------------- void main(void){while(1){Int18b20();if(Flag){Start18b20(); //开始转换温度Get18b20(); //得到温度chinT(); //数据转换display(); //显示}else P3=0x01;}}。
基于DS18B20的水温控制系统c语言实现
一、电路图二、代码实现#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define delayNOP(){_nop_();_nop_();_nop_();_nop_();}sbit alarm = P3^6; //报警信号sbit DQ = P3^7; //DS18B20数据线sbit ADD10 = P3^3; //十位加1sbit ADD1 = P3^2; //个位加1uchar code df_Table[] = {0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9}; //温度小数位对照表uchar code DSY_CODE[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xFF, 0xBF}; //共阳数码管段码及空白显示uchar currentT = 0; //当前读取的温度整数部分uchar Temp_Value[] = {0x00, 0x00}; //从DS18B20读取的温度值uchar Display_Digit[] = {0,0,0}; //待显示的各温度数位uchar Display_Alarm_Digit[] = {0,0,0}; //待显示的警告温度数位bit alarm_flag = 0; //高温报警标志bit ds18b20_is_ok = 1; //传感器正常标志uint Time0_Count = 0; //定时器延时累加uchar alarm_temp; //报警温度//延时void Delay(uint x){while(--x);}//初始化ds18b20uchar Init_DS18B20(){uchar status;DQ = 1; Delay(8);DQ = 0; Delay(90);DQ = 1; Delay(8);status = DQ;Delay(100);DQ = 1;return status; //初始化成功返回0}//读一字节uchar ReadOneByte(){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){uchar i;for(i=0; i<8; i++){DQ = 0; DQ = dat & 0x01; Delay(5); DQ = 1; dat>>=1;}}//读取温度值void Read_Temperature(){if(Init_DS18B20() == 1) //DS18B20故障ds18b20_is_ok = 0;else{WriteOneByte(0xCC); //跳过序列号WriteOneByte(0x44); //启动温度转换Init_DS18B20();WriteOneByte(0xCC); //跳过序列号WriteOneByte(0xBE); //读取温度寄存器Temp_Value[0] = ReadOneByte(); //温度低8位Temp_Value[1] = ReadOneByte(); //温度高8位ds18b20_is_ok = 1;}}//设置ds18b20温度报警值void set_Alarm_Temp_Value(uchar alarm_t){alarm_temp = alarm_t;Init_DS18B20();WriteOneByte(0xCC); //跳过序列号WriteOneByte(0x4E); //将设定的温度报警值写入ds18b20 WriteOneByte(alarm_t);WriteOneByte(0x7F); //12位精度Init_DS18B20();WriteOneByte(0xCC); //跳过序列号WriteOneByte(0x48); //温度报警值存入ds18b20}//显示当前传感器温度void Display_Temperature(){uchar i;uchar t = 150; //延时值char signed_current_temp;//查表得到温度小数部分Display_Digit[0] = df_Table[Temp_Value[0] & 0x0F];//获取温度整数部分(无符号)?currentT = ((Temp_Value[0] & 0xF0)>>4)|((Temp_Value[1] & 0x07)<<4);//当前值signed_current_temp = currentT;//高温标志设置alarm_flag = signed_current_temp >= alarm_temp ? 1 : 0;//将整数部分分解为二位待显示数字Display_Digit[2] = currentT % 100 / 10;Display_Digit[1] = currentT % 10;if(Display_Digit[2] == 0){Display_Digit[2] = 10;}//查表得到报警温度小数部分Display_Alarm_Digit[0] = df_Table[0];//将整数部分分解为二位待显示数字Display_Alarm_Digit[2] = alarm_temp % 100 / 10;Display_Alarm_Digit[1] = alarm_temp % 10;if(Display_Alarm_Digit[2] == 0){Display_Alarm_Digit[2] = 10;}//刷新显示若干时间for(i=0; i<30; i++){P1 = DSY_CODE[Display_Digit[0]]; //小数位P0 = DSY_CODE[Display_Alarm_Digit[0]]; //小数位P2 = 0xFE; Delay(t); P2 = 0xFF;P1 = (DSY_CODE[Display_Digit[1]]) & 0x7F; //个位及小数点P0 = (DSY_CODE[Display_Alarm_Digit[1]]) & 0x7F; //个位及小数点P2 = 0xFD; Delay(t); P2 = 0xFF;P1 = DSY_CODE[Display_Digit[2]]; //十位P0 = DSY_CODE[Display_Alarm_Digit[2]]; //十位P2 = 0xFB; Delay(t); P2 = 0xFF;}}//十位加1void Add_Ten(){while(ADD10 == 1);Delay(30);alarm_temp += 10;if(alarm_temp >= 100){alarm_temp = alarm_temp%100;}}//个位加1void Add_One(){while(ADD1 == 1);Delay(30);alarm_temp += 1;if(alarm_temp >= 100){alarm_temp = alarm_temp%100;}}//定时器中断,熄灭加热灯,停止加热void T0_INT() interrupt 1{TH0 = -1000 / 256;TL0 = -1000 % 256;if(++Time0_Count == 400){Time0_Count = 0;if(alarm_flag){alarm = 0;}}}//主程序void main(){IE = 0x82;TMOD = 0x01;TH0 = -1000 / 256;TL0 = -1000 %256;TR0 = 0;alarm = 1; //加温状态alarm_temp = 70; //初始报警温度Read_Temperature(); //读取温度Delay(50000);Delay(50000);while(1){Read_Temperature();if(ds18b20_is_ok){if(alarm_flag == 1)TR0 = 1;elseTR0 = 0;if(ADD10 == 0){Add_Ten();Delay(60);}if(ADD1 == 0){Add_One();Delay(60);}set_Alarm_Temp_Value(alarm_temp);Display_Temperature();}else{P1 = P0 = 0x00;P2 = 0xFF;}}}。
关于DS18B20在单片机中的应用
关于DS18B20在单片机中的应用摘要:DS18820是美国DALLAS半导体公司生产的单总线数字温度传感器,它可直接实现数字化输出和测试,具有控制功能强,高精度,传输距离远,抗干扰能力强,微型化和微功耗等特点.本文介绍了单线数字温度传感器DS18820的结构,特点和工作原理;在蓝桥杯CT107D开发平台了上利用DS18820测量正负范围内带小数的实时温度并显示,测量系统的硬件结构及设计C51程序所注意事项。
关键词:DS18820实时测温正负温度Abstract:DS18820 is a single bus digital temperature sensor produced by DALLAS Semiconductor Company in the United States. It can directly realize digital output and test, with strong control function, high precision, long transmission distance, strong anti-interference ability, miniaturization and micro-power consumption. This paper introduces the structure, characteristics and working principle of single-wire digital temperature sensor DS18820. On the development platform of Lanqiao CT107D, DS18820 is used to measure the real-time temperature with decimal in the range of positive and negative and display the hardware structure of the measurement system and thematters for attention in the design of C51 program..Keywords:DS18820,real-time temperature measuring,the positive and negative temperature温度传感器是比较常用的一种传感器,早期多使用模拟式温度传感器,如热敏电阻;随着科技进步,现在温度传感器多用数字式的,如DS18B20。
DS18b20温度测量程序。单片机C51控制
//DS18B20的读写程序,数据脚P3.3 ////温度传感器18B20汇编程序,采用器件默认的12位转化 ////最大转化时间750微秒,显示温度-55到+125度,显示精度 ////为0.1度,显示采用4位LED共阳显示测温值 ////P0口为段码输入,P24~P27为位选 ///***************************************************/#include "reg51.h"#include "intrins.h" //_nop_();延时函数用#define Disdata P1 //段码输出口#define discan P0 //扫描口#define uchar unsigned char#define uint unsigned intsbit DQ=P3^2; //温度输入口uint h;//**************温度小数部分用查表法***********//uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };//uchar dd[10]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};//共阳LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-"uchar scan_con[4]={0x00,0x01,0x02,0x03}; //列扫描控制字uchar temp_data[2]={0x00,0x00}; //读出温度暂放uchar display[4]={0x00,0x00,0x00,0x00,}; //显示单元数据,共4个数据和一个运算暂用///////***********11微秒延时函数**********///void delay(uint t){for(;t>0;t--);}///***********显示扫描函数**********/scan(){uchar k;for(k=0;k<3;k++){P0=0xff;dd[k]=dd[display[k]];dd[k]=dd[k]*16;dd[k]=dd[k]|scan_con[k];P0=dd[k];delay(90);P0=0xff;}}/////***********18B20复位函数**********/ ow_reset(void){char presence=1;while(presence){while(presence){DQ=1;_nop_();_nop_();DQ=0; //delay(50); // 550usDQ=1; //delay(6); // 66uspresence=DQ; // presence=0继续下一步 }delay(45); //延时500uspresence = ~DQ;}DQ=1;}/////**********18B20写命令函数*********/ //向 1-WIRE 总线上写一个字节void write_byte(uchar val){uchar i;for (i=8; i>0; i--) //DQ=1;_nop_();_nop_();DQ = 0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us DQ = val&0x01; //最低位移出delay(6); //66usval=val/2; //右移一位}DQ = 1;delay(1);}///*********18B20读1个字节函数********///从总线上读取一个字节uchar read_byte(void){uchar i;uchar value = 0;for (i=8;i>0;i--){DQ=1;_nop_();_nop_();value>>=1;DQ = 0; //_nop_();_nop_();_nop_();_nop_(); //4usDQ = 1;_nop_();_nop_();_nop_();_nop_(); //4usif(DQ)value|=0x80;delay(6); //66us}DQ=1;return(value);}///***********读出温度函数**********///read_temp(){ow_reset(); //总线复位write_byte(0xCC); // 发Skip ROM命令write_byte(0xBE); // 发读命令temp_data[0]=read_byte(); //温度低8位temp_data[1]=read_byte(); //温度高8位ow_reset();write_byte(0xCC); // Skip ROMwrite_byte(0x44); // 发转换命令}/***********温度数据处理函数**********/void work_temp(){display[3]=temp_data[0]&0x0f;display[0]=ditab[display[3]]; //小数部分display[3]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x07)<<4); display[2]=display[3]/10%10;display[1]=display[3]%10;}/////**************主函数****************/main(){Disdata=0xff; //初始化端口discan=0xff;ow_reset(); // 开机先转换一次write_byte(0xCC); // Skip ROMwrite_byte(0x44); // 发转换命令for(h=0;h<500;h++){scan();} //开机显示"0000"2秒while(1){read_temp(); //读出18B20温度数据work_temp(); //处理温度数据scan(); //显示温度值2秒}}////*********************结束**************************//。
基于单片机和DS18B20的数字温度计
温度测量在物理实验、医疗卫生、食品生产等领域,尤其在热学试验中,有特别重要的意义。
随着人们生活水平的不断提高,,人们对温度计的要求越来越高,传统的温度计功能单一、精度低,要为现代人工作、科研、生活、提供更好的更方便的设施就需要从单片机技术入手,一切向着数字化控制,智能化控制方向发展。
数字温度计(Digital Thermometer)简称D温度是许多监控系统中的一个重要参数。
TM,它是采用数字化测量技术,把连续的温度值转换成不连续、离散的数字形式并加以显示的仪表。
采用单片机控制的数字温度计,由于精度高、可扩展性强、集成方便、抗干扰能力强,得到了广泛的应用。
本设计以单片机和温度传感器为核心,设计数字温度计。
实现对温度的采集、监视和报警。
在温度采集的实现中,使用了AT89C51单片机和温度传感器DS18B20,温度监视部分利用动态驱动技术,以单片机驱动4位LED数码管。
温度测量范围-55℃~+125℃,通过按键设置上下限报警温度,并用4位共阳极LED数码管以串口传送数据,实现温度显示,能准确达到设计要求。
正文还介绍了AT89C51和集成温度传感器DS18B20。
1 设计的意义及主要功能 (3)1.1 意义 (3)1.2 主要功能 (3)2 总体方案设计 (4)2.1 方案比较 (4)2.2 方案论证 (5)2.3 方案选择 (5)3 硬件电路设计 (6)3.1 元器件的选择 (6)3.2 电路原理图 (6)3.3 特殊元器件的介绍 (6)3.3.1 AT89C51介绍 (6)3.3.2 DS18B20介绍 (9)4 总结 (13)5 参考文献 (13)附录 (14)1 设计的意义及主要功能1.1 意义随着人们生活水平的不断提高,数字化无疑是人们追求的目标之一,它所给人带来的方便也是不可否定的,其中数字温度计就是一个典型的例子,一切向着数字化控制,智能化控制方向发展。
数字温度计与传统的温度计相比,具有读数方便,测温范围广,测温准确,其输出温度采用数字显示,主要用于对测温比较准确的场所,或科研实验室使用。
DS18B20温度计完整单片机程序(汇编语言)
end
sjmp dis1
dis :
movc a,@a+dptr
CLR P2.2
clr P2.1 ;低位灭
mov p0,a
call delay3
dis1:
mov a,b
movc a,@a+dptr
setb P2.2
clr P2.1 ;高位灭
mov p0,a
call delay3
djnz r1,write_bit
ret
;*****************************************
;读一个字节(内容放在在A中)
read_byte:
mov r2,#8
read_bit:
clr p1.7
nop
nop
nop
nop
setb p1.7 ;释放总线的目的是为了读18b20发出的数据,低电平是不能读的。
sjmp f1
f:clr 20h.0 ;初始化失败置0
f1:
ret
;*****************************************
;写一个字节(内容在A中)
write_byte:
mov r1,#8
;写一位
write_bit:
rrc a ;先写低位
clr 20h.0
mov a, #0cch ;跳过序列号
call write_byte
mov a,#0BEH ;送入读内部ram命令
call write_byte
call read_byte
mov r6,a
call read_byte
单片机DS18B20温度传感器C语言程序含CRC校验
单片机中使用DS18B20温度传感器C语言程序(参考1)/******************************************************************************** DS18B20 测温程序硬件:AT89S52(1)单线ds18b20接 P2.2(2)七段数码管接P0口(3)使用外部电源给ds18b20供电,没有使用寄生电源软件:Kei uVision 3**********************************************************************************/ #include "reg52.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned intsbit ds=P2^2;sbit dula=P2^6;sbit wela=P2^7;uchar flag ;uint temp; //参数temp一定要声明为 int 型uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //不带小数点数字编码uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //带小数点数字编码/*延时函数*/void TempDelay (uchar us){ while(us--); }void delay(uint count) //延时子函数{ uint i;while(count){ i=200;while(i>0)i--;count--; } }/*串口初始化,波特率9600,方式1 */void init_com(){ TMOD=0x20; //设置定时器1为模式2TH1=0xfd; //装初值设定波特率TL1=0xfd;TR1=1; //启动定时器SM0=0; //串口通信模式设置SM1=1;// REN=1; //串口允许接收数据PCON=0; //波特率不倍频// SMOD=0; //波特率不倍频// EA=1; //开总中断//ES=1; //开串行中断}/*数码管的显示 */void display(uint temp){ uchar bai,shi,ge;bai=temp/100;shi=temp%100/10;ge=temp%100%10;dula=0;P0=table[bai]; //显示百位dula=1; //从0到1,有个上升沿,解除锁存,显示相应段dula=0; //从1到0再次锁存wela=0;P0=0xfe;wela=1;wela=0;delay(1); //延时约2msP0=table1[shi]; //显示十位dula=1;dula=0;P0=0xfd;wela=1;wela=0;delay(1);P0=table[ge]; //显示个位dula=1;dula=0;P0=0xfb;wela=1;wela=0;delay(1); }/*****************************************时序:初始化时序、读时序、写时序。
温度传感器DS18b20介绍和汇编度温度程序-16页文档资料
基于proteus的51单片机仿真实例六十七、单总线温度传感器DS18B20读写实例标签: proteus 温度传感器单片机单总线实例2019-02-20 01:031、I2C总线器件与单片机之间的通信需要两根线,而单总线器件与单片机间的数据通信只要一根线。
单总线适用于单主机系统,能够控制一个或多个从机设备。
主机通常是单片机,从机可以是单总线器件,他们之间通过一条信号线进行数据交换,单总线上同样允许挂接多个单总线器件,因此,每隔单总线器件必须有各自固定的地址,但总线器件通常需要接一个4.7k左右的上拉电阻,这样,当总线空闲时,状态为高电平。
2、单总线器件的数据操作过程1)初始化单总线上的所有处理均从初始化开始,单片机先发送一个复位脉冲,当单总线其间接收到复位脉冲后,先单片机发出应答信号,以便通知单片机:该器件已经准备好等待下一步操作2)识别单总线器件总线上允许挂接多个但总线器件,为便于单片机识别,每个单总线器件在出厂前都分配好了64为序列号以作为地址序列码。
所以单片机能够根据该序列号来识别和判断对那一个单总线器件进行操作3)数据交换单片机与单总线器件之间的数据交换必须遵循严格的通信协议。
单总线协议定义了复位信号,应答信号,写/读0,写/读1的集中信号类型,所有的单总线命令都是由这些基本的信号类型组成的,除了应答信号外,其余信号都由单片机发出,并且发送的所有命令和数据都是低位在前,高位在后。
3、DS18B20的工作时序1)初始化单片机将数据线拉低480-960us后释放,等待15-60us,单总线器件即可输出一个持续时间为60-240us的低电平(应答信号),单片机受到此应答后即可进行后续操作2)写时序当主机将数据线的电平从高拉到低时,形成写时序,有写0和写1两种时序。
写时序开始后,DS18B20在15-60us期间从数据线上采样,如果采样到低电平,则向DS18B20写0,否则写1,两个独立的时序之间至少需要1us的回复时间按(拉高总线电平)3)读时序当主机从DS18B20读取数据时,产生读时序,此时,主机将数据线的电平从高拉到低使读时序被初始化。
单片机C与汇编混合编程在DS18B20温度采集中的应用
单片机C与汇编混合编程在DS18B20温度采集中的应用林建英;周其辉
【期刊名称】《实验室科学》
【年(卷),期】2010(13)5
【摘要】在嵌入式程序设计中,C语言和汇编语言是两种应用最广泛的编程语言,它们各有突出的优点.本文中详细介绍了这两种编程语言混合调用的方法,并以
DS18820温度采集系统为例,在程序设计中灵活运用这两种编程语言,使程序简洁而高效,对学生学习、运用单片机C语言与汇编语言的混合调用,解决实际问题具有一定的参考价值.
【总页数】5页(P121-125)
【作者】林建英;周其辉
【作者单位】大连理工大学,电子信息与电气工程学部,辽宁,大连,116024;大连理工大学,电子信息与电气工程学部,辽宁,大连,116024
【正文语种】中文
【中图分类】TP383
【相关文献】
1.基于AVR单片机与温度传感器DS18B20的多点温度测量 [J], 朱丽丽;王长友
2.单总线数字温度传感器DS18B20及其在单片机系统的应用 [J], 吴永春
3.C51与汇编语言混合编程在单片机IAP中的应用 [J], 余新拴;李建忠
4.高精度数字温度测量系统设计——由Keil C51单片机和DS18B20温度传感器
组成 [J], 吴春龙
5.基于51单片机温度传感器 DS18B20的应用 [J], 王秀俊
因版权原因,仅展示原文概要,查看原文内容请购买。
18b20温度检测(C语言及汇编)
18b20温度检测(C语言及汇编);*******************18B20 温度检测程序*****************************;***************显示范围-50-125度,显示精度为0.1度*******************;***********p3.5接1820的DQ端,P2口是接共阳极数码管******************;**********当温度为负时,不知道程序是否正确,现在没法测试**********;*************************************************qq:65341709 4******;**************************************************2011-9-14********ORG 00Hmov 30h,#0ffh ;显示缓冲区,小数部分mov 31h,#0ffh ;个位mov 32h,#0ffh ;十位mov 33h,#0ffh ;百位TEMPER_L EQU 29H ;用于保存读出温度的低8位TEMPER_H EQU 28H ;用于保存读出温度的高8位FLAG1 EQU 38H ;是否检测到DS18B20标志位FLAGT BIT 20H.0 ;温度正负标志位,0为正,1为负bai equ 2ah ;数码管百位数存放内存位置shi EQU 2bH ;数码管十位数存放内存位置g equ 2ch ;数码管个位数存放内存位置xiao equ 2dh ;数码管小数位存放内存位置clr FLAGTMAIN:LCALL GET_TEMPER ;调用读温度子程序MOV A,28H ;温度的高位,判断符号anl a,#0f0hjz ss ;为0,则为正setb flagtmov a, 28hcpl amov 28h,amov a,29hcpl ainc amov 29h,acjne a,#0,NNjin: mov a,28h ;低位为0,高位进位inc amov 28h,aNN: mov a,29hanl a,#0fhmov dptr,#tab3movc a,@a+dptrmov xiao,a ;查小数表,存入xiao中jb flagt,yyss:MOV A,29H ;在18b20中,温度以带扩展的16位二进制补码形式给出,负数需取反再加1anl a,#0fhmov dptr,#tab3movc a,@a+dptrmov xiao,ayy:mov r0,#00h ;处理温度的整数部分mov a,29hanl a,#0f0hswap amov r0,amov a,28hanl a,#0fhswap aorl a,r0MOV 29H,A ;保存调整后的温度值LCALL DISPLAY ;调用数码管显示子程序lcall scanAJMP MAIN;******************DS18B20复位初始化子程序********************INIT_1820: SETB P3.5NOPCLR P3.5;主机发出延时537微秒的复位低脉冲MOV R1,#3TSR1: MOV R0,#107 ;大于480us,小于960us都行DJNZ R0,$DJNZ R1,TSR1SETB P3.5 ;然后拉高数据线NOPNOPNOPMOV R0,#25HTSR2: JNB P3.5,TSR3 ;等待DS18B20回应DJNZ R0,TSR2 ;延时LJMP TSR4TSR3: SETB FLAG1 ;置标志位,表示DS1820存在LJMP TSR5TSR4: CLR FLAG1 ;清标志位,表示DS1820不存在LJMP TSR7TSR5: MOV R0,#117TSR6: DJNZ R0,$ ;时序要求延时一段时间TSR7: SETB P3.5RET;******************读出转换后的温度值**********************GET_TEMPER: SETB P3.5LCALL INIT_1820 ;先复位DS18B20JB FLAG1,TSS2RET ;判断DS1820是否存在?若DS18B20不存在则返回TSS2: MOV A,#0CCH ;跳过ROM匹配LCALL WRITE_1820MOV A,#44H ;发出温度转换命令LCALL WRITE_1820;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒LCALL scanLCALL INIT_1820 ;准备读温度前先复位MOV A,#0CCH ;跳过ROM匹配LCALL WRITE_1820MOV A,#0BEH ;发出读温度命令LCALL WRITE_1820LCALL READ_18200 ;将读出的温度数据保存到35H/36HRET;****************写DS18B20的子程序(有具体的时序要求)***********WRITE_1820: MOV R2,#8 ;一共8位数据CLR CWR1: CLR P3.5 ;先发送低电平脉冲MOV R3,#6 ; 15us-60usDJNZ R3,$RRC A ;被写入的数据在A中存放MOV P3.5,C ;读写都是从低位开始MOV R3,#23DJNZ R3,$SETB P3.5NOPDJNZ R2,WR1SETB P3.5RET;***********读DS18B20的程序,从DS18B20中读出两个字节的温度数据********READ_18200: MOV R4,#2 ;将温度高位和低位从DS18B20中读出MOV R1,#29H ;低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)RE00: MOV R2,#8 ;数据一共有8位RE01: CLR CSETB P3.5 ;先把DQ拉高NOPNOPCLR P3.5 ;低脉冲,大于1us,小于15usNOPNOPNOPSETB P3.5 ;再把DQ拉高MOV R3,#9RE10: DJNZ R3,RE10 ;大于15us,小于60usMOV C,P3.5MOV R3,#23RE20: DJNZ R3,RE20RRC ADJNZ R2,RE01MOV @R1,ADEC R1DJNZ R4,RE00RET;******************显示子程序***************************** DISPLAY: MOV A,29H ;将29H中的十六进制数转换成10进制MOV B,#100 ;10进制/10=10进制DIV ABMOV bai,AMOV a,Bmov b,#10div abmov shi,amov g,bjnb flagt,N1mov a,shijz n2mov 33h,#0bfh ;温度为负MOV DPTR,#tab1 movc a,@a+dptrmov 32h,ajmp n3n2: mov 32h,#0bfhn3: mov dptr,#tab2 mov a,gmovc a,@a+dptrmov 31h,amov dptr,#tab1mov a,xiaomovc a,@a+dptrmov 30h,aN1: mov a,bai ;温度为正jz n4mov dptr,#tab1movc a,@a+dptrmov 33h,an4: mov a,shimov dptr,#tab1 movc a,@a+dptr mov 32h,an5: mov a,g mov dptr,#tab2 movc a,@a+dptr mov 31h,amov dptr,#tab1 mov a,xiao movc a,@a+dptr mov 30h,aretscan:clr p2.0mov p0,30hcall delaysetb p2.0clr p2.1mov p0,31hcall delaysetb p2.1clr p2.2mov p0,32hcall delaysetb p2.2clr p2.3mov p0,33hcall delaysetb p2.3delay: mov r6,#6 ;3msd1: MOV R7,#248DJNZ R7,$djnz r6,d1RETtab1: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH ;8段数码管0~9数字的共阳显示代码tab2: db 40h,79h,24h,30h,19h,12h,02h,78h,00h,10h ;含有小数点的0~9tab3: db 00,01,01,02,03,03,04,04,05,06,06,07,08,08,09,09END/************18b20C语言程序****************************************************************** ***********显示温度范围-50.0~125.0度精确到0.1度************************************************************************************************************* *********************************这两个程序的灵敏度感觉没啥差异,但这个程序显示时感觉没有上面的汇编程序的稳定,有点闪烁的*****感觉,我修改了延时时间,还是不行。
转基于DS18B20数字温度计C语言程序设计
看了好多天单片机,找了好多资料想自己利用实验板上的DS18B20做个温度计(最近温度实在是太热了)。
在网上找了好多关于这个的程序,结果发现对我的板子来说就这个好用,温度三十度不算高,因为我把它放到风扇下面了,现在和大家分享一下吧,不过里面我自己也改了一点点。
希望高手不要见笑,红色的部分是我改的或者是后加上的。
如果还有什么更好的建议或意见请记得给我留言哦……#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit PS2=P2^6; //数码管十位,位选sbit PS1=P2^7; //数码管个位,段选sbit P_L=P1^0; //测量指示sbit DQ=P2^2; //DS18B20数据接口void delay(uint); //延时函数void DS18B20_init(void); //DS18B20初始化void get_temper(void); //读取温度程序void DS18B20_write(uchar in_data); //DS18B20写数据函数uchar DS18B20_read(void); ////读取数据程序uchar htd(uchar a); //进制转换函数void display(void); //显示函数uchar temp; //温度寄存器bit DS18B20; // 18B20存在标志,1---存在0---不存在uchar tab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //字段转换表void main(void){uint a;while(1){get_temper(); //测量温度for(a=0;a<200;a++) ;//显示,兼有延时的作用display();}}/****************************DS18B20读取温度函数**************************//*函数原型:void get_temper(void)/*函数功能:DS18B20读取温度/*输入参数:无/*输出参数:无/*调用模块:/*建立时间:2005/11/14/*作者:站长/**********************************************************************/void get_temper(void){uchar k,T_sign,T_L,T_H;DS18B20_init(); //DS18B20初始化if(DS18B20) //判断DS1820是否存在?若DS18B20不存在则返回{DS18B20_write(0xcc); // 跳过ROM匹配DS18B20_write(0x44); //发出温度转换命令DS18B20_init(); //DS18B20初始化if(DS18B20) //判断DS1820是否存在?若DS18B20不存在则返回{DS18B20_write(0xcc); //跳过ROM匹配DS18B20_write(0xbe); //发出读温度命令T_L=DS18B20_read(); //数据读出T_H=DS18B20_read();k=T_H&0xf8;if(k==0xf8)T_sign=1; //温度是负数elseT_sign=0; //温度是正数T_H=T_H&0x07;temp=(T_H*256+T_L)*0.0625; //温度转换常数}}}/****************************DS18B20写数据函数**************************//*函数原型:void DS18B20_write(uchar in_data)/*函数功能:DS18B20写数据/*输入参数:要发送写入的数据/*输出参数:无/*调用模块:_cror_()/*建立时间:2005/11/14/*作者:站长/**********************************************************************/void DS18B20_write(uchar in_data) //写DS18B20的子程序(有具体的时序要求){uchar i,out_data,k;out_data=in_data;for(i=1;i<9;i++) //串行发送数据{DQ=0;DQ=1;_nop_();_nop_();k=out_data&0x01;if(k==0x01) //判断数据写1{DQ=1;}else //写0{DQ=0;}delay(4); //延时62usDQ=1;out_data=_cror_(out_data,1); //循环右移1位}}/**************************DS18B20读函数**************************/ /*函数原型:void DS18B20_read()/*函数功能:DS18B20读数据/*输入参数:无/*输出参数:读到的一字节内容/*调用模块:delay()/*建立时间:2005/11/14/*作者:站长/******************************************************************/uchar DS18B20_read(){uchar i,in_data,k;in_data=0;for(i=1;i<9;i++) //串行发送数据{DQ=0;DQ=1;_nop_();_nop_();k=DQ; //读DQ端if(k==1) //读到的数据是1{in_data=in_data|0x01;}else{in_data=in_data|0x00;}delay(3); //延时51usDQ=1;in_data=_cror_(in_data,1); //循环左移1位}return(in_data);}/**************************DS18B20初始化函数**************************/ /*函数原型:void DS18B20_init(void)/*函数功能:DS18B20初始化/*输入参数:无/*输出参数:无/*调用模块:delay()/*建立时间:2005/11/14/*作者:站长/******************************************************************/void DS18B20_init(void){uchar a;DQ=1; //主机发出复位低脉冲DQ=0;delay(44); //延时540USDQ=1;for(a=0;a<0x36&&DQ==1;a++){ //等待DS18B20回应a++;a--;}if(DQ)DS18B20=0; //18B20不存在else{DS18B20=1; // 18B20存在delay(120); //复位成功!延时240US}}/**************************数码管显示函数**************************//*函数原型:void display(void)/*函数功能:数码管显示/*输入参数:无/*输出参数:无/*调用模块:delay()/*建立时间:2005/11/14/*作者:站长/******************************************************************/void display(void){PS1=1;P0=0x01;PS1=0;PS2=1;P0=tab[htd(temp)>>4]; //转换成十进制输出PS2=0;delay(200);PS1=1;P0=0x02;PS1=0;PS2=1;P0=tab[htd(temp)&0x0f]; //转换成十进制输出PS2=0;delay(200);P_L=~DS18B20;}/*********************原显示函数***********************************void display(void){P0=tab[htd(temp)>>4]; //转换成十进制输出PS2=1;PS1=0;delay(200);P0=tab[htd(temp)&0x0f]; //转换成十进制输出PS1=1;PS2=0;delay(200);P_L=~DS18B20;}*******************************************************//**************************十六进制转十进制函数**************************//*函数原型:uchar htd(uchar a)/*函数功能:十六进制转十进制/*输入参数:要转换的数据/*输出参数:转换后的数据/*调用模块:无/*建立时间:2005/11/14/*作者:站长/******************************************************************/uchar htd(uchar a){uchar b,c;b=a%10;c=b;a=a/10;b=a%10;c=c|b<<4;return c;}/*******************************延时函数*********************************/ /*函数原型:delay(unsigned int delay_time)/*函数功能:延时函数/*输入参数:delay_time (输入要延时的时间)/*输出参数:无/*调用模块:无/*建立时间:2005/10/21/*作者:站长/**********************************************************************/ void delay(unsigned int delay_time) //延时子程序{for(;delay_time>0;delay_time--){}}。
基于AT89C51单片机与DS18B20的温度测量系统
第24卷 第9期2008年5月甘肃科技Gansu Science and TechnologyV ol.24 N o.9M ay. 2008基于AT89C51单片机与DS18B20的温度测量系统蔺 鹏1,柴世红2(兰州工业高等专科学校;1电子信息工程系2软件工程系,甘肃兰州730050)摘 要:介绍了单总线数字温度传感器DS18B20的特性及工作原理,给出了A T89C51单片机与DS18B20构成温度测量系统并详细介绍利用汇编语言编程实现对DS18B20访问。
实际测试结果表明这种测温系统转换速度快、精度高,整个系统具有稳定性强等特点。
关键词:DS18B20;数字温度传感器;A T89C51;中图分类号:TN925 典型的温度测控系统是由模拟温度传感器、A/D 转换电路和单片机组成。
但是由于模拟温度传感器输出为模拟信号,必须经过A/D 转换环节获得数字信号后才能与单片机等微处理器接口,使得硬件电路结构复杂,成本较高。
近年来,由于以DS18B20为代表的新型单总线数字式温度传感器的突出优点使得它得到充分利。
DS18B20集温度测量和A/D 转换于一体,直接输出数字量,接口几乎不需要外围元件,硬件电路结构简单,传输距离远,可以很方便的实现多点测量;与单片机接口几乎不需要外围元件,使得硬件电路结构简单,广泛使用于距离远,节点分布多的场合。
1 DS18B20介绍DS18B20是美国DALL AS 公司推出的一种可组网的数字式温度传感器,能够直接读取被测物体的温度值[1]。
具有TO -92、TSOC 、SOIC 多种封装形式,可以适应不同的环境需求。
1.1 DS18B20具有以下主要特性(1)单总线接口方式:与微处理器连接时仅需要一条信号线即可实现双向通讯;(2)使用中无需外部器件,可以利用数据线或外部电源提供电能,供电电压范围3.3-5.5V ;(3)直接读出数字量,工作可靠,精度高,且通过编程可实现9~12位分辨率读出温度数据,转换12的温度数据最大仅需要750ms ;(4)温度测量范围-55℃~+125℃,-10℃~+85℃之间测量精度可达±0.5℃;(5)可设定非易失的报警上下限值,一旦测量温度超过此设定值,即可给出报警标志;(6)每片DS18B20上有唯一的64bit 识别码,可轻松组建分布式温度测量测量网络。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目前多数单片机系统, 在 C 语言中使用汇编有 两种情况: 一种是 C 程序部分和汇编程序部分为不 同模块或不同文件, 通常由 C 程序调用汇编程序模
块的变量和函数 (也可称为子程序或过程 ) , 另一种 是嵌入式汇编, 即在 C语言程序中嵌入一段汇编语 言程序。这种将 C 语言和汇编语 言的优点结合起 来的混合编程方法, 已经成为目前单片机开发最流 行的编程方法。其中, 在汇编语言与 C 语言的混合 编程中, 参数的传递、模块的连接以及调用关系的确 定是值得注意的关键问题 [ 2] 。本文以 51系列单片 机中广泛应用的 C51语言为例, 介绍 C51语言和汇 编语言混合编程的两种编程方法。
PUBL IC _de lay ; 输出函数名 RSEG ? PR? _de lay? LED ; 定义可重定位段 delay: ; 延时函数 USING0 ; 使用寄存器组 0 MOV A, R7 DJNZ A, $ RET CSEG AT 0000H ; 以下代码定位到复位地址 L JM P m ain ; 跳转到主函数 RSEG ? PR? m a in? LED ; 主函数 m ain: USING0 MOV P1, # 01H L 1: MOV A, P1 RL A MOV P1, A MOV R7, # 32H LCALL _de lay SJM P L1 END 由以上示例可以看出: 功能函数需要段名, 段名的转换规则如表 1所 示。功 能 函 数 m ain 和 _ delay 都 放 在 代 码 区 ( CODE ) , 故段名开头为? PR。为了使 C 语言和编 译器生成的汇编程序兼容, 必须为汇编程序指定段 名, 其转换规则如表 1所示。
Application of m ixed calls of C and assem bly language in DS18B20 tem perature gathering system
L IN J ian- y ing, ZH OU Q i- hu i
( Faculty o f E lectron ic Inform at ion and E lectrica l Eng ineering, Da lian U niversity of T echno logy, Dalian 116024, China)
在此例中, 在调用 _de lay函数时, 将 R7中的数 传递到累加器 A, 原因在于其函数调用的参数传递 机制。在 K eil C51编译器中参数传递有两种方式: 一种是通过工作寄存器传递, 使用工作寄存器传递
林建英, 等: 单片机 C 与汇编混合编程在 DS18B20温度采集中的应用
123
时最多只能传递三个参数, 如果要传递更多的参数 就需要通过内部存储器来传递。
ISSN 1672- 4305 CN 12 - 1352 /N
实验室科学 LABORATORY SC IEN CE
第 13卷 第 5 期 2010年 10 月 Vo l 13 No 5 Oct 2010
单片机 C与汇编混合编程在 DS18B20 温度采集中的应用
林建英, 周其辉
( 大连理工大学 电子信息与电气工程学部, 辽宁 大连 116024)
2. 1 标准汇编文件格式 K eil C51编译器的标准汇编文件格式要求: ( 1) 每个功能函数都有自己的段名; ( 2) 每个局部变量都必须指定数据段如 DATA,
XDATA; ( 3) 有参数传递的函数名前加 _ [ 5] , 如果只使
用固定存储区传递参数则不加, 对于重入函数名前 加 _? ;
C语言是一种通用的编程语言, 它提供高效的 代码, 结构化的编程和丰富的操作符。目前在嵌入 式编程中 C 语言已经被广泛应用, 在绝大多数场合 采用 C 语言编程即可完成预期的目的, 但对执行效 率要求较高的实时系统, 往往采用 C 语言与汇编语 言混合编程。汇编语言具有直接和硬件打道、执行 代码的效率高等特点, 可以做到 C 语言所不能做到 的一些事情, 例如对时钟要求很严格时, 使用汇编语 言成了唯一的选择。因此, 常常需要使用多种语言 混合编程, 从而充分利用各种语言的优势, 使开发和 编程工作达到事半功倍的效果 [ 1 ] 。
( 1) 通过寄存器传递 函数间的调用往往需要传递参数, 这样也必须 保证 C 语言和汇编程序传递参数的位置相兼容, 在 K eil C51编译器里面参数传递一般采用当前工作寄 存器, 但是最多不超过 3个参数 [ 6] 。用做接受参数 的寄存器如表 2所示。
表 2 接受参数的寄存器
下面举例说明: ! Function1 ( char a) a在 R7中 传递
下面一个例子说明如何编写标准汇编程序: /* * * * * * * * * * * * * * * * * * * * * /
函数: De lay_18B20 功能: 延时 参数: 延时时间 返回值: 无 /* * * * * * * * * * * * * * * * * * * * * / ? PR? _De lay_18B20? DS18B20 SEGM ENT CODE ; 程序存储区声明 PUBL IC _Delay_18B20 ; 输出函数名 RSEG ? PR? _Delay_18B20? DS18B20 ; 声明了 _De lay_18B20函数可被链接器放在存储器 的任何位置
2 模块间调用
首先了解汇编和 C51语言混合编程的可行性。 目前多数厂家的 C51 语言程序编译器都提供了把 C51语言程序转化为标准汇编程序文件的功能, 而 且, 许多 C 编译工具软件包也含有或附带有汇编 器 [ 3] 。如果用户 的汇编程序文件以 这种标准汇编 语言文件的形式来编写, 编译器和连接器就能把用 户的汇编代码和 C51语言代码无缝地结合到一起, 从而实现汇编与 C51 的混合编程。标准汇编语言 是针对相应的 C51编译器来说的, 因为不同的编译 器其标准汇编语言可能不同, 但是只要用户汇编程 序与所用的编译器的汇编程序格式一样, 那么这个 用户汇编程序就是标准的 (本文中使用的 Ke il C51 编译器 ) [ 4] 。
; A ssem bler Code H ere
# pragm a ENDASM 在 C51程序中嵌入汇编的方法虽然比较简单, 但不灵活, 可读性差。随着软件规模越来越大, 很多 大型项目需要多人合作进行分工设计, 由主函数来 调用各功能模块。如果还是采用模块内嵌入汇编, 则会使得程序的可读性大大降低汇。因此需要寻找 另外一种方法来实现汇编与 C 语言的混合调用 [ 3] 。
Ab stract: In em bedded prog ramm ing, C language and assem bly language are two k inds of the m ost w ide ly used languagesw ith their respect ive prom inent advantages in program designing. T his paper in troduces the m ixed ca lls m ethods by using two kinds o f programm ing language together. T ak ing DS18B20 temperature gathering system as an exam ple, it proves that it can m ake the process concise and efficient by using tw o languages flex ib ly. It supp lies a reference for students to learn and use C language and assemb ly language to solve pract ical problem s. Key w ord s: C language ; assemb ly language; m ixed calls; DS18B20
∀ F unct ion2 ( int a) a 在 R6,( char a, int b, in t* c) a在 R7中 传递, b在 R4, R5中传递, c在 R1, R2, R3中传递。
∃F unct ion4 ( long a, long b) a在 R4~ R7中传 递, b不能通过寄存器传递而只能通过固定存储区 传递。
以下通过一个流水灯的例子来说明标准汇编程 序的编写格式。 /* * * ; 程序功能: 流水灯
; 模块名称: LED. c ; 函数名: m a in( ) ; 参数: 无 ; 调用函数: _delay( unsigned t) * * * / ? PR? delay? LED SEGM ENT CODE ; 申明代码段 ? PR? m a in? LED SEGMENT CODE ; 申明代码段 PUBL ICm a in ; 输出函数名
表 1 转换规则
2. 2 参数传递 如果所调用的函数没有参数, 则 LCALL 调用指
令直接是 C51函数的函数名, 如果 C51函数需要通 过寄存器传递参数, 则需要在 C51函数的函数名前 加下划线 _ 。这是因为编译器在把有参数传递的 C51函数转换为汇编语言时在 C51函数的函数名前 添加了下划线, 所以要访问这个 C51函数也必须在 这个 C51函数前添加下划线才能保证正确的访问 到该函数。