hnr_s5.c

来自「msp430开发版程序」· C语言 代码 · 共 279 行

C
279
字号
//DS18B20温度测量实验
//在 “1602字符型液晶显示实验” 的基础上修改

//功能:在数码管上显示当前DS18B20测到的温度
//小数部分为4位,温度为负时,最高位显示"-"
//测量范围:-55℃ ~ +125℃

/*
将多功能模块电路板接到P3口,
需要将电路板16*2液晶模块接到J12的LCD接口上,注意引脚顺序。
*/

#include "msp430x14x.h"
#define  uchar unsigned char
#define  uint unsigned int
#define RS_HIGH P6OUT|=BIT5 //指令数据选择信号
#define RS_LOW P6OUT&=~BIT5 
#define RW_HIGH P6OUT|=BIT6 //读写信号
#define RW_LOW P6OUT&=~BIT6
#define E_HIGH P6OUT|=BIT7 //使能信号
#define E_LOW P6OUT&=~BIT7
#define BUSY_OUT P1DIR|=BIT7
#define BUSY_IN P1DIR&=~BIT7
#define BUSY_DATA P1IN&BIT7
uchar Data1[16]={"                "};
uchar Data2[16]={" www.huanor.com "};

//DS18B20测温////////////////////////////
#define DQ_OUT P3DIR|=BIT1
#define DQ_IN P3DIR&=~BIT1
#define DQ_LOW P3OUT&=~BIT1
#define DQ_HIGH P3OUT|=BIT1
#define DQ_DATA P3IN&BIT1

uchar Bit[8]={17,0,0,0,0,0,0,0}; //数码管各位显示的数字
uchar BitCode=0x80; //数码管位码初值
uchar MSB; //温度高字节
uchar LSB; //温度低字节
int t1=0; //温度整数部分数值
uint t2=0; //温度小数部分数值
uchar flag; //负温度标志
////////////////////////////////////////


//延时子程序
DelayMS(uint ms)
{
	uint i;
	while(ms--)
	{
		for(i=0; i<800;i++);
	}
}

// 测试LCD忙碌状态
void LcdBusy()
{
	RS_LOW;
	RW_HIGH;
	E_HIGH;
	_NOP();
	_NOP();
	BUSY_IN;
	while(BUSY_DATA);
	BUSY_OUT;
	E_LOW;
}

//写入指令到LCD
WriteCommand(uchar Command)
{
	LcdBusy();
	RS_LOW;
	RW_LOW;
	E_HIGH;
	_NOP();
	_NOP();
	P1OUT=Command;
	_NOP();_NOP();
	E_LOW;
}

//写入字符数据到LCD
WriteData(uchar Data)
{
	LcdBusy();
	RS_HIGH;
	RW_LOW;
	E_HIGH;
	_NOP();
	_NOP();
	P1OUT=Data;
	_NOP();
	_NOP();
	E_LOW;
}

//LCD初始化设定
LcdInit()
{
	WriteCommand(0x38);//8位数据端口,2行显示,5*7点阵
	DelayMS(5);
	WriteCommand(0x0c);//开启显示, 无光标
	DelayMS(5);
	WriteCommand(0x06);//AC递增, 画面不动
	DelayMS(5);
	WriteCommand(0x01);//清屏
	DelayMS(5);
}


//DS18B20程序/////////////////////////////////////////
//10us级延时子程序
void Delayus(uint us)
{
	while(us--)
	{
		for(uint i=0;i<8;i++);
	}
}

//初始化DS18B20
void DS18B20Init(void)
{
	DQ_OUT;//设置为输出方向
	DQ_LOW;//拉低总线
	Delayus(50);
	DQ_HIGH;//释放总线
	Delayus(6);
	DQ_IN;//设置为输入方向
	while(DQ_DATA);//等待应答信号
	while(~DQ_DATA);//等待释放总线
}

