CC2530+Contiki+DS18B20+LCD12864

前言

CC2530 + Contiki操作系统,使用DS18B20温度传感器进行温度的采集和显示(串口打印和LCD显示)。

串口输出

LCD12864


驱动代码

LCD程序驱动参考CC2530+Contiki+LCD12864【传送门

ds18b20.h

驱动代码放到

1
$PROJ_DIR\contiki3.0\contiki-3.0\platform\cc2530dk\dev

不要忘了在工程里面添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef DS18B20_H_
#define DS18B20_H_

#include "cc253x.h"
#include "sys/clock.h"
/**************************************************
以下定义为DS18B20支持的所有命令
***************************************************/

#define SEARCH_ROM 0xF0 //搜索ROM
#define READ_ROM 0x33 //读ROM
#define MATCH_ROM 0x55 //匹配ROM(挂多个DS18B20时使用)
#define SKIP_ROM 0xCC //跳过匹配ROM(单个DS18B20时跳过)
#define ALARM_SEARCH 0xEC //警报搜索

#define CONVERT_T 0x44 //开始转换温度
#define WR_SCRATCHPAD 0x4E //写便笺
#define RD_SCRATCHPAD 0xBE //读便笺
#define CPY_CCTATCHPAD 0x48 //复制便笺
#define RECALL_EE 0xB8 //未启用
#define RD_PWR_SUPPLY 0xB4 //读电源供应

#define DQ P1_7 //DS18B20数据IO口
#define DQ_DIR_OUT 0x80 //DS18B20 IO方向
#define CL_DQ() DQ = 0 //清除数据
#define SET_DQ() DQ = 1 //设置数据
#define SET_OUT() P1DIR |= DQ_DIR_OUT //设置IO方向,out设置IO方向为输出
#define SET_IN() P1DIR &= ~DQ_DIR_OUT //设置IO方向,in设备IO方向为输入

extern void DS18B20_Write(unsigned char x); //DS18B20写命令

extern unsigned char DS18B20_Read(void); //DS18B20读数据

extern void DS18B20_Init(void); //DS18B20初始化/复位

extern void DS18B20_SendConvert(void); //发送转换温度命令

extern void DS18B20_GetTem(unsigned char *integer, unsigned char *decimal); //DS18B20获取温度

#endif

ds18b20.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "ds18b20.h"

/*
* 写命令函数
* 输入参数: 命令(DS18B20.H中定义)
* 输出参数: 无
* 返回参数: 无
*
*/
void DS18B20_Write( unsigned char cmd )
{
unsigned char i;
SET_OUT(); //设置IO为输出,2530->DS18B20
/*每次一位,循环8次*/
for( i = 0; i < 8; i++ )
{
CL_DQ(); //IO为低
if( cmd & ( 1 << i ) ) //写数据从低位开始
{
SET_DQ(); //IO输入高电平
}
else
{
CL_DQ(); //IO输出低电平
}
clock_delay_usec( 40 ); //保持15~60us
SET_DQ(); //IO口拉高
}
SET_DQ(); //IO口拉高
}


/*
* 读数据函数
* 输入参数: 无
* 输出参数: 无
* 返回参数: 读取的数据
*
*/
unsigned char DS18B20_Read( void )
{
unsigned char rdData; //读出的数据
unsigned char i, dat; //临时变量
rdData = 0; //读出的数据初始化为0
/* 每次读一位,读8次 */
for( i = 0; i < 8; i++ )
{
CL_DQ(); //IO拉低
SET_DQ(); //IO拉高
SET_IN(); //设置IO方向为输入 DS18B20->CC2530
dat = DQ; //读数据,从低位开始
if( dat )
{
rdData |= ( 1 << i ); //如果读出的数据位为正
}
else
{
rdData &= ~( 1 << i ); //如果读出的数据位为负
}
clock_delay_usec( 70 ); //保持60~120us
SET_OUT(); //设置IO方向为输出 CC2530->DS18B20
}
return ( rdData ); //返回读出的数据
}


/*
* DS18B20初始化/复位函数
* 输入参数: 无
* 输出参数: 无
* 返回参数: 无
*
*/
void DS18B20_Init( void )
{
unsigned char x = 60;
do
{
SET_OUT();
SET_DQ(); //IO口拉高
CL_DQ(); //IO口拉低
clock_delay_usec( 500 ); //IO拉低后保持一段时间 480-960us
SET_DQ(); //释放
SET_IN(); //IO方向为输入 DS18B20->CC2530
clock_delay_usec( 20 ); //释放总线后等待15-60us
}
while( x-- && DQ ); /* 等待DQ变低 */
clock_delay_usec( 100 ); //检测到DQ 变低后,延时60-240us
SET_OUT(); //设置IO方向为输出 CC2530->DS18B20
SET_DQ(); //IO拉高
}


