智能家居DIY教程连载(1)——如何正确使用 Sensor 框架

2019-7-17 17:56 [复制链接] 27 609

本帖最后由 WillianChan 于 2019-7-31 16:47 编辑 # a. a! D! g2 k; K# x0 D7 F

智能家居DIY教程连载(1)

, n9 g$ p; ]5 M8 i! g6 o
8 N/ W2 x7 `# g' ^3 K$ O: [

如何正确使用 Sensor 框架

! N9 e$ Q; ~$ t- I$ x
6 |1 L9 _+ n4 L( ~% h7 [$ `- o

Hi~各位小伙伴们,距离 DIY 项目的发布已经有一周的时间了,第一周的任务已经完成了吗?会不会遇到了问题无从下手?没关系,这篇文章很好的解决了大家的困惑,一起来看看吧。

" F  G+ A1 q  O9 D; t& a

1. 第一周任务回顾

9 q: g4 |; l+ W2 X5 T) K" b

我们来回顾一下第一周安排的任务:

) }" \% L8 q' P
    ; E, B, j; X7 u* Q- m
  • 正确读取 ds18b20 温度数据
  • , U; E2 l1 _7 f7 r6 |
  • 了解 RT-Thread 的 Sensor 框架,并将 ds18b20 对接到 Sensor 框架上
  • $ |* {7 Z8 L6 u6 z2 y+ Y7 B
  • 了解线程的使用,创建一个线程,在线程中读取温度数据,并通过FinSH控制台实时打印出来
  • + b$ M$ C; k9 d: I: t
, K3 A/ ]! ?# j

上述任务的重点,其实不在于把温度读取到就好了的,重点在于如何将 ds18b20 对接到 RT-Thread 的 Sensor 框架上去。

. [, l+ u" C3 J- m# V. }

Sensor 是物联网重要的一部分,“Sensor 之于物联网”相当于“眼睛之于人类”。人没有眼睛就看不到这大千的花花世界,物联网没有了 Sensor 更是不能感知这变化万千的世界。

4 c; a0 P+ V+ E# ]( L: S

现在,为物联网开发的 Sensor 已经很多了,不同的传感器厂商、不同的传感器都需要配套自己独有的驱动才能运转起来,这样在开发应用程序的时候就需要针对不同的传感器做适配,自然加大了开发难度。为了降低应用开发的难度,增加传感器驱动的可复用性,我们设计了 Sensor 驱动框架。

+ R/ _. K8 z: L4 ?4 ?! S2 X

Sensor 驱动框架的作用是:为上层提供统一的操作接口,提高上层代码的可重用性;简化底层驱动开发的难度,只要实现简单的 ops(operations: 操作命令) 就可以将传感器注册到系统上。

3 P0 l" C/ j, u

本次 DIY 活动,以 ds18b20 温度传感器为例子,教大家如何正确使用 Sensor 框架。

! g3 H/ u% n- U- _- W

2. Sensor 框架介绍

9 u0 a  Y# \  @* _( n3 J$ p* d

[align=center] sensor整体框架图.png
' q) m% W5 `. n; |  h" ~[/align]5 p+ ~3 }6 `  q7 Z' f Sensor 框架的整体框架图如上。它为上层提供的是标准 device 接口 open/close/read/write/control,这些接口与上层用户程序对接,为底层驱动提供的是简单的 ops(operations: 操作命令)接口:fetch_data/control,这两个接口对接具体硬件的底层驱动。除此之外,Sensor 框架还支持 module(模块),为底层存在耦合的传感器设备提供服务,如果,ds18b20 的底层不存在耦合,此处不需要用到 module。

: a, W* D' ?4 v. j+ H; `' b4 x

Sensor 框架更多的介绍在 RT-Thread 的文档中心已有详细说明,这里不过多赘述,详情请查看

8 w; A' |+ [0 u/ @* g- L: G: \/ H

3. Sensor 框架的使用

  q5 Y, g6 g, n: \% }8 \& U5 \7 j2 n

看完文档中心的 Sensor 介绍后,相信大伙儿已经对这个框架有了一定的了解。有的小伙伴是不是早就按耐不住想要跃跃欲试将传感器对接到 Sensor 框架上?这里以 ds18b20 温度传感器为例子。

/ H2 i+ M9 M' q0 ~

Sensor 框架的使用分两个步骤:ops 接口对接、传感器设备注册。

% i  y% c$ O  U3 T+ f, x2 M! ^' w

3.1 ops 接口对接

8 O. _+ P6 u1 j1 e

我们知道,Sensor 框架的接口分为上层接口和底层接口两种。将 ds18b20 的底层驱动对接到框架上,其实对接就是 Sensor 框架的底层接口,具体的,是底层的 ops 接口。

$ o3 @% j8 d1 b' r

我们在 RT-Thread 源码中可以找到 Sensor 框架的源码,源码路径为:rt-thread\components\drivers\sensors,在 sensor.h 文件中,我们可以找到对 ops 接口的定义,有两个函数指针,fetch_datacontorl