//读一个字节
uchar ReadByte(void)
{
	uchar i;
	uchar ReadData=0;
	for(i=0;i<8;i++)
	{
		DQ_OUT;
		DQ_LOW;
		ReadData>>=1;
		DQ_HIGH;
		Delayus(1);
		DQ_IN;
		if(DQ_DATA) ReadData|=0x80;
		Delayus(6);
	}
	return ReadData;
}

//写一个字节
WriteByte(uchar WriteData)
{
	uchar i;
	uchar tmpData;
	for(i=0;i<8;i++)
	{
		tmpData=WriteData&0x01;
		WriteData>>=1;
		DQ_OUT;
		DQ_LOW;
		if(tmpData)
		{
			DQ_HIGH;
		}
		else
		{
			DQ_LOW;
		}
		Delayus(5);
		DQ_HIGH;
	}
}

//温度计算程序
void GetT()
{
	if((MSB&0xF0)>0)
	{ //判断是否为负温度
		flag=1;
	}
	else
	{
		flag=0;
	}
	if(flag)
	{ //如果为负温度取反加1
		MSB=~MSB;
		LSB=~LSB+1;
	}
	t1=MSB<<4; //得到温度整数部分
	t1|=(LSB>>4);
	t2=(LSB&0x0F)*0.0625*10000; //得到温度小数部分并扩大10000倍
	//计算各位数码管要显示的数值
	if(flag)
	{
	  	Bit[0]='-';
		Bit[1]=0; //如果为负温度则显示"-"
	}
	else
	{
	  	Bit[0]='+';
		Bit[1]=t1/100;
	}
	Bit[2]=t1%100/10;
	Bit[3]=t1%10;
	Bit[4]=t2/1000;
	Bit[5]=t2%1000/100;
	Bit[6]=t2%100/10;
	Bit[7]=t2%10;
}
//////////////////////////////////////////////////////


main()
{
	uchar i;
	WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
	//端口初始化  
	P1DIR=0xFF;//P1口所有引脚设置为输出方向
	P6DIR=0xFF;//P6口所有引脚设置为输出方向
	//初始化时钟  
	BCSCTL1=RSEL2+RSEL1+RSEL0;//XT2开启 LFXT1工作在低频模式 ACLK不分频 最高的标称频率
	DCOCTL=DCO2+DCO1+DCO0;//DCO为最高频率
	do
	{
		IFG1&=~OFIFG;//清除振荡器失效标志
		for(uint i=255;i>0;i--);
	}while(IFG1&OFIFG);//判断XT2是否起振
	BCSCTL2=SELM1+SELS;//MCLK SMCLK时钟源为TX2CLK不分频
	
	LcdInit();//Lcd初始化
//	_DINT();//关闭中断
	while(1)
	{
	  	DS18B20Init();
		WriteByte(0xCC); //跳过ROM配置
		WriteByte(0x44); //启动温度转换
		
		DelayMS(750);	//等待转换完毕
		
		DS18B20Init();
		WriteByte(0xCC);
		WriteByte(0xBE); //读温度寄存器
		LSB=ReadByte(); //读温度数据低字节
		MSB=ReadByte(); //读温度数据高字节
		GetT(); //计算温度

		Data1[2] = 'T';
		Data1[3] = '=';
		Data1[4] = Bit[0];	//+-温符号
		for(i=1;i<8;i++)
		{
			if(i==3)
			{ //显示数据及小数点
			  	Data1[i+4] = Bit[i]+48;	//HEX 转为字符
				Data1[i+5] = '.';
			}
			else if(i<3)
			{ //显示整数部分
				Data1[i+4] = Bit[i]+48;	//HEX 转为字符
			}
			else
			{//显示小数部分
				Data1[i+5] = Bit[i]+48;	//HEX 转为字符
			}
			DelayMS(1); //延时1ms
		}
		WriteCommand(0x80);//定位在第一行第一个位置
		for(i=0;i<16;i++) WriteData(Data1[i]);
		WriteCommand(0x80|0x40);//定位在第二行第一个位置
		for(i=0;i<16;i++) WriteData(Data2[i]); 
	};
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?