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

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

[复制链接]
STMCU小助手 发布时间:2022-1-26 23:55
普通IO口模拟串口通信
  • 串口通信协议  
  • 1756507-20190801171211417-2072826917.png 6 ~( Y; A$ e- x; `. d
  • 串口传输 默认 波特率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开启一次,数据一多时间误差大,自然丢包。可以尝试每发一串数据,重新计时校准一次)。外部中断较为准确,检测的高低电平跳变较为明显唯一,一个跳变就是一个数据,只是分析情况比较多。
    , |" ?& Y! J6 z3 ]4 z: o# T
  1. //IO模拟串口初始化 1 void IRrec_Init(){
    * M  w8 q3 \  h8 x- E8 U3 P$ b: E
  2. 2
    ; L& ~; M6 Z: T2 [; |
  3. 3
    - b& w% @) f9 y
  4. 4     EXTI_InitTypeDef EXTI_InitStructure;
    7 V2 |4 W0 w5 [+ K3 |/ Q+ [
  5. 5     NVIC_InitTypeDef NVIC_InitStructure;) K% b2 g( y/ I1 l
  6. 6     GPIO_InitTypeDef GPIO_InitStructure;* D& m5 n% y" m
  7. 7 - _9 F+ `4 K9 [! q' {
  8. 8     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC时钟
    * A+ {. x5 t4 @; R( ~% \0 Q
  9. 9
    5 A5 M2 |. w3 {6 W) t. t6 z6 S3 j
  10. 10
    ; _, r5 q& C8 a3 d- d
  11. 11     //IR TX C9 使能' j8 N' N: w8 [) w/ L
  12. 12     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    6 w: Q, f; @! ~/ v
  13. 13     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   3 a: |- z9 W! P& s: C* M3 b
  14. 14     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; % ?) K+ t+ e! n* Y
  15. 15     GPIO_Init(GPIOC, &GPIO_InitStructure);
    ) g  R/ {9 \+ _; ?, m2 \
  16. 16     GPIO_SetBits(GPIOC, GPIO_Pin_9);//  引脚拉高3 b% F9 B- H0 O% n1 Y& s
  17. 17             * r6 b6 d6 Z9 L  O9 U9 a8 J
  18. 18
    ' [  S' Q7 w' N/ M7 u. ^  l
  19. 19     //IR RX C8+ u1 m' F. @' N3 T- Y7 t0 s" r7 q
  20. 20     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    1 R2 |0 {$ F4 F/ z+ K2 d3 p2 g
  21. 21     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;( ^* h5 T) D6 V3 g! o
  22. 22     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;7 V$ W5 G3 U9 o
  23. 23     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;6 i$ O" C& d6 y
  24. 24     GPIO_Init(GPIOC, &GPIO_InitStructure);$ c# e+ R; q& T5 d4 `+ e
  25. 25     GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource8);
    + f. \; [/ q9 r% m4 D! E
  26. 26
    4 I: F. V- z2 x7 \5 m1 T- b, ?
  27. 27     EXTI_InitStructure.EXTI_Line=EXTI_Line8;: {0 y: D0 X; g! N( Z, q$ d) b
  28. 28     EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
    0 T# U. M5 W! m- t$ ?; s2 s- m0 N' W
  29. 29     EXTI_InitStructure.EXTI_Trigger=      
    . f8 ]6 q2 |3 I7 n' ~
  30. 30     EXTI_Trigger_Rising_Falling;
    1 J. ~# s; Z7 \# r# x0 A
  31. 31     EXTI_InitStructure.EXTI_LineCmd=ENABLE;' I8 _: k5 l/ x, n
  32. 32     EXTI_Init(&EXTI_InitStructure);
    ! ~% t" M3 p' c) e/ w. _: U2 q
  33. 33     
    5 h  }5 |. o- c& z
  34. 34     NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;2 w  ^/ @& N, U" p3 O) r
  35. 35     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    ' c5 _& E  n% s6 M8 R& r
  36. 36     NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
    2 t5 }( m( i) h; D* l
  37. 37     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;/ O& u0 }. N8 `2 ?" Y
  38. 38     NVIC_Init(&NVIC_InitStructure);
    - p3 p7 n$ N' y8 A1 f0 w; Y
  39. 39         
    ; ~5 W) e, w, {" X# C0 I, n  Z
  40. 40 }
复制代码
  1. void IR_SendByte(u8 val)//发送bit位
    5 d, G  L  I: |1 f7 U/ e
  2. {( [1 ~6 e/ X8 y
  3.     u16 i;4 g# i+ I. r* T2 K  q) r' m* d/ _

  4. ( E- Z9 v0 K: u+ C+ ?% g
  5.     IRSEND=0;//拉低 开始传输
    7 B' T$ s! [& ?( H3 @" P
  6.     SysTick_Delay_Us(53);//波特率根据延时在设置  19200波特率
    4 q3 H4 ~# O, {$ ]7 m% G$ H

  7. : f) Y0 W& Z% m4 k; Z  D
  8.     for(i=0;i<8;i++)
    # c) u5 Q; W8 G4 ?6 ]8 p' J' N
  9.     {& o+ f' `4 U7 }% H
  10.         if(val&0x1)! g$ r4 G( B+ d, T2 }4 a
  11.         {. O3 [* w5 W% i8 b1 h: t/ [$ }: |8 V, p
  12.             IRSEND=1;; a; o; s5 q6 W& ~/ T: c
  13.         }
    " ^& v- c: u# [( z- }. \  G
  14.         else0 N$ _( E' j* K
  15.         {2 ^2 T' r7 u/ |" O  r8 o2 l
  16.             IRSEND=0;
    9 M! A, Q4 t# y
  17.         }$ N3 s5 K) }% c1 V5 F

  18. ; O$ \0 }0 Y8 v" c0 L% X$ N* T
  19.         val>>=1;9 F0 S9 V/ K4 Z, {
  20.         SysTick_Delay_Us(53);
    1 S) N. \1 f  S2 q7 c
  21.     }- `* u' d7 P( W& I( v, d7 s: d& J

  22. 4 Z3 P/ s4 l3 L6 a* ^
  23.     IRSEND=1;
    ! W- c8 ^! T3 F  B2 I
  24.     SysTick_Delay_Us(53);( v9 y& ~  P! z2 q
  25. }0 Y9 w' p6 {. F5 z* u# x( M

  26. . b! u( i  `6 A+ P6 E" K, Y

  27.   R2 T  n5 z0 m" H! V
  28. void IR_SendStr(u8*st,u16 len){//在这填入16位数据即可* g" C1 {* Y1 V
  29.     int i=0;8 d, m! b9 E. L3 K
  30.     while ((len--)!=0)
    1 w" h* P8 i; P1 v" h
  31.     {
    : b3 I. g$ C( V* ~' P" [8 R1 U
  32.         IR_SendByte(st[i]);0 i# `4 e1 `- V  `# j
  33.         i++;
    6 C% l1 y- y4 Y" _( E# z' M" `
  34.     }* T' s9 j1 Q( n8 U
  35. 1 t$ D# J& {) b. [9 F
  36. }
复制代码
  1. u8 IRREC_RX_BUF[64]={0};    //接收缓冲,最大64个字节.
    0 b7 i7 _! w+ a1 l* O  m* Q
  2.     //接收到的数据长度( b3 k0 V$ N* d0 M! h7 v3 [6 j
  3.     u8 IRREC_RX_CNT=0;9 k2 b, d" a' Q8 x9 f$ L! a0 f

  4. " V; f2 `& c& B% ^+ Y; B2 k( q
  5. char rebit=stopbit;//记录接收一个字节的二进制位所处何种位置3 g5 ~$ p1 i6 {2 {8 A+ c0 R
  6. u8 Recev[8]={0};//记录接收的一个字节的二进制流
    ) B1 q( k7 c& s; D9 g6 G+ B

  7. + M& m! v. A( |! q
  8. static volatile unsigned long long m_rx_previous_time = 0;//上一次进入中断时间& [3 J) o5 j  ]1 k! l* ^
  9. static volatile unsigned char m_rx_begin_f = 0;//开始一个字节的接收标志 0-无数据开始接收 1-有数据开始接收/ x$ B5 y% T  I% i9 B/ U  A# v
  10. void EXTI9_5_IRQHandler(void){
    " P- K2 [; D8 ~3 V+ }

  11. 5 J" u& ~" \7 k2 y' A. T# J
  12.     if(EXTI_GetITStatus(EXTI_Line8)!=RESET): }8 K( R' Z/ L! H% ?/ z4 Z( X
  13.     {
    2 B0 K! Y# M9 c9 ]' E8 h6 k! i( Z: Q
  14.         unsigned char skip_index = 0;2 ~5 r* M# T$ j& O5 c/ }9 M) H7 j
  15.         unsigned char i = 0;; r9 C/ v% g/ _" N6 ~/ s" l: C: a
  16.         unsigned char temp_bin = 0;//用于记录二进制值- U& \8 `9 ]9 j) _4 Z+ E5 [
  17.         unsigned long long current_time = sys_micros();//记下此刻时间
    - V$ ^2 [" k4 j' h+ Q5 w+ j
  18.         unsigned short interval_time = current_time - m_rx_previous_time;//计算一个状态持续的时长
    - P7 n2 V. S6 z" v3 t3 J
  19.         m_rx_previous_time = current_time;//为下次计算时长做准备
    1 r. q8 z1 K" q5 k* I+ C) z

  20. 9 l- S( D5 _  }# k/ A  |
  21.         //当前未开始一个字节的接收且此时为下降沿
    * ]$ y9 h' K/ k6 V% e+ h0 D  a
  22.         if(rebit == 10)//10 当数据不合法时或者结束传输时 rebit值设为10
    6 p; ?/ {3 @- u# P8 y5 ~
  23.         {! `; g. Z2 S( i5 s5 i: W
  24.             if(!PCin(8))//下降沿
    ; d: s1 l5 j: X
  25.             {
    3 Z2 y7 n" k' W
  26.                 rebit = 0;//记下开始接收7 o0 W$ R9 B+ Y$ h8 d. \
  27.                 m_rx_begin_f = 1;
    5 y7 [4 G0 z% m' t# ~
  28.                 debug_led(1,LED_TOGGLE);
    2 c0 Z0 |" z' n
  29.             }
      k1 h8 }# Q# Q
  30.         }3 M( N; e. J" j3 i: O' C1 i
  31.         //已经开始接收
    0 Q6 y, q( Z! }' J9 R( U
  32.         else
    5 d0 h3 `. a! O9 L& Y0 Z
  33.         {
    + ~  J$ x. A. A( H# T. Q7 e
  34.             //上一状态为起始位- O# o$ i2 X+ ?
  35.             if(!rebit)//起始位0
    " k0 `' y, I! w9 b- n
  36.             {+ ]6 j1 V. E- J' H! e  e
  37.                 //计算二进制数据的个数
    ' W1 q# i, q. ^8 g5 ?" K. i! ]6 P0 {7 e
  38.                 skip_index = (interval_time/50)-1;2 h% {+ X( [* o4 M6 Z
  39. # x# g2 P4 `- a. v( ^$ S3 {0 J
  40.                 //个数合法
    * v: J8 x4 ]" V
  41.                 if(skip_index <= 9)
    . ~  D0 s; O( _9 y& o0 _
  42.                 {
    ( k( Y" @8 L# _# _7 l/ b
  43.                     //根据状态保持时间更新接收值" W4 L- r% D) p' y1 |
  44.                     for(i = 0;i < skip_index;i++)
    * Z% w$ P/ c8 j6 h. `
  45.                     {7 |6 z4 M' H; L$ O# f7 j: D
  46.                         Recev[i] = 0;. o: o: z  z2 F9 p- ~2 g
  47. & b+ e6 [( F4 w! B) M9 }4 W& @
  48.                     }% |3 U+ H% `" A3 Y  U

  49. * q$ G$ c' M* L
  50.                     //更新接收二进制位的下标  h' s) X8 @/ v: o& C
  51.                     rebit = skip_index;
    / f6 N3 J6 [- Y6 [8 t( O
  52. ! N/ p  j' ~% A: B
  53.                 }
    % P( P' d' H, b, `/ x
  54.                 //不合法-重新接收) y0 Y; v9 v* m6 W( t# |
  55.                 else# L1 ]0 r7 F( G7 b7 _4 r% w* {  J
  56.                 {
    : C5 Q! ?+ U# `2 B
  57.                     rebit = 10;. B; j* m! M/ X8 v* ~4 R
  58.                     m_rx_begin_f = 0;8 M$ ~) J$ V' x6 e% [

  59. ; r" Z- w3 y' o0 V& U
  60. & ?* z  U) r8 B$ d4 D2 h
  61.                 }- |( q( A6 ]3 Z! Y) |
  62.             }. P$ B/ ]: u* [1 C: s# R
  63.             //上一状态为数据位4 ]( ~( P: e/ s/ S$ ^$ V( y+ _
  64.             else
    / C0 W5 D5 J1 j$ G- T+ ~
  65.             {; g# a$ b! k) W6 n: {8 g4 H0 x+ d
  66.                 //计算二进制数据的个数
    / v/ `. [( ]' _& ?6 i
  67.                 skip_index = interval_time/50;% U  D2 w; v, H

  68. 1 `) }+ o8 Z* K/ f2 q
  69.                 //数据不合法-重新接收
    ' c+ L) p* i9 T: r* }
  70.                 if((skip_index+rebit) > 9)//所处位置+数据个数 判断数据是否超10 合法判断7 B, s$ e3 a9 \) B
  71.                 {
    7 n) S) ]9 F( N% J& n6 T
  72.                     //printf("skip_index %d   rebit=%d \r\n",skip_index,rebit);
    - y! X- U* O3 z. _9 P& t  [+ A
  73.                     rebit = 10;" j0 O+ n8 `$ a) N2 n
  74.                     m_rx_begin_f = 0;
    4 `; p+ q: t/ n) Y5 N9 L: m$ |
  75.                     debug_led(3,LED_TOGGLE);) j! K6 ]! i8 Q9 v8 J2 K" O
  76.                 }
    - i: u& b: M: A* m9 Z
  77.                 //数据合法. ]9 P% |0 R6 Y# b6 p
  78.                 else2 n% z# D  X8 T' R" B* _
  79.                 {" N& f+ B  H* U8 N# Y& {
  80.                     //当前为高电平, y; _2 l  Q+ a) C( @) I4 |0 T
  81.                     if(PCin(8))
    , D) p& v0 p! T& p- e
  82.                     {
    - s4 v& ~3 c6 u
  83.                      temp_bin = 1;//0
    # O/ A) q$ z! ~$ Y& ]
  84.                     }
    + X# Q$ k& c9 x6 Q4 V' b6 n; H
  85.                     else( D* y. u3 K2 }: B" B5 O8 A6 e
  86.                     {, x( z8 \, ]2 N/ m
  87.                      temp_bin = 0;//1 change4 l" [0 q! f, I# [
  88.                     }/ Q. ]2 w  c1 P9 f
  89.                     debug_led(2,LED_TOGGLE);
    5 }& _+ u0 Z7 s% Z: I
  90.                     for(i = 0;i < skip_index ;i++)//根据几个数据 给予相应的位
    1 {8 t2 u, G. Q! v, X8 G0 G1 j" k
  91.                     {( H1 W& T7 f/ V& J  \  B: Y0 E% v
  92.                         Recev[rebit+i+1] = temp_bin;//change +1( u  [9 j* B2 ^3 h
  93.                         rebit++;! y. b2 f" }3 r4 Y5 h. F. y

  94. ) J  W1 T" v4 z8 T# \. }' P
  95.                     }
    ; \% G; K" x8 B5 U' x
  96.                 }4 e  R8 r  ^4 z( M2 E! ^! R: g

  97. 9 n# g2 \+ Z( G% P
  98.                 //数据已接收至结束位+ N( `3 J. P* e" x. b, r
  99.                 if(rebit >= 8 )//=8>?* P) D( \2 X  y1 |
  100.                 {, H1 L" R" j" \( c. {  j8 N# j
  101.                     if(IRREC_RX_CNT < 64)
    . V& G' a& k& O1 U& M
  102.                     {
    4 s, c$ ]$ U  [8 h: x' P$ X
  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];7 t4 E& O# H8 W9 e$ W7 m0 c2 T
  104. " V  T: ~2 g' l. s# B) u+ ~5 o" C6 N
  105.                     }
    + j* K  y6 r( E; r. O, F
  106.                     rebit = 10;+ Z' a' q; i( s4 ^9 U# W  `
  107.                     m_rx_begin_f = 0;
    * i4 M# d9 V5 T; m* I0 V% G
  108. ( j) F/ |! D/ W; n. M- L7 j5 G; F
  109. ; L3 T, @9 I( J- \& D( \
  110.                 }
    3 F% R4 z9 B0 S$ r/ p
  111. $ y! B! ~4 p* A' A. g) V( r
  112.             }$ z0 K+ t4 m3 x
  113.         }
    1 d% b( l8 ]7 D5 V" [) Y

  114. & o/ ^5 w# ]3 X2 g
  115. 4 L: k9 c7 U7 p
  116.         #endif$ p, s7 r1 u0 q6 {3 m# m: s+ t/ c. p
  117.         EXTI_ClearITPendingBit(EXTI_Line8);//清除中断挂起标志位
    * T) E) m, z* c/ \0 b+ w; S

  118. & f3 M/ a1 O1 F) H! m8 H
  119.     }  ~' A4 @, q2 R! T1 q, S

  120. : Z3 `  [: U! C- b$ k  Q' @, @* R9 V
  121. }
复制代码

. A% b& c8 ]* E5 f
赞 收藏 评论0 发布时间:2022-1-26 23:55

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版