在调试Modubus协议时需要用到串口的奇偶校验位,但是平时用串口时很少用到奇偶校验位,网上搜相关的历程也很少,将自己写的串口奇偶校验代码分享上来方便以后查阅。, g3 d0 T. B( q4 v
% I# V4 z0 m/ V& Q" | 如果用库函数的话,添加奇偶检验位就很简单,在初始化串口的时候,将默认的无校验位修改为奇校验或者偶校验,同时将数据位设置为9位。* A, v" t6 U' _) n" @* l' g1 g4 l7 e
. Q/ f& \: I/ s" U1 Q& d
串口初始化代码如下:
5 h! ~+ Q9 ~- X: ~; Z7 M+ |) E
5 ]$ d/ s4 J3 N1 Q; u- #include "uart2.h") L; H4 g6 x* E/ @" y
) q; x9 T$ J* z% A- #define CHECK_NONE_ONE_STOP 0 //无校验位 1个停止位 1有效 0 无效 ) t1 P d% v- {
- #define CHECK_NONE_TWO_STOP 1 //无校验位 2个停止位 1有效 0 无效
4 Y/ ?2 P6 j6 o c* a- h - #define CHECK_EVEN 1 //偶数校验 1有效 0 无效 6 Q) Z5 y9 X E- m6 D
- #define CHECK_ODD 0 //奇数校验 1有效 0 无效
- N9 C# G, w' S# h. M1 `! P
1 u" D" v1 {& V c- void uart2_init( u32 baud )
# d/ h6 h# |0 x* L) n: z - {. F8 t% Y# P# R9 N4 j# G
- GPIO_InitTypeDef GPIO_InitStructure;# T) q" E- G# ~$ T! X9 G
- USART_InitTypeDef USART_InitStructure;
. W* W j- g+ N/ c( T! q - NVIC_InitTypeDef NVIC_InitStructure;
/ s6 _: g/ M8 s- v9 n2 W" w% E m$ R - , @/ E8 U; E9 Y9 d, G: ]
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );8 }, [/ K( j1 X+ u
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE );' ]( R# l6 l. h5 o. _; x/ G; p
- ! U- X9 A6 j7 o
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
6 F' M( r0 b) S" m+ U) d - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;4 B( v* Q, X7 A! I7 O, I" z2 q
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;0 a+ [2 H1 c3 L" R* n. B% `6 c
- GPIO_Init( GPIOA, &GPIO_InitStructure );; c: E$ i& \1 ^# N" {4 P0 j! t
* b; n( O. J9 D6 q- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
3 B+ O2 Q* J) E( m/ Y- F - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- K4 b8 |' x& v* d9 n- Q - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
$ e6 n- I. N) T' z( Y N: k4 B! t - GPIO_Init( GPIOA, &GPIO_InitStructure );- J. Y3 W0 k" F
- " j* p+ M( ?; [; K7 h7 x
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;4 D5 b: }7 Z) |2 ?6 _4 i
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;: P% @/ p5 b; v: S8 \3 s
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
- ?/ J+ N/ ?! [ - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
) T& |8 _) E, ?* d8 [* [: ` - & h X6 j5 m; \# T
- NVIC_Init( &NVIC_InitStructure );
# m9 c5 W' ]7 y3 j
$ A7 k m0 V3 K& }7 J B4 L# |: q+ s- USART_InitStructure.USART_BaudRate = baud;
5 v* ?/ x% P" O - USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位
8 g6 n, z! T0 g0 q, T _6 [- ? - USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位6 S/ {/ U0 u* [9 @& O
- USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
- b; P1 H. n! a S+ ?/ j5 E, N6 m
7 Z3 s: u+ }+ ? n- #if(CHECK_EVEN == 1) //如果定义了偶校验 数据位长度要改为9位' Y) B: p, e; _7 y) R/ D
- USART_InitStructure.USART_WordLength = USART_WordLength_9b;
. c9 l0 M0 S% M2 B$ j. ~ - USART_InitStructure.USART_Parity = USART_Parity_Even;
3 e! L# u* c2 e/ ]% G8 ^ ] - #endif0 m4 a6 U. Y! K" w( I% | `& |
- 6 V9 _' V% O4 I/ z& G1 c; W
- #if(CHECK_ODD == 1) //如果定义了偶校验 数据位长度要改为9位 Y$ c& A0 ~* G9 k9 i2 E- m
- USART_InitStructure.USART_WordLength = USART_WordLength_9b;( B& ]1 u3 i+ t: O
- USART_InitStructure.USART_Parity = USART_Parity_Odd;. A; C q' O( p* I, F1 C/ D
- #endif }2 ^2 ^0 h) G! f0 [/ @+ s
- + z: D# C% e+ F- h" D( {# n7 A
- #if(CHECK_NONE_ONE_STOP==1) //停止位为 一位
: _# {6 T0 _; w& H - USART_InitStructure.USART_StopBits = USART_StopBits_1;
' }$ a) k" u' b; q, { - #endif3 j( E; q& A. ] c) |$ W8 T6 {
/ z4 |$ L5 a, g @/ u5 T m% e- #if(CHECK_NONE_TWO_STOP==1) //停止位为 两位
3 X3 N$ Q5 I6 d7 I! h - USART_InitStructure.USART_StopBits = USART_StopBits_2;* H% t& Q6 r; r T
- #endif
* v2 q, b9 X/ F5 }5 o: ~ - 9 `' {. E, n, w# }: L6 c6 k- p
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
& U* i. D) e+ L& i3 }; {. E* r - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;0 p5 S" n) R5 N% J
& X4 k/ c1 W j O1 O% O- USART_Init( USART2, &USART_InitStructure );7 V( Y8 H1 C0 t& P+ |3 w# g
4 Q9 F' [: h' `0 l- USART_ITConfig( USART2, USART_IT_RXNE, ENABLE );
0 S! Q( d. B3 |" w; g - USART_Cmd( USART2, ENABLE );
5 L+ l7 D g8 w& a7 m
- V+ S; J* V' j- }
# {8 [* p$ x1 C, Q: p8 N) M6 `; D - + }3 h0 g" } \; S$ x
- void USART2_IRQHandler( void )" X# f- g) u: w: D5 o8 ]
- {1 [2 O7 W& E/ d- j9 V; c
- u16 tem = 0;$ b3 s- X: G0 K5 j9 n1 R& \
- if( USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET )
* R+ \' ^: e( f3 s - {& m& b3 Q% u# \
- tem = USART_ReceiveData( USART2 );; l$ X) [3 B4 Q; v* K
- USART_SendData( USART2, tem );
0 D a& A- D) f) Y - }
, q" W) I L+ g5 v
) {9 U m* X( y& }: |( X$ m1 \: b- }
复制代码 8 _' q8 M. \2 V7 y
通过宏定义来设置是否使用奇偶校验位,停止位为1位还是2位。如果使用了奇偶校验时,要将数据位设置为9位。设置好之后就不用管了,具体校验工作由硬件来完成。8 X' ?8 Y: @+ {- `! J/ Q7 b
' x" K7 L$ u% `# D4 h- m. l4 a
在串口中断函数中实现的功能是,将串口2接收到的数据通过串口2发送出去。
8 {$ W; P) L, R, H" Y4 \. r: G! w) r% f5 I/ |7 e6 B. f5 t1 o
在宏定义中设置为2个停止位,偶校验。
* A; q% E8 ]. F- l) U2 S
% Z' `, p7 u- c# c! _& e) h' d
A! o) V- b3 K% {1 ^; T
2 A! W) [. K$ H ^. x
串口测试效果如下:* s) U! ~6 W1 m* ^( {2 ]# F
- X8 {: r1 l S" A# B
! ^: _9 L" P: e+ D U; m) W
' F! m# l6 s! U* P. D% C如果串口助手设置和单片机发送不一致时,接收到的数据就为乱码。' T- y% _% K5 R6 e; W4 N- ^) i
" R/ P$ p( ^& r9 R! e+ g
: X& f! E6 Z; T3 N x8 Q$ K2 Z
2 c) B6 Q; J! S0 `
( o. ]' \7 j7 ^7 n8 m |