你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】stm32 普通IO口模拟串口通信

[复制链接]
STMCU小助手 发布时间:2022-1-26 23:55
普通IO口模拟串口通信
  • 串口通信协议  
  • 1756507-20190801171211417-2072826917.png
    5 ^8 _# a9 t2 R
  • 串口传输 默认 波特率9600 1起始位 1停止位 其他0 数据位是8位(注意图上的给错了)。
  • 传输时,从起始位开始,从一个数据的低位(LSB)开始发送,如图从左向右的顺序,对电平拉高或拉低,最后停止位时拉高。
  • 波特率大小,改变延时时间即可。例如9600 波特率    根据公式 : 1/9600=0.000104s(大致) 也就是说每发送1bit延时104us (下面我用9600波特率来说,代码用的是19200)
  • 串口发送       将电平拉低 延时104us(视为 起始位 0   传输数据正式开始)  其中数据我发送的是16进制数据(8bit  一字节  例如10001000)  将想要发的数据按照二进制的‘0’‘1’高低电平的方式,每发送1bit 延时104us   直到发送完到终止位 将电平拉高视为一包数据传输结束。(根据需求更改即可)
  • 串口接收    (稍微麻烦一些) 两种方法:第一种可以用定时中断,每隔104us开启一次定时中断,中断函数内进行高低电平判断,将这些bit存储最后转换成需要的数据。第二种,用外部中断处理函数,外部中断设置同时开启上升沿下降沿,思路:根据上升下降的电平跳变分析。比如说,触发外部中断后检测电平高低,记录一下当前时间,然后再进入外部中断后 计算出总共几个bit   (两个沿跳变之间的时间 =现在记录的时间 — 之前记录的时间        bit=这个时间/104us)  ,知道这个就可以转换数据了。
  • 定时中断逻辑相对外部中断而言简单好写,但是数据多的时候准确率下降很多,容易丢数据(因为定时中断毕竟用计时开启中断,不可能时间准确每104us开启一次,数据一多时间误差大,自然丢包。可以尝试每发一串数据,重新计时校准一次)。外部中断较为准确,检测的高低电平跳变较为明显唯一,一个跳变就是一个数据,只是分析情况比较多。4 p0 K( p& T% L6 Q0 H/ `3 \- \
  1. //IO模拟串口初始化 1 void IRrec_Init(){
    , g, X# }/ n/ [! Z6 h! |) `1 C
  2. 2 " L$ H7 H% a2 o- Q6 g$ d
  3. 3 " @  ]/ l( }( \& o7 S
  4. 4     EXTI_InitTypeDef EXTI_InitStructure;
    " @0 \9 x3 I8 f' X% v( u" n
  5. 5     NVIC_InitTypeDef NVIC_InitStructure;
    1 h) r$ w( \: R/ U- v" V
  6. 6     GPIO_InitTypeDef GPIO_InitStructure;+ I0 m2 I4 g1 `
  7. 7 & V/ m) Z* y$ ?/ U$ l3 r2 f( D
  8. 8     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC时钟
    ; _# K, e+ T. a. k/ f( a
  9. 9 # }; s+ L4 g5 {1 j" ?3 l& z  c
  10. 10
    ) @6 d1 x; k; m
  11. 11     //IR TX C9 使能
    & _' z# X# S- z
  12. 12     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;' Y. n2 A' {' T- v) n- N  A2 S' ^
  13. 13     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    - j: S/ J, v, a- e, S
  14. 14     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 9 s5 B8 B: \9 U
  15. 15     GPIO_Init(GPIOC, &GPIO_InitStructure);. G" Q7 f( o' y# y  r. @
  16. 16     GPIO_SetBits(GPIOC, GPIO_Pin_9);//  引脚拉高& p# N$ R6 W) C: H  y
  17. 17            
    ' m1 ]- s! \. P0 ]" ^* l
  18. 18 . ]; K' e2 R+ C6 }4 |* D
  19. 19     //IR RX C8
    ' K2 C. h/ `1 M& F& h6 @
  20. 20     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    - n! P8 E# p$ [
  21. 21     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    & T$ h5 y; y; w. }
  22. 22     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    2 N1 P" C) @1 d$ ~. @: x4 |" l
  23. 23     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;1 k  ~4 H9 ~1 S
  24. 24     GPIO_Init(GPIOC, &GPIO_InitStructure);' p; Z6 |4 i' Q9 K+ Q
  25. 25     GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource8);
    4 g* d2 D$ n7 J9 D4 _. O. o
  26. 26
    - Z. q/ j1 N6 V  p- W: `* k, r
  27. 27     EXTI_InitStructure.EXTI_Line=EXTI_Line8;, s$ A/ L1 Y! _! O0 s8 r# L
  28. 28     EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
    , s9 Y# G1 f1 g8 E/ A
  29. 29     EXTI_InitStructure.EXTI_Trigger=      5 m# X7 J' p# r8 |4 C! \
  30. 30     EXTI_Trigger_Rising_Falling;* {- h1 T8 f% T. U! T( U
  31. 31     EXTI_InitStructure.EXTI_LineCmd=ENABLE;7 _$ s! [6 b& t7 W
  32. 32     EXTI_Init(&EXTI_InitStructure);1 [2 A8 Q! |' {4 O4 h! G( m
  33. 33     0 f: c2 i3 X* Z( t3 f, p' O' |% x
  34. 34     NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
    7 k. _' a- p+ T3 G) B) V/ V! K- T8 D
  35. 35     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;9 Q7 r2 {; V2 }. J( ]5 S1 b
  36. 36     NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;, y5 y% L& n1 v9 {  \7 F
  37. 37     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    % m9 a6 H: g  d% L: X! p/ U
  38. 38     NVIC_Init(&NVIC_InitStructure);- G9 ]* K# T0 b2 p
  39. 39           g# M1 j6 O' A/ \
  40. 40 }
复制代码
  1. void IR_SendByte(u8 val)//发送bit位
    - {; O5 S1 {1 Y7 k
  2. {* q$ Y* A: ^" f- `4 u- f9 ?
  3.     u16 i;
    4 q, ]6 o& D& ^1 i+ L7 [. H

  4. 1 ~7 ~9 ^- q0 c  [7 f
  5.     IRSEND=0;//拉低 开始传输6 B* J' z0 x7 U4 [
  6.     SysTick_Delay_Us(53);//波特率根据延时在设置  19200波特率7 Y, g& J+ q3 _

  7. % R1 y5 [! ~+ ~6 s) v) E( Q
  8.     for(i=0;i<8;i++)
    " m# A/ ~! L0 k  [) }& w  J
  9.     {
    0 |' c/ R! a3 {9 Q
  10.         if(val&0x1): K$ }  @- G; g! u* U4 y6 f, ^
  11.         {
    ! F/ N7 g0 [: W
  12.             IRSEND=1;, k& K  U# K( F' h4 J6 S7 i; i
  13.         }
    ! V) u, g( m6 i% V" L7 ]; D
  14.         else
    ; [8 J( I% ?# [* v5 Q8 c- r
  15.         {8 x5 R+ |8 @" u+ Z& G( E
  16.             IRSEND=0;# r- j) v7 M, W3 E( l
  17.         }
    % P1 M- H* Q4 L& o. ?

  18. * p1 g5 L, f- r6 f
  19.         val>>=1;
    ' g. K, t- A" v3 ^( x' Y
  20.         SysTick_Delay_Us(53);, r5 p* g0 f  F5 x1 e; k  _
  21.     }
    # j" a( a$ `2 d4 E

  22. / S4 |# K; X0 W4 z3 K/ X
  23.     IRSEND=1;
    * e2 C9 i$ ^5 F+ ^; N3 I, o
  24.     SysTick_Delay_Us(53);
    & n3 W5 N2 x# o+ d9 O
  25. }+ S! S% t  g6 f1 b3 f2 G
  26. : ^6 I% B4 D$ f' {/ l2 P% E" k4 _2 {

  27. 3 ^9 [2 J! y+ Z
  28. void IR_SendStr(u8*st,u16 len){//在这填入16位数据即可5 t% P6 q4 K' w* D, e6 `
  29.     int i=0;' X( K. ?7 o" ?! K
  30.     while ((len--)!=0)6 r1 ~& c9 X- B7 K
  31.     {
    # Q" h) L$ U; g& V( \4 ^! _" Q
  32.         IR_SendByte(st[i]);% `, _- a4 N) P  k8 ^$ r1 f$ d
  33.         i++;6 H6 _$ i& }( ~7 v5 y+ B8 M
  34.     }2 W; `4 O. a' [8 _% n- }
  35. . b7 O5 N5 ]" c( b+ e* M# y' c
  36. }
复制代码
  1. u8 IRREC_RX_BUF[64]={0};    //接收缓冲,最大64个字节.; t2 r6 `+ h  U- ^9 i
  2.     //接收到的数据长度; I, l  ~- i( N4 I6 d. V+ P
  3.     u8 IRREC_RX_CNT=0;9 G1 S7 b9 `' L+ c$ Q4 u
  4. 3 i+ N2 Z( n" [2 y$ W  i
  5. char rebit=stopbit;//记录接收一个字节的二进制位所处何种位置
    1 k& G5 b( _0 r& e9 T- b
  6. u8 Recev[8]={0};//记录接收的一个字节的二进制流3 i- D. j* b+ }0 ^5 S; J
  7. 6 J$ k& o) U2 ^7 M# z" J
  8. static volatile unsigned long long m_rx_previous_time = 0;//上一次进入中断时间
    5 I' g1 K8 `2 U( Y" c& u
  9. static volatile unsigned char m_rx_begin_f = 0;//开始一个字节的接收标志 0-无数据开始接收 1-有数据开始接收# |& H4 A. p* D5 B" K7 I
  10. void EXTI9_5_IRQHandler(void){" |5 r/ g/ }+ G% Z
  11. : W4 x3 ^& h" I4 x8 p, I
  12.     if(EXTI_GetITStatus(EXTI_Line8)!=RESET)
    ! j" v1 ]' u! B- k1 M- q" M
  13.     {
    - o& s* k; W/ {  [( E2 V/ [, Y
  14.         unsigned char skip_index = 0;$ D2 Z4 h5 q7 B, r+ s3 l
  15.         unsigned char i = 0;0 W3 h5 e1 ?! b- g
  16.         unsigned char temp_bin = 0;//用于记录二进制值4 o2 I1 ~1 x& i6 l; d
  17.         unsigned long long current_time = sys_micros();//记下此刻时间
    , P2 e; k. j0 S8 x7 l+ s/ X
  18.         unsigned short interval_time = current_time - m_rx_previous_time;//计算一个状态持续的时长
    0 l, B/ b7 S3 ^: e; W
  19.         m_rx_previous_time = current_time;//为下次计算时长做准备% p& c1 P4 V7 x! ~  z" J  q
  20. ' X' f. [1 n- a; z  ]6 ^
  21.         //当前未开始一个字节的接收且此时为下降沿  \7 f" @* v7 N" I
  22.         if(rebit == 10)//10 当数据不合法时或者结束传输时 rebit值设为10! e7 I) }1 K* M9 p3 C5 Z
  23.         {, c' W! E8 c, @! p# U
  24.             if(!PCin(8))//下降沿, x& Z, f7 n, `# {
  25.             {
    # e: \0 m0 k& R. v5 K$ v
  26.                 rebit = 0;//记下开始接收
    1 D% l  }+ w# |" @
  27.                 m_rx_begin_f = 1;1 G& s" C& r( ^  T/ i
  28.                 debug_led(1,LED_TOGGLE);8 {6 k$ g1 f! L3 U
  29.             }
    $ [; w* Y$ y7 O6 J* E) F7 \
  30.         }
    1 ~, _) Z' r+ S. o
  31.         //已经开始接收
    1 z, h; }5 p1 L5 T
  32.         else" {' K# ~$ @3 m# B/ {6 a
  33.         {+ S) S# u* m6 k# p3 H3 e! w0 |4 p0 \
  34.             //上一状态为起始位# E& m3 g* H' ]( P$ n
  35.             if(!rebit)//起始位0
    - V- k* X: v9 R5 n9 B2 r
  36.             {7 ^8 y& I& _- h" f' K
  37.                 //计算二进制数据的个数
    1 b. M9 @- u" d  s) A
  38.                 skip_index = (interval_time/50)-1;
    ! @! h7 B# O$ V$ p4 C+ q; `5 p+ p

  39. 5 A- D; \9 w% w4 P! z5 X+ j
  40.                 //个数合法5 O# B1 T- W' Y8 V, w! t0 R
  41.                 if(skip_index <= 9). [6 |4 }/ s0 E' b- V% d3 n2 ~
  42.                 {& s/ r! X3 j7 `8 s+ O3 J
  43.                     //根据状态保持时间更新接收值
    ( b' |" G3 B( w' o" w" s" [! n5 j
  44.                     for(i = 0;i < skip_index;i++)1 j$ M' w! T' X1 R* @" C# f: ^
  45.                     {
    ) {5 j( H# Q0 R! Z0 p: ?/ i/ I
  46.                         Recev[i] = 0;
    $ a( ~# h- K% l$ n6 t
  47. . M9 `/ ]  U/ x* J4 n, K
  48.                     }
    2 ~8 H# h  r5 ]+ Y# n' x

  49. . u: w5 p, `. o) J
  50.                     //更新接收二进制位的下标/ ~' \6 {" d8 r. _) w. K0 O
  51.                     rebit = skip_index;
    ; q( n8 x/ ]! }: z, W. H

  52. / o$ d* P5 e- @  S
  53.                 }
    7 G+ O6 \3 [# x6 d) `
  54.                 //不合法-重新接收
    & L4 Q" |$ `; D$ r# L
  55.                 else
    5 ]+ c2 s, ~; @  J. o* d& d
  56.                 {1 u0 D) w& g0 `- O9 @- j
  57.                     rebit = 10;1 G  w; T. j( |8 v: x
  58.                     m_rx_begin_f = 0;1 Q, W- k2 o! o2 C, x, V. y! }
  59. : h( @- X+ K8 S

  60. 8 ^' u3 q, \: r
  61.                 }3 r% M" _! I5 ^/ {/ @* d7 |
  62.             }
    / a! r) a7 Q( o. }- N0 [' V; `. W
  63.             //上一状态为数据位
    + j1 e, D$ C/ p
  64.             else% {& Q; [! @! K. y5 E  D
  65.             {, P+ M; y2 {5 ^4 c" `
  66.                 //计算二进制数据的个数
    * M7 n% h7 O+ d5 d6 L0 V
  67.                 skip_index = interval_time/50;; n7 N% U9 {' ]; \! f/ A) j

  68. 9 E' q1 O4 I; b$ K6 T* }9 l
  69.                 //数据不合法-重新接收
    3 n* |# K& W% n/ E' F: d2 x
  70.                 if((skip_index+rebit) > 9)//所处位置+数据个数 判断数据是否超10 合法判断9 r5 F2 B, f7 w- H) R
  71.                 {7 n' j3 C# S6 Q1 I
  72.                     //printf("skip_index %d   rebit=%d \r\n",skip_index,rebit);2 ^: ?# O# Z" Z* x4 e# d
  73.                     rebit = 10;" ]6 c1 p$ C, T8 E: r- e
  74.                     m_rx_begin_f = 0;' i& u  {  t! S& l6 s
  75.                     debug_led(3,LED_TOGGLE);5 k! f& ]0 w4 {+ |  C' P3 q+ o. c# ~
  76.                 }
    2 G) @1 y; e# p4 T! W' h
  77.                 //数据合法  g" j+ u) s3 T. u0 b9 z
  78.                 else  G) u; f* ?7 B7 D
  79.                 {) k" P: r( e% ~; F3 W6 D/ H% V6 u5 D
  80.                     //当前为高电平
    : Q2 N0 `( W3 M4 _
  81.                     if(PCin(8))
    ) a( \8 O0 O: I; y- o
  82.                     {. q5 d6 ]+ y( ^$ L/ K
  83.                      temp_bin = 1;//0
    , }; K: A8 C" f
  84.                     }0 `# B9 U8 b1 g, ^! s) Z
  85.                     else: E) i' Q; i: ~) |
  86.                     {
    " f0 r0 Z3 M' E+ V& y8 p
  87.                      temp_bin = 0;//1 change
    ) \9 _( b0 ]% Y
  88.                     }5 [$ K# w! U) W; J) T7 w3 M
  89.                     debug_led(2,LED_TOGGLE);
    2 d1 F, r' h! j# a& V! B& {8 O
  90.                     for(i = 0;i < skip_index ;i++)//根据几个数据 给予相应的位" {2 X- Y- ]7 F
  91.                     {
    / q! W: x. A+ g8 J  s- J
  92.                         Recev[rebit+i+1] = temp_bin;//change +1
    % N) e2 |/ d% |# @  H
  93.                         rebit++;! _" n  u$ K( F" ~
  94. * Q) [; d  \3 N8 g* _3 a; p
  95.                     }0 u0 S7 k$ I* e' T) M
  96.                 }0 z# t3 u% d# B  P6 f9 R
  97. : g/ f0 i/ @# K& _  g8 l
  98.                 //数据已接收至结束位% O, Q) B- w$ H/ `1 s: w4 l% {! Z
  99.                 if(rebit >= 8 )//=8>?
    - `! I+ M- s9 }' A
  100.                 {9 N# h: D; ?6 k8 I! R9 J6 r
  101.                     if(IRREC_RX_CNT < 64)
    7 v, O) V. h/ |5 {
  102.                     {6 a5 ^/ Y( r% o/ ^9 k
  103.                         IRREC_RX_BUF[IRREC_RX_CNT++]     = (Recev[7] << 7) |(Recev[6] << 6)| (Recev[5] << 5)| (Recev[4] << 4)| (Recev[3] << 3) |(Recev[2] << 2) |(Recev[1] << 1) |Recev[0];4 A* H: d1 D1 u- `" t; \& }6 `. r' U
  104. . _, ~$ j1 f) }! A6 B
  105.                     }! A. y: ^: ]7 U- z2 [
  106.                     rebit = 10;6 D8 A* G7 h) X. X5 ]; l& A
  107.                     m_rx_begin_f = 0;$ j( X  d$ q8 S, X9 S! }

  108. - I% B/ m5 R1 Q, x. S: m$ V" ]4 g

  109. ( X1 T& _& y/ u/ v& F
  110.                 }
    ( X" ^3 [: n1 \2 H. T" w6 ]
  111. * v" q% A4 r8 r$ }  m- M& F
  112.             }4 Z' u9 t( d/ C  _+ l- \" U
  113.         }7 }6 |3 U  I+ N8 q8 v3 @

  114. 0 W# T# C" l$ \7 m+ i4 K( ^; d, D- d) C
  115. ; n  p% W/ M6 L7 {/ |3 P
  116.         #endif
    1 W1 U8 {2 s8 B& s; a1 E
  117.         EXTI_ClearITPendingBit(EXTI_Line8);//清除中断挂起标志位
    2 M( V& o6 ?) H% A

  118. - G9 R8 ?8 e( a! Q# U& O5 J; _/ P; f
  119.     }
    ( V/ `1 ~# g6 N* u' A# ]  ?1 P
  120. ; U3 v4 b# y# V2 o6 k1 R4 h
  121. }
复制代码
; P4 v/ `0 W  Q/ w# F; c
收藏 评论0 发布时间:2022-1-26 23:55

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版