|
前言 本文是个人笔记,文章只讲基本流程, 最后所有的资料原理图和程序都会上传至资源。
! B2 e: Y% S' l, X3 f2 {" C) T 一、硬件部分单品传感器的硬件部分还是很简单的: 1、STM32L051 和 STM32F103 是 Pin to Pin 的; 2、测温传感器使用的是I2C接口,使用了软件I2C,因为 D6T 是5V供电,所以使用了电平转换电路; 3、整个传感器项目需求是 485 通讯的,因为实际环境要求,所以采用了周立功的 485 模块; ! V* o- [2 V6 S/ N# A( w( k w
1.1 STM32部分老样子,最小系统都是一样的:
( f/ y5 E9 T; X
3 [1 B8 x# F. E- S- L 1.2 传感器部分
0 `/ G) R2 r. _* c7 T& c
# Z8 {% Z8 s, M: G' V5 S, }2 i% ~( o! ?5 [+ S* u
" n/ V( C3 S$ G) s; B" Q! }7 i9 g+ p+ L2 |
在这里插入图片描述2 U; e7 W7 {" N o. r1 {5 x
; Q' b% {) k- K1 c4 W0 D' u
1.3 485通讯部分. b: b" \6 H6 l* f: M
/ i ~1 v7 k1 J* B: g# @7 c
L& q- k7 g+ U! c: ^' g
. m' T9 s2 h) Y) ~9 c: i6 d, m' d3 T& ]
( v0 t G: V; V$ T# {
2 ]3 O i5 Z% v0 Q6 l7 X
& E8 Z- h% W1 X7 q8 q; I8 o* z
: v: |; m8 h4 s \& }4 _* b4 C% e1.4 电源部分
) [6 _/ Y4 c6 G3 d
' t& Z3 z) w7 O. @% I; u' t
! D. f4 S0 {7 g8 f) f二、☆软件部分☆硬件部分是简单的,本项目的核心就在于软件的实现,有2个部分是核心: 1、I2C 通讯驱动; 2、485 通讯驱动; 9 i5 B7 _5 x1 Z# i
2.1 传感器 I2C 通讯部分这里上一下上层调用的函数,具体的驱动细节见下文说明: - void D6T_Measure(); A6 U8 B4 G% \% K/ O( e
- {/ `& F' M/ a6 ? k" [
- u8 D6Tbuff[20];
6 b! ?$ S' q- r4 I) V" e - u8 D6T_Data=0;
& t, D$ Y+ O4 T, o. \* D+ [ - // u16 tPEC;0 M I/ x3 o( }9 J4 P) @6 ~) n# g
& J; v6 m- o' V- l/ } r( u- i2c_start();* C+ v. N; W5 R* u! `3 M: [
- i2c_send_byte(0X14); //地址,和读写指令( [. d& N. n. n1 m0 A) D
- i2c_wait_ack();: [( U! l) m5 [5 S6 ~% K/ j
- delay_us(150); //这里必须加
2 R# M* |9 j$ G! Z - 7 K% | c! S+ ?# v" N
- i2c_send_byte(0X4C);8 C' o& s m/ B9 a) j
- i2c_wait_ack(); ' ^6 T C$ {$ a8 B8 ~& A
- & k- q9 e! b& e! z& [
- delay_us(150);
1 ?9 t8 M2 o! q1 k2 v+ v
6 S! E8 X& ]5 y* n6 B& X- i2c_start();1 y$ n6 Q j8 o. d' A
- i2c_send_byte(0X15); //地址,读指令
, l3 d. u$ e! k* @' C1 I2 p - i2c_wait_ack();
/ T6 a- L' Q, T# V4 P) T - delay_us(120);
( _/ M4 Z8 r& }" s* c# f
% V c! i4 \; s5 ]* [6 w- // D6T44L_ReadLenByte(5); //D6T-1A-02 只有5个数值8 `& J4 i% u% p- k! c0 F
- u8 t;# h, g' _7 j5 w+ d! g" B
- D6T_Data=0;
& `, o! g H2 g2 F# p$ J0 q3 P2 { - for(t=0;t<(5-1);t++)
2 ~3 N% y- N8 h. |% N: j f4 I( c - {7 j3 n6 l2 A/ ^4 [, e; E
- D6Tbuff[D6T_Data++] = i2c_read_byte(1);: L; z) f% a- o
- delay_us(120);- |0 @0 q; p% w: L& l( t8 i
- }
' ^1 e& U/ S( }+ Z8 j' w - D6Tbuff[D6T_Data] = i2c_read_byte(0);6 {* @' l Z) s/ e- B' ], W8 j: z
- delay_us(120);7 R8 i+ l% G2 f) }
- i2c_stop();6 p9 p1 r/ {+ o3 }% A* C& v
' ~' A( c) T1 a- // tPTAT = 256 * D6Tbuff[1] + D6Tbuff[0];
[6 F5 X0 t" G1 [ - tP = 256 * D6Tbuff[3] + D6Tbuff[2];
: K1 ]% a% I9 ~( q - }
$ N9 e4 I: `5 |& Q
/ X0 y6 q! Y. f7 z. [- / r9 d9 S; v, Z% A& q, _" E
- unsigned char calc_crc(unsigned char data) 4 \5 n- ^3 V6 E
- {
# S. G, J( C( e - int index; 6 A3 |. N% A* z, K" k K" l; ^5 m( S
- unsigned char temp;
8 y- e g# D4 V5 y( Z0 n -
7 L9 R5 n3 k) b5 r. ?: n - for(index=0;index<8;index++){ ; {- Y5 X8 P0 b0 M# z' L
- temp = data; ; K* @+ s) k- K6 ^$ b9 {1 L
- data <<= 1;
7 l& G8 t1 i$ P n. _4 Z - if(temp & 0x80) data ^= 0x07;
; p8 j7 v1 h4 K7 e1 Y0 G) x - } ) H- z1 }8 e5 {# W1 x0 T3 D2 a. j! _
- return data;
- q; @1 w$ v/ T* c) P3 a- } - }
复制代码
* k8 {. b, c/ [4 k$ M! W/ T1 z' z! C" M& O
2.2 485 通讯部分本传感器是作为 485 从机设备,所以需要写一下 ModbusRTU 协议驱动,这里就不墨迹,直接源码奉上: - #include "Modbus_rtu.h"
% e+ Y9 m1 _2 l( G) V& O ? - #include "stdio.h"
- Z. x8 _3 q1 e7 {- Q6 d4 w- ?
& C4 M9 ~. a z- ~! I1 m& p- void Modbus_check()8 @3 D& Q' ]: H }
- {
- j7 ]7 y7 {0 i ` - u16 crc;
, O3 d5 C( a, g* F% R - u16 receivecrc1;# g8 M+ S/ Z/ Y
- u16 receivecrc2;
; Q3 ?) B7 A- C2 ~ - u8 sendbuff[5];! b1 j8 Q2 q! A
- /* * J0 o, W4 p( f" z/ ]
- 收到了8个数据:01 03 00 10 00 01 D5 CA
& q: D* e% O+ d! s. A3 h3 k$ E( a - USART2_Data = 8;
" ^/ f) X* x7 B9 W1 Y$ U6 e - USART2_BUF[0] ~ USART2_BUF[7] ;
, E8 a! N$ K/ @: a$ o1 e - 要做校验的数为6个,所以是 USART2_Data - 2;( R, c! `) I$ c! p' G7 S- `9 {: K$ u
- 校验需要计算的是 USART2_BUF[6], USART2_BUF[7]3 W( m: O/ A( X8 b
- USART2_BUF[USART2_Data - 2] 和 USART2_BUF[USART2_Data - 1]3 v6 V9 Z0 `& A' J# S5 }
- */- ]8 B# E: b9 O, A
- crc = Checksum_CRC16(USART2_BUF,USART2_Data - 2);! T+ s j/ l( C/ h
- // printf("crc is :0x%x\r\n",crc);+ P, M* b3 P) J& N( j* [
- /*No matter the high bits before or the low bits before*/; h. r, B5 W: d" t3 x
- receivecrc1 = (USART2_BUF[USART2_Data - 2]<<8) + USART2_BUF[USART2_Data - 1];
$ M2 @' W8 P, N4 n1 |& }1 ~4 x7 N( @ - receivecrc2 = (USART2_BUF[USART2_Data - 1]<<8) + USART2_BUF[USART2_Data - 2];- O! v* O- f/ b( O) w0 x
- // if((lrc == receivelrc2)||(lrc == receivelrc1)){
0 S Z" Q! l) c0 C; U - // if(USART2_BUF[0] == mymodbus_add){
* P' d7 k1 n2 j! G4 @ - //这里说明一下,先判断地址,然后返回错误,如果先判断校验,如果出错了,那么总线上所有都同时返回就有问题了2 p$ x; ]% T& O" Y$ v* y5 B6 ?
- if(USART2_BUF[0] == mymodbus_add){ . l- G7 J; v8 b4 X) A3 R( s" ~
- if((crc == receivecrc2)||(crc == receivecrc1)){
! f; f5 N! S4 `6 e$ X - switch (USART2_BUF[1]){3 \- a' E4 N* w9 B* F6 {
- case 3:3 K& k( I# {( l1 a
- Modbus_03_ack();
9 z2 A g: G9 t v, k - break;* _1 q7 N$ s! a- ?# ?! m
- case 6:
: M, b" p% Q' I( W5 _: c - Modbus_06_ack();6 B9 l* R b8 x8 f e% s
- break;
* O+ k5 H9 f- E0 a: U& U - default:
" t; N% n$ Q! Z. L0 b; R# Q - // printf("An unsupported command!\r\n");//for test- L+ E0 Y. [" `7 Y5 k
- sendbuff[0] = mymodbus_add;
$ P4 \0 G% r* [1 z. r - sendbuff[1] = 0x80 | USART2_BUF[1];' D4 S4 z. k: `9 `+ Q$ W
- sendbuff[2] = 2;
* Z0 ^0 T1 R; i0 b: D - crc = Checksum_CRC16(sendbuff,3);
& q; ^8 E. d1 T& l/ f8 \: B k - sendbuff[3] = (u8)(crc >> 8);& m* |/ D. P# r4 W9 U% W1 Q
- sendbuff[4] = (u8)crc;
( L5 i/ f# S; U8 ` - Uart2_sendBuffer(sendbuff,5);
: I% ?( Z, t/ G( p - break;
$ b/ T' T% ?( w - }7 m8 y' r; V" A) ~) ~7 n
- }
' H, e2 ^% e* R! z - else{ //校验错误,返回异常: Q6 c* H* T, f
- sendbuff[0] = mymodbus_add;/ T- n j, ^. Z* L6 ]2 p. a
- sendbuff[1] = 0x80 | USART2_BUF[1];% F2 Y5 {" x( Y" J K3 Z6 y* J6 A
- sendbuff[2] = 0;
$ r7 n, K4 R8 b* y% B - crc = Checksum_CRC16(sendbuff,3);
% U# A+ [% {7 z* w+ p - sendbuff[3] = (u8)(crc >> 8);. G* c$ T3 O1 e" ^( P" A" o
- sendbuff[4] = (u8)crc;
# }/ d, g2 z+ q1 K) M4 `2 D - Uart2_sendBuffer(sendbuff,5);- o0 W7 `! g" P `' M
- }
% E8 i. x" k. Z; q5 t8 s2 P9 W x- ?+ I - }
C- {, @' Y& K9 K - }- k6 G, c. a+ N* O; {. f+ i* M
; h T# ?* e, j$ e% h- void Modbus_03_ack(){
K! I% M0 J" G, F - u16 Register_add; // 2,3$ x% v# u; o+ H _' I# S% \
- u16 Register_len; // 4,5
( w! j9 W% |+ a$ G - u16 crc;
, M; ?& o( _! a0 ^ - u8 i;
5 T( z/ O! [) }% Q. t/ X3 ^( D5 } - u8 j;
* f! w) p- k$ e' T+ D0 ~) ?
0 V/ { I! W# Q( x! n t- Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;" k0 h8 E! X$ b9 a
- Register_len = (USART2_BUF[4]<<8) + USART2_BUF[5]; //get len;
/ j5 n5 U% Y' p9 D - ( }3 D8 A: Z" W6 ^) n G! a& x& g: _
- u8 sendbuff[Register_len*2 + 5];& D3 o/ \! z/ j0 M* J
- /*
2 X: x* p6 P* u' h) e. e - 如果读取的地址写错了,或者读取长度超过规定的长度3 ]- F/ M( H" E, V: t6 _( X! `* |5 b
- 返回错误
- Z' D% z1 q" ~ - *// i8 R" ~1 R$ r
- if(( 0x0010 <= Register_add)&&( Register_add <= 0x0014 )&&(Register_len < 6)){ # C* T6 a. x* W u6 Q) k- a
- i = 0;
$ ~' i7 C$ o: L# c) y9 E' V - sendbuff[i++] = mymodbus_add;5 e. Y6 q Q; w6 ]( E3 k, f
- sendbuff[i++] = 0x03;7 ^7 m: N; s* `1 u$ U+ F w
- sendbuff[i++] = Register_len<<1;9 J! R3 \. y8 }* `6 n( k
- switch(Register_add){
v3 p ~ d/ t - case 0x0010:& j! s M* [' {
- for(j=0;j<Register_len;j++){
$ o3 p- d! O$ K% p4 D - sendbuff[i++]= (u8)(Register_value[0+j]>>8); //发送读取数据字节数的高位 8 O9 H* L9 t! b8 b* Z) K5 r
- sendbuff[i++]= (u8)Register_value[0+j]; //发送读取数据字节数的低位 4 E k- o; d0 K' i
- }7 g5 |. d4 c r- l1 B' R
- break;, ]- S* A! m2 X. e
- case 0x0011:4 f' d4 U9 M% }" l# P4 N9 s
- for(j=0;j<Register_len;j++){' i5 S+ e' z8 o' v) H
- sendbuff[i++]= (u8)(Register_value[1+j]>>8);
, p/ }7 J1 `9 \) H - sendbuff[i++]= (u8)Register_value[1+j]; 5 G8 h G) Y7 \" g" e( M
- }# ]2 N% t2 E7 J
- break; 3 j7 h6 p0 i! _) s; e
- case 0x0012:
, V* _. d% I* x. _/ a: u - for(j=0;j<Register_len;j++){. s q7 g1 y ^, U
- sendbuff[i++]= (u8)(Register_value[2+j]>>8);
$ ~! r8 l$ ~8 d7 F: ~" R8 R - sendbuff[i++]= (u8)Register_value[2+j]; / k- u. J7 s5 w
- }" a- t# q6 l, o. ?: ^
- break;# X( ]' f& V5 d* x4 P/ s& }8 t1 U
- case 0x0013:
3 C4 a( P* v9 U9 | b- U$ p - for(j=0;j<Register_len;j++){
5 u' }3 U& g0 t& {9 m - sendbuff[i++]= (u8)(Register_value[3+j]>>8); / |) B6 V/ r N9 @$ Y
- sendbuff[i++]= (u8)Register_value[3+j]; 7 V8 K- E" k4 C5 `) Y
- }3 {! C4 M+ j+ D% G
- break; 7 J" b$ H' s4 e" |4 B
- case 0x0014:' A4 `( e. A4 R- Z2 g; {! D
- for(j=0;j<Register_len;j++){* `/ T6 b: [$ V% C2 E8 U0 A6 c: U- E; O. m
- sendbuff[i++]= (u8)(Register_value[4+j]>>8);
6 R1 y, \( j) n! L U: K1 I - sendbuff[i++]= (u8)Register_value[4+j];
$ H J; ~1 M& c8 d% ? - }& E$ b) A+ m. s8 p$ x4 r
- break;
: R9 w& @: g! ]2 o6 U0 s - default:break; & O0 Z$ m* e! \9 X
- }
( Z) _" B. U/ D; H+ p8 e+ [' W: Z5 N - crc = Checksum_CRC16(sendbuff,i);
; A, Z3 y+ B/ X* S3 ] - sendbuff[i++] = (u8)(crc >> 8);7 D/ k( @' f( C4 V3 u/ A' L
- sendbuff[i++] = (u8)crc;8 Z1 P3 T6 @3 r/ k
- Uart2_sendBuffer(sendbuff,i);5 D7 T: y/ A3 [, o1 v4 x
- } c) u4 \, Q e; L k
- else{//地址不在规定返回或者长度太长,返回错误
: R) t1 r4 R: p: W# d - sendbuff[0] = mymodbus_add;
: \3 }8 ^8 k& e# S8 E: t2 B - sendbuff[1] = 0x80 | USART2_BUF[1];9 g h! O, J: u. z# |, x
- sendbuff[2] = 1;! S% O1 _, d+ q
- crc = Checksum_CRC16(sendbuff,3);1 `! {1 o6 [6 r* B6 q( Q9 Q
- sendbuff[3] = (u8)(crc >> 8);) T& T o4 t- i# j
- sendbuff[4] = (u8)crc;' K$ \# ~. ^% E3 W/ |1 z; s
- Uart2_sendBuffer(sendbuff,5);( o9 T* W, z' l$ s/ [1 U+ `3 p
- }$ ?- t e% l/ E& o8 u" P6 e
- }
2 H/ K5 a$ _, R# @5 a! F
- ?( e2 f3 O8 i- void Modbus_06_ack(){& x- H+ E5 ^8 Z# a9 g x
- u16 Register_add; //
1 B6 C9 N3 w# i% R - u16 val; //
+ ~; D+ v4 a+ c8 g+ p- Z1 t% t- ?; b - u16 crc;; ]; s- [# P( _' h' z# T/ Z: i
- u8 i;
1 f. z& \# V. h) b4 E ?0 Z2 r - u8 sendbuff[8] = {0};
) E% c9 |8 e+ C2 `1 t$ ?1 E - if(USART2_Data < 9){ " Y2 S) Y+ d$ E2 H. r# k% s
- Register_add = (USART2_BUF[2]<<8) + USART2_BUF[3]; //get add;
+ E4 ? ^, w, m" ~+ e - val = (USART2_BUF[4]<<8) + USART2_BUF[5]; //
6 p! n7 w; O& O9 o
2 d3 m4 j, P4 A- if((val > 0)&&(val < 248)){, S- v9 s* ~$ x0 K V/ D
- if(Register_add == 0x0013){: r! M# u+ S) i+ t7 K6 k
- mymodbus_add = val;
7 H6 D, C4 W1 K" V - Register_value[3] = mymodbus_add;
3 A" ~- O3 E. O9 [, p - MY_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,Modbus_ID_ADDR,mymodbus_add);; r7 K; B0 p# G' X2 k& }
- i = 0;
: A" e, v! C* H6 x/ b3 m/ x$ s8 v: ] - sendbuff[i++] = mymodbus_add;
+ P6 ]8 \' z$ M" b - sendbuff[i++] = 0x06;
G+ q* Q& ]3 n; i2 l2 w' `+ g - sendbuff[i++] = (u8)(Register_add>>8); % R1 w; F- J4 J/ G7 \4 `
- sendbuff[i++] = (u8)Register_add; 7 H# X6 @: u! h
- sendbuff[i++] = (u8)(val>>8); : P. I- j; U1 \/ z" X
- sendbuff[i++] = (u8)val;% N/ l, V0 K% H( z
- crc = Checksum_CRC16(sendbuff,i);7 U \3 n7 \7 m/ n+ \% P, Y
- sendbuff[i++] = (u8)(crc >> 8);
% u5 C2 [4 r; j9 r- c& d6 w" O% r - sendbuff[i++] = (u8)crc;8 R6 f" y7 S( h& ?' ]; l
- Uart2_sendBuffer(sendbuff,i); 4 |7 i. v( ]8 I7 U6 j
- }/ r4 Z, p$ Q ~, j6 X) v) R8 I
- else{//写地址不在规定范围
3 X. l" Y& E- z. ]* u2 [4 y - sendbuff[0] = mymodbus_add;
1 e4 O; |/ O7 v1 d/ h0 S- L% H6 a - sendbuff[1] = 0x80 | USART2_BUF[1];
* N3 h& J, `% ~ u" Z; U$ o - sendbuff[2] = 3; C6 f- \0 q4 H, E: R% ]; v
- crc = Checksum_CRC16(sendbuff,3);3 f- r% X G! \
- sendbuff[3] = (u8)(crc >> 8);/ }8 M C# }1 C0 M \; W H
- sendbuff[4] = (u8)crc;1 e9 d/ s# ?6 P6 ]/ ]
- Uart2_sendBuffer(sendbuff,5);
# y( W3 _9 m" D - }
3 V6 }. w j# F+ M - }else{//写地址不在规定范围0 {2 c" d4 ~4 y7 C8 }
- sendbuff[0] = mymodbus_add;. Z& N) k& g: T# ?# X" G
- sendbuff[1] = 0x80 | USART2_BUF[1];% M3 S9 w6 f+ n
- sendbuff[2] = 4;
* y5 h2 P- }7 r K6 i" w' v - crc = Checksum_CRC16(sendbuff,3);
" E0 U: V6 T4 k7 U4 i" n9 G6 U - sendbuff[3] = (u8)(crc >> 8);6 p) Z' ~6 I, }# p
- sendbuff[4] = (u8)crc;
- G8 W& p4 b# w$ _ r( c - Uart2_sendBuffer(sendbuff,5);2 i. j2 [; W. v6 H* A5 D! g2 W
- }
+ x% K! R7 H, w+ C - }9 s& @1 |! w. r3 P4 U
- else{//写地址不在规定范围, E3 _4 ^( d& f/ {0 Z
- sendbuff[0] = mymodbus_add;, w/ x. ^) N x$ P( ?1 X1 P, W J+ N
- sendbuff[1] = 0x80 | USART2_BUF[1];
7 a5 n) u$ z f - sendbuff[2] = 1;
1 a$ e2 v9 C. _1 |" K - crc = Checksum_CRC16(sendbuff,3);; ?+ B" ^4 p+ Y J6 q, G# R2 \
- sendbuff[3] = (u8)(crc >> 8);# C0 D+ |3 q9 Q! P" ?5 F( s3 u
- sendbuff[4] = (u8)crc;0 y! c3 P( q; a9 \8 Q
- Uart2_sendBuffer(sendbuff,5);- y% \& s* F$ @7 o* n
- } ' x, U$ R/ r# a- n2 H
- }
5 S' p6 g/ e) ^! r
复制代码 . ^( @+ x7 y. i. B. O
2.3 其他代码说明此项目的核心就是上面2个的驱动,其他部分,STM32和一些基本的按键驱动,LED等操作都和以往项目基本一样。 实际上当初我在 FreeRTOS 记录 实例的时候就是使用的这个项目作为说明的,所以从 0 开始的设计思路 当然额外说一句,这种 单品传感器 的简单的项目一般来说用不用 RTOS 实际使用上区别不大。
# d4 [1 i) W; R0 e# q% z如有侵权请联系删除 转载自: [color=var(--weui-FG-2)]矜辰所致2 w, _0 [- C9 Q" ~: G7 ~- ?7 ^& z% e
1 k+ n3 ^( p! M0 u
% f& [! K5 d$ l9 A7 r
/ F5 Y7 p# E# [& D3 m3 V9 F2 ]
|