|
前言 本文是个人笔记,文章只讲基本流程, 最后所有的资料原理图和程序都会上传至资源。
7 r% O" P2 | ]1 T5 c* H 一、硬件部分单品传感器的硬件部分还是很简单的: 1、STM32L051 和 STM32F103 是 Pin to Pin 的; 2、测温传感器使用的是I2C接口,使用了软件I2C,因为 D6T 是5V供电,所以使用了电平转换电路; 3、整个传感器项目需求是 485 通讯的,因为实际环境要求,所以采用了周立功的 485 模块; 6 b1 V8 {6 Q5 k4 i& o% w" T: z
1.1 STM32部分老样子,最小系统都是一样的: 7 ]# o$ x% F) D; M
8 D7 g _) ~7 F+ M) w' G$ o 1.2 传感器部分
% A' L0 h2 u/ V d! s/ x" R
; g' w1 @" F, `
' m5 g1 N1 Z2 G+ L! ~; a) Q: Z# v
* R; i) [' Z. h: x; I/ v
0 V" s- x# k. ~- I在这里插入图片描述
5 g9 c6 c& P9 d" ~/ W, M$ k* b! b# w9 ~" A) v
1.3 485通讯部分
2 B- Z- o2 I; R9 s' y2 d$ N: d; _8 q7 d$ I2 u3 P7 c4 Q
: X9 ] r0 L" d) p
' C2 e V8 g$ R, p, j% q' J. ?8 _/ t4 [( m. `6 o0 V7 [
& i) f" p# j2 Y( w3 ?
! u! K9 I8 {' H. y6 x! ]
# D# l- E$ _4 T4 Q4 k1 f2 t
J3 ]* Q/ o2 a+ @! E7 O: f1.4 电源部分
+ ~: n, j8 i; g
8 U! @$ ~+ Y. T7 @9 B; Q( R
% ~6 G4 z9 u- T; I$ D/ ]7 j' \: ~+ d二、☆软件部分☆硬件部分是简单的,本项目的核心就在于软件的实现,有2个部分是核心: 1、I2C 通讯驱动; 2、485 通讯驱动;
6 [$ }7 \/ f! o: x( O 2.1 传感器 I2C 通讯部分这里上一下上层调用的函数,具体的驱动细节见下文说明: - void D6T_Measure()
& @$ A! r r5 l b5 ]8 Q: L, T6 V - {# \: i+ {+ P4 K4 [
- u8 D6Tbuff[20];
' L5 @; Q O- h2 Z$ s - u8 D6T_Data=0;: b$ m# T. }5 f+ z% B
- // u16 tPEC;. t! _; Z" ^ r: c/ _2 M) D
' y, K$ G! e4 S- Y ]% w- i2c_start();
+ c% l w% b) m, x$ P5 E - i2c_send_byte(0X14); //地址,和读写指令
0 i: T! Z" n$ z5 k( N2 K. n; H - i2c_wait_ack();; X- k5 x, ~, |8 `/ O
- delay_us(150); //这里必须加1 j$ a. z4 R' P7 k4 I' x5 l- G
1 W- U: y m; {" ^, q2 D5 F- i2c_send_byte(0X4C);8 N* I4 G5 u. F2 E, G
- i2c_wait_ack(); % X. k+ R0 ]$ u0 @1 o9 S7 ~
& U+ h2 e* F7 P% e- delay_us(150);
G# l$ m" X$ [, _3 S
1 I; \; }( d- E# g- i2c_start();! m x0 h( q' V; ]9 ]% j) L1 J
- i2c_send_byte(0X15); //地址,读指令
' ?/ x6 u" s: Z" e1 c" u9 o - i2c_wait_ack();: U3 C7 ^9 P; f
- delay_us(120); t1 q7 ` r2 z, p: R c& @; X
( t5 {4 C* }4 x! K/ [- // D6T44L_ReadLenByte(5); //D6T-1A-02 只有5个数值
& y4 A6 K" |3 \& f# P1 v7 {* I - u8 t;
& m9 I2 M$ H' c3 E4 u - D6T_Data=0;' s6 j$ k& s) @
- for(t=0;t<(5-1);t++)
0 `: S9 N9 R" {8 S" b! x2 Q# o7 ~ - {
& \! F- o. Q% a# T' F - D6Tbuff[D6T_Data++] = i2c_read_byte(1);
* y) w) O0 ~# Z$ V - delay_us(120);
8 O( H8 B& F5 I3 b# s1 M! ` - }
6 D+ s8 G! k- c9 m) J - D6Tbuff[D6T_Data] = i2c_read_byte(0);
* L! _# a' U w o - delay_us(120);
/ m; ]6 ]' S' b z% V0 P0 o - i2c_stop();
/ s' U7 P; G. @; C( [ K- m4 N6 M0 b9 Y - , h5 Y$ t1 R# z% J* C/ f* z" Z- g
- // tPTAT = 256 * D6Tbuff[1] + D6Tbuff[0];+ i, ?/ o+ b6 C' F) }) @
- tP = 256 * D6Tbuff[3] + D6Tbuff[2];3 P+ a$ q: H/ x+ f* V
- }
* J& x I( @% G0 [; r - ) W5 i: D6 u4 V# I6 [
- 8 g( x2 [* ?2 z: ^
- unsigned char calc_crc(unsigned char data)
$ C2 ^# m5 D3 G - { # d( h5 t* W+ h
- int index; 7 o& T/ |& M0 K6 s
- unsigned char temp; w/ M" Z" z. {4 E+ H
- " F& O% v& Q8 ~5 }+ E! v- h
- for(index=0;index<8;index++){
( x9 N# ?, V" q% w - temp = data; 0 d9 h* B3 G1 k( z) A$ {# @
- data <<= 1;
4 H% a# K, q! e( Y - if(temp & 0x80) data ^= 0x07;
! ]' t7 a+ {( i* ? - }
% k5 X( G9 }* T" [: M' F) L+ M! k - return data; & L$ \( H7 r2 M0 T& P
- }
复制代码 . V3 d( A4 D" k& R% Z7 ^. S
+ v, d" J0 [ V3 u* S2.2 485 通讯部分本传感器是作为 485 从机设备,所以需要写一下 ModbusRTU 协议驱动,这里就不墨迹,直接源码奉上: - #include "Modbus_rtu.h"& N1 T1 b* z5 z5 @$ k2 g/ V, t
- #include "stdio.h"
/ j/ D6 X' r5 q8 A( Y - 5 x7 d H9 ]8 X% ^4 N
- void Modbus_check(), V3 ]" u# ?, G
- {
- M8 i' A/ N* x* s$ E - u16 crc;
4 S8 [( U. v T0 p# x - u16 receivecrc1;! ^ ]# |- `2 I6 q" \: G
- u16 receivecrc2;
p [1 ^ ~0 d" y A - u8 sendbuff[5];
& r$ f4 c( i% c9 ^) Y j0 M - /*
w$ {: c- s( h2 v% t9 i - 收到了8个数据:01 03 00 10 00 01 D5 CA1 x, ~, s! `2 q3 Z" c
- USART2_Data = 8;3 ?2 X# |! l2 u" y2 S
- USART2_BUF[0] ~ USART2_BUF[7] ;
V7 d' W$ t7 B l# u# k - 要做校验的数为6个,所以是 USART2_Data - 2;
1 L2 W- @2 r& i( y# X: z( U - 校验需要计算的是 USART2_BUF[6], USART2_BUF[7]( _1 z, h, T& w) Z4 ?/ y
- USART2_BUF[USART2_Data - 2] 和 USART2_BUF[USART2_Data - 1]
3 h) x4 l$ z; b/ ?' J. l( G( V# B - */: a. O( g s( ^. V
- crc = Checksum_CRC16(USART2_BUF,USART2_Data - 2);
# g! }6 C2 ]4 B% B5 \6 X' q6 _7 s - // printf("crc is :0x%x\r\n",crc);
5 h# l# j5 i# U$ T4 T - /*No matter the high bits before or the low bits before*/- m( e! z0 I4 p- ~" b4 H: p. V. V
- receivecrc1 = (USART2_BUF[USART2_Data - 2]<<8) + USART2_BUF[USART2_Data - 1];
4 K7 o$ ]& M7 r r - receivecrc2 = (USART2_BUF[USART2_Data - 1]<<8) + USART2_BUF[USART2_Data - 2];
5 _- m( ~/ M+ o7 P - // if((lrc == receivelrc2)||(lrc == receivelrc1)){3 r" r& U% J" a! h {
- // if(USART2_BUF[0] == mymodbus_add){3 d& u; N, n+ C% `7 N6 q
- //这里说明一下,先判断地址,然后返回错误,如果先判断校验,如果出错了,那么总线上所有都同时返回就有问题了& H d( d2 C* H
- if(USART2_BUF[0] == mymodbus_add){ : ^8 @; q9 R* P7 {
- if((crc == receivecrc2)||(crc == receivecrc1)){) x! @; g* H& {% b
- switch (USART2_BUF[1]){
6 t2 {7 L# Q4 h8 r" m: r" q - case 3:- Z0 G" u6 `0 N( F" }* f& r7 M
- Modbus_03_ack(); e% a3 y B2 |
- break;1 n6 U, D0 D, J' n
- case 6: A9 [6 f0 }3 D/ R( e+ @% H
- Modbus_06_ack();, h* C7 Q0 h- q" V$ Y, i: E( y$ N
- break; ! H2 T. g. N% d) ~3 j! H3 y
- default:4 Z& S& H. q; _
- // printf("An unsupported command!\r\n");//for test
2 S( D! L' V( F5 p9 C2 ]# O - sendbuff[0] = mymodbus_add; w- d# ]0 U' H: G( l8 ]
- sendbuff[1] = 0x80 | USART2_BUF[1];2 g$ p* j0 x F
- sendbuff[2] = 2;
2 L9 B" A. i+ R3 [% P - crc = Checksum_CRC16(sendbuff,3);6 ?4 F/ a9 L$ G7 P) ~5 x+ B) Y
- sendbuff[3] = (u8)(crc >> 8);$ A2 i* B3 M# F9 O4 L
- sendbuff[4] = (u8)crc;
7 N$ _8 \7 e' t$ r: _7 X - Uart2_sendBuffer(sendbuff,5);
W5 p$ A- z% T& H. |- R* U - break;2 ]3 X% |& l- d- q5 S
- }
B) C0 e+ L F - }2 k' V* H" @7 \
- else{ //校验错误,返回异常
/ M; M0 E' b3 K - sendbuff[0] = mymodbus_add;
2 O6 z" T3 z( G1 k" {0 X) n - sendbuff[1] = 0x80 | USART2_BUF[1];
8 |; P5 b0 [# V% n2 ~# a - sendbuff[2] = 0;1 w3 I0 |1 X7 F* _8 g* d: w
- crc = Checksum_CRC16(sendbuff,3);
. G- p- {$ O j! A# t - sendbuff[3] = (u8)(crc >> 8);
% C1 W3 s4 ~6 d& } C* F - sendbuff[4] = (u8)crc;
% U2 Z8 C, s' h4 F. ?/ h - Uart2_sendBuffer(sendbuff,5);, H$ U! q: l. T( j" _4 u& X
- }4 p7 S+ `; a$ {8 @
- }
9 k+ H& a! q' ^/ y9 U" I - }" {3 @% h- g0 |) R
$ b$ }3 G' T- O5 C- void Modbus_03_ack(){
. f/ y1 |8 E3 E8 }; q: j - u16 Register_add; // 2,3
' Y7 Q z. S2 T, | - u16 Register_len; // 4,5
! y5 ~& z2 d5 ], ?* p0 F( l - u16 crc;9 ~* z N4 ?5 I
- u8 i;
% |# C" I/ R6 b T$ z+ Z0 O - u8 j;# [9 L: A. I* o( o$ u' V
- # v/ [& y3 ^5 A/ j
- Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
# O6 S9 F, G) T2 z- }% @ - Register_len = (USART2_BUF[4]<<8) + USART2_BUF[5]; //get len; N! X& E% j) F7 h
" h: f6 R6 X. l3 W- u8 sendbuff[Register_len*2 + 5];
+ N" \5 X8 [8 ]3 W - /*
& V" d1 e6 W( C4 e( N) F - 如果读取的地址写错了,或者读取长度超过规定的长度4 N7 P9 z+ E0 `$ w3 z& L4 j
- 返回错误
# q# e: r3 g/ G9 T1 m - */
" f$ S' J- Y# c) o - if(( 0x0010 <= Register_add)&&( Register_add <= 0x0014 )&&(Register_len < 6)){
/ `3 v' [' r. ~ i- v - i = 0;# i/ M% |7 {8 a
- sendbuff[i++] = mymodbus_add;
! C" f; l% a f2 J9 R - sendbuff[i++] = 0x03;. r d: J3 z( [
- sendbuff[i++] = Register_len<<1;
4 j% [# G0 y, N - switch(Register_add){' x B$ g7 x" _# ~7 y% O0 ^
- case 0x0010:
* S( `) s& U9 @* d2 T - for(j=0;j<Register_len;j++){3 s, x" V' I( w; ], ?$ G
- sendbuff[i++]= (u8)(Register_value[0+j]>>8); //发送读取数据字节数的高位
' @/ L6 j# }9 ?( x: y: ]5 b" S - sendbuff[i++]= (u8)Register_value[0+j]; //发送读取数据字节数的低位
# R0 I1 t1 t, G4 `0 ?6 G. j0 B6 T - } Z! T6 ^" d: k% K$ q) _' i
- break;
$ Z9 Z' W3 K! ] - case 0x0011:& T0 |& \/ ~' ?/ s3 t
- for(j=0;j<Register_len;j++){
; [- W* P- N i5 ~ - sendbuff[i++]= (u8)(Register_value[1+j]>>8);
! j8 v3 ]# k; n& I - sendbuff[i++]= (u8)Register_value[1+j]; 8 \0 i6 d I/ Z1 F: |7 B
- }* V, n* {, U. N: d$ m) s
- break; / }. R% ~) J; x+ [* [
- case 0x0012:" t( C9 L: j1 P0 Z
- for(j=0;j<Register_len;j++){" H$ V8 u( Q" \, x
- sendbuff[i++]= (u8)(Register_value[2+j]>>8); 6 S, c! b6 D7 n, I2 a+ D
- sendbuff[i++]= (u8)Register_value[2+j];
6 K0 B) D; G0 g. g4 J. e0 T+ \# O - }- {3 W) ?" t0 }5 f+ I9 y
- break;
z( Z( ^' j1 h6 M L* q - case 0x0013:- {: ^- N+ B6 |8 t
- for(j=0;j<Register_len;j++){9 A6 ?1 {1 m7 R4 P
- sendbuff[i++]= (u8)(Register_value[3+j]>>8); 9 o8 G8 [* N/ l! j7 _. T0 I
- sendbuff[i++]= (u8)Register_value[3+j]; ! l5 [/ Q3 D# r* E2 F# j: A
- }
5 c6 a4 {) g7 C: Y* i - break;
* i1 |# a+ G: [3 v; F. ]) J0 ` - case 0x0014:
6 J4 K/ @# k7 d! H& c8 i2 ? - for(j=0;j<Register_len;j++){* Q; E1 ~' b) O# a
- sendbuff[i++]= (u8)(Register_value[4+j]>>8); # Y, c3 j, r+ J, C) i
- sendbuff[i++]= (u8)Register_value[4+j]; 5 W7 a4 q5 ]1 O8 R# v1 a5 G' D
- }& t7 C/ B: ~; h. \; ?7 `3 D
- break;9 u; T4 b0 k E* s2 b6 b
- default:break;
% l# @$ h6 D4 H& _) W - }
: `7 U/ T8 G+ T; x( g+ i% Q - crc = Checksum_CRC16(sendbuff,i);
# t7 _8 G: F+ x, }4 N' X9 g7 |5 Y - sendbuff[i++] = (u8)(crc >> 8);
- `, K. A" M4 b; w4 \$ u7 T4 \ - sendbuff[i++] = (u8)crc;4 p7 d* T) x, C$ e2 K. Y
- Uart2_sendBuffer(sendbuff,i);" E0 X3 t' ]! z; k: }
- }8 D' A2 O" e1 T5 l0 S5 y
- else{//地址不在规定返回或者长度太长,返回错误
i q% Q0 R* L+ v% `. x - sendbuff[0] = mymodbus_add;
' Z8 y* b: }- e8 R. p - sendbuff[1] = 0x80 | USART2_BUF[1];
, f9 T* L$ T( I p+ M, V$ p - sendbuff[2] = 1;' A; V5 w) k$ A# l: I% ]/ ?
- crc = Checksum_CRC16(sendbuff,3);
5 a0 L4 K: J; { - sendbuff[3] = (u8)(crc >> 8);5 b5 z8 l- E, W+ z
- sendbuff[4] = (u8)crc;5 L% b _9 z {& _
- Uart2_sendBuffer(sendbuff,5);
: e8 X3 B& \! @1 Y/ Q6 A Q# Y - }- q7 A. [, Q" T! p0 X6 W
- }
9 K0 |# l" f8 n" i4 X2 ]8 N
, e* ?( s7 m! C8 `- void Modbus_06_ack(){: V0 Y# z+ c: V! s8 R
- u16 Register_add; // 1 q4 N4 q9 N% G" B' S7 A& X
- u16 val; // ( S: l5 @0 E/ I8 Q! q" g/ J1 [
- u16 crc;
) |- S, Q6 E* X! Q1 N - u8 i;
/ r. Y8 E7 _" Z1 e - u8 sendbuff[8] = {0};
( A! d+ a" y N" _7 I* @ - if(USART2_Data < 9){
, G e( K# m1 a+ c - Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
% l& N7 `5 ]) W1 A9 w+ |* l) |- n - val = (USART2_BUF[4]<<8) + USART2_BUF[5]; //
) h0 [" o" ]+ T
" Y+ u1 P, J* e. I9 ^- if((val > 0)&&(val < 248)){
6 e$ V, c# W! ?6 {' _# c7 S5 C - if(Register_add == 0x0013){; s5 ]( Q% P, A7 o. Z; z
- mymodbus_add = val;
. y. P2 }0 l& H0 X - Register_value[3] = mymodbus_add;; p. u7 r. Q3 H% H1 D! F |
- MY_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,Modbus_ID_ADDR,mymodbus_add);
6 S6 X, }% m, R7 T: {+ g. |7 k1 u - i = 0;4 |, D. J1 _9 Y8 o
- sendbuff[i++] = mymodbus_add;/ K1 V* R, p" m0 A2 o# m% S
- sendbuff[i++] = 0x06;
7 L' ^7 E3 Q& B- E# p. C% b - sendbuff[i++] = (u8)(Register_add>>8); 4 k0 r6 h3 ?" q4 W$ f. [$ @/ U
- sendbuff[i++] = (u8)Register_add;
& B: |" {7 @6 C - sendbuff[i++] = (u8)(val>>8); 0 Z! F4 u3 G8 N, \
- sendbuff[i++] = (u8)val;$ d9 j/ c7 u. ~. R. d
- crc = Checksum_CRC16(sendbuff,i);
/ a$ M: a0 J- N: R3 _ - sendbuff[i++] = (u8)(crc >> 8);8 i* _& D7 i) v* P& _/ E3 j) [$ |
- sendbuff[i++] = (u8)crc;
& F& y1 |/ Y3 W5 p4 |: r1 C3 ~ - Uart2_sendBuffer(sendbuff,i);
' N# |9 b( d( O) s7 {. I7 e - }7 y) q9 o( C4 C
- else{//写地址不在规定范围
3 h; y/ x/ O! v) F: [/ [ - sendbuff[0] = mymodbus_add;& }5 u: T# Z9 X6 z* Z
- sendbuff[1] = 0x80 | USART2_BUF[1];& ^/ N- I) j# B, W) h
- sendbuff[2] = 3;* u5 a6 g% B) V7 |5 G3 J C: `
- crc = Checksum_CRC16(sendbuff,3);6 ?9 C2 r9 p2 Q. _4 G$ P
- sendbuff[3] = (u8)(crc >> 8); C- v& a7 ^+ P$ d- g u+ N: I
- sendbuff[4] = (u8)crc;
1 C( l6 S/ s2 [0 X# p+ C& P - Uart2_sendBuffer(sendbuff,5);0 Z* j# K% b4 F( T- w: i
- }
8 g) H+ D. ^8 ~% b6 I - }else{//写地址不在规定范围
2 Z7 l- X+ y5 l5 o4 A8 E - sendbuff[0] = mymodbus_add;
! E1 Z# |( Z; j1 u/ } - sendbuff[1] = 0x80 | USART2_BUF[1];1 h/ [+ \9 E6 k9 u4 V7 x& S
- sendbuff[2] = 4;
8 z5 X* F% D/ E( Y/ |+ a+ v( K - crc = Checksum_CRC16(sendbuff,3);1 t, P! I# M- B% k7 ~) j; R
- sendbuff[3] = (u8)(crc >> 8);
2 {! V( c; ~/ t& K7 }# ?+ S( z - sendbuff[4] = (u8)crc;+ i9 r0 @/ h4 b# g- S
- Uart2_sendBuffer(sendbuff,5);
1 u3 Y6 V. y' `4 C+ o. `( L - }
6 ] f, ]4 J: n% l% z( Q - }2 S8 I' W0 j" C, d' J
- else{//写地址不在规定范围
% L: |; Q. i. P - sendbuff[0] = mymodbus_add;
. q# y, p1 i3 E& W) V# i( ^3 f - sendbuff[1] = 0x80 | USART2_BUF[1];0 |# |2 E$ t* m% Q* w, m0 h
- sendbuff[2] = 1;* |) b. A# f9 Y4 u3 \
- crc = Checksum_CRC16(sendbuff,3);
6 |" H$ Y/ F4 Y/ m - sendbuff[3] = (u8)(crc >> 8);
8 R+ N7 [& c( W: x, _+ Z - sendbuff[4] = (u8)crc;" r) X0 i; Z8 k( {, } Q; ^: R8 p: Z
- Uart2_sendBuffer(sendbuff,5);
# z, W5 T. m$ }! B" H6 u - } ; t& n- L( n) W) k& h
- }3 w( |2 }( b N! Y1 n( N: |. \2 c4 [
复制代码
% u- g$ O* a% w2 f% o2 a! K2.3 其他代码说明此项目的核心就是上面2个的驱动,其他部分,STM32和一些基本的按键驱动,LED等操作都和以往项目基本一样。 实际上当初我在 FreeRTOS 记录 实例的时候就是使用的这个项目作为说明的,所以从 0 开始的设计思路 当然额外说一句,这种 单品传感器 的简单的项目一般来说用不用 RTOS 实际使用上区别不大。 ( ]- h2 d9 x; C/ Z$ G% {% u
如有侵权请联系删除 转载自: [color=var(--weui-FG-2)]矜辰所致
+ f' S' |( ^% q( |4 W7 ^# V0 X f4 Y) h, a+ ^. p/ H5 O' [) ^6 Y' M1 N
f" {0 \! C; B$ J) m" I, b. P6 W. |/ G( A
|