|
前言 本文是个人笔记,文章只讲基本流程, 最后所有的资料原理图和程序都会上传至资源。
9 o. `* O9 I$ g* R% Y, r/ X 一、硬件部分单品传感器的硬件部分还是很简单的: 1、STM32L051 和 STM32F103 是 Pin to Pin 的; 2、测温传感器使用的是I2C接口,使用了软件I2C,因为 D6T 是5V供电,所以使用了电平转换电路; 3、整个传感器项目需求是 485 通讯的,因为实际环境要求,所以采用了周立功的 485 模块; 9 t2 c7 U& h( Q- E
1.1 STM32部分老样子,最小系统都是一样的:
* S+ [" ?: | O, L3 X
& W1 l: @7 z) W4 M: ~; e! l! X 1.2 传感器部分
- _0 I! m6 O6 w& m5 y( @( @0 t6 a5 B3 C$ G; E: G# b9 k
* m; x9 ]: J; x9 J Q" W! J% @5 V9 N' W2 [, p/ S
$ {" t" V" H$ n2 z: P! M
在这里插入图片描述1 ^3 q" | A2 ~2 h' Y2 |4 q, J# F& p
. H7 H& P" C3 l0 g
1.3 485通讯部分5 \, g# r$ M/ F' [3 ~0 Q3 ?$ S4 @
- X0 s3 {& _0 y! c4 n( v7 S6 ^
0 u# V1 D- l4 ^. y& @( T
: ]3 O+ C( g" j9 t+ O) o2 K
5 }0 }9 D- y0 G
1 {" w! n- A: V& z
1 P; N; O2 h' j" [1 T# J- }) u, k V1 U8 u4 }- A3 H
2 H- f7 _, T& L% \, [. R
1.4 电源部分 m+ s+ F' z) `/ m4 P. O
. W. [* _9 h4 ~; O r
$ W7 D ~; s4 W
二、☆软件部分☆硬件部分是简单的,本项目的核心就在于软件的实现,有2个部分是核心: 1、I2C 通讯驱动; 2、485 通讯驱动; : X2 C5 o4 X7 [6 U/ ^$ B
2.1 传感器 I2C 通讯部分这里上一下上层调用的函数,具体的驱动细节见下文说明: - void D6T_Measure()
8 ]4 `( b s5 r3 w- I - {, C3 q# a m- g5 X H
- u8 D6Tbuff[20];1 l8 X2 V& U, K, R! `
- u8 D6T_Data=0;2 {# |& B7 c. [3 y% p! G$ a
- // u16 tPEC;' \. E0 F# F- \' k7 l; Q
- 2 b. e8 [- p; J; C! W: q
- i2c_start();# ~3 M; Z8 k r4 P+ r7 l; R
- i2c_send_byte(0X14); //地址,和读写指令
" o$ [8 a) o$ J1 b - i2c_wait_ack();
( {5 T* M6 i# Z& n8 o - delay_us(150); //这里必须加9 y0 N. r( T1 b& M5 M
/ y# N( {9 v8 Y: X8 Y- i2c_send_byte(0X4C);3 j" {1 P0 h/ A. J; `; O" O2 ~) S
- i2c_wait_ack(); 1 E, u+ i5 _, B/ t- g a+ e5 |
- 8 M2 s: F. U/ e, P3 V. L/ `
- delay_us(150);/ n A& p6 s' N# k
- " @6 v: A' |9 A2 m* g$ n2 w; Z+ |( p% C
- i2c_start();0 x0 D4 K& x# ?0 U" W2 k
- i2c_send_byte(0X15); //地址,读指令
& j8 u" @& Q1 p5 M6 b& K - i2c_wait_ack();0 x% b8 f% _* n
- delay_us(120);
( @3 w; z2 j6 h9 x$ L+ g/ U' | - # `' V# r6 t; X
- // D6T44L_ReadLenByte(5); //D6T-1A-02 只有5个数值
1 k) H* h8 B+ w, u1 v3 K0 W - u8 t;
! p- ^% ^. Z$ B7 y& x/ t - D6T_Data=0;
/ y' K8 `- z! g: a8 ^+ [ - for(t=0;t<(5-1);t++)& T% c' J. T1 A; H; U# a
- {
( c* C: a$ o. u3 J) Q: e" X - D6Tbuff[D6T_Data++] = i2c_read_byte(1);+ G; d$ F! [' ~5 r
- delay_us(120);
& U- \6 Q- U- B# u" m8 A - }8 A" G. K% |4 |1 B9 ?) N
- D6Tbuff[D6T_Data] = i2c_read_byte(0);
$ b+ {' w3 |" u3 Y% T - delay_us(120);
6 z, ]& l3 A( C: j - i2c_stop();
8 ~1 {8 _2 c+ |6 v$ F- P! B" z+ D - ) z. t+ J O4 s, y. ^( s
- // tPTAT = 256 * D6Tbuff[1] + D6Tbuff[0];
2 ^& u) F2 U3 H( Z/ j. [ - tP = 256 * D6Tbuff[3] + D6Tbuff[2];
3 Z, A$ P0 M" _/ S - }3 P' v+ l8 S- z( t1 N0 G# ^
6 |& U2 B b+ o) p) q6 Z- 6 A. P1 f+ h$ R6 ?, z0 B ]; S
- unsigned char calc_crc(unsigned char data)
+ J! U& b* |1 H; O' c" F9 f - {
. w6 G% I# ?, l7 P$ k& E, E - int index; 2 ?9 o5 x# ~3 `0 R% w
- unsigned char temp; $ h2 d$ a: g R' Q: r" P8 O$ g; _
- ! F1 b @- ]# ^/ I' r/ t
- for(index=0;index<8;index++){
* p+ ?- A/ m) u - temp = data; 3 `8 r' { d) \* y8 A w% r* u8 N
- data <<= 1; 8 k4 {+ {! j- `1 b
- if(temp & 0x80) data ^= 0x07; 6 \4 q; |" y4 g5 a2 q/ [' S$ N5 d
- }
6 Q4 i4 d. c2 Q( @( p) A! x9 D: w - return data;
9 i3 E0 I! N( T - }
复制代码 4 d' P% B! U8 a4 p8 e* T7 I
; z0 B1 D1 O t
2.2 485 通讯部分本传感器是作为 485 从机设备,所以需要写一下 ModbusRTU 协议驱动,这里就不墨迹,直接源码奉上: - #include "Modbus_rtu.h"! E3 F3 z& ?5 t! d7 V
- #include "stdio.h"
8 M2 N5 S8 A, T& ^ - 6 `8 Z7 P& ~7 u; ~/ _
- void Modbus_check()
3 L8 A0 |- m) j* E3 d - {) m0 _# H. o2 P Q+ R
- u16 crc;) s5 p: S& I9 Y3 j, H
- u16 receivecrc1;
, V, {3 u3 h+ w0 f3 M* q, F6 @ - u16 receivecrc2;0 e" E% v" u) t$ r* {
- u8 sendbuff[5];: ?4 e( E1 Y0 n7 d; W/ o
- /*
) E6 F- r$ F( O3 p G2 m - 收到了8个数据:01 03 00 10 00 01 D5 CA, {0 a/ A0 a4 e! T0 O
- USART2_Data = 8;" a# { p4 {) A% a q4 G$ e
- USART2_BUF[0] ~ USART2_BUF[7] ;2 c4 {5 G5 }3 ?% V. C6 B
- 要做校验的数为6个,所以是 USART2_Data - 2; v# g* C4 ^+ O7 @ ~' X
- 校验需要计算的是 USART2_BUF[6], USART2_BUF[7]# }; O1 |1 \' W
- USART2_BUF[USART2_Data - 2] 和 USART2_BUF[USART2_Data - 1]
8 ^5 O/ ^: p/ z) i$ z6 ] - */
4 K! `: |7 x1 J. H" z; o - crc = Checksum_CRC16(USART2_BUF,USART2_Data - 2);
& \' X7 K, s7 p. |5 V - // printf("crc is :0x%x\r\n",crc);
& |, D8 o# l( {7 [0 v* X - /*No matter the high bits before or the low bits before*/6 `0 C$ k6 n) r
- receivecrc1 = (USART2_BUF[USART2_Data - 2]<<8) + USART2_BUF[USART2_Data - 1];
: ~, N2 {3 O- i$ D. d. o6 P - receivecrc2 = (USART2_BUF[USART2_Data - 1]<<8) + USART2_BUF[USART2_Data - 2];
" A/ C- X% _/ _ Q - // if((lrc == receivelrc2)||(lrc == receivelrc1)){, h' K% p) r: B, x9 e
- // if(USART2_BUF[0] == mymodbus_add){
/ O ]/ n2 ^* s% t, g6 u( R - //这里说明一下,先判断地址,然后返回错误,如果先判断校验,如果出错了,那么总线上所有都同时返回就有问题了8 M% M# n; s" |
- if(USART2_BUF[0] == mymodbus_add){ 5 d2 c$ G, b# ^" ?) ] U: H7 F
- if((crc == receivecrc2)||(crc == receivecrc1)){3 M5 ], m9 ^8 s8 w
- switch (USART2_BUF[1]){, t7 M A+ g! ?! s& w5 `
- case 3:
0 {+ ~: D3 p9 o e% z - Modbus_03_ack();; B1 d+ F& h4 W" M: P5 A
- break;
7 n7 z+ C! w) | C6 ?3 A. f - case 6:
. ~: I6 m. ?9 C' M$ X8 C - Modbus_06_ack();
. I: L7 y1 R5 d$ Z N: r% v# J3 c5 v - break; $ \/ m1 A, ?9 Q
- default:
" G9 j+ ~4 O$ D - // printf("An unsupported command!\r\n");//for test
2 e/ f/ k y' v5 F - sendbuff[0] = mymodbus_add;) J8 F; o7 m- Z2 k/ [( W
- sendbuff[1] = 0x80 | USART2_BUF[1];- ?8 R2 T% s0 A! R0 y1 x+ F
- sendbuff[2] = 2;( a! [, k6 I. M" D
- crc = Checksum_CRC16(sendbuff,3);
1 S' b$ d% S; ~/ t; W; Q - sendbuff[3] = (u8)(crc >> 8);
/ z" k* g* `0 n. i) R9 v- V0 y - sendbuff[4] = (u8)crc;
1 O$ j* c* M. z: J4 w - Uart2_sendBuffer(sendbuff,5);
3 l1 Q8 p% x! a. d9 ?; U - break;& ]9 N/ k- W1 ~1 Q
- }
: I) p0 ?+ Y3 l* W2 a - }
* G7 w; [; H3 H' p' ` \ - else{ //校验错误,返回异常* c+ w# ^% g" K* B5 m8 G" \
- sendbuff[0] = mymodbus_add;9 }' l# |7 Y2 R4 S6 p
- sendbuff[1] = 0x80 | USART2_BUF[1];
- ~, |7 _& a* o- c. ~ - sendbuff[2] = 0;! Y8 g/ C5 t) L
- crc = Checksum_CRC16(sendbuff,3);
5 [/ X! r9 @+ q3 W- }/ b0 s3 b - sendbuff[3] = (u8)(crc >> 8);
# J0 [; o& `/ l4 R) F( L - sendbuff[4] = (u8)crc;
( ~* s5 w2 N2 g* Z+ M0 } - Uart2_sendBuffer(sendbuff,5);
: ?6 z+ s$ Y" B- A/ ] - }
5 e ^; c0 |* K( Y7 o- o+ N - } + t( k) Q5 H; E3 x
- }( R5 _* j- v: }1 a
- # p1 q' ^5 Q+ `4 b) t4 H- h
- void Modbus_03_ack(){
, {" E; G7 r& G4 | - u16 Register_add; // 2,3
& S. J9 O, F# m h2 z* f - u16 Register_len; // 4,5" ?+ K; v5 |/ d7 W3 b# Y+ N" J7 A
- u16 crc;
2 }1 f, ?& G$ ^4 Z' a8 r* ^* ?3 c - u8 i;
+ S9 x- U1 _4 ^6 d" W T - u8 j;
0 b7 S) f6 s+ T0 K1 A1 x5 e2 x
: L( J+ N: J/ E! m$ s. \- Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;5 m; X4 w* ~6 x, [
- Register_len = (USART2_BUF[4]<<8) + USART2_BUF[5]; //get len;1 {) R6 i; X. V1 g
- # j( g- D, j- m1 G' a. F) k
- u8 sendbuff[Register_len*2 + 5];
6 t1 n# a" ]" c9 n1 P! e1 S - /*
( b2 I+ W, V. x1 u& Q/ o+ A. Q- U - 如果读取的地址写错了,或者读取长度超过规定的长度
T6 L/ @8 ~7 q8 j! e - 返回错误
8 j& ?( j) w% F3 X - */
5 m, I3 B& R5 t3 q3 H1 a$ D - if(( 0x0010 <= Register_add)&&( Register_add <= 0x0014 )&&(Register_len < 6)){
8 i+ X: L9 n: a - i = 0;
: ?. Y+ S4 y/ B3 a* s - sendbuff[i++] = mymodbus_add;
; P( U' C4 D9 n( w# `* @: H* G& V* Q - sendbuff[i++] = 0x03;* E g! g+ k0 ^# `9 O7 \
- sendbuff[i++] = Register_len<<1;
) d1 p: |. W- A; }/ G; W3 z. ` - switch(Register_add){1 l* V* q7 a) N. G
- case 0x0010:
4 ^6 r, e( n4 }1 O" t+ N- Y# W - for(j=0;j<Register_len;j++){
7 s: n9 z( ?1 _+ ]3 D5 u4 m - sendbuff[i++]= (u8)(Register_value[0+j]>>8); //发送读取数据字节数的高位 5 G3 Q/ f! l7 {7 w/ j9 g6 g/ ]
- sendbuff[i++]= (u8)Register_value[0+j]; //发送读取数据字节数的低位
* s( s% n* U" N' ~5 a& i - }
0 I" J1 L1 X. c, L. Q - break;
& L8 D; o4 X, N/ z - case 0x0011:
: U0 @0 B; h5 A - for(j=0;j<Register_len;j++){
$ H B0 z$ A8 L9 N5 z - sendbuff[i++]= (u8)(Register_value[1+j]>>8); + M* c+ _' n/ E8 e3 z5 d0 H
- sendbuff[i++]= (u8)Register_value[1+j];
$ b% K: h: |& o2 x; T - }
; |' C6 L. z) J" U3 u7 m$ X. j - break;
. Z8 @% m( @. B8 R - case 0x0012:
# [8 |. ^# l$ @4 g8 d4 p, X - for(j=0;j<Register_len;j++){
8 d6 N7 M' y$ b8 G& s8 {: O) ` - sendbuff[i++]= (u8)(Register_value[2+j]>>8);
2 K2 H& A- I1 Y. \ - sendbuff[i++]= (u8)Register_value[2+j];
: B: V. n8 T, g5 Z4 S - }
) U$ X v5 A q - break;
6 u/ V& f- H5 r# ~& s& l1 I- X - case 0x0013:
4 y' u5 |. h$ e% x9 K+ Q, K - for(j=0;j<Register_len;j++){3 d& S. R9 v" M8 q0 y
- sendbuff[i++]= (u8)(Register_value[3+j]>>8);
$ N& g3 i; R: K* j$ {; w - sendbuff[i++]= (u8)Register_value[3+j];
& _, q! B. ~2 F# W4 c1 v& A - }5 T6 r! Y0 F) h6 ?8 W' P
- break;
f% L- s6 w% s0 p; Z4 B. `! d - case 0x0014:8 h2 Q0 w" Z$ F5 v5 b6 k# l+ U0 ]
- for(j=0;j<Register_len;j++){6 y6 h2 X% d; t9 {& ^# z7 e) _
- sendbuff[i++]= (u8)(Register_value[4+j]>>8);
3 v7 R" m! w' Q* g' ~! K - sendbuff[i++]= (u8)Register_value[4+j];
6 j) u4 r- A; J9 m) j - }
' d+ o* m, S2 Q, t! S - break;
$ G2 I8 J# T# z1 S$ G2 U: |. l - default:break; 6 y! a1 ?/ z' ]! Y' w2 o$ l
- }
* o7 ~- t7 |3 |$ [ - crc = Checksum_CRC16(sendbuff,i);
( b* F" n! U7 G# S: S# [! D, Y! U - sendbuff[i++] = (u8)(crc >> 8);
! o' x, n& p0 O, z - sendbuff[i++] = (u8)crc;
& P9 _2 I# }. u; Q- H& c- o - Uart2_sendBuffer(sendbuff,i);/ p1 F( a3 }; Z- q' J7 B$ Z$ l
- }# a; P& ?% F3 V, K) N5 [3 T
- else{//地址不在规定返回或者长度太长,返回错误
, y: n/ {4 n* r9 L5 `# {1 z. ]) e - sendbuff[0] = mymodbus_add;+ Z$ Y( `' [4 t. o2 s) A
- sendbuff[1] = 0x80 | USART2_BUF[1];
# R) g7 @, t) a6 E, e0 L9 X - sendbuff[2] = 1;- u% U; L( O X2 ~
- crc = Checksum_CRC16(sendbuff,3);( h) N8 ?5 ~% ?* I
- sendbuff[3] = (u8)(crc >> 8);( J& R' s; X0 C" w4 q/ V* m
- sendbuff[4] = (u8)crc;* d! X9 j1 b2 i7 b( ]
- Uart2_sendBuffer(sendbuff,5);0 F: |4 B3 _! Y4 f
- }( q2 W9 v |7 K8 f$ C0 G9 z
- }
' x, d, H2 q( a* H0 Y5 i - : {& S/ \: C/ F
- void Modbus_06_ack(){2 w) q1 n5 q) _9 Q3 G& E; L/ ^
- u16 Register_add; // ( l# m( H! w+ T- w( u: F1 T
- u16 val; // * ]3 \5 e p* @/ M, T% s
- u16 crc;
$ W% Q# x$ F0 u6 R- O' ~/ \+ e - u8 i;
6 T" k& D& H. [. {9 v - u8 sendbuff[8] = {0};4 f4 q7 @' v9 F
- if(USART2_Data < 9){
. {' b; |$ Z, ~; c v& q - Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
7 Y; \. o& _) y! M5 S1 Q( ~ - val = (USART2_BUF[4]<<8) + USART2_BUF[5]; //4 l, Z" |; s# k) Y* q
- m9 u. ?7 ?0 t
- if((val > 0)&&(val < 248)){, }2 m* F O- n# D/ @ I2 F
- if(Register_add == 0x0013){- ~7 P; o: N) r7 ?+ c+ C
- mymodbus_add = val;5 X: N! @- k2 W
- Register_value[3] = mymodbus_add;
% l3 t8 t5 J& i - MY_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,Modbus_ID_ADDR,mymodbus_add);/ }0 F* t% V# {) K6 J
- i = 0;
% s7 N) d5 ~2 x! J - sendbuff[i++] = mymodbus_add;" g0 K0 [( P) |8 a9 C3 Z
- sendbuff[i++] = 0x06;8 N7 K& S Q @2 j/ m h) j
- sendbuff[i++] = (u8)(Register_add>>8); 3 R$ K$ C& ?% h' k6 W
- sendbuff[i++] = (u8)Register_add; w" L- y( K+ Y' }+ Z4 q6 A' L x
- sendbuff[i++] = (u8)(val>>8); / Z5 @2 d7 {9 _
- sendbuff[i++] = (u8)val;5 F$ j3 p) N7 \ J, }6 Y/ G
- crc = Checksum_CRC16(sendbuff,i);
3 Q' w- x. S& w' g2 m* w - sendbuff[i++] = (u8)(crc >> 8);
+ B6 i8 f U0 U- u6 w# a1 z - sendbuff[i++] = (u8)crc;# @( C% X2 k- f: H* I8 i
- Uart2_sendBuffer(sendbuff,i);
- i2 h! |& p& u7 z: } - }
9 j& t; Q3 X$ b9 j; p - else{//写地址不在规定范围' k& T O* }- Z9 d/ ?: `
- sendbuff[0] = mymodbus_add;
* ~3 l& D* \1 W, E$ v' E - sendbuff[1] = 0x80 | USART2_BUF[1];( {" s3 C3 Q9 ?
- sendbuff[2] = 3;: Q- R5 K9 o8 O# t
- crc = Checksum_CRC16(sendbuff,3);0 r( o6 M/ W1 o. g2 c8 \
- sendbuff[3] = (u8)(crc >> 8);
, u9 U, N0 R9 {" a. C - sendbuff[4] = (u8)crc;
/ M& B& z* V: k4 _7 x1 x5 { - Uart2_sendBuffer(sendbuff,5);0 d6 h' v [9 J" [# R' H; Q3 V
- }- ]; k+ N1 C) g
- }else{//写地址不在规定范围
& G4 \2 W" `* d P3 O - sendbuff[0] = mymodbus_add;
' U6 ^1 H2 r, m5 O$ e- k+ f; ^. \ - sendbuff[1] = 0x80 | USART2_BUF[1];) s: ~% x0 K$ u
- sendbuff[2] = 4;
5 S2 `7 ~, j5 r - crc = Checksum_CRC16(sendbuff,3);5 a9 z; V3 ^* l5 c4 G
- sendbuff[3] = (u8)(crc >> 8);
0 m: [( a6 K2 O' u3 V$ p8 G - sendbuff[4] = (u8)crc;
4 M7 `5 i% z! C( a - Uart2_sendBuffer(sendbuff,5);* x0 r! c* ], ?$ z+ k' V
- }
- `$ G- H0 }: k( Q& T; y - }4 a' o Z' e' L: G* T
- else{//写地址不在规定范围
, S) R3 _) Y) v0 E! K - sendbuff[0] = mymodbus_add;
3 y0 J- f& s' n. [2 G1 s - sendbuff[1] = 0x80 | USART2_BUF[1];, X9 y X1 w3 ^
- sendbuff[2] = 1;) |( h' V* [# P: J9 y
- crc = Checksum_CRC16(sendbuff,3);1 Q) C- c5 }! ?6 b
- sendbuff[3] = (u8)(crc >> 8);* X8 M: S3 G3 Z# P+ J. R: _
- sendbuff[4] = (u8)crc;! s' B5 N; Y( S7 C
- Uart2_sendBuffer(sendbuff,5);
, X& v( j4 p$ T$ j( _ - }
9 R8 } i* R* x% D: I! @ - }
$ z$ H. {& N- {3 n6 H" U6 K
复制代码
( d( k8 ?" o, y B" U2.3 其他代码说明此项目的核心就是上面2个的驱动,其他部分,STM32和一些基本的按键驱动,LED等操作都和以往项目基本一样。 实际上当初我在 FreeRTOS 记录 实例的时候就是使用的这个项目作为说明的,所以从 0 开始的设计思路 当然额外说一句,这种 单品传感器 的简单的项目一般来说用不用 RTOS 实际使用上区别不大。 * H0 X4 g+ w% _5 `; @& Y) j
如有侵权请联系删除 转载自: [color=var(--weui-FG-2)]矜辰所致9 K) L$ S0 I+ h+ z, E m
! f) D! P6 E0 C1 `- Q
" @9 D) ?( c5 K5 `( Q8 P# N
. |$ ~+ ^2 ~+ v0 |* c7 X |