|
前言 本文是个人笔记,文章只讲基本流程, 最后所有的资料原理图和程序都会上传至资源。 - E7 Y- j3 `5 T
一、硬件部分单品传感器的硬件部分还是很简单的: 1、STM32L051 和 STM32F103 是 Pin to Pin 的; 2、测温传感器使用的是I2C接口,使用了软件I2C,因为 D6T 是5V供电,所以使用了电平转换电路; 3、整个传感器项目需求是 485 通讯的,因为实际环境要求,所以采用了周立功的 485 模块; # }) @, r3 h- r' s
1.1 STM32部分老样子,最小系统都是一样的:
1 J- _2 t- Z0 J$ X9 Y; w9 A
# Y, @% C( R, P# E
1.2 传感器部分
3 J y# `; K8 }0 s8 l, P& Q! P, R) b- v4 ?! {1 `
' p; T; W o9 {7 r) ~$ q' _7 S5 M
5 w- Y" w) r8 h/ Q6 w0 T6 N$ T, _% F5 J6 ^
在这里插入图片描述
% e, v9 E! q1 S
: @/ t; |. k* D( b% M# e9 q1.3 485通讯部分
4 L$ Q1 \7 m" l+ g
' z- d4 [- X* d: @
3 s3 B$ g. S6 g7 N
) P2 E' s4 ^* ~8 y; u/ m/ _ T) r. y8 @- j& K
. B/ l$ g: `0 Z8 D
- N, J3 D3 |5 {% t& c) E- G! |& Z7 k2 p9 U
" F; B% }( _5 A% m4 r' `1.4 电源部分
5 {, { p8 \) O
0 p/ X# ^" |, s& S) F1 k/ S R2 C* U3 a3 c
二、☆软件部分☆硬件部分是简单的,本项目的核心就在于软件的实现,有2个部分是核心: 1、I2C 通讯驱动; 2、485 通讯驱动; 1 c' t+ C! R* P* }) n. T4 r J
2.1 传感器 I2C 通讯部分这里上一下上层调用的函数,具体的驱动细节见下文说明: - void D6T_Measure()' u1 f! \, k P9 Q g7 h
- {
7 ?) [6 ~+ h+ p+ ^. f5 @ - u8 D6Tbuff[20];- Z, w2 r6 s' w' R# { T
- u8 D6T_Data=0;9 q+ j7 l1 ~' g9 ?7 [/ z
- // u16 tPEC;
# _, J3 P$ y, F N2 W9 m; A1 x8 ]- H% { - 2 T8 b( M ]1 |6 e8 d! B
- i2c_start();6 j2 `' C3 Q% m5 I! X$ t( A. T
- i2c_send_byte(0X14); //地址,和读写指令
5 H! X0 }8 t. |3 W" S - i2c_wait_ack();
8 ^; Y5 k) O @8 F; d+ S2 W - delay_us(150); //这里必须加
3 Y6 @$ j! u! v" l - , j5 S# P8 Z- x1 z1 q
- i2c_send_byte(0X4C);1 M7 x4 L ~! _ }1 O+ Z
- i2c_wait_ack(); - l' I' N7 n' Y5 w; D" f& a
- 0 f' _/ e2 e8 f
- delay_us(150);5 u6 S- w5 @& p0 [% c2 u' P/ h b) B T
. ~. {; ?/ z( I- i2c_start();
7 a6 J+ b$ H( H/ H+ h - i2c_send_byte(0X15); //地址,读指令$ R. K$ z0 T+ R+ J. w n( N+ @
- i2c_wait_ack();3 b+ t9 t: d2 s& I1 ]9 m Y
- delay_us(120);% x9 _8 c( Q! i1 Y
9 x, s7 }0 F2 G- // D6T44L_ReadLenByte(5); //D6T-1A-02 只有5个数值8 r$ \7 j' L0 ]4 f1 W& c7 a* c/ {
- u8 t;1 }1 i, A0 O. d
- D6T_Data=0;9 X' C" O. d4 Y+ K2 s' g, ?
- for(t=0;t<(5-1);t++)
9 a8 [) b0 \( P. P - {3 p* {- ~' J$ j
- D6Tbuff[D6T_Data++] = i2c_read_byte(1);
& L9 V s. _) k0 a - delay_us(120);
5 @# l$ T% i1 s4 A1 i - }7 x4 B5 T1 d% s! X
- D6Tbuff[D6T_Data] = i2c_read_byte(0);8 v) y. b* l8 a0 x" Z- p4 z
- delay_us(120);
2 D5 W. l ]1 }2 C2 r9 [ M2 t - i2c_stop();
- p0 i+ n3 X7 q - / |- ]7 [, q& V6 v2 e% ]" _! y
- // tPTAT = 256 * D6Tbuff[1] + D6Tbuff[0];: i- R4 E; i9 T# }0 t l) }/ V
- tP = 256 * D6Tbuff[3] + D6Tbuff[2];
1 F/ d. t0 \# x) y - }
) V: f5 n) r4 G: X1 E
: |7 L, a- }7 S; L
: N& d1 q4 i/ D7 J2 i2 ?6 r- O; e- unsigned char calc_crc(unsigned char data)
5 ~3 |' W }0 W# z+ g+ } - { ! R, f( u; Z) ~* E; Q3 z. H
- int index; 0 x2 v/ O: I) q2 e6 _- s2 o9 Q7 l
- unsigned char temp;
& O) r& s1 A5 K - 8 a" J& c( x2 ^7 p1 ~+ y& v& p
- for(index=0;index<8;index++){
* ?0 f, Y7 a, c* _* _; q - temp = data; 1 r7 l `! b% s/ t5 h
- data <<= 1;
) Q2 _; O$ x+ m8 o - if(temp & 0x80) data ^= 0x07; ! V5 j* L1 N- k8 c1 C. j
- }
; G* ~2 r) `, U* ~2 D s5 Z M - return data;
5 f% J1 Q/ d$ O1 _ - }
复制代码
5 V5 y+ T( Q) \6 I" }2 E3 q# [0 S7 Z( k! |
2.2 485 通讯部分本传感器是作为 485 从机设备,所以需要写一下 ModbusRTU 协议驱动,这里就不墨迹,直接源码奉上: - #include "Modbus_rtu.h"
/ p7 ?9 z/ ~4 L7 i - #include "stdio.h"
" i# h3 ~6 @1 [- Z
: Q0 `0 e$ f% r# b, J. h( U6 q- void Modbus_check() _# s& K8 Z+ z0 Z0 b
- {( S# R( {8 H8 X' q: u
- u16 crc;8 h3 R# ^3 V+ Z8 {1 E0 h7 ?: V
- u16 receivecrc1;
# L/ |; _; |6 u4 u - u16 receivecrc2;& l4 X. J6 `9 {1 }, H" U( s* S
- u8 sendbuff[5];
) d @" k5 }) ?# `$ K. F7 `7 ]/ T9 b - /* ' r5 a$ ~/ {* X) A3 I
- 收到了8个数据:01 03 00 10 00 01 D5 CA! w9 f+ j: @: x9 e% Y
- USART2_Data = 8;0 G0 l$ `5 p! v* R( Q/ e( X8 u# ~
- USART2_BUF[0] ~ USART2_BUF[7] ;* r! x; j) [- G( C( Y
- 要做校验的数为6个,所以是 USART2_Data - 2;/ ]- {, V6 T+ K
- 校验需要计算的是 USART2_BUF[6], USART2_BUF[7]( r5 d3 ]& F8 Y3 f5 M: q) p8 X; `
- USART2_BUF[USART2_Data - 2] 和 USART2_BUF[USART2_Data - 1]9 V5 D$ B% l: ~4 q
- */4 U3 K w% { v
- crc = Checksum_CRC16(USART2_BUF,USART2_Data - 2);3 ]4 C/ t( L! _/ {" f2 K, k( S$ n0 ~
- // printf("crc is :0x%x\r\n",crc);
1 L. |7 k- z$ l. ~ - /*No matter the high bits before or the low bits before*/
$ A8 }' @* p# D' |9 |5 Z+ @ - receivecrc1 = (USART2_BUF[USART2_Data - 2]<<8) + USART2_BUF[USART2_Data - 1];* c9 V) u! ]5 C* i S6 b
- receivecrc2 = (USART2_BUF[USART2_Data - 1]<<8) + USART2_BUF[USART2_Data - 2];
* q) E/ X. t. t- H. @ Y" H3 D - // if((lrc == receivelrc2)||(lrc == receivelrc1)){
/ O0 D0 h( M+ n0 X) u! ]1 \1 {8 [' a - // if(USART2_BUF[0] == mymodbus_add){+ p# R" ~1 Z% D8 W" |
- //这里说明一下,先判断地址,然后返回错误,如果先判断校验,如果出错了,那么总线上所有都同时返回就有问题了7 I' H% p0 {' b7 S3 ?
- if(USART2_BUF[0] == mymodbus_add){
1 B: U! W$ M* O! m7 Z- _ [ - if((crc == receivecrc2)||(crc == receivecrc1)){
6 j) I6 \6 y' N9 \( V - switch (USART2_BUF[1]){
* y& z, c. [& A0 m0 }2 x3 {4 I - case 3:
+ @: Q7 o3 Y# O - Modbus_03_ack();- N! y9 G6 P1 R# q
- break;
; t8 R+ b: R a0 { J' O# e - case 6:
7 Y# V4 _* a7 Q5 U Q9 R4 ] - Modbus_06_ack();
- p* B6 _! @* i1 Z - break; ! N2 d5 n4 A6 [
- default:
# R" P& u' Y! v( `- g5 Z. u - // printf("An unsupported command!\r\n");//for test2 P7 f: L) [4 o
- sendbuff[0] = mymodbus_add;6 Y3 v9 R; V; J; M3 P$ O
- sendbuff[1] = 0x80 | USART2_BUF[1];
+ I) l' W# q7 j1 Z) d+ F( v( @ - sendbuff[2] = 2;
, o/ e# \1 K5 m; X$ ]$ l( i1 ` - crc = Checksum_CRC16(sendbuff,3);# C/ _4 C9 Y4 ]7 Q/ S
- sendbuff[3] = (u8)(crc >> 8);
4 _- Z0 ^" |' n! W - sendbuff[4] = (u8)crc;
6 o6 w' I" F$ h' Y' g k - Uart2_sendBuffer(sendbuff,5);
$ H, d+ m, d; {5 L' ?4 L2 D$ h - break;
1 I) n8 J. c/ \1 b. p - }
; v$ @: A/ H. D( l0 N q - }0 z7 P. h, v. p% b6 Z
- else{ //校验错误,返回异常
" M6 e% B) Y" c1 g p4 w - sendbuff[0] = mymodbus_add;
4 G4 W( W% l; t( u: Y6 c2 p - sendbuff[1] = 0x80 | USART2_BUF[1];
# |+ e+ P$ ?8 e9 q - sendbuff[2] = 0;; n4 q( m" d! [- L' S, `
- crc = Checksum_CRC16(sendbuff,3);' L$ G+ m3 Q5 ]8 [- v- N
- sendbuff[3] = (u8)(crc >> 8);
' Q4 n; J' {1 c M$ w' f - sendbuff[4] = (u8)crc;' l2 a* T% l5 a+ A
- Uart2_sendBuffer(sendbuff,5);& e* h( l) T) k" E& U
- }
. V1 J) f* e" D9 b+ C3 n - } 5 @8 [8 n* ^, L6 H6 T/ f
- }/ x- h8 V7 D9 t
- 6 N! h; ?5 P& k1 N! n$ F5 E: I
- void Modbus_03_ack(){: p& r0 L& P j
- u16 Register_add; // 2,3
6 }1 }+ {: m' }0 p9 B- U5 _' y b - u16 Register_len; // 4,5
, a; G9 ~% ~' h! L$ G - u16 crc;
! K' \' S" i1 [1 _- c" a3 H - u8 i;
: o$ i4 s. @; ]- E! x" H" L% c' c% T - u8 j;2 y7 `/ ~5 |1 S) |3 E' `3 F* E
- 5 L. v7 Q4 ?# n9 O1 u- ]3 G
- Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
, d" d% J6 Q4 v# \( H) g# [% F: c - Register_len = (USART2_BUF[4]<<8) + USART2_BUF[5]; //get len;2 |2 F4 B) F5 q1 i
- / ~+ k! g+ A7 R
- u8 sendbuff[Register_len*2 + 5];
+ Z$ c2 D0 U3 P/ W% h5 L' n+ Q - /*. v! T1 K: H2 t% `
- 如果读取的地址写错了,或者读取长度超过规定的长度
( ]0 o) ~, j, b - 返回错误. k/ P( D; A+ G0 h; E
- */
+ R2 |) n! r+ A! l5 t% b4 ] - if(( 0x0010 <= Register_add)&&( Register_add <= 0x0014 )&&(Register_len < 6)){ 2 R0 Z: ~9 ~! } {7 S5 \
- i = 0;
, o7 c) e9 X& d; p* }) r S - sendbuff[i++] = mymodbus_add;& G# u) S- f6 p1 d# l, T* j
- sendbuff[i++] = 0x03;0 f5 B4 x% ~) \ O# s: @3 ?! n
- sendbuff[i++] = Register_len<<1;$ u0 F( y" S3 V) T3 B1 O0 b7 U
- switch(Register_add){" N5 [" H3 J# `6 Y+ V1 ?
- case 0x0010:1 w, l- e, w! {" l; k0 S
- for(j=0;j<Register_len;j++){
8 v( U- D7 T/ Y9 S; L% G/ |. { - sendbuff[i++]= (u8)(Register_value[0+j]>>8); //发送读取数据字节数的高位
3 D5 J8 f& [0 n: Z/ X2 |2 g - sendbuff[i++]= (u8)Register_value[0+j]; //发送读取数据字节数的低位
# p& d+ K5 Q6 C+ g0 [5 { - }
p O3 n5 a% \5 _& N1 s* l - break;" {& g" U. p7 y4 U
- case 0x0011:2 h9 f/ R0 X! w3 v1 ]4 c
- for(j=0;j<Register_len;j++){. b- t* Y! y# ~- Z
- sendbuff[i++]= (u8)(Register_value[1+j]>>8);
. S0 n4 }- \) Z! y% O - sendbuff[i++]= (u8)Register_value[1+j]; + i) r/ g) b4 A" N! m' G! N4 `
- }* v: B" C& ?4 b5 F
- break;
" L, p& U$ D3 s" K: K5 Y; V3 n3 R+ j1 C7 v - case 0x0012:
, l( J: m9 E% K& X/ {) ]! s% \ - for(j=0;j<Register_len;j++){' ], u: y+ r* T( p; k4 Y O
- sendbuff[i++]= (u8)(Register_value[2+j]>>8);
6 n3 v! L1 {( u" Q# J# E - sendbuff[i++]= (u8)Register_value[2+j]; k7 I4 g( r% N0 L' Q }5 a/ y% N
- }8 [0 s' K {$ M+ S
- break;
- I- _, j5 W& I! m1 Q! } - case 0x0013:1 i* r' [' f# Y9 `5 j5 b4 H4 I& @6 H
- for(j=0;j<Register_len;j++){$ d& X2 X: \% L# S0 G
- sendbuff[i++]= (u8)(Register_value[3+j]>>8); 8 K1 s# ]/ X7 }, A' G. a4 h# Z
- sendbuff[i++]= (u8)Register_value[3+j];
- Y1 R$ L5 p9 x - }# u2 P0 Y4 v5 _- p8 ]* J
- break;
" H, `9 B5 p& e' `6 u - case 0x0014:
2 c3 P3 `7 _7 |& L - for(j=0;j<Register_len;j++){
6 C$ ^" a# r7 W& N* s/ u. n - sendbuff[i++]= (u8)(Register_value[4+j]>>8); ; @4 ~$ n. v2 x
- sendbuff[i++]= (u8)Register_value[4+j]; " g& w$ n5 K! `! u6 l5 s" x
- }. I X1 l# h1 `' U9 W1 ?5 }4 x- Y
- break;
$ h) O1 y$ a, A4 V- p9 |) } - default:break; 6 g' M4 y, D C0 r
- }( H/ v3 `0 N/ v" f/ N
- crc = Checksum_CRC16(sendbuff,i);
0 h$ ^3 `& I! l9 ^, h9 S; f% a* r& K - sendbuff[i++] = (u8)(crc >> 8);
5 B* Y) K5 G5 f8 S8 I - sendbuff[i++] = (u8)crc;5 M2 m V) z( n
- Uart2_sendBuffer(sendbuff,i);
$ G! A7 ~; T: `% O( z - }2 S0 K6 n, L, g
- else{//地址不在规定返回或者长度太长,返回错误
1 m: [3 z. O) e - sendbuff[0] = mymodbus_add;
6 g0 a& T. z6 ], p( ]/ ] - sendbuff[1] = 0x80 | USART2_BUF[1];; V! U1 x. u- O# I
- sendbuff[2] = 1;
5 d, C1 p* b+ s7 w4 W - crc = Checksum_CRC16(sendbuff,3);9 I. A) ]& L4 s# A+ o( e" E
- sendbuff[3] = (u8)(crc >> 8);* v7 p4 u; g1 }
- sendbuff[4] = (u8)crc;2 H: X% A# v7 U2 ]; A$ Y
- Uart2_sendBuffer(sendbuff,5);, V- I) _- R$ D7 i+ k
- }
, Q c( f! V8 [+ v" T# { - }
" S5 U6 W8 J- |8 `1 K% D5 \
{3 `% p% J) Y" Z" K- void Modbus_06_ack(){
. v' T0 A: x" k( @ - u16 Register_add; //
$ |! V# b9 Y o3 \+ u# @4 G3 K: d - u16 val; // ! j L8 b- f' M1 }- @5 B
- u16 crc;
# i9 [- w2 e$ k. ?+ w5 I( z - u8 i;
, S" H2 ^4 \- b8 R - u8 sendbuff[8] = {0};8 P2 H+ [2 M6 q) S, a
- if(USART2_Data < 9){
2 C7 I* K% l3 B! D - Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
' x$ m+ R! @- \0 p+ @* i6 I# r- L& H2 ~ - val = (USART2_BUF[4]<<8) + USART2_BUF[5]; //
+ |6 L$ K2 c; b& ]; N4 E - ) B0 T% ?7 _, ~
- if((val > 0)&&(val < 248)){/ F. d% i f6 g, c9 {
- if(Register_add == 0x0013){
0 q. H4 f" n3 \ - mymodbus_add = val;
7 {% ^. c9 ?8 W& E9 O. J - Register_value[3] = mymodbus_add;
7 }& }) E% g/ }" _3 ?+ I7 K, m - MY_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,Modbus_ID_ADDR,mymodbus_add);
q5 c9 W9 ?' a - i = 0;
# w- v! w7 g" B0 a - sendbuff[i++] = mymodbus_add;
( O; B& L) F/ d( T - sendbuff[i++] = 0x06;; n9 ^, x* g) C% W6 X
- sendbuff[i++] = (u8)(Register_add>>8); 5 a" M+ W* S# ], c# o
- sendbuff[i++] = (u8)Register_add; 5 A. i' A) M8 m- R6 ^
- sendbuff[i++] = (u8)(val>>8); + O, @ C& X3 S" `/ v G
- sendbuff[i++] = (u8)val;
# D7 v f7 \ `6 P# b. A - crc = Checksum_CRC16(sendbuff,i);
6 b" j) j" d; x9 @6 A - sendbuff[i++] = (u8)(crc >> 8);1 N. b- g% l. u. |0 f
- sendbuff[i++] = (u8)crc;
; b, }( M% z, ?" Q$ _( {! R# S M - Uart2_sendBuffer(sendbuff,i);
2 S2 t, L+ L' C+ @+ a1 R - }
% h, i1 I' o) Y a2 _% V0 d: A* E" u+ K - else{//写地址不在规定范围$ C- i/ D# _5 q/ W3 `& o
- sendbuff[0] = mymodbus_add;1 f2 j- Y+ T" k- H; d# D
- sendbuff[1] = 0x80 | USART2_BUF[1];3 l6 a3 |+ i# ?
- sendbuff[2] = 3;
, }* [ M0 s0 o! u; o5 R - crc = Checksum_CRC16(sendbuff,3);
. `# {5 e. E. U' w6 T* _ - sendbuff[3] = (u8)(crc >> 8);
0 U) k! b8 K( j5 l" ~% o - sendbuff[4] = (u8)crc;* @. m% q8 r/ |' _
- Uart2_sendBuffer(sendbuff,5);
2 ~5 m( P) A- Y1 @% @) r - }
3 ]& g' j. O& P- M/ } - }else{//写地址不在规定范围2 Z: {& g7 y9 D( u( D7 Z
- sendbuff[0] = mymodbus_add;
- y9 {8 S$ c& q2 D - sendbuff[1] = 0x80 | USART2_BUF[1];5 p X2 k( R& W, p
- sendbuff[2] = 4;
. Q7 w% d$ P( E7 E - crc = Checksum_CRC16(sendbuff,3);$ m1 N# k' q& H" j0 `% E
- sendbuff[3] = (u8)(crc >> 8);6 ` B) @8 q8 x# j
- sendbuff[4] = (u8)crc;0 W9 R) U {1 f+ a
- Uart2_sendBuffer(sendbuff,5);
$ t+ a: D9 e L; o0 ^, B) W - } Z! M1 h: K3 {: y. Q
- }& j& m/ o E* I7 Q7 f
- else{//写地址不在规定范围
7 O2 c7 E" ?) m- h7 S# x - sendbuff[0] = mymodbus_add;1 ~0 Z( x4 X ~
- sendbuff[1] = 0x80 | USART2_BUF[1];6 u$ k/ Z. q! c, X- d
- sendbuff[2] = 1;
1 t" Y1 E5 _7 E7 c6 M* ?1 @ - crc = Checksum_CRC16(sendbuff,3);" x2 u, J- \; ^$ r/ b
- sendbuff[3] = (u8)(crc >> 8);0 k7 S+ ^/ f+ U( Z) t i4 Q
- sendbuff[4] = (u8)crc;
: H& A0 Z! H( b! K, L( [9 x - Uart2_sendBuffer(sendbuff,5);- E& s/ S# h6 H% g, b3 h- a
- }
) w' ?2 w, l+ v* T% J - }
. l W, y) O2 W" Q* N( x5 X& m8 S
复制代码 ' x Q5 o9 T2 |6 T
2.3 其他代码说明此项目的核心就是上面2个的驱动,其他部分,STM32和一些基本的按键驱动,LED等操作都和以往项目基本一样。 实际上当初我在 FreeRTOS 记录 实例的时候就是使用的这个项目作为说明的,所以从 0 开始的设计思路 当然额外说一句,这种 单品传感器 的简单的项目一般来说用不用 RTOS 实际使用上区别不大。 ; E& ?. x9 y, F) [& D$ Q2 Q+ S$ j' j8 D
如有侵权请联系删除 转载自: [color=var(--weui-FG-2)]矜辰所致7 @; K; j& i7 X, B7 Y- I2 |
% P2 [( Q* n/ ?* r
) |; x8 C" ~5 J3 p m$ x/ m
4 i0 |; X d0 x |