MSP430F413做的DS18B20温度计
2008年11月05日 21:04 发布者:MSP430
/********************************************************
* MSP430F413测量显示DS18B20温度 *
* V1.3 *
* 2008-09-19 *
*********************************************************
更新内容: *
1. DS18B20的CRC校验; *
2. 增基本定时器定时1s,每5秒采集显示温度数据 *
3. P1.2中断进行电源电压判断 *
********************************************************/
#include //系统文件夹内找
#include "main.h" //当前文件夹内找
int main(void)
{
Sys_Init();
//开始温度转换-------------------------
i = 10;
while(Ds18b20_Init() & (--i) );
Ds18b20_WriteByte(SkipROM);
Ds18b20_WriteByte(Convert);
Delay_ms(900);
//ReleaseDQ(); //寄生电源时要拉高DQ
//------------------------------------
while(1)
{
TempCal(&wendu_fuhao, &wendu_zhensu, &wendu_yusu);
Display();
LPM3; //进入低功耗模式n,n:0~4。
//若不希望进入低功耗模式,屏蔽本句,但要加延时1s以完成温度转换。
}
}
/********************************************************
* Display *
********************************************************/
void Display(void)
{
if(wendu_fuhao)
LCDMEM[0] = digit[10]; //显示"-"
else
LCDMEM[0] = digit[12];
LCDMEM[3] = digit[wendu_zhensu%10];
LCDMEM[3] |= 0x10; //小数点
wendu_zhensu /= 10;
LCDMEM[2] = digit[wendu_zhensu%10];
LCDMEM[1] = digit[wendu_zhensu/10];
LCDMEM[4] = (digit[wendu_yusu/10] & 0x0f)<<4;//取低位放在高位,低位为标志符
LCDMEM[5] = (digit[wendu_yusu/10] & 0xf0)>>4; //取高位放在低位
LCDMEM[5] |= (digit[wendu_yusu%10] & 0x0f)<<4;
LCDMEM[6] = (digit[wendu_yusu%10] & 0xf0)>>4;
}
/********************************************************
* SYS初始化 *
********************************************************/
void Sys_Init(void)
{
/***以下填充用户代码,对各种模块、中断、外围设备等进行初始化***/
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
FLL_CTL0 |= XCAP14PF; // Configure load caps
SCFI0 |= FN_2; //频率范围
SCFQCTL =30; //N,如不设置默认=31
SCFI0 |= FLLD_2; //D=2,PUC后的默认值=2
//FLL_CTL1 |= FLL_DIV_4; //4分频,P1.5输出:f=32768/4
FLL_CTL0 |= DCOPLUS; //在MCLK前分频 f=D*(N+1)*faclk,2*(30+1)*32768=2031616Hz
LCDCTL = LCDON + LCD4MUX + LCDP2; // STK LCD 4Mux, S0-S17
BTCTL = BTFRFQ1; // STK LCD freq, 基本定时器输出fLCD=fACLK/64
P5SEL = 0xFC; // Common and Rxx all selected,公共极和 Rxx 选择
_EINT(); //打开全局中断控制,若不需要打开,可以屏蔽本句
IE2 |= BTIE; //打开基本定时器中断
BTCTL |= BTDIV + BTIP1+ BTIP2; // 1s interrupt
P1IES = BIT2 + BIT6; //P1.2,P1.6中断为1->0
P1IE = BIT2 + BIT6; //允许P1.2,P1.6中断,欠压检测
for(i=0;i<12;i++)
LCDMEM = digit[12];
time_yanshi = 5; //每5秒采集并显示温度
// P1DIR = 0x22; // P1.1 & P1.5 to output direction
// P1SEL = 0x22; // P1.1 & P1.5 to output MCLK & ACLK
// P6DIR |= BIT3;
// P6OUT = BIT3;
}
/*****************************************************************************
基本定时器中断函数 *
*****************************************************************************/
#pragma vector=BASICTIMER_VECTOR
__interrupt void BasTimer()
{
static uchar times;
times++;
if(times > time_yanshi)
{
times = 0;
// P6OUT ^= BIT3;
LPM3_EXIT; //退出中断后退出低功耗模式。
}
}
/*****************************************************************************
端口1中断函数
多中断中断源:P1IFG.0~P1IFG7
进入中断后应首先判断中断源,退出中断前应清除中断标志,否则将再次引发中断
******************************************************************************/
#pragma vector=PORT1_VECTOR
__interrupt void Port1()
{
if((P1IFG&BIT2) ==BIT2)
{
//处理P1IN.2中断
P1IFG &= ~BIT2; //清除中断标志
P1IES ^= BIT2; //P1.2中断为0->1
P1DIR&=~BIT2; //P1.2为输入方式
if(P1IN&BIT2 ) //判断P1.2电平高低
{
LCDMEM[0] &= ~BIT4;
IE2 |= BTIE; //打开基本定时器中断
}
else
{
LCDMEM[0] |= BIT4 ;
IE2 &= ~BTIE; //关闭基本定时器中断
}
}
else if((P1IFG&BIT6) ==BIT6)
{
//处理P1IN.6中断
P1IFG &= ~BIT6; //清除中断标志
//以下填充用户代码
key_yanshi ^= BIT0;
if(key_yanshi == BIT0) //奇次按下键盘,
time_yanshi = 1;
else
time_yanshi = 10;
}
}
/********************************************************
* DS18B20初始化 *
********************************************************/
uchar Ds18b20_Init(void) //存在返0,否则返1
{
uchar temp = 1;
uchar uttime = ReDetectTime; //超时时间
while(outtime-- && temp)
{
IoOut_DQ();
Delay_ms(2); //(250)1514us时间可以减小吗
ReleaseDQ();
Delay_us(2);
PullDownDQ();
Delay_us(600); //614us(480-960)
ReleaseDQ();
Delay_us(70); //73us(>60)
IoIn_DQ();
temp = ReadDQ();
Delay_us(500); //us
}
return temp;
}
/********************************************************
* 写bit2DS18B20 *
********************************************************/
void Ds18b20_WriteBit(uchar bitdata)
{
IoOut_DQ();
if(bitdata)
{
PullDownDQ();
Delay_us(2); //2us(>1us)
ReleaseDQ(); //(上述1-15)
Delay_us(85); //86us(45- x,总时间>60)
}else
{
PullDownDQ();
Delay_us(85); //86us(60-120)
}
ReleaseDQ();
Delay_us(2); //2us(>1us)
}
/********************************************************
* 写Byte DS18B20 *
********************************************************/
void Ds18b20_WriteByte(uchar chrdata)
{
uchar ii;
for(ii = 0; ii < 8; ii++)
{
Ds18b20_WriteBit(chrdata & 0x01);
chrdata >>= 1;
}
}
/********************************************************
* 写 DS18B20 *
********************************************************/
//void Ds18b20_Write(uchar *p_readdata, uchar bytes)
//{
// while(bytes--)
// {
// Ds18b20_WriteByte(*p_readdata);
// p_readdata++;
// }
//}
/********************************************************
* 读bit From DS18B20 *
********************************************************/
uchar Ds18b20_ReadBit(void)
{
uchar bitdata;
IoOut_DQ();
PullDownDQ();
Delay_us(2); //2us( >1us)
ReleaseDQ();
Delay_us(8); //8us( <15us)
IoIn_DQ();
bitdata = ReadDQ();
Delay_us(85); //85us(上述总时间要>60us)
return bitdata;
}
/********************************************************
* 读Byte DS18B20 *
********************************************************/
uchar Ds18b20_ReadByte(void)
{
uchar ii,chardata;
for(ii = 0; ii < 8; ii++)
{
chardata >>= 1;
if(Ds18b20_ReadBit()) chardata |= 0x80;
}
return chardata;
}
/********************************************************
* 读 DS18B20 ROM *
********************************************************/
//bit Ds18b20_ReadRom(uchar *p_readdata) //成功返0,失败返1
//{
// uchar ii = 8;
// if(Ds18b20_Init()) return 1;
// Ds18b20_WriteByte(ReadROM);
// while(ii--)
// {
// *p_readdata = Ds18b20_ReadByte();
// p_readdata++;
// }
// return 0;
//}
/********************************************************
* 读 DS18B20 EE *
********************************************************/
uchar Ds18b20_ReadEE(uchar *p_readdata) //成功返0,失败返1
{
uchar ii = 9;
if(Ds18b20_Init()) return 1;
Delay_us(1);
Ds18b20_WriteByte(SkipROM);
Delay_us(1);
Ds18b20_WriteByte(ReadScr);
Delay_us(1);
while(ii--)
{
*p_readdata = Ds18b20_ReadByte();
p_readdata++;
}
return 0;
}
/********************************************************
* 温度采集计算 *
********************************************************/
uchar TempCal(uchar *p_fuhao,uchar*p_wendu_zhensu,uchar *p_wendu_yusu) //成功返0,失败返1 (温度范围-55 --- +128)
{
uchar temp[9],ii,crc_data = 0;
uint tmp = 0;
uchar tmp_ys = 0;
*p_fuhao = 0;
//读暂存器和CRC值-----------------------
if(Ds18b20_ReadEE(temp))
{
return 1;
}
//-------------------------------------
//CRC校验------------------------------
for(ii = 0; ii < 9; ii++)
{
crc_data = CrcTable[crc_data^temp[ii]];
}
//-------------------------------------
if(crc_data == 0)
{
tmp = temp[1]; //
tmp <<= 8; //
tmp |= temp[0]; //组成温度的两字节合并
//温度正负数处理-----------------------
if(temp[1] >>= 4) //温度为负
{
tmp = ~tmp + 1;
*p_fuhao = 1; //返回值,1为负0为正
}
//-------------------------------------
//温度计算-----------------------------
tmp_ys =tmp % 16; //取十进制温度的余数
tmp_ys = (tmp_ys * 10) / 16; //十进制温度的小数*10(取小数点后一位)
*p_wendu_zhensu = tmp / 16;
*p_wendu_yusu = tmp_ys;
//-------------------------------------
}
//开始温度转换-------------------------
while(Ds18b20_Init() & (--ii) );
//Ds18b20_Init();
Ds18b20_WriteByte(SkipROM);
Ds18b20_WriteByte(Convert);
ReleaseDQ(); //寄生电源时要拉高DQ
//------------------------------------
return 0;
}
-----------main.h---------------
/********************************************************
* 命令字定义 *
********************************************************/
#define uchar unsigned char
#define uint unsigned int
/***精确定时方法*****/
#define CPU_F ((double)2031616) //8000000为 MCLK=8MHZ的意思*
#define Delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define Delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
/***调用此程序时实参必是数字,而不能使用变量作为实参。
Delay_us(1); //这是产生1微秒的延时
Delay_ms(1); //这是产生1毫秒的延时
Delay_us(3.5); //延时3.5毫秒,还是可以这样呢
Delay_ms(3.5); //延时3.5毫秒…是不是很实用?
***精确定时方法*****/
//设置重复检测次次数,超出次数则超时
#define ReDetectTime 20
//ds18b20命令
#define SkipROM 0xCC
#define MatchROM 0x55
#define ReadROM 0x33
#define SearchROM 0xF0
#define AlARMSearch 0xEC
#define Convert 0x44
#define WriteScr 0x4E
#define ReadScr 0xBE
#define CopyScr 0x48
#define RecallEE 0xB8
#define ReadPower 0xB4
//P2.0接DS18B20的DQ,P2.1为DQ的上拉电源
#define ReleaseDQ() P2OUT |= BIT0 //上拉/释放总线
#define PullDownDQ() P2OUT &= ~BIT0 //下拉总线
#define vcc() P2OUT |= BIT1
#define ReadDQ() P2IN&BIT0
#define IoIn_DQ() P2DIR&=~BIT0
#define IoOut_DQ() P2DIR|=BIT0
/********************************************************
* 函数 *
********************************************************/
void Display(void); //显示
void Sys_Init(void); //系统初始化
uchar Ds18b20_Init(void); //DS18B20初始化,存在返0,否则返1
void Ds18b20_WriteBit(uchar bitdata); //写bit2DS18B20
void Ds18b20_WriteByte(uchar chrdata); //写Byte DS18B20
void Ds18b20_Write(uchar *p_readdata, uchar bytes); //写 DS18B20
uchar Ds18b20_ReadBit(void); //读bit From DS18B20
uchar Ds18b20_ReadByte(void); //读Byte DS18B20
uchar Ds18b20_ReadRom(uchar *p_readdata); //读 DS18B20 ROM:成功返0,失败返1
uchar Ds18b20_ReadEE(uchar *p_readdata); //读 DS18B20 EE :成功返0,失败返1
uchar TempCal(uchar *p_fuhao,uchar*p_wendu_zhensu,uchar *p_wendu_yusu); //成功返0,失败返1 (温度范围-55 --- +128)
/********************************************************
* 变量 *
********************************************************/
uchar time_yanshi,key_yanshi;
uchar wendu_zhensu = 0;
uchar wendu_yusu = 0;
uchar wendu_fuhao = 0;
uchar i;
const unsigned char digit[13]=
{
0xAF, // "0" LCD segments a+b+c+d+e+f
0xA0, // "1" b+c
0xCB, // "2" a+b+g+e+d
0xE9, // "3" a+b+c+d+g
0xE4, // "4" b+c+f+g
0x6D, // "5" a+c+d+f+g
0x6F, // "6" a+c+d+e+f+g
0xA8, // "7" a+b+c
0xEF, // "8" a+b+c+d+e+f+g
0xED, // "9" a+b+c+d+f+g
0x40, // "-"
0x4f, // "E"
0x00 /* 不显示 */
};
const uchar CrcTable [256]={
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};