|
前言 本文是个人笔记,文章只讲基本流程, 最后所有的资料原理图和程序都会上传至资源。
; H% p/ T. O3 Y) T. l) _: H 一、硬件部分单品传感器的硬件部分还是很简单的: 1、STM32L051 和 STM32F103 是 Pin to Pin 的; 2、测温传感器使用的是I2C接口,使用了软件I2C,因为 D6T 是5V供电,所以使用了电平转换电路; 3、整个传感器项目需求是 485 通讯的,因为实际环境要求,所以采用了周立功的 485 模块; 0 t( E" o$ x/ [# \
1.1 STM32部分老样子,最小系统都是一样的: & @% W+ R3 h; ?1 k1 d
% F8 K6 c7 S7 {. b 1.2 传感器部分
, |+ n) g; Q6 I+ m d8 j2 S* D, N/ P/ s N+ g* b' G
, c3 {* I, Y4 Q7 G# J. p/ |( h* k/ J$ y
% {, b; r' T4 ~$ o- }4 U6 K在这里插入图片描述
, j8 c4 B- B) I1 c3 o! l
# b- s& Y0 m5 W9 `' V% f1.3 485通讯部分
1 F8 Z$ f: v5 p' e5 W+ D
" P2 D3 y$ u, |5 d
, a- N( c/ P9 {/ _6 Y) h" R! h2 @% c A' ^4 v+ H8 `) X# b/ @: C
* P# J7 y- k; u# h1 y. H7 E& b) l7 a( m9 |
1 S8 i+ v& Q# Y. }/ i& N# E; l2 r" t
$ u8 P$ E9 G3 q4 {( S, K P, V# e
1.4 电源部分
3 O( |, d" [. |1 o, Z# d
$ w/ f- v7 S4 t6 s& a0 h
0 ?) G4 ]& p5 f8 P" }二、☆软件部分☆硬件部分是简单的,本项目的核心就在于软件的实现,有2个部分是核心: 1、I2C 通讯驱动; 2、485 通讯驱动; 0 Y6 o5 x J& |
2.1 传感器 I2C 通讯部分这里上一下上层调用的函数,具体的驱动细节见下文说明: - void D6T_Measure() I4 s% d/ ^2 h% }
- {
& r0 B" U) k) `9 } - u8 D6Tbuff[20];% K6 d" K9 G* Z, y0 Z5 O
- u8 D6T_Data=0;$ d* {: E. K* k2 ?1 C' b: i
- // u16 tPEC;4 n8 f' p k6 K8 M( j5 G" T
( n2 m2 x" U; W) r- i2c_start();/ B/ g/ S/ a* H" m: z' a) [9 Y
- i2c_send_byte(0X14); //地址,和读写指令
; t, Y4 Q4 W! \+ }* ^) Z - i2c_wait_ack();9 k2 l9 M/ l( a1 n# f& d
- delay_us(150); //这里必须加* G! b; p& l5 c0 N) k( X
- 7 n& }+ t( o- }; x/ `
- i2c_send_byte(0X4C);
# Y- E- E/ f4 ]4 Q8 m: X N - i2c_wait_ack();
3 ]5 T4 n/ y% b8 \
4 u% q1 {" m4 S- delay_us(150);% a3 c) S, j2 R9 s: { h; |7 L( o
- ( L$ u: v7 h* j8 ?
- i2c_start();
& @' Z+ ^6 r& w; P2 q7 r' c# Y - i2c_send_byte(0X15); //地址,读指令
- _: v* Q# F" U; ` - i2c_wait_ack();
; S+ {' f9 [* m- |- O+ f" Z0 o - delay_us(120);6 X. `. K" A2 d. p: {% }7 z
4 A9 c3 w' O) o, Z3 d- // D6T44L_ReadLenByte(5); //D6T-1A-02 只有5个数值
# y2 a) ~* m4 h6 E" z. s' ^8 [ - u8 t;) T) k; f; o: F9 M5 x
- D6T_Data=0;* f7 N+ i$ h7 O7 Y X0 v" e
- for(t=0;t<(5-1);t++)
/ a- v2 ? ]% T3 F - {
. n. B4 V+ l4 t1 Q" R/ X ] - D6Tbuff[D6T_Data++] = i2c_read_byte(1);
/ y) d/ I* e! i9 {& Q - delay_us(120);, O6 G* P6 d6 P" O5 ~ L
- }
& u# l" a+ j2 Z$ f9 U7 G- t1 @: m; k - D6Tbuff[D6T_Data] = i2c_read_byte(0);* z5 J1 k# T1 e
- delay_us(120);
" O" `( ^3 [1 N7 ?6 g - i2c_stop();: I) f# K& U2 \1 [) O3 n e
- & g: q. d: C$ g4 |, }$ H/ W: s h- \
- // tPTAT = 256 * D6Tbuff[1] + D6Tbuff[0];
2 _0 h8 j9 g# l - tP = 256 * D6Tbuff[3] + D6Tbuff[2];
+ T: [" X, X4 B2 H) v. e - }& q* [+ V \- `* f
2 i7 `3 n$ R: g M, D( M6 x
1 c1 k, k4 A2 Z( k$ t- unsigned char calc_crc(unsigned char data)
5 }0 @) e. ~' u8 s4 L5 G D - {
4 ` U- c7 @; S, Y - int index; , o8 _5 y% v0 _2 g+ M% J! g
- unsigned char temp; ) K; _1 H7 \6 @2 t. N
- 6 a2 h8 D+ f7 {; j i+ @5 [( c
- for(index=0;index<8;index++){
6 I8 A, ^% _. I3 ]5 J4 g1 y2 ` - temp = data;
2 w: ~" e% o7 B" v$ N1 O$ D& H. p; K - data <<= 1; : `' w( x7 C$ {: [) I# N4 W2 |. b
- if(temp & 0x80) data ^= 0x07;
9 D+ r% U p/ ? - } 8 b& V* K7 ]7 @% P' N
- return data; 0 i. s' W( _. G* t8 C& W
- }
复制代码 9 S/ l# H+ L% v9 F( ?
2 d/ @: A& j3 b1 N3 g) n- v E% [
2.2 485 通讯部分本传感器是作为 485 从机设备,所以需要写一下 ModbusRTU 协议驱动,这里就不墨迹,直接源码奉上: - #include "Modbus_rtu.h"2 U K4 | d9 D- S' b
- #include "stdio.h"
9 s. \3 H Q2 z5 ^ - " L) p# W2 M9 O% L: ]2 H* T5 s/ t
- void Modbus_check()& K1 r* M$ V& D8 b9 {5 F
- {
9 V) }/ }1 h% b$ R& g' M - u16 crc;
. G B7 u2 n: _. G! W - u16 receivecrc1;7 k* t& ?; `0 Z& e; P" G
- u16 receivecrc2;' S6 d+ U! U: I6 ^& M* I! Q
- u8 sendbuff[5];
3 {$ y0 |$ B- A: `5 H# v0 ^ - /*
' k, a0 W% O% x9 D - 收到了8个数据:01 03 00 10 00 01 D5 CA, g# s# f. f( N5 ]6 P
- USART2_Data = 8;
2 ]% V. f! D h8 O6 l0 H/ W% u - USART2_BUF[0] ~ USART2_BUF[7] ;/ |' {3 ?2 o C; w B. j5 m
- 要做校验的数为6个,所以是 USART2_Data - 2;& d. k2 j6 C% s! D Z! R
- 校验需要计算的是 USART2_BUF[6], USART2_BUF[7]
3 B4 g7 t* C1 y- D! X' K& a - USART2_BUF[USART2_Data - 2] 和 USART2_BUF[USART2_Data - 1]
5 R' M5 A7 Q9 G# E+ f - */! T) I6 P8 ]) o9 i# }# d* E
- crc = Checksum_CRC16(USART2_BUF,USART2_Data - 2);
6 \/ Q) C) v) a; S% Z. W i( X3 \- ~9 m - // printf("crc is :0x%x\r\n",crc);
6 L- L) o R- b, ^& ] - /*No matter the high bits before or the low bits before*/' v$ C( e7 [* m4 k# v) @8 s3 h
- receivecrc1 = (USART2_BUF[USART2_Data - 2]<<8) + USART2_BUF[USART2_Data - 1];
4 U# q; W9 R4 k: b4 o( r: O6 E - receivecrc2 = (USART2_BUF[USART2_Data - 1]<<8) + USART2_BUF[USART2_Data - 2];
5 X/ @5 y" `* l) W - // if((lrc == receivelrc2)||(lrc == receivelrc1)){
* S8 e: p4 b; G, u& u7 a2 O - // if(USART2_BUF[0] == mymodbus_add){
& |5 w* K) {! a- v/ x" b - //这里说明一下,先判断地址,然后返回错误,如果先判断校验,如果出错了,那么总线上所有都同时返回就有问题了
/ T+ g- Y$ C( E" c1 o/ a) }. |% s5 H - if(USART2_BUF[0] == mymodbus_add){
) F* Y" L2 m- s - if((crc == receivecrc2)||(crc == receivecrc1)){9 e1 u1 w u( M( }- j& O7 k
- switch (USART2_BUF[1]){* I* I: _# B6 Z- m
- case 3:8 l' A" C( B% ^
- Modbus_03_ack();) q' |( R# ]" }
- break;( }/ Q. t% g# }
- case 6:$ z5 ?3 C0 P' G/ d1 c% U
- Modbus_06_ack();
7 N2 b7 L% S! U$ a3 N- k% F - break;
" A) ?! i! I- t9 }& f3 e - default:4 G3 \; ?$ |$ y; t" P
- // printf("An unsupported command!\r\n");//for test
2 F G1 u3 O- D( { d - sendbuff[0] = mymodbus_add;
+ T: x# u- ]( B$ ?/ m - sendbuff[1] = 0x80 | USART2_BUF[1];, y, e" W" b; P6 ? L
- sendbuff[2] = 2;
5 H- N1 s9 B( o5 A. M1 l/ O - crc = Checksum_CRC16(sendbuff,3);
7 I$ p( T- @% j - sendbuff[3] = (u8)(crc >> 8);1 j+ v% A$ N/ a; l; }1 s
- sendbuff[4] = (u8)crc;
0 K7 T% A& {9 t, m' D8 B - Uart2_sendBuffer(sendbuff,5);# y8 U2 }) U3 D! L) T& j X/ L% \
- break;. p5 W5 q B2 D
- }
4 {, A9 I! \* x7 N0 Z- Q, k - }. A$ P( |- `+ G8 f
- else{ //校验错误,返回异常
+ |1 \; y1 O! D+ G9 W( H - sendbuff[0] = mymodbus_add;' g" y. N- h' \0 B
- sendbuff[1] = 0x80 | USART2_BUF[1];
F9 }. Y6 @/ [. D/ w/ Q, k - sendbuff[2] = 0;' k% a4 } y) F# |% G) w$ C
- crc = Checksum_CRC16(sendbuff,3);5 D5 ?! L# w, O, Y# c
- sendbuff[3] = (u8)(crc >> 8);" ^4 R1 E* T' g+ W; e. v
- sendbuff[4] = (u8)crc;3 ^, n& u& [1 z* h6 c
- Uart2_sendBuffer(sendbuff,5);& i6 i% B: W2 f7 p' X
- }
& _* z9 Z) M/ ^+ P. N8 l - }
9 c+ M' z1 N V+ O) f - }4 o0 {% f3 z8 _) y4 y3 t
3 m. K8 T+ y7 Z! h- void Modbus_03_ack(){
5 ^2 Q1 N/ c- L! J; x4 o3 y$ } - u16 Register_add; // 2,3
! R" e, T- r0 h - u16 Register_len; // 4,5* V. m- G" P$ e- V( k
- u16 crc;
4 d9 P* z: S- X3 u2 b. ~9 I0 X3 O1 H - u8 i;
0 C! W1 L& V! B7 a0 b% \ - u8 j;
9 D/ {( J9 @) `5 u7 ^8 M
6 f( H8 B6 I; j9 o* f- Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
/ ~& n0 |- ^$ A$ W - Register_len = (USART2_BUF[4]<<8) + USART2_BUF[5]; //get len;# @* Z( l n+ R$ T5 {
v7 I* R" q( G& Y j+ b& J0 g- u8 sendbuff[Register_len*2 + 5];0 C. L# j) B- `- n" B. E
- /*7 \+ g3 z6 x" Z X
- 如果读取的地址写错了,或者读取长度超过规定的长度
A! r. Z) z. y* ~& j9 o! s - 返回错误
8 M0 O$ H# Q7 s3 l3 N) q9 B - */9 L9 R; J$ N# p( B" E: s: o- a6 S
- if(( 0x0010 <= Register_add)&&( Register_add <= 0x0014 )&&(Register_len < 6)){
, v0 c6 R( W! p6 a - i = 0;, u; a( I& a5 n+ j6 g7 |/ t& Z6 U& e$ L% R
- sendbuff[i++] = mymodbus_add;
. o) V/ M: e4 G4 Z$ t; o6 X - sendbuff[i++] = 0x03;
+ N4 {/ t3 ]& H2 k2 j4 l7 z - sendbuff[i++] = Register_len<<1;0 e& [0 M9 A- d
- switch(Register_add){) f2 o' e* s3 K" a6 ?' R
- case 0x0010:
0 O7 n7 A/ m/ Z! }. a2 l/ ] - for(j=0;j<Register_len;j++){; @: w/ }0 j# l
- sendbuff[i++]= (u8)(Register_value[0+j]>>8); //发送读取数据字节数的高位
* ~4 @, ^# q/ w - sendbuff[i++]= (u8)Register_value[0+j]; //发送读取数据字节数的低位 3 t0 d$ N( p) ~6 i4 G4 [7 e% z
- }1 S( T$ l! p: A
- break;
5 V" ^) Y! ^0 A$ ]0 J - case 0x0011:
* s( T% N" ~* `8 }3 L! m$ E9 _7 x - for(j=0;j<Register_len;j++){
; a6 }: l( u% Y% \# o, U9 ? - sendbuff[i++]= (u8)(Register_value[1+j]>>8);
% U( W' |/ l2 R t - sendbuff[i++]= (u8)Register_value[1+j]; . k. \" G% k( m% ~8 R
- }
2 P/ u B7 l6 U( E. V4 n - break; 9 N% E/ W" ~; v% d0 D: w5 P3 Q
- case 0x0012:. z5 F/ [# D, c6 u" A
- for(j=0;j<Register_len;j++){! Q7 O' x; ]3 a2 A; n4 ^5 D6 I% o
- sendbuff[i++]= (u8)(Register_value[2+j]>>8);
$ c2 a B& |, r& F6 M [% m+ o - sendbuff[i++]= (u8)Register_value[2+j]; ' N, v# _) _( Q1 s! a
- }
6 B! V* P- s( s, S% k' g! F; w - break;. N9 q$ g0 ]) l: v" t/ }
- case 0x0013:( Z! `. R$ m' g* G, C* I7 L
- for(j=0;j<Register_len;j++){
% ^1 o9 |& v2 y+ I6 Y - sendbuff[i++]= (u8)(Register_value[3+j]>>8); * |5 d2 w. E3 ?$ |1 q
- sendbuff[i++]= (u8)Register_value[3+j]; * f) F9 D1 j g, K
- }
, R2 J" r( l7 i8 A3 s - break;
7 I7 r% H, k" G& L9 {" \ - case 0x0014:
: g x5 j' D3 |# P - for(j=0;j<Register_len;j++){
- Z, T) _4 x( _6 k2 [9 P - sendbuff[i++]= (u8)(Register_value[4+j]>>8);
5 ]( i0 B4 K( o5 p1 k. U - sendbuff[i++]= (u8)Register_value[4+j]; ; E& Z$ c. b, Y* q
- }! i% G$ [. P& o9 a
- break;% M1 f3 ?9 U, Y/ D1 Q$ G; r
- default:break; 3 V9 s1 U! U$ u& q9 t' A
- }7 e. s4 I3 B1 y( i
- crc = Checksum_CRC16(sendbuff,i);
7 |, ~* [$ s9 B6 j9 E1 y: [* { - sendbuff[i++] = (u8)(crc >> 8);
2 b5 J5 O, _" d- C" B, h, n - sendbuff[i++] = (u8)crc;
/ ^$ G: [& m% B, l5 n; z8 P, Z' S8 C - Uart2_sendBuffer(sendbuff,i);
/ T/ B9 v# p I - }; L0 a/ B) t" Q4 A
- else{//地址不在规定返回或者长度太长,返回错误
% [7 S: K+ W4 U! X' c Y - sendbuff[0] = mymodbus_add;
. c6 E0 i7 V% r+ \ - sendbuff[1] = 0x80 | USART2_BUF[1];9 \. }. A% S" j5 Q9 x( p
- sendbuff[2] = 1;# s2 Y, W1 ` r
- crc = Checksum_CRC16(sendbuff,3);
. p g, `8 A1 h/ n* Y! { - sendbuff[3] = (u8)(crc >> 8);
: f# i9 [- _ {- W+ W - sendbuff[4] = (u8)crc;' o0 A. Z G7 D
- Uart2_sendBuffer(sendbuff,5);8 ~' w, L# d/ _6 z' C, l- G
- }* C& C& R) a+ R0 }& }# \( @! B
- }' f7 g6 ?1 M. w# C
5 [6 D& ~3 f% k Y" D$ f- void Modbus_06_ack(){; i6 H! n& f% X7 ^" ]# |
- u16 Register_add; // , o0 n/ _( Q$ k( f
- u16 val; // ) V& }- X! u. i( N( ^2 |. \$ Y
- u16 crc;
7 I! g) R$ G" z - u8 i;
( t& D! `) {' Q( t0 [- E - u8 sendbuff[8] = {0};' } k: _* N0 X7 W3 K) }) Y/ P% E
- if(USART2_Data < 9){
5 I1 \2 V z3 }4 p4 n+ \ - Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;; X+ Y) t) `/ e/ d& I" k
- val = (USART2_BUF[4]<<8) + USART2_BUF[5]; //# S8 M$ W/ ^+ G4 V9 c8 q# h6 J/ ?
6 o0 z1 w; f8 D$ C9 g- if((val > 0)&&(val < 248)){5 B8 @5 T5 _/ @# _" T
- if(Register_add == 0x0013){( n/ z! ?6 J2 n' X5 P
- mymodbus_add = val;
3 y0 S- R6 c# ^2 D+ l - Register_value[3] = mymodbus_add;/ [! o) B- a. ]. o& e' O1 J
- MY_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,Modbus_ID_ADDR,mymodbus_add);
9 k3 a! x5 t9 J7 Y - i = 0;1 n$ r m' \+ K, k
- sendbuff[i++] = mymodbus_add;
4 |: i2 k+ q/ E! T) R$ g - sendbuff[i++] = 0x06;
9 I6 n9 W0 _+ n. W0 W+ | - sendbuff[i++] = (u8)(Register_add>>8);
' p9 {9 q' q% F. P6 S, [' k! D! c - sendbuff[i++] = (u8)Register_add; y8 y& } H# |+ R
- sendbuff[i++] = (u8)(val>>8); 0 Y8 h+ {: V( Q: v# D# R
- sendbuff[i++] = (u8)val;2 ]; o! @; s' p1 B( V" K6 Q" }7 j/ w
- crc = Checksum_CRC16(sendbuff,i);- t7 _; s+ I' \3 B; b
- sendbuff[i++] = (u8)(crc >> 8);
1 y& |9 \1 D. t% g' }% @ - sendbuff[i++] = (u8)crc;4 b A) [' l N+ K7 F
- Uart2_sendBuffer(sendbuff,i); 1 L/ b/ L4 e. [. v! u
- }7 @3 _( g5 m* u1 I c
- else{//写地址不在规定范围
; h1 m# l h, n& s - sendbuff[0] = mymodbus_add;; L) ~2 {& ^0 u2 Q' s6 I/ `0 ]
- sendbuff[1] = 0x80 | USART2_BUF[1]; W! k2 W0 e+ B. [
- sendbuff[2] = 3;' @( W* U/ [% }5 z) q/ _8 u5 c! X H# T
- crc = Checksum_CRC16(sendbuff,3);
- E j: G4 d- D% M( N y - sendbuff[3] = (u8)(crc >> 8);. _, _8 L d6 L) n! [3 V; s
- sendbuff[4] = (u8)crc;9 B8 Q! y4 ^! T4 Q' D
- Uart2_sendBuffer(sendbuff,5);6 W9 k# k) j1 e( r
- }
6 b6 g5 m- R) d3 ^- ?8 u3 K) R8 P - }else{//写地址不在规定范围. p0 u e% R5 Q- t1 i3 l- t' |. \0 ~
- sendbuff[0] = mymodbus_add;1 @* K- I, F% B3 `4 Z& z( r
- sendbuff[1] = 0x80 | USART2_BUF[1];- y4 N8 v& a1 s9 X: J8 _
- sendbuff[2] = 4;
% ?- {) V3 [0 Z. ` - crc = Checksum_CRC16(sendbuff,3);
1 K' m9 n! t. b, p( e$ |, \ - sendbuff[3] = (u8)(crc >> 8); {" l# x# S- R$ I8 a- U6 f
- sendbuff[4] = (u8)crc;
3 m: d* @$ ], n1 j/ A) B - Uart2_sendBuffer(sendbuff,5);
# b8 `1 w: T9 M0 |+ u& s% _ - }- U2 f4 j0 y& u. p, d% [' O
- }
3 B8 k6 I! B4 z - else{//写地址不在规定范围
, k3 }, p1 x* l7 A; X9 n - sendbuff[0] = mymodbus_add;+ @# ?; W% M; V4 l( ~
- sendbuff[1] = 0x80 | USART2_BUF[1];/ } ^, x, C, ~ q0 j5 R. k! y
- sendbuff[2] = 1;
, F |3 K8 O. Z( T7 N - crc = Checksum_CRC16(sendbuff,3);& b( U) [+ t; ]3 G2 L4 ?' @: D5 i
- sendbuff[3] = (u8)(crc >> 8);& w$ {; x m T+ k/ j# c
- sendbuff[4] = (u8)crc;
' Q* B7 u! z& p0 C( X - Uart2_sendBuffer(sendbuff,5);5 m4 M7 R `6 o" r" e3 Z& b
- } ( {; e2 j' c' n# Q
- }4 `* _% H$ F- \9 y1 T; Z6 I1 ?
复制代码
0 l# M& A& v7 h, O& E8 s* A" a' x2.3 其他代码说明此项目的核心就是上面2个的驱动,其他部分,STM32和一些基本的按键驱动,LED等操作都和以往项目基本一样。 实际上当初我在 FreeRTOS 记录 实例的时候就是使用的这个项目作为说明的,所以从 0 开始的设计思路 当然额外说一句,这种 单品传感器 的简单的项目一般来说用不用 RTOS 实际使用上区别不大。 & ^ j2 ^+ H8 z" O% k% N, q
如有侵权请联系删除 转载自: [color=var(--weui-FG-2)]矜辰所致
* j9 p& d4 _& Q# A0 J
8 Z' H) D. i6 w3 L% [0 ]/ i; B# W
# v; I C* e: l# k" b( k7 c: h% j
|