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

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

[复制链接]
STMCU小助手 发布时间:2022-1-26 23:55
普通IO口模拟串口通信
  • 串口通信协议  
  • 1756507-20190801171211417-2072826917.png + ~( t6 O7 T/ ?' X/ r! o
  • 串口传输 默认 波特率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开启一次,数据一多时间误差大,自然丢包。可以尝试每发一串数据,重新计时校准一次)。外部中断较为准确,检测的高低电平跳变较为明显唯一,一个跳变就是一个数据,只是分析情况比较多。
    . g) U/ _( I$ q1 t& L' R4 J/ W; Y
  1. //IO模拟串口初始化 1 void IRrec_Init(){
    ; l* H  [% H8 x" b
  2. 2 + n; x# q$ G/ ^5 @9 I
  3. 3
    7 L2 u( j0 e- y$ a0 O$ Y
  4. 4     EXTI_InitTypeDef EXTI_InitStructure;6 D9 q9 f- S8 O. Y% Z4 A
  5. 5     NVIC_InitTypeDef NVIC_InitStructure;: s( R8 ~! J2 ~, M) x
  6. 6     GPIO_InitTypeDef GPIO_InitStructure;; N6 r# ?" Y- ?: R# n6 P8 s
  7. 7
    ( d. X* A/ n& |' r6 q2 C( ~
  8. 8     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC时钟: P6 K  Y0 o4 _, T* E% [
  9. 9
    % j2 `" O+ v  [" w5 w% R/ c& q
  10. 10 % Z4 [, O4 H; O7 y
  11. 11     //IR TX C9 使能3 K' ]. K  {1 t7 d" n
  12. 12     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    ; Q, T- T) z  l2 ]: z
  13. 13     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   : |3 a  [- Z, D0 q
  14. 14     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    + R9 L" I* p$ ]9 e( ?% t
  15. 15     GPIO_Init(GPIOC, &GPIO_InitStructure);
    % C7 V: c) F% r6 U8 ?; l; c  J/ d* a" E
  16. 16     GPIO_SetBits(GPIOC, GPIO_Pin_9);//  引脚拉高
    # K% y' _* k3 x, C9 o+ q8 p
  17. 17            
    : t" ?6 Z1 C8 j" {. X
  18. 18 " ^% T! \0 F+ c5 F2 U  I
  19. 19     //IR RX C80 G/ a" j  A+ R
  20. 20     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    9 B% a7 P0 H1 J- w  E
  21. 21     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;. C; G! E5 k' \, z8 E/ I; |
  22. 22     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;0 Z" z) v" ^# v. ^) Q
  23. 23     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;. T; @/ ?! L$ V/ D- z5 }+ Y6 u* S- x
  24. 24     GPIO_Init(GPIOC, &GPIO_InitStructure);$ r+ k# Y& R# _
  25. 25     GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource8);
    . k! @0 C. B. i, J! ]$ I, J
  26. 26 " x- ^: C  @1 N
  27. 27     EXTI_InitStructure.EXTI_Line=EXTI_Line8;
    ' u* {: A) }0 t. c$ Q: N
  28. 28     EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
      }3 M, [9 Q9 w- h8 q4 z0 e9 ~  ^
  29. 29     EXTI_InitStructure.EXTI_Trigger=      
    % e+ }$ a/ q( B) L
  30. 30     EXTI_Trigger_Rising_Falling;6 `* L/ w+ ?! [1 I! [" B
  31. 31     EXTI_InitStructure.EXTI_LineCmd=ENABLE;2 N8 e7 Z* D4 J1 b- S) B% V
  32. 32     EXTI_Init(&EXTI_InitStructure);
    9 Z1 I3 ?" l, Y- s! ^3 h  u8 @
  33. 33     ) H+ K6 H) r7 H0 n1 e! g
  34. 34     NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
    * x, E" S1 h' L( u! X9 ~, m
  35. 35     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    , e! \6 @, |: W- j
  36. 36     NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
    5 h* H- I8 w5 O& ?& f, {" m$ _: l
  37. 37     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    : G: b0 b3 m1 ^! j3 V! i5 m% h0 n
  38. 38     NVIC_Init(&NVIC_InitStructure);9 v5 q, \/ y' R( R. C- c
  39. 39         * N' Z$ L# H/ E9 \7 c# R, _
  40. 40 }
复制代码
  1. void IR_SendByte(u8 val)//发送bit位( w4 U! T: a  Y
  2. {. q( r* @7 u9 y
  3.     u16 i;3 h6 S7 j8 O  J9 k2 M
  4. ( t( \( U$ D" u2 O
  5.     IRSEND=0;//拉低 开始传输5 e& P. b$ h* J- ]
  6.     SysTick_Delay_Us(53);//波特率根据延时在设置  19200波特率
    . t9 D- x( y3 v. B1 u5 s0 H

  7. 6 b% E* K! K& ?* T
  8.     for(i=0;i<8;i++)/ r' T/ {8 W% L
  9.     {
    " c$ c9 p+ @" p6 A5 ^
  10.         if(val&0x1)
    ' u) b5 A  ?! D% I
  11.         {
    # e: @$ A) x3 a( P
  12.             IRSEND=1;6 S2 p) p  f' C# q) X7 u5 S
  13.         }
    ! f$ Q$ s1 h9 Q1 v, d
  14.         else0 @# t" t3 Q  N% z2 z
  15.         {: d8 l, x- Q# V% q$ a
  16.             IRSEND=0;
    8 k1 j+ k9 P$ J
  17.         }% ]0 y% M: a/ A$ O: V1 w; F% ^
  18. 7 @1 b3 j" S( I! A$ e
  19.         val>>=1;
    ; R# r; n1 M( g+ e
  20.         SysTick_Delay_Us(53);" o5 N- O& v- r8 G0 W% `2 L$ \
  21.     }
    5 u8 `& @4 ^5 w! Z* ~, c  F
  22. / B: _& E; {0 M1 `- n# j2 L- K6 K
  23.     IRSEND=1;0 o' w0 Z/ f4 g6 s  Q) J, D
  24.     SysTick_Delay_Us(53);
    2 z, o# V7 f( N1 {$ Q
  25. }
    + u$ G/ n- k' }: @& C$ ~/ x

  26. ! @# l/ ^, P& V
  27. : f2 z9 W! h+ y9 |7 V
  28. void IR_SendStr(u8*st,u16 len){//在这填入16位数据即可' y4 _# Z9 d+ R5 E
  29.     int i=0;
    , ^4 m9 |/ ]- D
  30.     while ((len--)!=0)
    : C# r" Z, P7 q! r7 J
  31.     {
      \7 g1 f) X& \9 X7 `7 v
  32.         IR_SendByte(st[i]);, ~  B/ p- a: f4 K# s
  33.         i++;0 Y$ M: m7 J* e, U/ ]0 l9 a
  34.     }
    0 v9 H' c; D- B& `

  35. ' @7 Z, y& x% @/ E
  36. }
复制代码
  1. u8 IRREC_RX_BUF[64]={0};    //接收缓冲,最大64个字节.. k: h4 U$ o% F, H5 g: w  E
  2.     //接收到的数据长度
    5 |2 c8 Y; o$ k# I+ ^
  3.     u8 IRREC_RX_CNT=0;" V. e  d0 X$ \# v% o5 ]- A

  4. ! q- C7 X, N+ h: G/ ~( j; Y
  5. char rebit=stopbit;//记录接收一个字节的二进制位所处何种位置
    , \3 R6 d$ e1 G
  6. u8 Recev[8]={0};//记录接收的一个字节的二进制流% V! F$ S5 w8 B8 [

  7.   R4 Z2 ~0 W; {
  8. static volatile unsigned long long m_rx_previous_time = 0;//上一次进入中断时间3 G: x$ G1 |% j% z% |. G8 g( E8 a
  9. static volatile unsigned char m_rx_begin_f = 0;//开始一个字节的接收标志 0-无数据开始接收 1-有数据开始接收
    / H" d) Y4 ^4 \# k/ o
  10. void EXTI9_5_IRQHandler(void){: }4 _) \8 l9 N. X2 B

  11. 3 E; Z$ j) O9 r; B* D
  12.     if(EXTI_GetITStatus(EXTI_Line8)!=RESET)1 L8 u- W. h: q- x3 n& I
  13.     {& D3 D; c8 X, L! y
  14.         unsigned char skip_index = 0;, K( {  _* P- P  x/ X1 W
  15.         unsigned char i = 0;
    7 W  C+ P% g: A/ g$ _
  16.         unsigned char temp_bin = 0;//用于记录二进制值2 S  d# q# U4 s+ l: i8 Y
  17.         unsigned long long current_time = sys_micros();//记下此刻时间, p6 b1 E7 V7 Z* z
  18.         unsigned short interval_time = current_time - m_rx_previous_time;//计算一个状态持续的时长
    ) |5 e, l9 }+ Q" H" a
  19.         m_rx_previous_time = current_time;//为下次计算时长做准备# g/ R8 b  ~( J5 E2 _; w) `0 o

  20. 7 w$ ^- r9 o' K, w% U
  21.         //当前未开始一个字节的接收且此时为下降沿
    ( F( K8 v7 ~" h- r
  22.         if(rebit == 10)//10 当数据不合法时或者结束传输时 rebit值设为104 r( o: ^. L5 N
  23.         {0 l( e( ]! m  Z  S. X% |! M  {0 K
  24.             if(!PCin(8))//下降沿6 A- n6 `4 y# M) r# z% u% @
  25.             {) D& j$ {; B1 R* K" U' K3 C
  26.                 rebit = 0;//记下开始接收9 |1 k6 `& ~, n% J9 `( l8 b
  27.                 m_rx_begin_f = 1;8 V! O- m- T( t1 q
  28.                 debug_led(1,LED_TOGGLE);! r2 Y# t7 d' Q- ^$ g, v% E
  29.             }% i8 D$ W7 P  ^4 x5 \
  30.         }
    & Z# F9 \* J- K6 A; ~2 B" N  J
  31.         //已经开始接收! ^$ h* w5 I$ G$ l  r
  32.         else# ~# a8 ]% x  u
  33.         {/ ?$ _/ Q' i! |( U4 ^
  34.             //上一状态为起始位
    $ E0 C) R6 j, A6 u- B9 _
  35.             if(!rebit)//起始位0- B+ m# P* ^, I% V" S5 s3 ~
  36.             {# E" @8 l4 N3 D5 a
  37.                 //计算二进制数据的个数
    - r( J( j2 H1 k3 m; H$ B6 }
  38.                 skip_index = (interval_time/50)-1;1 B4 s- ]+ p+ \  ^5 N
  39. ! G% K  H' Y/ p% m# F; X
  40.                 //个数合法4 \& A& t; T& S- j0 v, Q% d
  41.                 if(skip_index <= 9)# [6 Y" x0 U* k- l
  42.                 {/ a5 Z! H$ J1 A3 i
  43.                     //根据状态保持时间更新接收值0 x' P9 ^/ l! r. y$ F! x
  44.                     for(i = 0;i < skip_index;i++)
    % ]0 ~! @& w: F: o1 C' B6 l
  45.                     {
    # L' ?+ _; s8 }6 V# ^$ [
  46.                         Recev[i] = 0;( _% W0 K& K, n% f

  47. / n; |3 ^- ~: g/ a) d
  48.                     }, T& h; C& W6 K: O

  49. / X* d7 I2 a0 u& |# `
  50.                     //更新接收二进制位的下标- i% l' R, B  s+ ~* }# m5 v
  51.                     rebit = skip_index;( j( R# H$ e5 s
  52. & ]; _2 ~9 _7 R# d
  53.                 }  a8 m+ T1 {! J, C0 }/ v
  54.                 //不合法-重新接收
    " [) T3 W3 d! P0 X) T( o1 }
  55.                 else/ P! ~1 k" i* A3 H$ {4 e( c: p
  56.                 {+ P7 ]) W0 |, F, N: Z" y
  57.                     rebit = 10;
    & x7 T+ J/ C) n8 L6 E% J7 @* S
  58.                     m_rx_begin_f = 0;. v9 U! P2 [" u" {; W( C: f. t

  59. 8 C/ d9 P( \- s8 g# Y0 t3 d

  60. / ~' o; I+ O+ G
  61.                 }
    . p' f2 q3 H  C% ?$ U4 ~# ]
  62.             }% [, S* W  p8 G8 h
  63.             //上一状态为数据位8 O3 f0 T6 ?/ r/ T  E
  64.             else- m  g9 g- x4 ^( o+ d- V' Z
  65.             {
    1 k5 i8 r4 z. p
  66.                 //计算二进制数据的个数3 K9 b/ D3 Q, b8 g1 c3 l* j$ C) r; K
  67.                 skip_index = interval_time/50;/ h2 `4 y9 W& }9 P% t

  68. 2 v2 c0 z/ F; i8 X) m  S; u0 b
  69.                 //数据不合法-重新接收
    + \# d7 Z* A/ t+ i# |
  70.                 if((skip_index+rebit) > 9)//所处位置+数据个数 判断数据是否超10 合法判断3 Y7 U& m. C. V8 [0 s9 F8 F
  71.                 {5 ~$ [6 e% c$ J! `$ ?  }- p- M/ r
  72.                     //printf("skip_index %d   rebit=%d \r\n",skip_index,rebit);
    # k4 E1 T. v9 }, q
  73.                     rebit = 10;
    ! p, [. U7 _% e
  74.                     m_rx_begin_f = 0;: ?8 V8 d& R5 [1 Y
  75.                     debug_led(3,LED_TOGGLE);: z3 V3 ?5 a  ?5 V) ~
  76.                 }, \% C. b- p  \! l% _# s
  77.                 //数据合法
    ; \- X$ G5 k- F, Z8 \$ J
  78.                 else
    ' ]8 O6 Y3 C' E' Q; W
  79.                 {
    2 k: @( D; P7 p$ }! K
  80.                     //当前为高电平3 g4 O  s; X( Y1 c9 A
  81.                     if(PCin(8))% Y& H& G9 b, {; `
  82.                     {
    . l+ f+ P9 |" J0 d
  83.                      temp_bin = 1;//0
    $ r* y! d, `* |1 \% G, E; ]
  84.                     }
    0 _  _# C1 m% K* N
  85.                     else
    6 @% O5 B5 @1 v2 R  d# z" w
  86.                     {5 c! X2 P8 o5 i0 g- F3 y2 ?
  87.                      temp_bin = 0;//1 change
    ; {! n3 K* D) d/ m
  88.                     }
    4 _% n8 f: C  {8 i
  89.                     debug_led(2,LED_TOGGLE);$ L6 E( p% k1 w7 W7 X- o. n
  90.                     for(i = 0;i < skip_index ;i++)//根据几个数据 给予相应的位' `* ?9 k/ O" Y. Z7 i; d1 U
  91.                     {/ f5 q  d; \, A5 {" y$ z
  92.                         Recev[rebit+i+1] = temp_bin;//change +1
    - s3 N3 H% A9 ]. H) L% I% @
  93.                         rebit++;
    ) I: f6 J/ [, N

  94. ; G. I) ?' G3 N% Y* ^  h
  95.                     }) f% H9 c0 ?" c3 z/ f
  96.                 }
      n6 C$ j( q2 d1 o7 F" @' n: r, H

  97. + R, B2 [( A! q
  98.                 //数据已接收至结束位
    " d( Q, ~& m. p" T; O1 W
  99.                 if(rebit >= 8 )//=8>?
    6 r& z/ ?3 M9 J# I# b5 f
  100.                 {
    2 A/ z6 r6 Q. o5 b& j. O3 Q
  101.                     if(IRREC_RX_CNT < 64)
    / r1 g0 U+ p7 ?! v
  102.                     {
      d* A8 [) U& J
  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];
    ; t5 v$ w& C+ z3 B7 l0 d8 ]" g

  104. & T+ y2 o) \8 f9 E. v( f
  105.                     }- A) Y8 r" G! X& x
  106.                     rebit = 10;. M) `, s( d8 }2 K- g
  107.                     m_rx_begin_f = 0;0 T! }/ o1 T9 E3 n& b4 I/ y- _
  108. 3 {2 ~/ v( v) d2 U1 X3 p8 I" E
  109. # a9 v( f7 w. x# \
  110.                 }, F, ^, j) `* N1 a- [9 @; u
  111. ; I* c+ N+ s* Y' v
  112.             }7 X: K. m' [6 ?  I# u& A
  113.         }  t7 A9 Y! V* c6 E
  114. 7 ^1 E- {4 U- W) M: E$ j
  115. 2 f4 b; N1 i6 @* z' c: C8 A# z9 X' @
  116.         #endif9 R4 f! g* w/ G/ V: F# o" D2 i5 v
  117.         EXTI_ClearITPendingBit(EXTI_Line8);//清除中断挂起标志位! b! R' l) o; a) h' T) C

  118. # x4 G* n3 K  }* Z! }% R* D  u
  119.     }0 c: ^$ C, U/ V8 z+ A8 K  @

  120. % v% n. T! s0 I% l4 d/ d
  121. }
复制代码

/ |) V' H9 d5 @1 e- O6 i% q
收藏 评论0 发布时间:2022-1-26 23:55

举报

0个回答

所属标签

相似技术帖

官网相关资源

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