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

【经验分享】STM32智能雨刷器

[复制链接]
STMCU小助手 发布时间:2022-5-25 19:00
基于STM32智能雨刷器
0 r$ V- d# B) j5 S6 w* q7 v. _+ s  v8 ~6 O
所用物料
STM32' ]. u9 k. z1 g4 T
雨滴传感器* j( u$ @  `, A; a
SG90舵机( a. ?  f# @$ i% E: a
所用知识" E1 ^) Q: P8 F

) U: r* D% d* m& \+ a中段
7 V- h- {" r+ a. a/ E( gPWM
% [: N( c, `  ?7 D, |+ vADC
# c7 j% g! {% i3 T: O! F, n3 j
/ s+ |5 r6 K% V# K基本步骤( C& i7 _) y8 C) `$ j5 H6 _2 k
雨滴传感器使用ADC传输给stm32,stm32实时检测雨滴信号,然后根据判断控制PWM来实现舵机的不同动作,按键触发中断控制PWM5 `. K1 e( k+ S% Z0 b& W1 l8 m+ {

# l; r* _6 i/ t( k代码9 g$ ^( i* c+ H( A. B3 M
主函数
6 c  i+ k8 S' E9 ^$ gmain.c
1 k$ U8 g2 L; S  I
* {- ~! M/ U6 [6 {( x% [
  1. #include "led.h"  u# C# }  e' S: I. {4 h7 n
  2. #include "delay.h"
    ; a0 u$ P6 c! k5 X$ ~% W% [4 S% A/ U
  3. #include "key.h"
    . e. M$ a5 k0 T) {* \9 H
  4. #include "sys.h"
    # R7 z3 k' Q* C
  5. #include "usart.h"9 n! @. }7 t& I+ o5 R: W! d
  6. #include "exti.h"
    ( I7 Q+ z2 j! a% a- l
  7. #include "beep.h"
    6 q! ]& Q8 k- @( w9 [
  8. #include "timer.h"
    ! K  _1 z' X2 W* \
  9. #include "adc.h"
    3 C# V% U% I( w% q
  10. 5 J) S1 Z; c; A
  11. int main(void)& {; G$ ~  y. f
  12. {               
    ( C# e! N% o0 c6 x- k' Z2 T
  13.     u16 adcx;* [% X% {; O8 F2 `/ y+ T
  14.         int i = 0;//用于舵机转动的for循环
    ) v1 Q" E& q- e7 H: |9 M; [* b
  15.         int frequency = 175;//舵机转动的初始角度 175-195, }% o6 G4 A5 j0 F7 `3 O
  16.         float temp;     //通过ADC转换获取雨滴传感器的值% Y  B' [% o  ^- k$ A
  17.         int  integer;   % r1 j4 @( B( ^2 B" A' d
  18.         delay_init();                    //延时函数初始化         
    9 F/ M, X1 Z5 T' @. s1 @
  19.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级4 {4 I/ X! ~9 U1 s9 K( R, C& o
  20.         uart_init(115200);            //串口初始化为115200
    0 \0 I, `' ?* {. t4 N: O. a
  21.         LED_Init();                                  //初始化与LED连接的硬件接口 , l3 x  y# d/ C' @) G
  22.         BEEP_Init();                         //初始化蜂鸣器IO
    ! ]4 P/ E; ~3 o. r# y( g% W
  23.         EXTIX_Init();                 //初始化外部中断输入 ) w9 x6 X# H& m" u: y
  24.         LED0=0;                                        //先点亮红灯
    " s! H( u; s( p: Y1 m+ G
  25.         TIM3_PWM_Init(199,7199);         //不分频。PWM频率=72000000/900=80Khz
    ; {5 S& Q3 c, P5 X/ i3 k
  26.     Adc_Init();                                  //ADC初始化
    . a* p! l9 T5 `! @' R. |/ |) v
  27.         while(1)
    # I' p0 N, W. Z/ v
  28.         {3 v& n$ d. W" z- Y+ l
  29.             adcx=Get_Adc_Average(ADC_Channel_1,2);4 v8 N5 L$ n0 }* a
  30.                 temp=(float)adcx*(3.3/4096);4 M' ~5 g( {2 H% m; F4 m
  31.                 temp*=100;
    0 ]5 B1 i* k1 Z, u! t: x$ R: t
  32.                 integer = temp;! d) }) L! Y: G, H( `
  33.         if(integer > NUMERICAL_THREEHUNDRED && integer < NUMERICAL_FOURHUNDRED)//不下雨
    . P+ \; z4 b- X$ p8 P4 W1 Y
  34.                 {        9 I5 ]6 D% h: u! @
  35.                         delay_ms(1);. H5 T1 J8 x3 N0 Y2 F/ y
  36.                 }        . Z2 c( k0 v. k7 E. {
  37.                 if(integer > NUMERICAL_TWOHUNDREDANDTWENT && integer <= NUMERICAL_THREEHUNDRED)//小雨
    # \  X+ G% C+ F; g6 ~! t
  38.                 {
    3 N7 d8 Q6 v# [! g% L( A/ _& O8 z
  39.                         for(i = 0;i<20;i++)7 D# R3 [& W. q- X3 x
  40.                         {
    8 x. U7 B5 M1 P* a  m
  41.                             TIM_SetCompare2(TIM3,frequency);
    " ?! v9 p% {9 x- Y
  42.                                 frequency++;
    ' q+ M1 S4 h) I. u9 W# j9 V+ Y
  43.                                 delay_ms(DELAYMIN);/ F% r/ B% \; S# y( J
  44.                         }
    ( W/ W& V, M) _
  45.                         for(i = 0;i<20;i++)
    $ D: V8 ?! Q( F: _6 n6 R% U
  46.                         {
    5 l8 \' T6 U' k4 y
  47.                             TIM_SetCompare2(TIM3,frequency);! S9 h& R( E$ L
  48.                                 frequency--;2 X2 ~: p: B+ P7 f
  49.                                 delay_ms(DELAYMIN);
    $ Y% t) q% \$ l" w4 D
  50.                         }, V1 i( I' N6 m6 g- _
  51.                 }/ B" L4 {- A& I
  52.                 if(integer > NUMERICAL_ONEHUNDREDANDFORTY && integer <= NUMERICAL_TWOHUNDREDANDTWENT)//中雨, q; P" [: S+ c" s  ^, U$ T
  53.                 {* z! B7 ]* D+ {# A: d/ o! Z
  54.                         for(i = 0;i<20;i++)
    $ m2 F+ j! P. ?$ q
  55.                         {
    ) v* n# O8 u3 t. r
  56.                             TIM_SetCompare2(TIM3,frequency);
    & z7 `' H2 [+ ~. h
  57.                                 frequency++;, g$ m; J1 m. m( ~: r
  58.                                 delay_ms(DELAYMID);! k- T8 ?# F4 d$ }7 c9 D
  59.                         }
    " p& o% i9 T" U& ?8 u
  60.                         for(i = 0;i<20;i++)
    ' R4 v( A1 U& C' P
  61.                         {# e- m- o2 o0 C2 u, ~
  62.                             TIM_SetCompare2(TIM3,frequency);
    ! y' r6 t6 A2 L. Y
  63.                                 frequency--;3 F8 A& G" y. g( W
  64.                             delay_ms(DELAYMID);
    0 E# H+ N+ p: B8 j/ V6 a$ l9 K
  65.                         }
    " |" k1 A0 `$ A0 f) O( M; T7 u
  66.                 }
    7 |& E( w& F+ W! ]. _9 j
  67.                 if(integer > NUMERICAL_TEN && integer <= NUMERICAL_ONEHUNDREDANDFORTY)//大雨- r6 @" a% d  w( a4 V) S6 G1 Q
  68.                 {' b, }2 ]" u6 ~' K
  69.                         for(i = 0;i<20;i++)5 P7 H2 M8 d0 z9 F% R! X& t/ O
  70.                         {% }  P; T0 k. r4 O
  71.                             TIM_SetCompare2(TIM3,frequency);  H- r% S8 Q" W3 `
  72.                                 frequency++;4 y) {8 ?' ]  U; S! A1 r; q& _, Z3 a
  73.                                 delay_ms(DELAYMAX);4 H6 e1 j: q0 L7 F
  74.                         }
    $ q- H( M, y& z& r8 F* R$ U
  75.                         for(i = 0;i<20;i++)1 |& w/ I6 |# {5 K$ \/ Q1 f, s) R( E
  76.                         {
    % `. ^. m) b& g
  77.                             TIM_SetCompare2(TIM3,frequency);
    6 Z' E% @2 L, d/ t8 v+ S
  78.                                 frequency--;& }$ y5 S. S5 w
  79.                                 delay_ms(DELAYMAX);& U1 G9 b5 \5 `) Q- ?
  80.                         }
    6 y/ g$ J5 w& ]9 M
  81.                 }
    . v/ d  \5 f7 E. J9 w- ]3 C
  82.         //printf("%d\r\n",integer);//串口发送LOG值, h9 C, j5 v: ?7 k
  83.             //delay_ms(500);          * k+ M' A$ `" \/ l  [9 T8 ^8 p
  84.         }        
    * G8 b6 T$ E) q4 ]# p& P2 N
  85. }
    4 J- l( p, T' H, z" u- ^+ d6 v7 a
复制代码

3 O* N) u* r% v, Y7 F6 t. g雨滴传感器数据传输% W: ?( b$ C7 s  g2 F
ADC数模转换,将模拟信号转换成数字信号,以下是配置代码
; t, h  @4 N6 A7 s4 _) C
0 j! v: j3 L0 f下面是各个代码简述
' _0 b; P- `% t( W5 Hadc.h
  1. #ifndef __ADC_H
    % G! P8 W: b, ]# K3 R# B
  2. #define __ADC_H        
    ; Z+ W: t1 I! P  I
  3. #include "sys.h"
    % x/ p! ]: D, O: P/ O
  4. 6 I! [( d1 P8 A! U' ]$ G
  5. void Adc_Init(void);4 m* j  q* {0 U, d8 v+ r
  6. u16  Get_Adc(u8 ch); 0 X" ?7 V9 H* T/ G
  7. u16 Get_Adc_Average(u8 ch,u8 times); / O- r$ H. e; p# o  ]& b! h1 h
  8. " I; p5 o- j! W- O( p
  9. #endif
复制代码
; E% Z+ S6 p' Z5 G* ~
adc.c6 _' R6 @& z* _$ y. l

6 f7 S3 A$ L5 `) i/ d/ Z
  1. #include "adc.h"
    . n2 Q/ V2 a  B$ z2 }7 T
  2. #include "delay.h"; V+ ]) j- D( S4 Y
  3.                   
    ! f$ E& H8 a4 A7 y
  4. //初始化ADC; B/ y: o( F+ E1 Y+ Q  s
  5. //这里仅以规则通道为例/ {! o% c+ {9 H$ x
  6. //我们默认将开启通道0~3                                                                                                                                          
    0 E  c4 m* i& m/ T1 X
  7. void  Adc_Init(void)
    ) s0 u# o: Z* _* r' r
  8. {         : w3 _* l% G  ]" e& b+ L
  9.         ADC_InitTypeDef ADC_InitStructure; / f# J3 d# C( E' m$ w: Y
  10.         GPIO_InitTypeDef GPIO_InitStructure;: Q2 Q: h# G3 q# M/ D: K. t
  11. ) N0 l9 E' A% o. @8 m+ U( ~* W" l
  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟5 w$ u+ [& P/ j) x  k9 W: C" l9 j

  13. . D$ S' A9 I* T) f+ @" g/ C

  14. " y2 M# ^& b. c6 ~$ B+ b4 |
  15.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
    " u& K; Y& Y, G$ e
  16. ' k3 f' [$ J+ [8 l  {
  17.         //PA1 作为模拟通道输入引脚                         / \& I3 w) {0 ?1 e5 e& e0 _
  18.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;/ D+ ~4 B" f' }, W3 n
  19.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
    / f; ^9 H  r( _: O5 h9 H
  20.         GPIO_Init(GPIOA, &GPIO_InitStructure);        
    $ r" o& A' _. M: p

  21. ' `; o* c1 ^$ q5 b
  22.         ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
    3 b8 U& h* I+ u& R

  23. : G# z- I1 x9 j) _
  24.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式/ w* u* K  @# E5 V
  25.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
    $ [3 }9 i- l5 Q: Y: U7 p5 w
  26.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在单次转换模式+ L/ {4 c* |: N* K) p
  27.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动9 l8 c) P. u# A6 W2 F" R) _6 k: Z
  28.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐6 T7 ^; m5 l" F+ V7 t2 d% I( G6 y
  29.         ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目5 ]$ R' W: A) r5 G7 q& n: I" K) @
  30.         ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   ) ?9 r, X5 S) C2 p$ h& Y, w

  31. % E$ C% b0 J( P1 y; q" D' f
  32. / a! `# k4 J/ @# A
  33.         ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1+ m0 [0 U+ ?. ]# s
  34.         
    ) h3 k: l5 K3 o% B5 {
  35.         ADC_ResetCalibration(ADC1);        //使能复位校准  + W  k! A. F" y- a) G9 T) G
  36.          % o: \0 d% j# g
  37.         while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
      S2 D# k  O. g1 f) q  f. Y) C
  38.         
    1 h9 F4 [9 ?2 c3 a: c& j
  39.         ADC_StartCalibration(ADC1);         //开启AD校准% S' ^% o* H: `3 K9 u8 L) c

  40. + _9 f  C' E* x( T, c; w  D6 X
  41.         while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束9 T# \# r) z( M7 r

  42.   `) y8 j5 X- k# [5 `" l- r( o
  43. //        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能0 B; Q6 G8 d0 I

  44. + S  X" _' z* _+ @' Z- W" l8 D, Q+ \
  45. }                                  * h, _/ s6 x1 e/ Y- p+ W7 u/ u* Y& k
  46. //获得ADC值* t& Y/ M! u; d$ {+ D/ U/ N) a& R/ a6 m
  47. //ch:通道值 0~3( _2 o: Y* Z. u0 a( T  n8 S
  48. u16 Get_Adc(u8 ch)   0 w" n, M; ^2 L+ I3 ^1 w
  49. {  w" \5 ^- N' P! D
  50.           //设置指定ADC的规则组通道,一个序列,采样时间; E( z1 F) c# y8 C( p
  51.         ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期                                      / r8 x( b% x7 C) d& i' C! g

  52. , T7 M/ \! J) L+ n+ W6 k
  53.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能        ( X; U  t- i: v% Z  O& y
  54.          % h" T2 t9 I/ ^5 a5 M1 S) |. I; {
  55.         while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束- X4 B/ ^+ C% F0 \. f' w7 U

  56. & {  Z, Z1 V9 C
  57.         return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果0 p3 @& X! M! f" Y( r5 {
  58. }5 U3 j+ h; C* N- X/ i4 B' X

  59. . S) H, \6 G) g' ]7 ]6 U( d% I6 r6 y
  60. u16 Get_Adc_Average(u8 ch,u8 times)
    * w2 U& I1 C5 R# H( u
  61. {7 i# Y: J' f/ w. l1 Y3 M: e! V4 }
  62.         u32 temp_val=0;
    % R8 r9 }' R0 S
  63.         u8 t;; x& A. \( ?: D( {1 J# X
  64.         for(t=0;t<times;t++)  ]4 s  p% o0 R  y) ?* z
  65.         {6 V+ }+ b3 L5 ^1 z; Z& I
  66.                 temp_val+=Get_Adc(ch);
    , P4 i/ ^' X  U
  67.                 delay_ms(5);
    1 ^( n( e6 f4 [! X
  68.         }$ Z. |: o  k- `- c3 K2 @/ x
  69.         return temp_val/times;0 H; P; m6 L  w
  70. }         
复制代码

4 x0 v. c2 F4 \( j: x! v0 n% nPWM时钟配置
% ^6 }% ]( ^6 p: W# L/ z; q* q$ i) mtime.h
. U' Z: @6 M. C: @4 k
7 _/ g1 z2 Z2 d8 X& t
  1. #ifndef __TIMER_H3 P6 P& A9 ^$ k- f6 P
  2. #define __TIMER_H
    * g* P, x2 Q! m2 c8 E% t
  3. #include "sys.h"
    ( l$ H6 a( _6 Y2 }) J( `- s9 p% w

  4. & P' x, S" E' M( Q
  5. void TIM3_Int_Init(u16 arr,u16 psc);9 G+ W# x4 y/ i5 A
  6. void TIM3_PWM_Init(u16 arr,u16 psc);- Q" r/ @% F; E0 b, N5 o# N/ K
  7. #endif
复制代码

  m$ S/ A' Y& \. v1 P+ Ptime.c$ U% t1 @1 V. e" \9 @; n+ R4 y! j! M
# {  _! O  Y  a$ C. A) w( `
  1. #include "timer.h"
    : Y6 R6 F: r! e' }
  2. #include "led.h"
    1 K* s- w+ I5 J, M* e! M5 q5 H
  3. #include "usart.h"% }% g  W3 H1 g* ~8 L" z+ R3 y
  4.              8 F7 V4 D% I0 U7 A/ m5 l/ ~+ K3 `
  5. //通用定时器3中断初始化
    : M1 }: r+ J9 i( |9 B, D
  6. //这里时钟选择为APB1的2倍,而APB1为36M9 J' B; O1 j4 a0 {
  7. //arr:自动重装值。
    0 {6 |) B0 U3 u8 Y$ Q4 M# g  E
  8. //psc:时钟预分频数+ g. e! T7 z5 f. P: Y7 [' ]
  9. //这里使用的是定时器3!
    4 i0 V* }3 \5 a  ]! [8 w# W  }
  10. void TIM3_Int_Init(u16 arr,u16 psc)
    3 ?: {5 G+ Q5 x0 F
  11. {$ @5 O$ S( G, b4 W2 Q, k9 r
  12.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    ' s5 w3 I' A+ W. B& Z' \
  13.         NVIC_InitTypeDef NVIC_InitStructure;! W0 }& s" o5 r0 m3 z

  14. 0 e9 t7 H! n1 ~4 |* _9 A/ |
  15.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
    % U$ y4 h0 i+ ]/ h0 G/ o* [

  16. , q( N* N, M/ Y$ t  d5 G
  17.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms
    3 Z# C+ w9 s$ [1 p3 J& x
  18.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  ' w" f6 c. Y4 d* I1 T/ c0 P+ }' M
  19.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim" q  E; D& o0 g' ^! U
  20.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式# G- V% j1 k& d  {, g- e
  21.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位0 Q! g3 J) z) [4 W2 f

  22. # I. z/ E8 i1 e  a+ C) Y  j* V
  23.         TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
    1 n. j% t* f" V) f0 ?. Y& }

  24. , }7 ^/ F9 i; K- w0 {3 ?
  25.         NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
    ( P9 Y$ Y8 g9 L+ {/ f/ G
  26.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级& ^* }" r" f% A2 n
  27.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级1 z  k1 J- z8 \; |
  28.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    / C! g; w. L+ m0 j
  29.         NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器! x) [) y" @8 L7 X" c2 H8 D
  30. 6 f5 a5 c% J7 B3 t
  31.         TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
    * T4 c4 y) A! }2 p/ c
  32.                                                          4 K4 V3 K# n0 k. p$ ^
  33. }# N% }3 E; `# _# O9 h% h- Y- B' k
  34. //定时器3中断服务程序
    2 K, b. g0 H/ w: H: f
  35. void TIM3_IRQHandler(void)   //TIM3中断
    / H: |6 a2 R9 v
  36. {# N3 x% W' j2 I+ B& h+ M
  37.         if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
    5 x0 Z) Q- ]+ `: O5 g  N4 \7 A+ L
  38.                 {% [1 l$ n! V- ]+ i; p8 j
  39.                     TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
    2 t4 c! F  F, U; C/ }% Y, ]! E7 i3 r
  40.                     LED1=!LED1;3 R+ _  Y- B9 Q; V, j
  41.                 }1 W( l7 _" J4 ~8 K: [. R/ s9 a
  42. }: P, }7 J, a- w5 H" H
  43. //TIM3 PWM部分初始化
    9 a) y0 N4 y& b/ H6 J
  44. //PWM输出初始化
    4 T9 b) S5 F" n- m0 A
  45. //arr:自动重装值
    , l- C: {7 ~4 A! U
  46. //psc:时钟预分频数
    ; F& y4 x4 m  V# |
  47. void TIM3_PWM_Init(u16 arr,u16 psc)
    # B( B8 c6 P3 y/ t
  48. {  ; q& _6 c$ p) b
  49.         GPIO_InitTypeDef GPIO_InitStructure;
    2 a" K+ R# `3 B9 W( u5 _
  50.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    1 G# e# n4 ~* w- w/ ~
  51.         TIM_OCInitTypeDef  TIM_OCInitStructure;
    4 P( c# d6 J8 a9 C: Z2 m
  52.         6 R1 }8 Y, y! Q; Z- q
  53. * `- D- G9 }  v% k" @$ M  |, P' t
  54.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);        //使能定时器3时钟
    4 D: X: S6 [. ?" m# ^! T
  55.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
    $ S3 Z5 {! O+ z  _- d' Z. W
  56.         
    ) e# H  O9 e" E( V% s2 N
  57.         GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5   
    & e1 f+ Z! q3 y
  58. , Z( Q" _" S2 \: F  z8 }& G
  59.    //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形        GPIOB.5- Y0 u1 L/ t, R/ c5 `" d3 Z  x
  60.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
      l$ I5 A" J* O% n+ y) Z8 v7 [
  61.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    $ f9 r( p, D. {
  62.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;( k/ z- }) M8 v' A. I/ O2 g
  63.         GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO7 o9 i! b& n4 Q

  64. ' S- n2 t( O2 H& q" H/ u& x# Z/ [
  65.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
    : B0 H3 X& Z9 {
  66.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
    . W' [3 o3 y& L- f0 |' w
  67.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;" n! @( t& p6 Z0 l% N9 B6 k3 u4 `
  68.         GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIO
    3 D6 U; |% N+ d( j% l9 I2 F0 i
  69.         
    7 Y! ^* S( F" o' l
  70.    //初始化TIM3
    4 N% S/ o; y. J, U
  71.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
      t' ~, @, E3 E. I: ]
  72.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 1 }# i1 h4 j+ i( v
  73.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
      b9 M+ ~& |, G8 b3 P
  74.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式9 H9 e( x3 S* t7 p
  75.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位- h$ s' n: G* Q$ a% E/ v% n
  76.         
    1 L! p& M; M4 \5 c4 k
  77.         //初始化TIM3 Channel2 PWM模式         6 {! U- y1 t* S, ?* w3 b
  78.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式24 Z- S. m* _4 R& W
  79.          TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能3 d  c4 X' Z. x% Y& G6 {
  80.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
    " m, q% Z; @+ r  k
  81.         TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2
    * S- A, p& o# m
  82. 9 ]  p+ k; {$ S4 s/ X/ b
  83.         TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
    3 p7 ?0 \0 k) n
  84. , a: T8 j: R! M% N# Q- d# a0 ~
  85.         TIM_Cmd(TIM3, ENABLE);  //使能TIM3/ R! A" q8 ^7 J  z, R
  86. }
复制代码

' I- m4 N) L& }中断配置3 [+ y, r1 y) f/ D: t+ ]
exti.h
. @7 _1 I1 E6 ]/ Y6 H: x) C  w6 l9 F2 k' N
  1. #ifndef __EXTI_H
    . w; Z6 u# b8 J
  2. #define __EXIT_H           l( K2 X* R- _& N# Z
  3. #include "sys.h"
    1 j4 c% l7 G0 N6 a
  4.          # V! t8 B. ?" A" W' u, A
  5. void EXTIX_Init(void);//外部中断初始化                 ( k& n2 @" s' J" _$ u# k1 ?( L
  6. #endif
复制代码

; [- o/ o  ^5 d: d3 Z1 _7 qexti.c
, r, _  _9 C" h1 O0 {2 f9 w7 t* t" _
  1. #include "exti.h"
    ) u3 x: Q+ n( y, F& o
  2. #include "led.h"
    / L/ n9 y! @4 K4 {: j/ }. Z4 r
  3. #include "key.h"7 h- [. x1 Z/ x3 X2 T9 O' R+ H
  4. #include "delay.h"
    . V3 s2 a; B' I. {  V1 L- L& m
  5. #include "usart.h"0 W+ K$ G$ f0 _& Y: k2 D& J: Z" G
  6. #include "beep.h"
    + P) X: H! U% p+ i5 [% c2 T

  7. 6 |/ [7 t# d% r. n8 C' u
  8. void EXTIX_Init(void)1 ~0 B* s" `4 J8 T) W9 ~! i
  9. {
    ; ^7 v! H! J% A7 r" ~7 r+ U

  10. $ V  O+ I1 G& j% q' Y; H
  11.            EXTI_InitTypeDef EXTI_InitStructure;
    ) L; P% n5 K3 i, g- \+ p) D) d! Y0 [4 |
  12.          NVIC_InitTypeDef NVIC_InitStructure;
    . u- m* t7 F6 x  ?- u
  13. 2 V# k- @* l3 @2 o6 a# K, F
  14.     KEY_Init();         //        按键端口初始化# h+ D5 s) y$ L6 G) V" }
  15.           RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);        //使能复用功能时钟1 u4 g. E6 s' z+ g; O, h

  16. 8 E$ {8 D- {* H% T
  17.    //GPIOE.3          中断线以及中断初始化配置 下降沿触发 //KEY1
    , ^; y+ q$ V4 u8 P8 V8 S7 y% m: Q
  18.           GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
    2 V- ~$ l  h$ O1 P! u; f1 g4 B
  19.           EXTI_InitStructure.EXTI_Line=EXTI_Line3;  u8 A4 W7 B: T( h
  20.           EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;        4 o+ w9 U! U1 R# }& S: w
  21.           EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    & T" N% G! r% S# {
  22.           EXTI_Init(&EXTI_InitStructure);                  //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器( {- ^( y/ w& `' H
  23. 9 [& R. i4 W. ~, ?( g
  24.    //GPIOE.4          中断线以及中断初始化配置  下降沿触发        //KEY05 w/ k0 _( {  x" r7 S
  25.           GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
    $ X8 M; [; `3 }5 s, b. c* d
  26.           EXTI_InitStructure.EXTI_Line=EXTI_Line4;
    ! [- r5 }7 y5 Y* O: `; }
  27.           EXTI_Init(&EXTI_InitStructure);                  //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
      S; h! n& b$ ^/ C/ c9 S. I' |* B8 Z
  28. 7 h& `2 a7 R/ j3 |- l7 @
  29. 1 g# @& m" a  |. \5 |
  30.    //GPIOA.0          中断线以及中断初始化配置 上升沿触发 PA0  WK_UP
    - D" |  O* y7 v0 D$ M, j+ x
  31.          GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
    7 c  A- B8 x7 ^2 b1 R0 D: b

  32. 2 @% X" X$ x, ~) h
  33.           EXTI_InitStructure.EXTI_Line=EXTI_Line0;
    ' ~3 `4 Q  V( a0 O4 d: \: q, E
  34.           EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  Z% G) X* r6 G7 W% ~
  35.           EXTI_Init(&EXTI_InitStructure);                //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
    + w$ s% V8 R8 j. q

  36. % B6 r7 x/ ^9 w% D' k0 I: ^

  37. ) V" o& o8 H) h8 s4 M' P
  38.           NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                        //使能按键WK_UP所在的外部中断通道6 X9 |; a2 @, U6 X+ u
  39.           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;        //抢占优先级2, , Z5 M- u1 \# |8 L" a
  40.           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;                                        //子优先级3- `: p( U, U. v" @; l
  41.           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道  @6 v  S. g2 ?! d/ |  G( B6 B
  42.           NVIC_Init(&NVIC_InitStructure);
      t2 X* u$ x5 o/ }: K! h
  43. : n2 t, s' o: ?5 t% l  x( D
  44.           NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;                        //使能按键KEY1所在的外部中断通道% g- F/ G) s, }
  45.           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;        //抢占优先级2
    % ?9 e. A' s) ]- W' y' b9 q2 ?" C
  46.           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;                                        //子优先级1 9 `$ K- K6 g* N$ V* ^( x7 F
  47.           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
    ' \0 s! P* b  L: }2 x$ t8 o! Z: z) N- V
  48.           NVIC_Init(&NVIC_InitStructure);            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
    7 N/ D2 a# S1 K( a4 t  C  }
  49. + _. n' R& ?) y9 A# O7 }1 ^
  50.           NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;                        //使能按键KEY0所在的外部中断通道
    # ^( U0 l1 s! Y! n. p- D' R2 }
  51.           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;        //抢占优先级2 + ]" [2 L$ a5 }6 B% z
  52.           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;                                        //子优先级0 % f. }- e% `* y# t9 L/ h" v( [
  53.           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
    ' ]9 J( o$ y. [. q" c. J) Z9 K
  54.           NVIC_Init(&NVIC_InitStructure);            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器; L, J) {" a" B, M! @3 ]$ h" n9 t

  55. & B8 q4 `1 X; N
  56. }/ B8 b/ C- ]4 P
  57. //外部中断0服务程序 4 t5 r2 X* a0 A. k% U
  58. void EXTI0_IRQHandler(void)//亮度最亮
    8 ]2 e6 b1 E) X) `- |. Q. H
  59. {# L2 u0 l% k! a/ f: {, D
  60.         delay_ms(10);//消抖
    # b3 I9 p: h; C- |+ D
  61.         if(WK_UP==1)                  //WK_UP按键: }5 |: v: i+ V
  62.         {                                 # i! ?0 Z  m( R, @) }5 S- g$ `
  63.         for(i = 0;i<10;i++)8 A& \, L; r6 l6 X' u( |% Q& S+ |
  64.                 {
    0 n8 k) U  O5 J( D
  65.                         for(i = 0;i<20;i++)* q5 q7 I$ j4 P. {
  66.                         {
    + M" i6 d$ f5 j
  67.                             TIM_SetCompare2(TIM3,frequency);3 i" i/ A3 |( _
  68.                                 frequency++;. b0 `# p+ `7 }- B/ d: [' v) s7 P
  69.                                 delay_ms(DELAYMIN);
    ! h2 h3 h* C: V: b7 h. t* I7 E
  70.                         }
    7 a7 P  \  _' w. s; F: E, d
  71.                         for(i = 0;i<20;i++)% J1 f5 H+ ~3 s) d
  72.                         {
    * f* g: O6 P( n, Q/ H
  73.                             TIM_SetCompare2(TIM3,frequency);4 q: Q; T' S2 v/ A2 ~1 q/ ]
  74.                                 frequency--;) d$ g* z3 y/ l' L( r
  75.                                 delay_ms(DELAYMIN);; f; c" G" ^  C' v/ v  x5 g* t- u2 n
  76.                         }8 i8 `. ]: f8 t3 {1 m  \
  77.                 }  ' Z- a1 I9 T& @: }) P9 U1 Q; f% c' Y
  78.                 delay_ms(1000);        2 @8 ], U( K" N0 d+ P+ P
  79.         }2 R- A/ H  _8 B) W/ b/ o8 F% Q$ |
  80.         EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位  ! b3 R: B7 y" E. C
  81. }. D: x# S3 B2 y- E
  82. //外部中断3服务程序
    ; f' v/ z' u8 v& L, \
  83. void EXTI3_IRQHandler(void)//亮度
    : f0 P$ k; s/ c% {% q0 ?
  84. {
    6 k( S, N! ^0 ], B# Y
  85.         delay_ms(10);//消抖# H. X4 l1 k. I) C: k: x$ ]
  86.         if(KEY1==0)         //按键KEY1
    ! S$ n, w/ s/ q6 y
  87.         {                                 
    7 q5 k) f1 b: ~. i: D; t
  88.                 for(i = 0;i<10;i++)
    5 {( `0 C3 C0 J
  89.                 {1 B7 l9 y4 c8 }1 `
  90.                         for(i = 0;i<20;i++)
    & c; n: \% Y& x1 w) h
  91.                         {
    1 u, @! ?, Z6 Q+ @6 E$ e7 C
  92.                             TIM_SetCompare2(TIM3,frequency);
    2 v3 }+ ~/ f6 I5 N4 M' f: h
  93.                                 frequency++;3 ?/ m% W7 l% I2 h. A% h
  94.                                 delay_ms(DELAYMIN);- V4 z5 N7 _4 ?7 \. P  W+ a/ S8 N9 G
  95.                         }. X2 B+ a# Z8 i* K2 u7 T4 M5 w
  96.                         for(i = 0;i<20;i++)
    ' m( a8 t* }$ S) ~
  97.                         {
    1 m) t. Q9 g" _% Z% w. t  A
  98.                             TIM_SetCompare2(TIM3,frequency);- o/ W9 b. A. ~" Q
  99.                                 frequency--;
    ! J6 i! i2 [# k: ~) p
  100.                                 delay_ms(DELAYMIN);
    ) ^" m1 {9 o. P2 d$ k
  101.                         }
    2 ?1 q# T. l; x/ o
  102.                 }  ) y. l. V- R) J+ I
  103.         delay_ms(1000);                          1 k& z( w2 m: v9 P) ~% r
  104.         }                 
    . C1 e$ I; e2 W( M) S
  105.         EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位  % F7 x6 r8 o" R& g: _  G% S
  106. }) {$ `: t3 c  Q0 t6 t3 W
  107. void EXTI4_IRQHandler(void)//亮度在中间; a7 J6 Q1 x1 e/ ?
  108. {7 o0 A* r7 H7 h3 w
  109.         delay_ms(10);//消抖
    . [  v  |1 V/ r/ Q6 a" B: |( o
  110.         if(KEY0==0)         //按键KEY0
    # Z! c) f8 w$ |2 b  P7 B; C0 I6 _" E7 A
  111.         {% r* R) B+ M# i/ {" O
  112.             for(i = 0;i<10;i++)% e1 s: M6 s" N4 f+ p) E# K/ O0 H
  113.                 {
    4 n) t1 l' s3 F4 I
  114.                         for(i = 0;i<20;i++)# n! a6 z$ k$ h& q; Z
  115.                         {  H  K* o: g+ [
  116.                             TIM_SetCompare2(TIM3,frequency);0 t$ W" J; r2 W
  117.                                 frequency++;: ^' n8 l+ l% _4 A
  118.                                 delay_ms(DELAYMIN);& h2 p4 T) n& y. O# @
  119.                         }3 x# q; h: k. Q; E! k3 f
  120.                         for(i = 0;i<20;i++)' G0 w, ^- Y# @; h# F  O
  121.                         {
    - C: }: I$ i0 D7 F
  122.                             TIM_SetCompare2(TIM3,frequency);
    . A" }$ }5 d* K# ?* r0 e( k) }
  123.                                 frequency--;( X) B7 g( V' w1 x( p( j
  124.                                 delay_ms(DELAYMIN);- ~3 z$ V+ X, W3 g# J9 L
  125.                         }
    # a# V* a# k5 A2 D
  126.                 }  : m+ J( {1 A' R3 E6 M; r. c
  127.                 delay_ms(1000);        - b4 R9 I6 c, ^. U
  128.         }                 
      C) N, o9 {% h+ z1 g
  129.         EXTI_ClearITPendingBit(EXTI_Line4);  //清除LINE4上的中断标志位  
    3 I6 A/ H! _2 d) N2 k  i
  130. }9 U4 `% x3 }* s# l8 Z# K
复制代码
' ?4 j$ T* m& E& \" r- ?9 H
按键中断配置4 @- H1 d  |: l% y3 ]; V
key.h
9 d1 h- K6 r+ h. _* |7 I1 r3 b& x/ _# O8 J# ]6 Q9 F/ ^+ `2 }  D3 l3 \! r
  1. #ifndef __KEY_H
    - ?. V8 L- ~" W+ J" B( }" ~2 }: r
  2. #define __KEY_H         / q7 j# B1 ]4 }) V
  3. #include "sys.h"          + P* S" S7 H3 F) ~' b
  4. / M5 i6 X" v7 Z- w& y: d
  5. #define KEY0  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0+ Q. B8 T- B' k' V/ I9 m0 |; Z" \
  6. #define KEY1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1
    : @. Z* h" V; \* ]& [7 X
  7. #define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP) 2 m7 r4 h! G9 W- R, m7 v; L
  8. , N' h" A9 K  u8 j; E. Z
  9. #define KEY0_PRES         1        //KEY0按下5 j- R5 j" @, U- v9 f) d* i; u
  10. #define KEY1_PRES          2        //KEY1按下. t: d0 S% f: F+ C. l- a/ \% ^
  11. #define WKUP_PRES   3        //KEY_UP按下(即WK_UP/KEY_UP)
    4 R- n1 b, F% Q; z7 ?+ E4 {0 p# O! M
  12. ) H" S4 I- _" D3 F9 L
  13. void KEY_Init(void);//IO初始化* f" B  d5 M3 S6 C8 v/ A
  14. u8 KEY_Scan(u8);          //按键扫描函数                                            
    ! b9 K$ `& y8 U
  15. #endif
复制代码

4 m" x% l0 p: s% o$ w+ y. Lkey.c
: A% M. x: ~+ H" ]) y8 Y9 c& w% B$ G9 Q. ]
  1. #include "stm32f10x.h"
    ( m; v$ c1 G' H  M
  2. #include "key.h"
    # |! k! F, s6 l3 k2 k1 N
  3. #include "sys.h"
    / [$ j7 z0 r" ~& g7 z" S0 F) e
  4. #include "delay.h"
    ) \9 e1 }/ R' Z6 I8 o/ ]* }; Y
  5.                                                                     
    3 L2 y. `7 R; g2 c$ _! ~
  6. //按键初始化函数5 R4 E6 B8 ?- k7 L7 T$ x9 O
  7. void KEY_Init(void) //IO初始化
    , [  H, Q! c/ h' q* [
  8. { " R5 {! O# a5 T1 z* }
  9.          GPIO_InitTypeDef GPIO_InitStructure;: a7 I5 Y  n+ K2 Z# z( I
  10. - B6 e7 w  F8 Z$ N, S2 F) m+ I2 T
  11.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟
    9 A/ [# S5 k( Z/ g7 w
  12. 2 g3 U/ ?9 {3 n7 Q) R
  13.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4|GPIO_Pin_3;//KEY0-KEY1
    3 f: Z+ e; d' c
  14.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入. ?3 `" h# Y6 R7 W0 t% m4 T
  15.          GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE4,3
    / e& w2 Z4 y, j9 M. e

  16. # }  }( \" `# _" N
  17.         //初始化 WK_UP-->GPIOA.0          下拉输入
    $ o2 f+ ?% `2 Z" ^" d: |
  18.         GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;
    . N& L# j+ m$ M5 @# J
  19.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉         
    ; ~5 x; a& I- P2 r) o
  20.         GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0
    " Y0 _' N' a- _
  21. }9 N+ S- @3 g) a1 V# |/ S! c8 q
复制代码
; e# P. g* q7 S1 w$ j8 \
时钟配置
9 r9 J9 s1 f# l; Jsys.h
' V4 B) _" {, N" ~
* J7 d4 E9 G: D5 @, t, Q, v
  1. #ifndef __SYS_H. {% N, q- |/ _# l! [2 C
  2. #define __SYS_H        8 w2 U& \& C3 a7 ?, k. n+ C+ d0 x
  3. #include "stm32f10x.h"2 ~5 K' ]" G' k

  4. 2 E& B* n9 ?! }2 n6 Z5 A9 D+ a
  5. //0,不支持ucos
    : @$ D. k6 d# O
  6. //1,支持ucos% r9 `1 I9 L! i1 N/ @( C- G
  7. #define SYSTEM_SUPPORT_OS                0                //定义系统文件夹是否支持UCOS
    8 B7 l) o( N* ?7 G6 [& c
  8.                                                                                                                                             " U# N* c4 W- k- |6 N* u. h$ d
  9.          ( s5 f* Y9 P# G% w5 y, j) v
  10. //位带操作,实现51类似的GPIO控制功能" a8 l' m" _$ Q+ p2 i# B% W
  11. //具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
    " g3 ~: q! f$ A$ V- |2 g
  12. //IO口操作宏定义
    ' x6 M7 j8 d# h8 ]- z# Q
  13. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) $ G. P- ~0 U7 D
  14. #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 0 m5 K! |6 c' W; n0 l
  15. #define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 1 w1 O) S$ f  T. B. Y
  16. //IO口地址映射# s+ j7 L9 A2 ^3 i' p3 A
  17. #define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C
    . |, @( g7 n0 v/ U
  18. #define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C
    + D, n: p8 S- P6 s: {( j- Y/ w: |
  19. #define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C $ s0 h: ^+ `  \. Y4 H
  20. #define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C
    - ~) }2 O0 A5 S1 Q+ n! \, O7 O
  21. #define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 2 H8 S5 P9 }& Z/ i4 t5 t
  22. #define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C   
    # x! J* q' \: }3 Y$ _) y
  23. #define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    , p2 U) A. S% M

  24. ) R7 |; w+ c7 i( B
  25. #define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 $ p2 D% w0 [8 c  \- j: A
  26. #define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08
    ' b: `# h- i* j# `4 _" x2 @  X7 M
  27. #define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008
    8 E8 A5 ^( J7 K) ^. w
  28. #define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408
    $ B- R7 g% K8 k. f6 G3 |# ?
  29. #define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 5 O, P7 h$ J9 X  i% v# X/ h
  30. #define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 ( ]) s4 f! C# j/ V! r- U
  31. #define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 4 u0 q; k* g' K+ R; S& n- D9 R

  32. 9 a1 d3 k  I3 e) t6 L! d. \
  33. //IO口操作,只对单一的IO口!% @: L& p. Y2 A2 a. Y
  34. //确保n的值小于16!
    . w) B' Q. P  h! u
  35. #define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出
    + f( A: ?( W: ?+ w6 [* T
  36. #define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 ) ^  |7 O. ]6 B( }( ?0 A* [

  37. , H. e/ o7 q+ x) ~' X$ ]8 ~
  38. #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 " k; ?1 p2 @8 w9 Y- t
  39. #define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入
    2 w2 W* s( e! M

  40. + R- o3 H1 P; P8 ~  v# \
  41. #define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 ' U' v: `( t) h& {& N+ ]8 M/ z
  42. #define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 1 Y$ J2 x( v/ \0 S0 O

  43. 0 s: [" R7 o# G1 }1 s
  44. #define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 ; k. d0 o+ O8 h) k* H
  45. #define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 $ B6 p* L5 R5 D) [' v

  46. 5 R/ ^* V1 x- B* U/ S" h# Y
  47. #define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出
    $ g5 B6 r& J* o" Y1 G
  48. #define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入
    * m: {) R5 t1 f4 G% K* |9 d5 j

  49. * p1 @0 y/ V6 w6 h. w
  50. #define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 - t$ @6 I" \& z$ w0 p; S1 U$ w
  51. #define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入# q) l( G- y) t/ `1 L

  52. 9 G* @. [" G9 a, K
  53. #define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 % e- u; P0 }8 k. O$ L2 d  |; r0 ~
  54. #define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入% U/ y& s: ]. b' i  `: ^
  55. 0 P% v9 g& y+ V9 e. _% t& i2 N/ d
  56. //以下为汇编函数
    - i$ `; U8 e/ d. }8 Q& l
  57. void WFI_SET(void);                //执行WFI指令% P8 J+ n. M  S- d9 j
  58. void INTX_DISABLE(void);//关闭所有中断
    2 n/ f* M0 |6 @8 M" n, s
  59. void INTX_ENABLE(void);        //开启所有中断! [2 r/ `% M% m$ O" n
  60. void MSR_MSP(u32 addr);        //设置堆栈地址" G/ X9 ?* X% F: d$ s

  61. : v  T- H9 |- d8 Y. _' W" }! u; Z
  62. #endif
      |) s$ I6 o. C) }/ E' `+ A+ [  j
复制代码
) Q$ r9 F) i& k" l# J
sys.c6 Y! @$ L2 O: H
: @4 Q/ B8 t$ J
  1. #include "sys.h"
    ! N( d3 m+ n9 K7 a

  2. 8 @/ w; C3 A. |+ B
  3. //THUMB指令不支持汇编内联- s" o- E; A2 B8 ~9 O. R. \' C
  4. //采用如下方法实现执行汇编指令WFI  1 P7 j- D% o9 }  N0 [# l9 m; [' I
  5. void WFI_SET(void)
    $ k  d9 u5 }8 {3 Z  ^1 y5 c
  6. {
    9 T' X, ]& B7 C
  7.         __ASM volatile("wfi");                  
    $ r" h! C0 z- |. r
  8. }
    7 _# x$ X# ~& w/ U
  9. //关闭所有中断5 ~: h$ r2 }% w# X3 z
  10. void INTX_DISABLE(void)) e1 B3 ^- ]" f6 _# c
  11. {                  5 r, e) R8 a: F) c
  12.         __ASM volatile("cpsid i");
    5 Q0 `. v, M. {/ ~7 ^+ w& B, Q& Z
  13. }' H; C1 E' ^( Z' z  }' J' j
  14. //开启所有中断, a' w* V8 e, D' G$ t
  15. void INTX_ENABLE(void)
    5 h: r9 R& q/ A. O  U
  16. {; O1 z5 _; c4 J( C- |
  17.         __ASM volatile("cpsie i");                    O. r+ D2 b$ C% v4 \* L
  18. }
    + p: H5 ^& D4 b4 `. x1 x0 O  f
  19. //设置栈顶地址
    3 c( M7 K3 E/ m1 ?
  20. //addr:栈顶地址( J; s  |$ c- [
  21. __asm void MSR_MSP(u32 addr)
    / ^( Q2 a1 j/ {9 Y
  22. {& \+ H- C2 D$ y3 L3 `0 T6 Z
  23.     MSR MSP, r0                         //set Main Stack value
    ) w7 b7 o: N; W% |. B
  24.     BX r14
    , S0 a' T7 l# a8 ]; B5 h
  25. }! P' u6 J1 u. {, d7 t' \0 j
复制代码
: N1 q, F* L6 y9 `
延时函数配置
; Q( f$ |$ _4 V' O9 sdelay.h4 M5 d2 N! x+ ]. b

" u  U  M4 v$ W5 z  L
  1. #ifndef __DELAY_H
    ( d% n; P! D- [: @* h
  2. #define __DELAY_H                            " K4 G: Z7 }. m2 c8 a  K, H
  3. #include "sys.h"  
    1 A$ j3 S( Y+ e5 L
  4.          
    * s# a7 N: V2 S; s' r% n
  5. void delay_init(void);
    ( ?( q/ \4 c% ?- K- Z8 J
  6. void delay_ms(u16 nms);, e+ I/ \# H; X9 Q2 L/ p5 m' U' O
  7. void delay_us(u32 nus);( R& x7 n9 t, U1 C4 e

  8. ; M$ `4 j" f- Q/ _6 s/ X
  9. #endif
    ; J8 a8 Q3 ]$ c; r6 v8 h7 M
复制代码
6 m% H( O2 Y" u
delay.c
& H5 @& s0 o7 O, }. V
: q4 q8 P/ S% \( x+ x
  1. #include "delay.h"
    6 ^+ ]  R+ c9 Z  R' b+ L% K
  2. //          9 P* v2 m# }5 m! j7 P
  3. //如果需要使用OS,则包括下面的头文件即可.* ^3 H3 _+ ~/ Y& K5 z' G; `% E
  4. #if SYSTEM_SUPPORT_OS7 w  H+ ^+ h4 o
  5. #include "includes.h"                                        //ucos 使用         
    2 a% _- o# _1 z9 W) W$ L3 d5 R
  6. #endif
    ; [+ ]9 N3 Q, y4 X2 K& e( ]

  7. 2 B) a7 @/ l' f5 Z0 Z# p0 ?
  8. static u8  fac_us=0;                                                        //us延时倍乘数                           ) f4 q9 X: d/ N9 z1 [. @
  9. static u16 fac_ms=0;                                                        //ms延时倍乘数,在ucos下,代表每个节拍的ms数/ n5 `$ U9 s5 b% K
  10.         
    % r3 n/ R* u; v/ E' V
  11.         
    ! K6 a5 i* N6 v$ p6 ?# @
  12. #if SYSTEM_SUPPORT_OS                                                        //如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).) }( B6 h7 v) w
  13. //当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
    5 G# a& R2 K; c, n; U
  14. //首先是3个宏定义:, d% a  L$ s2 T4 w. ^
  15. //    delay_osrunning:用于表示OS当前是否正在运行,以决定是否可以使用相关函数: x9 M& `2 K1 V6 b
  16. //delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始哈systick' W) e" W# U: l2 p& ?
  17. // delay_osintnesting:用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行+ n5 o1 o+ ?4 j4 [8 P: F( I8 l
  18. //然后是3个函数:
    ( }0 |3 X0 w: b/ p' j3 n- O" f/ v
  19. //  delay_osschedlock:用于锁定OS任务调度,禁止调度
    ; a; W/ ~2 y# V7 Z% F' B& y7 v
  20. //delay_osschedunlock:用于解锁OS任务调度,重新开启调度* A7 n1 d& a8 X
  21. //    delay_ostimedly:用于OS延时,可以引起任务调度.  z3 n+ s0 U# R8 D# ?' S
  22. / B& r& A* b$ k- k- F- F& B
  23. //本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考着移植
    + M( ~" \5 Z! R3 \8 P
  24. //支持UCOSII" @" ?1 z3 ?3 h" ~% e
  25. #ifdef         OS_CRITICAL_METHOD                                                //OS_CRITICAL_METHOD定义了,说明要支持UCOSII                                ! H8 C3 }- {; ?! Y* _
  26. #define delay_osrunning                OSRunning                        //OS是否运行标记,0,不运行;1,在运行9 H' @5 |, N' b  t0 m' z/ |# j
  27. #define delay_ostickspersec        OS_TICKS_PER_SEC        //OS时钟节拍,即每秒调度次数+ O9 s/ o6 n& a- U5 |. V
  28. #define delay_osintnesting         OSIntNesting                //中断嵌套级别,即中断嵌套次数' @. Q- E0 X4 A1 Q$ e3 C5 y8 X
  29. #endif. w- p* }+ R$ \& x
  30. 6 r5 c) N2 d, h: D7 R
  31. //支持UCOSIII
    * j8 A* W% W) O3 R% R. D
  32. #ifdef         CPU_CFG_CRITICAL_METHOD                                        //CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII        + D, H0 p; K" d
  33. #define delay_osrunning                OSRunning                        //OS是否运行标记,0,不运行;1,在运行
    , b9 z- Q  {# H6 X# U. Z
  34. #define delay_ostickspersec        OSCfg_TickRate_Hz        //OS时钟节拍,即每秒调度次数
    8 k3 j. P$ R+ v+ @
  35. #define delay_osintnesting         OSIntNestingCtr                //中断嵌套级别,即中断嵌套次数
    5 M& U# R# F- V
  36. #endif
    ! Z( x  `0 H: F% u* t. |
  37. 3 ~5 ~6 v$ _& F5 u& U) v

  38. 3 h! a' ^2 |- y7 C9 j
  39. //us级延时时,关闭任务调度(防止打断us级延迟)  o5 I. L  V  r
  40. void delay_osschedlock(void)
    / }1 x, @. o2 s( n# T) a
  41. {
    $ G$ Z' G; m" v% j6 I8 a0 d( o
  42. #ifdef CPU_CFG_CRITICAL_METHOD                                   //使用UCOSIII5 K/ y8 [. m: U1 {: f1 N+ h, x
  43.         OS_ERR err; ; F  t. O- [: A* T# r9 ~: q) M1 A
  44.         OSSchedLock(&err);                                                        //UCOSIII的方式,禁止调度,防止打断us延时' @5 L' _( W% \, S0 h& s4 P
  45. #else                                                                                        //否则UCOSII
    % E7 i) f* {5 i! S/ d  w
  46.         OSSchedLock();                                                                //UCOSII的方式,禁止调度,防止打断us延时
    * i# H! _& S, \3 F: x3 u/ v5 x9 F
  47. #endif
      K: A1 t' |2 l7 Q( q8 o1 W) W) c# ~) d
  48. }6 n( p2 ]: }3 M8 Y  c$ w  Y

  49. $ k$ u. G7 |5 v! {9 e# \2 T; j
  50. //us级延时时,恢复任务调度
    * X- ]. \3 t4 Q8 s
  51. void delay_osschedunlock(void)
    6 b) R5 o4 U  K- E3 d
  52. {        
    ' S: J, \% m! U, ^4 i
  53. #ifdef CPU_CFG_CRITICAL_METHOD                                   //使用UCOSIII
    2 g/ H- y5 z9 f$ `" g0 x# W% }
  54.         OS_ERR err; + x; w( o2 _) B) i6 }
  55.         OSSchedUnlock(&err);                                                //UCOSIII的方式,恢复调度, X9 d; S1 @0 m7 ]2 J
  56. #else                                                                                        //否则UCOSII
    ) X4 o& m  S9 \* E* @6 _9 D
  57.         OSSchedUnlock();                                                        //UCOSII的方式,恢复调度
    / P: @& _$ L. F' ^
  58. #endif4 R, W: _; M1 B7 ?' I5 |. e
  59. }
    ( m7 q& C" U) q9 z

  60. " E1 s* }, N, P8 k
  61. //调用OS自带的延时函数延时3 c0 S6 C+ X2 E4 D" T
  62. //ticks:延时的节拍数# f) x9 \7 K1 m
  63. void delay_ostimedly(u32 ticks)
    8 F+ V5 ~3 T$ K4 L
  64. {! k9 u- L* E6 |/ |% A
  65. #ifdef CPU_CFG_CRITICAL_METHOD
    ) n+ O1 _, z8 {. C8 T+ r- s- w
  66.         OS_ERR err; 9 G6 l% H; i) `
  67.         OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);        //UCOSIII延时采用周期模式
    ( F* _) z( z9 H/ J! b
  68. #else
    0 ^. _6 `$ x) w" v; a7 W& r
  69.         OSTimeDly(ticks);                                                        //UCOSII延时
    6 M( _/ N- m5 k+ M# n
  70. #endif
    ) e7 n: i; y  F9 m0 D" B
  71. }
    ; k  O/ g" ~7 c: V, Z

  72. - |0 D# Y9 X8 B% X* u
  73. //systick中断服务函数,使用ucos时用到+ U2 g7 p: O, @7 a
  74. void SysTick_Handler(void)$ B! }8 n( }6 T$ M1 @2 S0 C
  75. {        
    . \" E: Q/ y- f; |  l+ z, Y" W
  76.         if(delay_osrunning==1)                                                //OS开始跑了,才执行正常的调度处理2 J2 j' h4 y4 S
  77.         {+ t( l* k. k5 Q' |
  78.                 OSIntEnter();                                                        //进入中断2 I  b9 r7 m% v+ {& e( Z' `
  79.                 OSTimeTick();                                               //调用ucos的时钟服务程序               1 b$ f' `9 `8 O% m7 A/ J7 a
  80.                 OSIntExit();                                                        //触发任务切换软中断: ?4 D/ ]4 J, M( U) \; Q. [
  81.         }1 Q6 M* C' S  z% X0 g
  82. }6 w$ p" z; G5 D) ~+ R# t+ K
  83. #endif- P; q- o: \2 B9 i

  84. 2 T& v; r% e( j2 _  [% t
  85. //初始化延迟函数9 i( i6 _5 w: u* Z' R
  86. //当使用OS的时候,此函数会初始化OS的时钟节拍
    ! b/ N# W8 \& v; A
  87. //SYSTICK的时钟固定为HCLK时钟的1/8: k- I! u. Q2 X: Q
  88. //SYSCLK:系统时钟4 l) s2 p4 R  O; T: Z; ?" P! f
  89. void delay_init()& B& ?  }- @* i# O5 F+ m
  90. {$ z. w! x1 u; }' K. ?( U
  91. #if SYSTEM_SUPPORT_OS                                                          //如果需要支持OS.! A; }( U$ R2 |8 Y3 P# Y2 q7 g" L
  92.         u32 reload;8 q% `* D8 R3 N$ Q7 }
  93. #endif4 j. d* u* {9 C
  94.         SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);        //选择外部时钟  HCLK/8! h6 z) ]) K% D5 g/ W, ^
  95.         fac_us=SystemCoreClock/8000000;                                //为系统时钟的1/8  
    3 _( J  a5 J0 \
  96. #if SYSTEM_SUPPORT_OS                                                          //如果需要支持OS.
    / K" |3 X+ l8 I  @) S, M3 ^
  97.         reload=SystemCoreClock/8000000;                                //每秒钟的计数次数 单位为K           * e. i9 Y* @% P6 b
  98.         reload*=1000000/delay_ostickspersec;                //根据delay_ostickspersec设定溢出时间* n2 M5 Z" K# Q
  99.                                                                                                 //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右        
    & H8 E8 Y. r- n/ x
  100.         fac_ms=1000/delay_ostickspersec;                        //代表OS可以延时的最少单位           
    4 f4 a, n! n; B4 A% s) K
  101. 4 K8 K5 x7 a' r; f( k5 l
  102.         SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;           //开启SYSTICK中断
    8 u! Q4 N: u2 e3 j  [) I
  103.         SysTick->LOAD=reload;                                                 //每1/delay_ostickspersec秒中断一次        # C  ]/ ~; ?' }6 L0 o+ V
  104.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;           //开启SYSTICK    , q4 N7 H+ }# g4 F; A
  105. / u0 ]- [5 v. o$ M4 r8 |
  106. #else
    9 Z6 o8 N# m8 ]2 e+ a
  107.         fac_ms=(u16)fac_us*1000;                                        //非OS下,代表每个ms需要的systick时钟数   
    0 P% @" o* W$ K
  108. #endif$ o5 \) @1 H. G- l. D4 k$ R
  109. }                                                                    3 {. o5 j( ~( @1 R7 E1 O4 T/ r

  110.   b  a  s5 ?  n1 N; c& `5 j
  111. #if SYSTEM_SUPPORT_OS                                                          //如果需要支持OS.
    # `& }6 D7 f0 N# b
  112. //延时nus
    $ o! b0 i  [3 l+ K9 A* f
  113. //nus为要延时的us数.                                                                                       ' I' D# J% H: P
  114. void delay_us(u32 nus)
    % d$ K  U% i6 j  W+ e9 o
  115. {               
    0 T8 t7 C% s2 S8 o0 V8 L1 @
  116.         u32 ticks;
    * L: N2 O: K; V! _) Q
  117.         u32 told,tnow,tcnt=0;' X6 w3 v5 c' a  Y
  118.         u32 reload=SysTick->LOAD;                                        //LOAD的值                     $ x# i6 |% ~  w( r1 h8 \
  119.         ticks=nus*fac_us;                                                         //需要的节拍数                           7 {! O5 h) N; k+ }1 a; L
  120.         tcnt=0;. @1 e2 P+ h7 o$ m
  121.         delay_osschedlock();                                                //阻止OS调度,防止打断us延时
    " V- Q/ D$ O+ ^0 O1 j2 }$ x8 S7 T
  122.         told=SysTick->VAL;                                                //刚进入时的计数器值
    * Y( A; w3 V+ n' H6 t3 o, Q/ }
  123.         while(1)9 e1 u' m: q4 U" _, \* L5 o$ `
  124.         {5 i/ l6 R( |0 W. W9 y' n
  125.                 tnow=SysTick->VAL;        
    / [' }8 @! _' [' [! G+ \
  126.                 if(tnow!=told)
    - ]% p9 x3 q+ S
  127.                 {              j1 B8 W* d: \0 G
  128.                         if(tnow<told)tcnt+=told-tnow;                //这里注意一下SYSTICK是一个递减的计数器就可以了.
    ; T. t0 k2 R' ?' r- U/ L$ a# Z1 f9 C
  129.                         else tcnt+=reload-tnow+told;            5 D6 f$ [$ h9 ?7 W5 b7 P7 d
  130.                         told=tnow;
    . V# p+ ~. R* C/ O: K9 _
  131.                         if(tcnt>=ticks)break;                                //时间超过/等于要延迟的时间,则退出.2 v! P5 b: V8 ~; C& I  w
  132.                 }  ; b# e! p! M3 D$ g3 o
  133.         };8 `8 J) h1 G% @
  134.         delay_osschedunlock();                                                //恢复OS调度                                                                           
    . g1 l1 d6 }0 B6 g) G* T
  135. }
    % n% N0 l$ D& e/ f
  136. //延时nms" g' R( O6 W0 w) U6 Q2 V
  137. //nms:要延时的ms数
      ~. m/ V& Y. Y, o: L1 y% |  T
  138. void delay_ms(u16 nms)
      W6 }. E4 |. B5 b/ K) W
  139. {        . D8 s! f! t" D+ o+ i8 Y
  140.         if(delay_osrunning&&delay_osintnesting==0)        //如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)            
    . d( \& F3 P, h
  141.         {                 
    ; N% K2 ]! [4 T* y
  142.                 if(nms>=fac_ms)                                                        //延时的时间大于OS的最少时间周期 6 @2 h: e/ [; s  k4 s, I/ X
  143.                 {
    7 J# l9 h6 F' e4 ~! q4 b
  144.                            delay_ostimedly(nms/fac_ms);                //OS延时
    4 |# d& @3 g( p  ~" J9 n& x' Q9 t
  145.                 }
    # n: f: H: Y4 P/ [
  146.                 nms%=fac_ms;                                                        //OS已经无法提供这么小的延时了,采用普通方式延时    ( F' J1 W& J( L8 i( t2 }
  147.         }7 S7 [; L1 ], d* }
  148.         delay_us((u32)(nms*1000));                                        //普通方式延时  % p8 ]1 G, ^- B* o6 R/ v% I0 H! X
  149. }9 z) w% A" T: N3 y9 W
  150. #else //不用OS时
    # X+ d# f8 \; }( W7 z
  151. //延时nus7 B, L! f9 q7 F* T
  152. //nus为要延时的us数.                                                                                       
    3 H6 c  a- j' u5 `# P$ K
  153. void delay_us(u32 nus)+ C: B( @4 Z# X5 D) g1 b
  154. {               
    - K( z' b- W/ m0 ~  o# c
  155.         u32 temp;                     
    3 Q. b1 ?6 b% l
  156.         SysTick->LOAD=nus*fac_us;                                         //时间加载                           
    6 u5 ~* p3 ?' J% z0 G
  157.         SysTick->VAL=0x00;                                                //清空计数器* o' H; o! Y% {' U. B2 s$ g1 A
  158.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;        //开始倒数         
    8 U3 N2 D8 v3 G5 f! w: C
  159.         do
    7 \$ e, Q3 y" k/ {" X
  160.         {
    : {1 R' N8 }+ s" s
  161.                 temp=SysTick->CTRL;5 ?) \4 d  _7 T0 F6 x/ ^
  162.         }while((temp&0x01)&&!(temp&(1<<16)));                //等待时间到达   
    4 a8 x# T4 r: m+ d! m3 c! p
  163.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;        //关闭计数器1 o2 w, m/ z  L3 E3 T0 ]
  164.         SysTick->VAL =0X00;                                               //清空计数器         2 o5 F& r$ `# \! g9 M8 Z
  165. }: D& Y7 V6 M- w
  166. //延时nms( @, T4 l0 S$ O$ [* f6 e/ n% i6 ~
  167. //注意nms的范围: E" ~  Y1 j+ u" }: L& ?/ R: g& U
  168. //SysTick->LOAD为24位寄存器,所以,最大延时为:  C. F0 o: {; u( Z- s5 c1 l
  169. //nms<=0xffffff*8*1000/SYSCLK+ V! S* ]: J) p  G$ v+ E* P3 ^
  170. //SYSCLK单位为Hz,nms单位为ms# A0 J) [+ k8 k! x( K/ e" g1 @3 Q
  171. //对72M条件下,nms<=1864 0 F& n6 z' [) J- n7 {
  172. void delay_ms(u16 nms), X+ v, B2 O8 `6 r
  173. {                                     * I" I' P$ U1 j4 j' a5 x* g  w
  174.         u32 temp;                   : f  `, s6 q' Y3 p! x# h
  175.         SysTick->LOAD=(u32)nms*fac_ms;                                //时间加载(SysTick->LOAD为24bit); [, `" m1 F% U. l2 D  M- I. u6 [
  176.         SysTick->VAL =0x00;                                                        //清空计数器
    2 w4 c+ C" z9 @% p& ]& E
  177.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;        //开始倒数  
    4 q. B! t0 q. g) l1 D* g+ R, M; m
  178.         do3 @5 M, C5 u5 H* F) T+ l
  179.         {
    4 C% Z8 y, N0 m4 {2 E0 Z+ X" l
  180.                 temp=SysTick->CTRL;* N5 c$ h2 `* x/ k
  181.         }while((temp&0x01)&&!(temp&(1<<16)));                //等待时间到达   - }9 c' ^/ d# K& c. U$ m) e- c* r
  182.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;        //关闭计数器7 p7 N( m  f* z6 D/ O3 y
  183.         SysTick->VAL =0X00;                                               //清空计数器                     
    " ^, K3 }- \' b# N( o  Q! z
  184. }
    % ?# c! s. v" K, q  G8 y5 j
  185. #endif
复制代码
' N5 D! ], l. T% [/ R6 t3 ~
串口打log配置,可用可不用/ ^0 n( @' \0 _
usart.h5 `6 j8 K+ ~" x. V0 e5 \

0 k3 v# D) _* P# s  ^7 Z% k
  1. #ifndef __USART_H
    - V8 l* W, x* e
  2. #define __USART_H4 \( x1 ?1 T' L
  3. #include "stdio.h"        
    - Q6 D- e4 \- V) S
  4. #include "sys.h" ( i7 b8 j8 l! q# r: ~
  5. 7 L' \: n# q9 P$ Q
  6. #define USART_REC_LEN                          200          //定义最大接收字节数 200: g7 x+ S0 a& W, u: u2 C6 s$ d
  7. #define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收
    1 v: ?2 v7 H4 D/ ~
  8.                   
    0 e$ k8 X) ^- b
  9. extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 7 C1 L* H/ _, ?9 W) I( A
  10. extern u16 USART_RX_STA;                         //接收状态标记        
    9 D1 {8 E& }" S) a/ z# F
  11. //如果想串口中断接收,请不要注释以下宏定义( x' w: T( g  b# z* a2 O! L
  12. void uart_init(u32 bound);
    8 ^. o3 M' X% o
  13. #endif
复制代码
+ _" Q* n. G) X; P3 X4 S0 J& o: B
usart.c
# R6 m" `1 P0 H
5 I9 x: G' b2 [" U2 B
  1. #include "sys.h"
    4 y7 U( Q: v' c3 A
  2. #include "usart.h"         
    8 ]1 o# M/ }( Z; b! m+ O! W! j2 h
  3. //          ' x, q* G. \% C2 g6 i( S
  4. //如果使用ucos,则包括下面的头文件即可.
    & r+ R, e' o$ n8 T
  5. #if SYSTEM_SUPPORT_OS
    1 d# h. U- F9 o6 D6 |$ Q
  6. #include "includes.h"                                        //ucos 使用          % A' Y4 W- m2 H$ B- Q8 D5 y' E' [
  7. #endif
    2 z( J9 B8 a* F4 B
  8. 8 t" ]7 H$ a" R4 k5 y7 `
  9. //加入以下代码,支持printf函数,而不需要选择use MicroLIB         
    * o' }. ]* u; h+ ]& Z+ ?
  10. #if 1
    7 g! x, {7 B& b  W7 z
  11. #pragma import(__use_no_semihosting)            
    ( |  V& `0 N5 K) p# V6 c
  12. //标准库需要的支持函数                 
    9 h( f: x( N" N, E' W. e" b
  13. struct __FILE
    ' F' y0 z- ]. `$ d' H* w9 m+ n* l; G' Y) \
  14. {
    $ {4 x1 n7 V' m3 [
  15.         int handle; 2 H( R% l) T0 h$ m' k
  16.   s$ Q4 e8 }3 C
  17. }; . K3 m! y0 z) h# N" Z& ^
  18.   S# h2 Z: S9 Q
  19. FILE __stdout;       3 d- K% l. O& }1 r5 h. l& r. F
  20. //定义_sys_exit()以避免使用半主机模式   
    # x9 z6 r- O( ]: ?+ I
  21. void _sys_exit(int x) 6 \- z# x( K% f. _+ t
  22. {
    + d' X2 [) ^" }
  23.         x = x; 1 ~; O7 t* s1 B: ^7 q. z$ u/ f
  24. }
    9 `6 E3 J3 C4 ~
  25. //重定义fputc函数
    - `" y7 ?6 ?* W" ?. S& t' f
  26. int fputc(int ch, FILE *f)
    1 ?" e% k) ]# R' u& [, |
  27. {      & @: r) k8 f  ]$ u7 h  A& G
  28.         while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   8 e% |1 |1 v# t
  29.     USART1->DR = (u8) ch;      ! x# w1 r  y9 I' x# N# M# r. V
  30.         return ch;- N. W! R- N( M5 ?0 A6 k, ]5 u
  31. }: X) v7 B& I, B! W
  32. #endif
    " G( }* O+ g( d, w
  33. 0 A1 Q  h) Q2 D% u5 O! G
  34. /*使用microLib的方法*/8 m1 V+ [% a% J' Y* V3 P! j
  35. /*
    / F7 W4 n  ?+ N; g- h( @6 S- ^+ B
  36. int fputc(int ch, FILE *f)  u2 m7 D& T  d2 o7 u4 N
  37. {! _; D: L$ `4 W
  38.         USART_SendData(USART1, (uint8_t) ch);  @6 a' e, R$ F) U6 ]) U9 A5 ?# J

  39. * H" m# s. G/ B( S! e/ l
  40.         while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}        0 u2 y2 ^, }5 M6 t
  41. 4 n* `* E- \' e; ?# y( R
  42.     return ch;
      D) p/ ?% t* [- V
  43. }
    $ X* S6 q3 @3 ~  U7 y
  44. int GetKey (void)  {
    / F; A7 R# M5 {, \9 f
  45. * U, Z. E9 M: E5 ^$ Q. z- m4 b' n, O
  46.     while (!(USART1->SR & USART_FLAG_RXNE));% f; e+ z, `2 b5 r0 C* H

  47. 8 T% Y& \8 o$ ^1 r9 ?9 ~
  48.     return ((int)(USART1->DR & 0x1FF));/ \) o" D: ~0 a8 k, e4 H
  49. }
    ( L3 d+ B  P( D# N) \
  50. */- L5 ~' a: W) N
  51. : B3 U& l: P! Q) f5 O0 F7 x9 h
  52. #if EN_USART1_RX   //如果使能了接收. C* G* H* ?4 j' T
  53. //串口1中断服务程序2 w+ X! \. r  f, n
  54. //注意,读取USARTx->SR能避免莫名其妙的错误           
    0 J2 g, r& r' B6 F5 g
  55. u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
    - B1 j$ \) H; U/ t9 a2 L* t: R
  56. //接收状态
    ( g: p9 U; _% i7 c! {
  57. //bit15,        接收完成标志- `9 H9 C3 ?' Y8 v/ ^8 ^7 P
  58. //bit14,        接收到0x0d
    ! u' _5 F. G! _
  59. //bit13~0,        接收到的有效字节数目: v  \5 O: M. j2 R
  60. u16 USART_RX_STA=0;       //接收状态标记          ; n% s% A) l! ?7 ~
  61. . A: H4 e; K6 k/ g
  62. void uart_init(u32 bound){2 f5 C  F+ f7 e
  63.   //GPIO端口设置7 X# B& Z6 D! z% z& v8 k
  64.   GPIO_InitTypeDef GPIO_InitStructure;3 o! q# ~) q  b
  65.         USART_InitTypeDef USART_InitStructure;
    4 {6 }3 u$ R4 y7 {- }* X
  66.         NVIC_InitTypeDef NVIC_InitStructure;% B' C' ]8 L6 ~) P/ ~
  67.          
    / F3 p. d8 m/ d" y' {
  68.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟
    # M% e! a" H9 p4 ^) E
  69. 8 Y5 S1 l' C$ @' N% R. J
  70.         //USART1_TX   GPIOA.9- K  e6 p4 Q4 G' y+ I
  71.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9' F9 A  ~$ g' i, V' W- y) h
  72.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;" J& M+ C& o9 u5 z; `* E  I9 ~
  73.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出5 t; H6 _4 S! ?7 j. E( q: L8 q
  74.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9- G; R8 M; X; P) a( ^& ^

  75. / ^+ t3 n+ K0 W
  76.   //USART1_RX          GPIOA.10初始化2 \* T2 f% L7 P" \/ t6 W/ p: }
  77.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
    6 A$ V& z+ i6 d. F% |' S& A# L
  78.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    0 P) [$ k' m/ u! O& r; a
  79.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
    & r4 D; s5 N: a8 L  ~* t. A5 w

  80. + T) s; Q. ?2 V% j3 g) ^
  81.   //Usart1 NVIC 配置" Q7 Y- O: G2 W( d. a6 h) L3 H
  82.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    4 j. g, w( V- J
  83.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
    2 V) \+ u/ b& P* y/ U9 ]
  84.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3; _+ P( ]6 `. u& p
  85.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能& f! V3 O. W7 I/ Z0 O1 A
  86.         NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
      V4 c+ v  Q4 ~) {) G6 J$ a* H

  87. 5 i8 m6 \( y* w, f0 y: \( @4 K
  88.    //USART 初始化设置
    , c/ ]( t5 o0 _: Z& u
  89. 3 Z" v. M" s/ T$ x. y
  90.         USART_InitStructure.USART_BaudRate = bound;//串口波特率6 S7 I6 c5 d, C; X- E
  91.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    - u( L8 m1 d/ \. K2 N
  92.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位+ {* S) m1 B# c; ]: ~
  93.         USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位+ X$ Y# m1 k: X! }. a) ^- t
  94.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    + d6 ~- _: n$ u4 I
  95.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式
    & F5 E. A& E, C
  96. , j2 A2 T' k: u$ c- V
  97.   USART_Init(USART1, &USART_InitStructure); //初始化串口1
    + N/ f# S9 I: T
  98.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断0 v3 O7 z" @$ S1 E
  99.   USART_Cmd(USART1, ENABLE);                    //使能串口1 7 H4 Z% r( z- ?; ?+ i4 q  w
  100. }! Y- _) m( k6 v5 C0 Z7 g5 C/ p* }
  101. # [6 F8 c3 G: Z1 Z
  102. void USART1_IRQHandler(void)                        //串口1中断服务程序
    / i0 W' k1 E4 y% |, c* k* ]2 I
  103.         {
    0 [8 m: {8 n+ `3 Y- U0 m
  104.         u8 Res;
    ) K. l  G$ N( u  Q6 u
  105. #if SYSTEM_SUPPORT_OS                 //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    % g" ?, _# U& a
  106.         OSIntEnter();    4 T; j4 I% n6 V9 v8 r4 U7 f4 t5 N
  107. #endif
    ; l4 ]  Q8 |8 ]; z. U
  108.         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    : U: k2 j7 n7 _9 V+ a, K) \( |0 q
  109.                 {
    : }2 n) R" \( K+ m
  110.                 Res =USART_ReceiveData(USART1);        //读取接收到的数据9 M( e: G+ m" C* w8 C5 F
  111.                
    8 i: N/ _0 M" v8 D; `
  112.                 if((USART_RX_STA&0x8000)==0)//接收未完成
    + E; \  ~( L5 I
  113.                         {
    ( D7 D- r4 o1 M
  114.                         if(USART_RX_STA&0x4000)//接收到了0x0d
    # n& ^& T, }0 ?
  115.                                 {
    + v8 Z$ W8 n8 v
  116.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始! n4 t# _* ~: G8 F, v
  117.                                 else USART_RX_STA|=0x8000;        //接收完成了
    ; [$ j& N, ]" S& j
  118.                                 }
    6 ?7 V6 Y8 [' O4 A* r8 n
  119.                         else //还没收到0X0D) |- Q% g  i$ w9 Z. K
  120.                                 {          G- T& X7 c8 ?8 V1 Y) H# i* c
  121.                                 if(Res==0x0d)USART_RX_STA|=0x4000;
    # c; _, ~8 h) i- y
  122.                                 else" k+ r1 r4 |1 [9 c
  123.                                         {
    7 B2 F8 `0 F& N. m# x
  124.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;& h' Z& G# r5 x; w- P" @$ C
  125.                                         USART_RX_STA++;
    ' ?6 L* ~' `2 _$ G- X
  126.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收         
    2 K7 {( `4 i' q( k/ b& R, f6 u
  127.                                         }                 
    / x6 y9 U% L- k0 ]
  128.                                 }
    6 N: w  M* n! w
  129.                         }                    * M9 p3 P2 g) P
  130.      } / _. U5 R4 r: h8 g  q) w
  131. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    1 Y2 h* |3 n7 a' I2 w9 ^) ]
  132.         OSIntExit();                                                                                           8 E4 l* t+ Q1 X5 }5 Y! f' ~
  133. #endif
    1 n. r  j. u% X) T
  134. } ' l7 H# K4 O% r" p8 H: t* ~
  135. #endif
    / L  T' m/ F7 }5 K8 P
复制代码

% `: Z! g( ^4 _; U, F2 Y" c0 ]6 U! f8 V- ?4 M& S0 [& N9 n: o+ j
+ d4 w) K8 j  _0 D& k& |8 B, b
赞 收藏 评论0 发布时间:2022-5-25 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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