* I# x' ^2 d; @3 a1 [! X5 Q  T" I
struct rt_sensor_ops
1 p4 l7 r; v' y3 R+ w5 b{
( `5 P; i1 K  }  R    rt_size_t (*fetch_data)(struct rt_sensor_device *sensor, void *buf, rt_size_t len);- I" g5 ^" B6 d7 K& @, Q, e
    rt_err_t (*control)(struct rt_sensor_device *sensor, int cmd, void *arg);: s5 }: t$ e$ v  Y
};
& Y! x8 B" W- ?% D9 J3 i  y$ i" I

fetch_data 作用是获取传感器数据,control 作用是通过控制命令控制传感器,ds18b20 并不支持 control,我们只需要实现 fetch_data 就好了。

+ `" t* y8 V7 ?$ K% E+ ?  ~

Sensor 框架当前默认支持轮询(RT_DEVICE_FLAG_RDONLY)、中断(RT_DEVICE_FLAG_INT_RX)、FIFO(RT_DEVICE_FLAG_FIFO_RX) 这三种打开方式。需要在这里判断传感器的工作模式,然后再根据不同的模式返回传感器数据。我们以轮询的方式读取 ds18b20 的温度数据,那么 fetch_data 的实现如下:

' z8 F% a9 m! l3 i1 J
static rt_size_t ds18b20_fetch_data(struct rt_sensor_device *sensor, void *buf, rt_size_t len)' t# T+ \) P: n) m& w6 p4 V1 a
{# l$ c$ i7 g: ?4 M7 O5 h9 t
    RT_ASSERT(buf);
9 Y! D3 `# Q6 e7 f/ B/ Y
. r( r! i9 Y: b7 ~  L- b! F4 W( |    if (sensor->config.mode == RT_SENSOR_MODE_POLLING)
$ W( U/ c: p4 o1 l% [/ D9 o7 i    {/ k' e( \, W0 }0 n  V
        return _ds18b20_polling_get_data(sensor, buf);
; S' B8 F8 V9 g$ H4 z8 w% `% v    }
' T) o' F  N" n6 P4 c    else
  w3 y% G! v- x% Z# C- i( ?/ W8 c        return 0;
+ d6 l8 s( g! }$ d}
) n; Q+ W# x2 Y: c% Y5 w' P+ N6 P

具体的,_ds18b20_polling_get_data(sensor, buf) 的实现如下,其中,ds18b20_get_temperature 函数就是 ds18b20 温度传感器底层驱动的获取温度的函数。

0 @2 Q$ E( p, _$ P( L
static rt_size_t _ds18b20_polling_get_data(rt_sensor_t sensor, struct rt_sensor_data *data)
$ ^* r# {6 i5 s8 H) ~! f" W2 K+ `{6 h! n% E) a# c: A2 P& i
    rt_int32_t temperature_x10;
- t- r9 K( @  f- r    if (sensor->info.type == RT_SENSOR_CLASS_TEMP)1 X- S7 q) c) z# E% r6 E
    {
# e" z# m5 S. T( S6 {9 A        temperature_x10 = ds18b20_get_temperature((rt_base_t)sensor->config.intf.user_data);' O" i) e& g1 w9 |" {1 e
        data->data.temp = temperature_x10;& a$ b, b% z% ?* V" |" n
        data->timestamp = rt_sensor_get_ts();( A, u+ J) ?3 f* m* Q" G
    }    
) g# R0 X, z* F- j* o* w    return 1;
' l$ w* J$ l" ^6 v  e}
  l1 E8 M7 A0 g- ^- C1 r

因为不需要 control,我们直接让 control 返回 RT_EOK 即可

8 L5 X$ m( m, G1 g3 x
static rt_err_t ds18b20_control(struct rt_sensor_device *sensor, int cmd, void *args)' `( k1 ]) M3 G9 ~/ j: k
{
& d: c1 d0 V/ c1 n2 L5 J1 J+ J    rt_err_t result = RT_EOK;! b% Z2 ?. B( J* k0 \! C

8 a. N  w5 U1 j% m    return result;4 H6 I" Q3 M5 u# E, @/ ~
}
# p7 r8 {- J" v' O: C* N$ m% O

这样,我们的 ops 函数就写好了。然后,需要实现一个设备接口的结构体 ops 存储上面的接口函数:

; b( o' P% k( u; M" [
static struct rt_sensor_ops sensor_ops =
7 ~( d9 W1 N; E: }1 @{  s: V/ r+ N7 x7 {
    ds18b20_fetch_data,1 @) p# G6 U; c' X# a2 n
    ds18b20_control
' M6 w, a4 L' t5 @/ z" H5 J};
) q' s- {* T2 E9 M3 b5 O  r

这样一来, ops 接口就对接成功了。

) y) h5 q3 p' B9 w. B! R4 _

3.2 传感器设备注册

5 P# L; e* q; d$ h  M

完成 Sensor 的 ops 的对接之后还要注册一个 Sensor 设备,这样上层才能找到这个传感器设备,进而进行控制。

' H# {6 i( V, c2 [* o+ L/ V

设备的注册一共需要下面几步:

1 T& P% a! ]/ d# `* H: N" N; x2 ]4 A
    7 k, w  D' }6 H
  • 创建一个 rt_sensor_t 的结构体指针
  • 8 w- ?$ w% x% a3 y
  • 为结构体分配内存
  • 9 R  X  U; r! k! P
  • 完成相关初始化
  • 9 x! \1 ^/ }8 p  h" H
  A+ _% C/ u) ~" G+ u0 m; m) [$ g