/*
* DS18B20 转换温度函数
* 输入参数: 无
* 输出参数: 无
* 返回参数: 无
*
*/
void DS18B20_SendConvert( void )
{
DS18B20_Init(); //复位18B20
DS18B20_Write( SKIP_ROM ); //发出跳过ROM匹配操作
DS18B20_Write( CONVERT_T ); //启动温度转换
}


/*
* DS18B20获取温度函数
* 输入参数: 无
* 输出参数: 无
* 返回参数: 无
*
*/
void DS18B20_GetTem( unsigned char* integer, unsigned char* decimal )
{
unsigned char tem_h, tem_l; //温度高位字节及低位字节
unsigned char a, b; //临时变量
unsigned char flag; //温度正负标记,正为0,负为1
unsigned char FRACTION_INDEX[16] = {0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9 };//小数值查询表
DS18B20_Init(); //DS18B20复位
DS18B20_Write( SKIP_ROM ); //跳过ROM匹配
DS18B20_Write( RD_SCRATCHPAD ); //写便笺
tem_l = DS18B20_Read(); //读温度低位
tem_h = DS18B20_Read(); //读温度高位
/* 判断温度正负 */
if( tem_h & 0x80 )
{
flag = 1; //温度为负
a = ( tem_l >> 4 ); //取温度低4位原码
b = ( tem_h << 4 ) & 0xf0; //取温度高4位原码
tem_h = ~( a | b ) + 1; //取整数部分数值,不符号位
tem_l = ~( a & 0x0f ) + 1; //取小数部分原值,不含符号位
}
else
{
flag = 0; //为正
a = tem_h << 4;
a += ( tem_l & 0xf0 ) >> 4; //得到整数部分值
b = tem_l & 0x0f; //得出小数部分值
tem_h = a; //整数部分
tem_l = b & 0xff; //小数部分
}
*decimal = FRACTION_INDEX[tem_l]; //查表得小数值
*integer = tem_h | ( flag << 7 ); //整数部分,包括符号位
}

主进程代码

新建一个C文件,添加到以下目录

1
$PROJ_DIR\contiki3.0\contiki-3.0\examples\cc2530dk

不要忘了添加到工程里面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdio.h>
#include "contiki.h"
#include "dev/ds18b20.h"
#include "sys/clock.h"
#include "lcd_dis.h"

PROCESS( get_ds18b20_val, "get ds18b20 value" );
AUTOSTART_PROCESSES( &get_ds18b20_val );

unsigned char integer, decimal;
char temp[20];

/**
* 自定义延时函数
*/

void delay_ms( uint16_t dt )
{
while( dt-- )clock_delay_usec( 1000 );
};

/*
* 主进程
*/
PROCESS_THREAD( get_ds18b20_val, ev, data )
{
PROCESS_BEGIN();
// DS18B20 初始化
DS18B20_SendConvert();
// LCD 初始化
LCD_Init();
SetBackLight( 0 ); //设置背光的亮度等级为0
ClrScreen(); //清屏
FontSet_cn( 1, 1 );
FontSet( 1, 1 );
FontMode( 1, 0 );

while( 1 )
{
DS18B20_SendConvert();
DS18B20_GetTem( &integer, &decimal );

if( integer < 100 )
{
ClrScreen(); //清屏
sprintf( temp, "当前温度:%d.%d℃", integer, decimal );
printf( "%s\r\n", temp );
PutString_cn( 0, 0, temp );
}

if( integer > 31 )
{
printf("当前温度过高!\r\n");
PutString_cn( 0, 16, "当前温度过高!" );
}

delay_ms( 1000 );
}

PROCESS_END();
}

效果

串口

LCD

-------------本文结束感谢您的阅读-------------

本文标题:CC2530+Contiki+DS18B20+LCD12864

文章作者:FisherCloud/鱼摆摆

发布时间:2019年04月17日 - 14:08

最后更新:2019年06月11日 - 15:08

原始链接:http://fishercloud.tech/2019/04/17/CC2530-Contiki-DS18B20-LCD12864/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%