具体的,放到 ds18b20 上面来,具体实现如下:

  m+ O9 ^2 r7 T/ b( K$ J
int rt_hw_ds18b20_init(const char *name, struct rt_sensor_config *cfg)7 V( ^: j9 e6 ?  E3 _. Z
{. y, D/ J% u& |
    rt_int8_t result;
: o# K9 e- N  N    rt_sensor_t sensor_temp = RT_NULL; 
, R: c8 N8 z# E+ q! H0 T! k
, M0 w, `  j& I    if (!ds18b20_init((rt_base_t)cfg->intf.user_data))5 i; a: S7 I. j4 w/ y! ]/ N9 f
    {
) \& J: A$ R9 Y  m        /* temperature sensor register */  y* e% E  K: X! W2 h
        sensor_temp = rt_calloc(1, sizeof(struct rt_sensor_device));8 ]# Q5 O6 y: M  f- A. @. G
        if (sensor_temp == RT_NULL)# P' a0 E- f6 `" }1 u2 z
            return -1;
$ d. `1 g3 |. R- ~, \# d, D
/ V; Y5 @6 s5 @) @: d        sensor_temp->info.type       = RT_SENSOR_CLASS_TEMP;
6 L: a1 x- J/ ]) Y( l/ s8 r        sensor_temp->info.vendor     = RT_SENSOR_VENDOR_DALLAS;
: ~' i- r' B2 c5 L        sensor_temp->info.model      = "ds18b20";
1 S; F6 p& w( w        sensor_temp->info.unit       = RT_SENSOR_UNIT_DCELSIUS;) ~! q4 M8 k- A* \7 g: [$ b
        sensor_temp->info.intf_type  = RT_SENSOR_INTF_ONEWIRE;; q9 J, p9 M- |- f' v+ x+ t
        sensor_temp->info.range_max  = SENSOR_TEMP_RANGE_MAX;
1 I, {4 W/ n  Y        sensor_temp->info.range_min  = SENSOR_TEMP_RANGE_MIN;
" w1 V1 Z- ?: ], m- D        sensor_temp->info.period_min = 5;2 [5 o% \3 q6 n

7 O+ ~& D* h6 b8 o) ?        rt_memcpy(&sensor_temp->config, cfg, sizeof(struct rt_sensor_config));. q+ w+ n) h* X% d1 W7 u% B
        sensor_temp->ops = &sensor_ops;: a( G3 z. `/ Z0 |
8 ?) y6 j, {. Q
        result = rt_hw_sensor_register(sensor_temp, name, RT_DEVICE_FLAG_RDONLY, RT_NULL);
" b( ~( o4 Z9 u        if (result != RT_EOK)$ O# Y4 T, h5 `* o7 K
        {
; A7 Q( D& q& ]$ t4 W            LOG_E("device register err code: %d", result);5 h0 y( T( ^0 r8 I: g- H
            goto __exit;& b' n- l, A) e. |
        }
  q2 Z9 W% c6 r$ f  R- N2 D* l" u& D, t- J+ j4 L6 @0 n; A& s7 `
    }
9 l2 ]" d: S8 u% ~7 s    return RT_EOK;# \0 Y/ Q+ M- K  V: q' @
! F" w% L- [. S* e/ I  j6 u
__exit:4 |) N8 h# c! U, h7 _: g
    if (sensor_temp)$ {* h0 i3 D8 h' v/ \
        rt_free(sensor_temp);
' h1 a" i$ u' e# |# u- J9 x; C* G    return -RT_ERROR;     
# y. w: S) e; p  p  ^9 s: b}
, J# C! |; d  c# j* m2 T! g

我们来解读一下。

9 G7 k) W- ]: P3 C$ c

传感器设备注册的第一步:创建一个 rt_sensor_t 的结构体指针,上述代码中是这么实现的:

6 ?1 h- z! {! ^
rt_sensor_t sensor_temp = RT_NULL;
- P% ~, ?' g& W4 c8 ^% k

传感器设备注册的第二步:为结构体分配内存,上述代码中是这么实现的:

, A* Q5 m: t& ~: `& S
sensor_temp = rt_calloc(1, sizeof(struct rt_sensor_device));
* T: n& a+ [  U: I* Jif (sensor_temp == RT_NULL)( i  ?% `+ S2 ^5 u
    return -1;
, Z- I" l' \+ i$ X  {; [

传感器设备注册的第三步:完成相关初始化,上述代码中是这么实现的:

8 a. B5 C  T( {0 ~
sensor_temp->info.type       = RT_SENSOR_CLASS_TEMP;- O# @9 H/ f7 V
sensor_temp->info.vendor     = RT_SENSOR_VENDOR_DALLAS;4 x: g) `2 l2 o
sensor_temp->info.model      = "ds18b20";
+ n; k, [& K5 k8 }sensor_temp->info.unit       = RT_SENSOR_UNIT_DCELSIUS;* J0 |. Q, b8 I7 P" r& R
sensor_temp->info.intf_type  = RT_SENSOR_INTF_ONEWIRE;
; k) [" N4 @. T9 s$ u$ q7 \+ {sensor_temp->info.range_max  = SENSOR_TEMP_RANGE_MAX;
. L+ Q: o7 d5 E" Ssensor_temp->info.range_min  = SENSOR_TEMP_RANGE_MIN;
' D7 s3 t4 L6 K) I4 csensor_temp->info.period_min = 5;
1 o" T) K2 J2 {* H9 [  V( E8 P: N- L2 F1 r
rt_memcpy(&sensor_temp->config, cfg, sizeof(struct rt_sensor_config));
! I/ w' B# D- L% ssensor_temp->ops = &sensor_ops;8 a9 F1 c: i8 H
, ~0 D" E1 f, v

传感器设备注册的三个步骤完成之后,就可以放心大胆地注册传感器设备了,上述代码中是这么实现的:

3 ^: t3 K7 Q6 h7 U
rt_hw_sensor_register(sensor_temp, name, RT_DEVICE_FLAG_RDONLY, RT_NULL);$ V" O' v1 F8 h. l
9 `9 W+ W7 N+ T; d, E

上述的“ops 接口对接”和“传感器设备注册”两个工作完成后,就可以通过 Sensor 框架中的上层接口 open/close/read/write/control,对 ds18b20 进行操作了。

9 ]- P& R+ y8 `: f$ X3 _

先不着急,我们在 FinSH 中输入 list_device 命令查看 ds18b20 温度传感器是否真的已经被注册上去了:

& D% H' y& S8 z0 t

[align=center] list_device.jpg ; V! P2 y9 @; ]8 Y0 i [/align]
  X/ K6 ?% h6 K/ b' }$ T$ R哇!成功将 ds18b20 注册成传感器设备了,可喜可贺!!!

. E3 g) W+ e# Y. i

传感器驱动对接 Sensor 框架的操作中的更多细节,请在 RT-Thread 的文档中心中查看

: L; [( \, Y7 F

4. 在线程中读取温度数据

1 f4 j1 r$ Q% N5 K

我们通过一个线程,去实时获取 ds18b20 的温度数据。

4 D# H+ d5 H4 R) F7 ]) \9 u

线程的基本操作有:创建/初始化( rt_thread_create/rt_thread_init)、启动(rt_thread_startup)、运行(rt_thread_delay/rt_thread_control)、删除/脱离(rt_thread_delete/rt_thread_detach)。

) h, G2 i; E8 R8 \0 j3 t; \

之前我们已经将 ds18b20 对接到 ops 接口并成功注册成传感器设备了,接下来就可以利用 Sensor 框架的上层接口 open/close/read/write/control 对 ds18b20 进行操作了。

& E3 X$ s! Z9 B* w* t

main 函数中创建一个读取 ds18b20 温度数据的线程并启动它,线程入口函数是 read_temp_entry

: E7 T5 V, H4 D1 T5 e
rt_thread_t ds18b20_thread, led_thread;
- F4 Z4 Z. ^5 R% b9 Y& o0 I8 y( o0 q" \6 B% u
ds18b20_thread = rt_thread_create("18b20tem",/ P) z3 o* ^# V4 L0 z( D6 c$ r
                                  read_temp_entry,
# f$ ?! @$ u7 t" Y, X6 k. H! Q3 t                                  "temp_ds18b20",. f" R4 Q* @' F* H6 u
                                  512,
) N4 n' k" D6 o- U: B                                  RT_THREAD_PRIORITY_MAX / 2,' |& E( n0 |' l  P) P
                                  20);
$ X. c" e1 ^$ jif (ds18b20_thread != RT_NULL)1 s3 j, T* w1 g/ {5 c! z3 K) T
{
/ |$ b$ j7 q; v+ R; x6 \    rt_thread_startup(ds18b20_thread);8 ^& {" a  w% [$ Q' O
}; t+ }6 N* t' X% u$ S; k& g
) F. k7 }3 n( m' x. d

在线程入口函数 read_temp_entry 中,我们通过几个步骤,就可以读取 ds18b20 的温度数据了:

9 a6 n% b. M+ c% H5 \
    , h2 d! f: w: @# v
  • 创建一个 rt_sensor_data 的数据结构体
  • + ~/ D: o" |8 q$ @* c7 Y$ y' A
  • 查找传感器设备驱动
  • 8 o5 P8 ]$ W1 @( A7 E
  • 打开对应的传感器设备
  • 6 g; W" c* S% Y2 V0 M7 Z: z3 y
  • 读取传感器设备数据
  • " a' q1 N, F  G4 e& O0 O4 b
7 r# W0 W4 k0 y6 Z2 G

上述步骤具体实现如下:

" Y/ F" X/ Z; Q4 _3 o# |
static void read_temp_entry(void *parameter)0 q  a' g$ q0 z. T$ d. \  J$ Y
{% S  i$ {7 N1 q
    rt_device_t dev = RT_NULL;
+ x( S0 a. H: o" m; z1 j) Y    struct rt_sensor_data sensor_data;
% u. E% O/ I6 Y% x    rt_size_t res;
6 ?& O( v5 I& u
1 O. y0 N4 P5 t0 [    dev = rt_device_find(parameter);: |- C+ o" ^' D/ O5 l( u
    if (dev == RT_NULL)
$ c! R4 q' }5 a1 o& r    {
+ E; F: q; `  u( D5 @, r0 |8 ]        rt_kprintf("Can't find device:%s\n", parameter);
5 u0 h& e' a8 ^3 \, k0 }6 T# u        return;2 r- g" y$ q: x9 N" g
    }4 K- c, a, c  `; W) r. J& W, j
% B+ ^( a4 U3 r$ B' T& ^
    if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK)  P, {, F! ^1 A8 p& g. w* G
    {# `  {; N2 w" S1 C
        rt_kprintf("open device failed!\n");
4 b7 }3 q9 y+ \& `# o- q        return;
9 w, h* b( ?& h- r    }8 z$ Y8 u* Q. g$ M
    rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100);
8 k4 w$ E' L$ r& s, j7 ]# N  x3 j1 ]
    while (1)9 B, `( B7 ^% b1 X$ h4 P4 F' R( D8 g
    {
( i$ \0 X0 b3 G" x+ U2 F        res = rt_device_read(dev, 0, &sensor_data, 1);
: ?* Y' x6 q  \1 R% i# J9 |1 E        if (res != 1)' \4 g- V, s' C
        {
, b) f1 L1 f% ^( ~* r& Y            rt_kprintf("read data failed!size is %d\n", res);
* A" @4 z  _& X. C            rt_device_close(dev);4 C' @) x9 U8 q* q0 R
            return;# J# {/ p" R# T. i9 i# G
        }; x4 z% L: h* Q3 A: S" C
        else
3 Q1 K1 O* G% q$ c2 F# I# m, p5 d5 u        {
, I1 d7 E, e7 K) L+ A$ J0 U2 ]* ~            rt_kprintf("temp:%3d.%dC, timestamp:%5d\n", sensor_data.data.temp / 10, sensor_data.data.temp % 10, sensor_data.timestamp);
0 w3 ^# k! X) B! x        }+ W0 ]) J# k) k) Z0 _
        rt_thread_mdelay(100);
4 b, \; Y% U* I; }    }( q6 h0 c, V' a# c2 P
}
: E* Q7 m* z# _& M
; g2 Y6 n0 [( ], E5 n; L1 r

通过 FinSH 控制台,查看该线程源源不断输出的数据:

( f( `2 y5 p5 t& t

[align=center] result.jpg ' K0 _' \: ~8 | [/align]
4 W2 l, ]* x# w2 X8 Z$ r4 U9 a+ B温度数据在线程中被正确读取出来了,到此为止,本周任务就算是成功完成了的,因吹斯听~(^_^)

2 U" D  c6 R+ e  E6 |3 w

5. 开源代码

' ~6 Z2 t: a! K

为了更进一步便于大家学习,第一周任务的代码已经开源啦~ 请点击这里查看

$ N) F" N0 g/ p" ]

6. 注意事项

2 w% A* R+ T4 Z+ R" C1 r" E
    ! W! H' N  s- b6 C' b! s
  • 欲使用 Sensor 框架,当然是要在 menuconfig 中将它开启啦:
  • - _  K$ e) z. O4 A2 v) B( w' {
0 h- n3 Y& [7 e" y1 B$ p# }- p1 i
RT-Thread Components  ---》* @( b" _( M; q7 U
    Device Drivers  ---》: w+ A! ?! M8 [
        Using Sensor device drivers
. L# V( Z- D8 l! h
5 D1 W! I5 u5 _+ [  O0 E6 x
    - \8 f& `2 g) g- o2 h
  • 打开之后,需要使用 scons --target=mdk5 更新工程即可。看,Sensor 框架加入到工程当中了:
  • * P1 z* l7 I; ~# S' d7 K% G: b9 y9 l
( v  B, J2 `5 _5 I0 y( j

[align=center] sensor in project.jpg
/ T" G! @0 {2 `; b& C[/align]

4 c' j- T1 V2 y7 W. X4 b
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-7-17 17:56:34 | 显示全部楼层
我自己顶自己(沙发
使用道具 举报 回复
发表于 2019-7-17 18:00:41 | 显示全部楼层
地板
使用道具 举报 回复
发表于 2019-7-17 18:02:38 | 显示全部楼层
先顶后看,楼主NB!
使用道具 举报 回复
发表于 2019-7-17 18:03:29 | 显示全部楼层
使用道具 举报 回复
发表于 2019-7-17 18:08:50 | 显示全部楼层
flyboy 发表于 2019-7-17 18:00+ s8 }3 f' t' T; Q7 Y
地板

( W5 l( Y4 Z8 T- f你是板凳
使用道具 举报 回复
发表于 2019-7-17 18:11:42 | 显示全部楼层
论坛的排版功能好辛苦啊, > [align]9 z" W; ?3 q$ R, z0 _! i
% h" u1 h, U7 m9 w, {8 M7 [
如果能增加源码模式就好了
使用道具 举报 回复
发表于 2019-7-17 18:19:06 | 显示全部楼层
不知道从WordPress转自己的博文方便不
使用道具 举报 回复
发表于 2019-7-17 18:20:53 | 显示全部楼层
word天 发表于 2019-7-17 18:19
) i6 V1 L0 U( W% ?/ h+ r不知道从WordPress转自己的博文方便不
% |; Y6 Z# }7 \6 u1 i
可以试试
使用道具 举报 回复
发表于 2019-7-17 18:21:26 | 显示全部楼层
wuhanstudio 发表于 2019-7-17 18:11
% k7 T) `7 x- U论坛的排版功能好辛苦啊, >
% `+ D: \3 p+ [& ?
+ \2 M  M* h; ?- ?如果能增加源码模式就好了
  v8 b+ L0 L8 k- I& K  {& Q7 g$ t
>全部变成>了
使用道具 举报 回复
发表于 2019-7-17 18:21:47 | 显示全部楼层
2 z4 Z) U! X* c* k/ `6 N/ P  s
使用道具 举报 回复
发表于 2019-7-18 08:44:34 | 显示全部楼层
过来顶一下
使用道具 举报 回复
发表于 2019-8-3 21:43:14 | 显示全部楼层
写到rt_hw_sensor_register(sensor_temp, name, RT_DEVICE_FLAG_RDONLY, RT_NULL)这句就能在finsh上查看到注册的ds18b20设备了?
使用道具 举报 回复
发表于 2019-8-6 17:33:13 | 显示全部楼层
欲盖弥彰1314 发表于 2019-8-3 21:43
# x, r5 T. l8 w3 I; N% j9 F写到rt_hw_sensor_register(sensor_temp, name, RT_DEVICE_FLAG_RDONLY, RT_NULL)这句就能在finsh上查看到 ...

7 A* ?1 U8 k. b( |) Q当然,这句代码之前的前期工作要做到位,才行
使用道具 举报 回复
发表于 2019-8-11 16:22:30 | 显示全部楼层
请教一下,我用的潘多拉板,如果用aht110代替ds18b20的话,这是温湿度,能不能只注册一个传感器就能输出两个参数呀
使用道具 举报 回复
发表于 2019-8-11 17:54:48 | 显示全部楼层
aprilhome 发表于 2019-8-11 16:22
; a5 P* B/ Y# x0 }请教一下,我用的潘多拉板,如果用aht110代替ds18b20的话,这是温湿度,能不能只注册一个传感器就能输出两 ...

( p, A) ^2 E! q( Q/ E完全可以的,而且AHT10可以在menuconfig中打开了,轮子已经造好了,直接用就行
使用道具 举报 回复
发表于 2019-8-11 20:57:55 | 显示全部楼层
谢谢大神回复,实际应该怎么写这个函数呢,我自己这样弄的,我觉得是不是能调用一个rt_device_read就可以把数据都写到一个sensor_data呢,就像sensor_data->temp,sensor_datat->humi,这种?% H4 ~6 @# ~/ ?: D; n& U0 y
  1. static void read_aht10_entry(void *parameter)- m# E) u4 S: Z; L
  2. {+ `( D" e0 U6 L( V" {
  3.     rt_device_t dev_temp = RT_NULL;; f# O( W# Z' i& {
  4.     rt_device_t dev_humi = RT_NULL;7 y- a! M7 q6 ~" D8 A0 w" L
  5.     void *parameter_temp = "temp_aht10";
    1 x' L+ R% r1 j9 e7 t2 _- G3 B
  6.     void *parameter_humi = "humi_aht10";
    & o* S: K* x/ M  s$ O! a- ?, L
  7.     struct rt_sensor_data sensor_data1, sensor_data2;0 t" ^) `1 J% k
  8.     rt_size_t res1, res2;
    8 Q! v9 W7 q/ S& ?# ]% \
  9.     $ q  @  S/ _/ L( u- ]  y
  10.     dev_temp = rt_device_find(parameter_temp);
      I8 N. ^0 D; \
  11.     dev_humi = rt_device_find(parameter_humi);
    ; {5 \( [7 Q! H2 l
  12.     if (dev_temp == RT_NULL)
    : X' N0 f7 }* C( }
  13.     {
    7 h; s* n' D* x$ t& f
  14.         rt_kprintf("can't find device:%s\n", parameter_temp);/ t2 b+ Y$ G, G1 p# h
  15.         return;
    7 \  B" [  j; t; R. A5 p6 Z5 V
  16.     }5 {, G8 `5 }& k9 [% N
  17.     if (dev_humi == RT_NULL)) B* @( F0 m* D6 E- M- J
  18.     {
    $ L" F8 }: i& X1 {2 p
  19.         rt_kprintf("can't find device:%s\n", parameter_humi);6 ~4 [+ }0 Y' p6 {
  20.         return;! ?& X$ B2 R) }' i9 [0 g
  21.     }
    3 f1 }. D; m/ [& b
  22.     6 `! t6 K2 G: a: n% E3 f" \) ~
  23.     if (rt_device_open(dev_temp, RT_DEVICE_FLAG_RDWR) != RT_EOK)
    ( _6 y2 E+ R) Z2 q2 L
  24.     {/ `- R# ]3 }0 d
  25.         rt_kprintf("open device failed\n");; W6 w8 B6 n; }1 \. {
  26.         return;# _- p) G& Z9 i5 c4 z5 x7 ~# I
  27.     }
    4 k6 r% x/ \0 m( v9 J
  28.     if (rt_device_open(dev_humi, RT_DEVICE_FLAG_RDWR) != RT_EOK)$ X" p! ~! \. A& B% v+ I- I
  29.     {6 L" p( i0 D; ]9 w! s9 W5 g
  30.         rt_kprintf("open device failed\n");( }2 f$ G/ N  a3 p+ P; a! G4 u" x
  31.         return;0 }+ p+ O7 D7 X* e
  32.     }( ]% D& H5 P$ Q* n' _- V$ s
  33.     ' g. ~! D8 E+ A. ^, Z# V5 F
  34.     rt_device_control(dev_temp, RT_SENSOR_CTRL_SET_ODR, (void *)100);
    * E2 v9 o0 i# H& ~$ P/ F) `
  35.     rt_device_control(dev_humi, RT_SENSOR_CTRL_SET_ODR, (void *)100);
    6 Q) I3 n4 ~: h
  36.     8 Z7 n) Z# ]1 T2 n
  37.     while (1)7 @, O! @0 R! s7 S6 d. k( [
  38.     {! u4 \! G$ g5 r. R* D
  39.         res1 = rt_device_read(dev_temp, 0, &sensor_data1, -1);: W3 P8 L" i2 U8 X8 U
  40.         res2 = rt_device_read(dev_humi, 0, &sensor_data2, -1);, [: _. @) @( O2 @& f2 f8 D+ m  d! w
  41.         if ((res1 != 1) || (res2 !=1))# I) }& J, |; F* |8 X$ W$ d7 z' F
  42.         {/ |4 F8 F. H" }- n6 k- |
  43.             rt_kprintf("read datat failed,size if %d\n", res1);) l6 a6 K* j3 [
  44.             rt_device_close(dev_temp);
    % F' J2 b* V$ ]% a, B3 V9 y' ]5 N2 p: }3 n
  45.             return;. }4 r9 q! u8 f9 A
  46.         }
    0 Q8 H6 _; f) ^$ g% B! o. m) e
  47.         else
    , m, X( R9 r; b7 d+ F
  48.         {% `9 H3 |" R. m- S4 r3 I$ g- ^0 X( \
  49.             rt_kprintf("temp:%3d.%dC, humi:%3d.%d%%, timestamp:%5d\n",
    - Y5 \4 _+ A: p+ N) P. l/ V
  50.                         sensor_data1.data.temp / 10, sensor_data1.data.temp % 10,
    2 V& z, ^, H2 ~; R: y
  51.                         sensor_data2.data.humi / 10, sensor_data2.data.humi % 10,- z9 G. m9 h8 [  `/ a- m
  52.                         sensor_data1.timestamp);' C0 O+ J6 f- u( a
  53.         }( m8 K; J* J: O0 {
  54.         rt_thread_mdelay(100);        
    7 _) X9 N0 m. z  {* d1 b, P+ k( U
  55.     }) K" G. ]1 F$ Q" @  S( I
  56. }
    5 Z) G3 h+ g* g7 K, o" N4 W
  57. . s* }- t& a0 S7 A
  58. static void led_shine_entry(void *parameter)
    ' G$ y2 j( k" Q4 c; d
  59. {' @$ A& \( G0 W% {" E
  60.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    1 h! i+ ~) ]# T: h' x" C
  61.     ) l; O% O+ }% o& H
  62.     while(1)
    2 q/ C' K4 N' H" \" X
  63.     {$ X$ q; D. ?; M; H8 k
  64.         rt_pin_write(LED0_PIN, PIN_HIGH);
    1 [9 n+ {: }. t7 B2 A, S
  65.         rt_thread_mdelay(500);
    8 d% E! P$ v9 \- v2 t
  66.         rt_pin_write(LED0_PIN, PIN_LOW);/ l) @4 w( K) H1 n6 }( X" ?
  67.         rt_thread_mdelay(500);
    5 h9 n# p+ k0 i9 _9 F7 b2 _% P
  68.     }& N4 {5 L4 j0 O/ q
  69. }
复制代码
使用道具 举报 回复
发表于 2019-8-12 15:24:27 | 显示全部楼层
aprilhome 发表于 2019-8-11 20:57
. Y5 ~$ r8 i9 t, D谢谢大神回复,实际应该怎么写这个函数呢,我自己这样弄的,我觉得是不是能调用一个rt_device_read就可以把 ...

9 X8 Q: ~" Z% D: W直接在menuconfig中将aht10的软件包获取下来参照一下就好了
使用道具 举报 回复
发表于 2019-8-12 22:04:59 | 显示全部楼层
WillianChan 发表于 2019-8-12 15:242 h% L/ ]1 D. H4 w& A8 ]
直接在menuconfig中将aht10的软件包获取下来参照一下就好了
) |8 W7 K! T1 h1 x
嗯,好的,我在看看哈
使用道具 举报 回复
发表于 2019-8-12 22:17:57 | 显示全部楼层
WillianChan 发表于 2019-8-12 15:24
, ]9 N4 q- K% o8 p' j直接在menuconfig中将aht10的软件包获取下来参照一下就好了

9 S5 R$ r  O* _0 r$ [我把第一个任务的例程下载下来,编译提示找不到sensor.h,这可能是哪的问题呀
使用道具 举报 回复
发表于 2019-8-13 10:37:48 | 显示全部楼层
aprilhome 发表于 2019-8-12 22:17. I! e6 z2 W6 ^  |' P7 c+ d
我把第一个任务的例程下载下来,编译提示找不到sensor.h,这可能是哪的问题呀 ...
9 ~: O2 r7 C% }4 x
你的例程代码是直接从GitHub上克隆下来的吗?请提供相关报错截图,方便进一步分析问题
使用道具 举报 回复
发表于 2019-8-13 10:38:38 | 显示全部楼层
aprilhome 发表于 2019-8-12 22:17
+ P: H( U) `' \( C2 D: \8 ?4 [, j我把第一个任务的例程下载下来,编译提示找不到sensor.h,这可能是哪的问题呀 ...

/ `( H- l0 N; U1 S+ Q) l; fGitHub上的代码经过编译、下载验证的,不会有问题。有可能是你clone不全
使用道具 举报 回复
发表于 2019-8-13 20:55:46 | 显示全部楼层
WillianChan 发表于 2019-8-13 10:38' Q- I* `7 Q# H8 C
GitHub上的代码经过编译、下载验证的,不会有问题。有可能是你clone不全
! u/ e6 a6 S+ x0 {6 v
你好,是从github下载的zip压缩包。试了一下,错误是这样的,iar版本为
{80F56690-7D26-456E-A61C-C3F7D84F5583}.png.jpg
{2C96CA07-7A8F-4407-8377-C46A408D77BB}.png.jpg
{07E2222F-D0BC-4D09-A7FE-A16180CE2BDB}.png.jpg
使用道具 举报 回复
发表于 2019-8-13 20:57:39 | 显示全部楼层
WillianChan 发表于 2019-8-13 10:38) h" f/ m# K) T5 i3 C+ v
GitHub上的代码经过编译、下载验证的,不会有问题。有可能是你clone不全

0 |- b* h2 A  W) Q* o8 B  {& V后来参考您另一个帖子的回帖,下载了一个MDK5,编译通过,没有问题,版本是5.27.0.0,这是跟开发环境有关吗....
使用道具 举报 回复
发表于 2019-8-19 09:48:26 | 显示全部楼层
aprilhome 发表于 2019-8-13 20:573 b' G/ i% U1 A8 \1 j+ C1 O/ |5 v
后来参考您另一个帖子的回帖,下载了一个MDK5,编译通过,没有问题,版本是5.27.0.0,这是跟开发环境有关 ...

9 b6 Y# ^2 d5 M, c8 K0 _这个关系不大
使用道具 举报 回复
发表于 4 天前 | 显示全部楼层
C:\Users\99642\Desktop\1568190888(1).jpg为什么我直接下载软件包,将代码下到板子里面还是找不到ds18b20
1568190888(1).jpg
使用道具 举报 回复
发表于 4 天前 | 显示全部楼层
检查一下代码上定义的DS18B20数据引脚和实际硬件上连接的数据引脚是否一致
使用道具 举报 回复
发表于 4 天前 | 显示全部楼层
WillianChan 发表于 2019-9-11 17:22$ @" a. J  o' t1 n+ d
检查一下代码上定义的DS18B20数据引脚和实际硬件上连接的数据引脚是否一致
' u1 N5 c' l( C7 I9 e# J5 g$ F
一致的,检查过了,还换过DS18b20了,刚开始搞RTT,不是很懂,按照您的贴一步一步看着底层弄,最后结果就是没把device弄上去。
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区 ( 沪ICP备13014002号-1

有害信息举报电话:021-31165890 手机:18930558079

© 2006-2019 上海睿赛德电子科技有限公司

Powered by RT-Thread

快速回复 返回顶部 返回列表