基于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% [- #include "led.h" u# C# } e' S: I. {4 h7 n
- #include "delay.h"
; a0 u$ P6 c! k5 X$ ~% W% [4 S% A/ U - #include "key.h"
. e. M$ a5 k0 T) {* \9 H - #include "sys.h"
# R7 z3 k' Q* C - #include "usart.h"9 n! @. }7 t& I+ o5 R: W! d
- #include "exti.h"
( I7 Q+ z2 j! a% a- l - #include "beep.h"
6 q! ]& Q8 k- @( w9 [ - #include "timer.h"
! K _1 z' X2 W* \ - #include "adc.h"
3 C# V% U% I( w% q - 5 J) S1 Z; c; A
- int main(void)& {; G$ ~ y. f
- {
( C# e! N% o0 c6 x- k' Z2 T - u16 adcx;* [% X% {; O8 F2 `/ y+ T
- int i = 0;//用于舵机转动的for循环
) v1 Q" E& q- e7 H: |9 M; [* b - int frequency = 175;//舵机转动的初始角度 175-195, }% o6 G4 A5 j0 F7 `3 O
- float temp; //通过ADC转换获取雨滴传感器的值% Y B' [% o ^- k$ A
- int integer; % r1 j4 @( B( ^2 B" A' d
- delay_init(); //延时函数初始化
9 F/ M, X1 Z5 T' @. s1 @ - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级4 {4 I/ X! ~9 U1 s9 K( R, C& o
- uart_init(115200); //串口初始化为115200
0 \0 I, `' ?* {. t4 N: O. a - LED_Init(); //初始化与LED连接的硬件接口 , l3 x y# d/ C' @) G
- BEEP_Init(); //初始化蜂鸣器IO
! ]4 P/ E; ~3 o. r# y( g% W - EXTIX_Init(); //初始化外部中断输入 ) w9 x6 X# H& m" u: y
- LED0=0; //先点亮红灯
" s! H( u; s( p: Y1 m+ G - TIM3_PWM_Init(199,7199); //不分频。PWM频率=72000000/900=80Khz
; {5 S& Q3 c, P5 X/ i3 k - Adc_Init(); //ADC初始化
. a* p! l9 T5 `! @' R. |/ |) v - while(1)
# I' p0 N, W. Z/ v - {3 v& n$ d. W" z- Y+ l
- adcx=Get_Adc_Average(ADC_Channel_1,2);4 v8 N5 L$ n0 }* a
- temp=(float)adcx*(3.3/4096);4 M' ~5 g( {2 H% m; F4 m
- temp*=100;
0 ]5 B1 i* k1 Z, u! t: x$ R: t - integer = temp;! d) }) L! Y: G, H( `
- if(integer > NUMERICAL_THREEHUNDRED && integer < NUMERICAL_FOURHUNDRED)//不下雨
. P+ \; z4 b- X$ p8 P4 W1 Y - { 9 I5 ]6 D% h: u! @
- delay_ms(1);. H5 T1 J8 x3 N0 Y2 F/ y
- } . Z2 c( k0 v. k7 E. {
- if(integer > NUMERICAL_TWOHUNDREDANDTWENT && integer <= NUMERICAL_THREEHUNDRED)//小雨
# \ X+ G% C+ F; g6 ~! t - {
3 N7 d8 Q6 v# [! g% L( A/ _& O8 z - for(i = 0;i<20;i++)7 D# R3 [& W. q- X3 x
- {
8 x. U7 B5 M1 P* a m - TIM_SetCompare2(TIM3,frequency);
" ?! v9 p% {9 x- Y - frequency++;
' q+ M1 S4 h) I. u9 W# j9 V+ Y - delay_ms(DELAYMIN);/ F% r/ B% \; S# y( J
- }
( W/ W& V, M) _ - for(i = 0;i<20;i++)
$ D: V8 ?! Q( F: _6 n6 R% U - {
5 l8 \' T6 U' k4 y - TIM_SetCompare2(TIM3,frequency);! S9 h& R( E$ L
- frequency--;2 X2 ~: p: B+ P7 f
- delay_ms(DELAYMIN);
$ Y% t) q% \$ l" w4 D - }, V1 i( I' N6 m6 g- _
- }/ B" L4 {- A& I
- if(integer > NUMERICAL_ONEHUNDREDANDFORTY && integer <= NUMERICAL_TWOHUNDREDANDTWENT)//中雨, q; P" [: S+ c" s ^, U$ T
- {* z! B7 ]* D+ {# A: d/ o! Z
- for(i = 0;i<20;i++)
$ m2 F+ j! P. ?$ q - {
) v* n# O8 u3 t. r - TIM_SetCompare2(TIM3,frequency);
& z7 `' H2 [+ ~. h - frequency++;, g$ m; J1 m. m( ~: r
- delay_ms(DELAYMID);! k- T8 ?# F4 d$ }7 c9 D
- }
" p& o% i9 T" U& ?8 u - for(i = 0;i<20;i++)
' R4 v( A1 U& C' P - {# e- m- o2 o0 C2 u, ~
- TIM_SetCompare2(TIM3,frequency);
! y' r6 t6 A2 L. Y - frequency--;3 F8 A& G" y. g( W
- delay_ms(DELAYMID);
0 E# H+ N+ p: B8 j/ V6 a$ l9 K - }
" |" k1 A0 `$ A0 f) O( M; T7 u - }
7 |& E( w& F+ W! ]. _9 j - if(integer > NUMERICAL_TEN && integer <= NUMERICAL_ONEHUNDREDANDFORTY)//大雨- r6 @" a% d w( a4 V) S6 G1 Q
- {' b, }2 ]" u6 ~' K
- for(i = 0;i<20;i++)5 P7 H2 M8 d0 z9 F% R! X& t/ O
- {% } P; T0 k. r4 O
- TIM_SetCompare2(TIM3,frequency); H- r% S8 Q" W3 `
- frequency++;4 y) {8 ?' ] U; S! A1 r; q& _, Z3 a
- delay_ms(DELAYMAX);4 H6 e1 j: q0 L7 F
- }
$ q- H( M, y& z& r8 F* R$ U - for(i = 0;i<20;i++)1 |& w/ I6 |# {5 K$ \/ Q1 f, s) R( E
- {
% `. ^. m) b& g - TIM_SetCompare2(TIM3,frequency);
6 Z' E% @2 L, d/ t8 v+ S - frequency--;& }$ y5 S. S5 w
- delay_ms(DELAYMAX);& U1 G9 b5 \5 `) Q- ?
- }
6 y/ g$ J5 w& ]9 M - }
. v/ d \5 f7 E. J9 w- ]3 C - //printf("%d\r\n",integer);//串口发送LOG值, h9 C, j5 v: ?7 k
- //delay_ms(500); * k+ M' A$ `" \/ l [9 T8 ^8 p
- }
* G8 b6 T$ E) q4 ]# p& P2 N - }
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- #ifndef __ADC_H
% G! P8 W: b, ]# K3 R# B - #define __ADC_H
; Z+ W: t1 I! P I - #include "sys.h"
% x/ p! ]: D, O: P/ O - 6 I! [( d1 P8 A! U' ]$ G
- void Adc_Init(void);4 m* j q* {0 U, d8 v+ r
- u16 Get_Adc(u8 ch); 0 X" ?7 V9 H* T/ G
- u16 Get_Adc_Average(u8 ch,u8 times); / O- r$ H. e; p# o ]& b! h1 h
- " I; p5 o- j! W- O( p
- #endif
复制代码 ; E% Z+ S6 p' Z5 G* ~
adc.c6 _' R6 @& z* _$ y. l
6 f7 S3 A$ L5 `) i/ d/ Z- #include "adc.h"
. n2 Q/ V2 a B$ z2 }7 T - #include "delay.h"; V+ ]) j- D( S4 Y
-
! f$ E& H8 a4 A7 y - //初始化ADC; B/ y: o( F+ E1 Y+ Q s
- //这里仅以规则通道为例/ {! o% c+ {9 H$ x
- //我们默认将开启通道0~3
0 E c4 m* i& m/ T1 X - void Adc_Init(void)
) s0 u# o: Z* _* r' r - { : w3 _* l% G ]" e& b+ L
- ADC_InitTypeDef ADC_InitStructure; / f# J3 d# C( E' m$ w: Y
- GPIO_InitTypeDef GPIO_InitStructure;: Q2 Q: h# G3 q# M/ D: K. t
- ) N0 l9 E' A% o. @8 m+ U( ~* W" l
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟5 w$ u+ [& P/ j) x k9 W: C" l9 j
. D$ S' A9 I* T) f+ @" g/ C
" y2 M# ^& b. c6 ~$ B+ b4 |- RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
" u& K; Y& Y, G$ e - ' k3 f' [$ J+ [8 l {
- //PA1 作为模拟通道输入引脚 / \& I3 w) {0 ?1 e5 e& e0 _
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;/ D+ ~4 B" f' }, W3 n
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
/ f; ^9 H r( _: O5 h9 H - GPIO_Init(GPIOA, &GPIO_InitStructure);
$ r" o& A' _. M: p
' `; o* c1 ^$ q5 b- ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
3 b8 U& h* I+ u& R
: G# z- I1 x9 j) _- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式/ w* u* K @# E5 V
- ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
$ [3 }9 i- l5 Q: Y: U7 p5 w - ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式+ L/ {4 c* |: N* K) p
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动9 l8 c) P. u# A6 W2 F" R) _6 k: Z
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐6 T7 ^; m5 l" F+ V7 t2 d% I( G6 y
- ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目5 ]$ R' W: A) r5 G7 q& n: I" K) @
- ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 ) ?9 r, X5 S) C2 p$ h& Y, w
% E$ C% b0 J( P1 y; q" D' f- / a! `# k4 J/ @# A
- ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1+ m0 [0 U+ ?. ]# s
-
) h3 k: l5 K3 o% B5 { - ADC_ResetCalibration(ADC1); //使能复位校准 + W k! A. F" y- a) G9 T) G
- % o: \0 d% j# g
- while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
S2 D# k O. g1 f) q f. Y) C -
1 h9 F4 [9 ?2 c3 a: c& j - ADC_StartCalibration(ADC1); //开启AD校准% S' ^% o* H: `3 K9 u8 L) c
+ _9 f C' E* x( T, c; w D6 X- while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束9 T# \# r) z( M7 r
`) y8 j5 X- k# [5 `" l- r( o- // ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能0 B; Q6 G8 d0 I
+ S X" _' z* _+ @' Z- W" l8 D, Q+ \- } * h, _/ s6 x1 e/ Y- p+ W7 u/ u* Y& k
- //获得ADC值* t& Y/ M! u; d$ {+ D/ U/ N) a& R/ a6 m
- //ch:通道值 0~3( _2 o: Y* Z. u0 a( T n8 S
- u16 Get_Adc(u8 ch) 0 w" n, M; ^2 L+ I3 ^1 w
- { w" \5 ^- N' P! D
- //设置指定ADC的规则组通道,一个序列,采样时间; E( z1 F) c# y8 C( p
- ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期 / r8 x( b% x7 C) d& i' C! g
, T7 M/ \! J) L+ n+ W6 k- ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 ( X; U t- i: v% Z O& y
- % h" T2 t9 I/ ^5 a5 M1 S) |. I; {
- while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束- X4 B/ ^+ C% F0 \. f' w7 U
& { Z, Z1 V9 C- return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果0 p3 @& X! M! f" Y( r5 {
- }5 U3 j+ h; C* N- X/ i4 B' X
. S) H, \6 G) g' ]7 ]6 U( d% I6 r6 y- u16 Get_Adc_Average(u8 ch,u8 times)
* w2 U& I1 C5 R# H( u - {7 i# Y: J' f/ w. l1 Y3 M: e! V4 }
- u32 temp_val=0;
% R8 r9 }' R0 S - u8 t;; x& A. \( ?: D( {1 J# X
- for(t=0;t<times;t++) ]4 s p% o0 R y) ?* z
- {6 V+ }+ b3 L5 ^1 z; Z& I
- temp_val+=Get_Adc(ch);
, P4 i/ ^' X U - delay_ms(5);
1 ^( n( e6 f4 [! X - }$ Z. |: o k- `- c3 K2 @/ x
- return temp_val/times;0 H; P; m6 L w
- }
复制代码
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- #ifndef __TIMER_H3 P6 P& A9 ^$ k- f6 P
- #define __TIMER_H
* g* P, x2 Q! m2 c8 E% t - #include "sys.h"
( l$ H6 a( _6 Y2 }) J( `- s9 p% w
& P' x, S" E' M( Q- void TIM3_Int_Init(u16 arr,u16 psc);9 G+ W# x4 y/ i5 A
- void TIM3_PWM_Init(u16 arr,u16 psc);- Q" r/ @% F; E0 b, N5 o# N/ K
- #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( `
- #include "timer.h"
: Y6 R6 F: r! e' } - #include "led.h"
1 K* s- w+ I5 J, M* e! M5 q5 H - #include "usart.h"% }% g W3 H1 g* ~8 L" z+ R3 y
- 8 F7 V4 D% I0 U7 A/ m5 l/ ~+ K3 `
- //通用定时器3中断初始化
: M1 }: r+ J9 i( |9 B, D - //这里时钟选择为APB1的2倍,而APB1为36M9 J' B; O1 j4 a0 {
- //arr:自动重装值。
0 {6 |) B0 U3 u8 Y$ Q4 M# g E - //psc:时钟预分频数+ g. e! T7 z5 f. P: Y7 [' ]
- //这里使用的是定时器3!
4 i0 V* }3 \5 a ]! [8 w# W } - void TIM3_Int_Init(u16 arr,u16 psc)
3 ?: {5 G+ Q5 x0 F - {$ @5 O$ S( G, b4 W2 Q, k9 r
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
' s5 w3 I' A+ W. B& Z' \ - NVIC_InitTypeDef NVIC_InitStructure;! W0 }& s" o5 r0 m3 z
0 e9 t7 H! n1 ~4 |* _9 A/ |- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
% U$ y4 h0 i+ ]/ h0 G/ o* [
, q( N* N, M/ Y$ t d5 G- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
3 Z# C+ w9 s$ [1 p3 J& x - TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率 ' w" f6 c. Y4 d* I1 T/ c0 P+ }' M
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim" q E; D& o0 g' ^! U
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式# G- V% j1 k& d {, g- e
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位0 Q! g3 J) z) [4 W2 f
# I. z/ E8 i1 e a+ C) Y j* V- TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
1 n. j% t* f" V) f0 ?. Y& }
, }7 ^/ F9 i; K- w0 {3 ?- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
( P9 Y$ Y8 g9 L+ {/ f/ G - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级& ^* }" r" f% A2 n
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级1 z k1 J- z8 \; |
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
/ C! g; w. L+ m0 j - NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器! x) [) y" @8 L7 X" c2 H8 D
- 6 f5 a5 c% J7 B3 t
- TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
* T4 c4 y) A! }2 p/ c - 4 K4 V3 K# n0 k. p$ ^
- }# N% }3 E; `# _# O9 h% h- Y- B' k
- //定时器3中断服务程序
2 K, b. g0 H/ w: H: f - void TIM3_IRQHandler(void) //TIM3中断
/ H: |6 a2 R9 v - {# N3 x% W' j2 I+ B& h+ M
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
5 x0 Z) Q- ]+ `: O5 g N4 \7 A+ L - {% [1 l$ n! V- ]+ i; p8 j
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
2 t4 c! F F, U; C/ }% Y, ]! E7 i3 r - LED1=!LED1;3 R+ _ Y- B9 Q; V, j
- }1 W( l7 _" J4 ~8 K: [. R/ s9 a
- }: P, }7 J, a- w5 H" H
- //TIM3 PWM部分初始化
9 a) y0 N4 y& b/ H6 J - //PWM输出初始化
4 T9 b) S5 F" n- m0 A - //arr:自动重装值
, l- C: {7 ~4 A! U - //psc:时钟预分频数
; F& y4 x4 m V# | - void TIM3_PWM_Init(u16 arr,u16 psc)
# B( B8 c6 P3 y/ t - { ; q& _6 c$ p) b
- GPIO_InitTypeDef GPIO_InitStructure;
2 a" K+ R# `3 B9 W( u5 _ - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
1 G# e# n4 ~* w- w/ ~ - TIM_OCInitTypeDef TIM_OCInitStructure;
4 P( c# d6 J8 a9 C: Z2 m - 6 R1 }8 Y, y! Q; Z- q
- * `- D- G9 } v% k" @$ M |, P' t
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
4 D: X: S6 [. ?" m# ^! T - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟
$ S3 Z5 {! O+ z _- d' Z. W -
) e# H O9 e" E( V% s2 N - GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5
& e1 f+ Z! q3 y - , Z( Q" _" S2 \: F z8 }& G
- //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5- Y0 u1 L/ t, R/ c5 `" d3 Z x
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
l$ I5 A" J* O% n+ y) Z8 v7 [ - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
$ f9 r( p, D. { - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;( k/ z- }) M8 v' A. I/ O2 g
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO7 o9 i! b& n4 Q
' S- n2 t( O2 H& q" H/ u& x# Z/ [- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
: B0 H3 X& Z9 { - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
. W' [3 o3 y& L- f0 |' w - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;" n! @( t& p6 Z0 l% N9 B6 k3 u4 `
- GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIO
3 D6 U; |% N+ d( j% l9 I2 F0 i -
7 Y! ^* S( F" o' l - //初始化TIM3
4 N% S/ o; y. J, U - TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
t' ~, @, E3 E. I: ] - TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 1 }# i1 h4 j+ i( v
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
b9 M+ ~& |, G8 b3 P - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式9 H9 e( x3 S* t7 p
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位- h$ s' n: G* Q$ a% E/ v% n
-
1 L! p& M; M4 \5 c4 k - //初始化TIM3 Channel2 PWM模式 6 {! U- y1 t* S, ?* w3 b
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式24 Z- S. m* _4 R& W
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能3 d c4 X' Z. x% Y& G6 {
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
" m, q% Z; @+ r k - TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2
* S- A, p& o# m - 9 ] p+ k; {$ S4 s/ X/ b
- TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器
3 p7 ?0 \0 k) n - , a: T8 j: R! M% N# Q- d# a0 ~
- TIM_Cmd(TIM3, ENABLE); //使能TIM3/ R! A" q8 ^7 J z, R
- }
复制代码
' 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
- #ifndef __EXTI_H
. w; Z6 u# b8 J - #define __EXIT_H l( K2 X* R- _& N# Z
- #include "sys.h"
1 j4 c% l7 G0 N6 a - # V! t8 B. ?" A" W' u, A
- void EXTIX_Init(void);//外部中断初始化 ( k& n2 @" s' J" _$ u# k1 ?( L
- #endif
复制代码
; [- o/ o ^5 d: d3 Z1 _7 qexti.c
, r, _ _9 C" h1 O0 {2 f9 w7 t* t" _
- #include "exti.h"
) u3 x: Q+ n( y, F& o - #include "led.h"
/ L/ n9 y! @4 K4 {: j/ }. Z4 r - #include "key.h"7 h- [. x1 Z/ x3 X2 T9 O' R+ H
- #include "delay.h"
. V3 s2 a; B' I. { V1 L- L& m - #include "usart.h"0 W+ K$ G$ f0 _& Y: k2 D& J: Z" G
- #include "beep.h"
+ P) X: H! U% p+ i5 [% c2 T
6 |/ [7 t# d% r. n8 C' u- void EXTIX_Init(void)1 ~0 B* s" `4 J8 T) W9 ~! i
- {
; ^7 v! H! J% A7 r" ~7 r+ U
$ V O+ I1 G& j% q' Y; H- EXTI_InitTypeDef EXTI_InitStructure;
) L; P% n5 K3 i, g- \+ p) D) d! Y0 [4 | - NVIC_InitTypeDef NVIC_InitStructure;
. u- m* t7 F6 x ?- u - 2 V# k- @* l3 @2 o6 a# K, F
- KEY_Init(); // 按键端口初始化# h+ D5 s) y$ L6 G) V" }
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟1 u4 g. E6 s' z+ g; O, h
8 E$ {8 D- {* H% T- //GPIOE.3 中断线以及中断初始化配置 下降沿触发 //KEY1
, ^; y+ q$ V4 u8 P8 V8 S7 y% m: Q - GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
2 V- ~$ l h$ O1 P! u; f1 g4 B - EXTI_InitStructure.EXTI_Line=EXTI_Line3; u8 A4 W7 B: T( h
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 4 o+ w9 U! U1 R# }& S: w
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
& T" N% G! r% S# { - EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器( {- ^( y/ w& `' H
- 9 [& R. i4 W. ~, ?( g
- //GPIOE.4 中断线以及中断初始化配置 下降沿触发 //KEY05 w/ k0 _( { x" r7 S
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
$ X8 M; [; `3 }5 s, b. c* d - EXTI_InitStructure.EXTI_Line=EXTI_Line4;
! [- r5 }7 y5 Y* O: `; } - EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
S; h! n& b$ ^/ C/ c9 S. I' |* B8 Z - 7 h& `2 a7 R/ j3 |- l7 @
- 1 g# @& m" a |. \5 |
- //GPIOA.0 中断线以及中断初始化配置 上升沿触发 PA0 WK_UP
- D" | O* y7 v0 D$ M, j+ x - GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
7 c A- B8 x7 ^2 b1 R0 D: b
2 @% X" X$ x, ~) h- EXTI_InitStructure.EXTI_Line=EXTI_Line0;
' ~3 `4 Q V( a0 O4 d: \: q, E - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; Z% G) X* r6 G7 W% ~
- EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
+ w$ s% V8 R8 j. q
% B6 r7 x/ ^9 w% D' k0 I: ^
) V" o& o8 H) h8 s4 M' P- NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键WK_UP所在的外部中断通道6 X9 |; a2 @, U6 X+ u
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, , Z5 M- u1 \# |8 L" a
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级3- `: p( U, U. v" @; l
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 @6 v S. g2 ?! d/ | G( B6 B
- NVIC_Init(&NVIC_InitStructure);
t2 X* u$ x5 o/ }: K! h - : n2 t, s' o: ?5 t% l x( D
- NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //使能按键KEY1所在的外部中断通道% g- F/ G) s, }
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2
% ?9 e. A' s) ]- W' y' b9 q2 ?" C - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1 9 `$ K- K6 g* N$ V* ^( x7 F
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
' \0 s! P* b L: }2 x$ t8 o! Z: z) N- V - NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
7 N/ D2 a# S1 K( a4 t C } - + _. n' R& ?) y9 A# O7 }1 ^
- NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //使能按键KEY0所在的外部中断通道
# ^( U0 l1 s! Y! n. p- D' R2 } - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2 + ]" [2 L$ a5 }6 B% z
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级0 % f. }- e% `* y# t9 L/ h" v( [
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
' ]9 J( o$ y. [. q" c. J) Z9 K - NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器; L, J) {" a" B, M! @3 ]$ h" n9 t
& B8 q4 `1 X; N- }/ B8 b/ C- ]4 P
- //外部中断0服务程序 4 t5 r2 X* a0 A. k% U
- void EXTI0_IRQHandler(void)//亮度最亮
8 ]2 e6 b1 E) X) `- |. Q. H - {# L2 u0 l% k! a/ f: {, D
- delay_ms(10);//消抖
# b3 I9 p: h; C- |+ D - if(WK_UP==1) //WK_UP按键: }5 |: v: i+ V
- { # i! ?0 Z m( R, @) }5 S- g$ `
- for(i = 0;i<10;i++)8 A& \, L; r6 l6 X' u( |% Q& S+ |
- {
0 n8 k) U O5 J( D - for(i = 0;i<20;i++)* q5 q7 I$ j4 P. {
- {
+ M" i6 d$ f5 j - TIM_SetCompare2(TIM3,frequency);3 i" i/ A3 |( _
- frequency++;. b0 `# p+ `7 }- B/ d: [' v) s7 P
- delay_ms(DELAYMIN);
! h2 h3 h* C: V: b7 h. t* I7 E - }
7 a7 P \ _' w. s; F: E, d - for(i = 0;i<20;i++)% J1 f5 H+ ~3 s) d
- {
* f* g: O6 P( n, Q/ H - TIM_SetCompare2(TIM3,frequency);4 q: Q; T' S2 v/ A2 ~1 q/ ]
- frequency--;) d$ g* z3 y/ l' L( r
- delay_ms(DELAYMIN);; f; c" G" ^ C' v/ v x5 g* t- u2 n
- }8 i8 `. ]: f8 t3 {1 m \
- } ' Z- a1 I9 T& @: }) P9 U1 Q; f% c' Y
- delay_ms(1000); 2 @8 ], U( K" N0 d+ P+ P
- }2 R- A/ H _8 B) W/ b/ o8 F% Q$ |
- EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位 ! b3 R: B7 y" E. C
- }. D: x# S3 B2 y- E
- //外部中断3服务程序
; f' v/ z' u8 v& L, \ - void EXTI3_IRQHandler(void)//亮度
: f0 P$ k; s/ c% {% q0 ? - {
6 k( S, N! ^0 ], B# Y - delay_ms(10);//消抖# H. X4 l1 k. I) C: k: x$ ]
- if(KEY1==0) //按键KEY1
! S$ n, w/ s/ q6 y - {
7 q5 k) f1 b: ~. i: D; t - for(i = 0;i<10;i++)
5 {( `0 C3 C0 J - {1 B7 l9 y4 c8 }1 `
- for(i = 0;i<20;i++)
& c; n: \% Y& x1 w) h - {
1 u, @! ?, Z6 Q+ @6 E$ e7 C - TIM_SetCompare2(TIM3,frequency);
2 v3 }+ ~/ f6 I5 N4 M' f: h - frequency++;3 ?/ m% W7 l% I2 h. A% h
- delay_ms(DELAYMIN);- V4 z5 N7 _4 ?7 \. P W+ a/ S8 N9 G
- }. X2 B+ a# Z8 i* K2 u7 T4 M5 w
- for(i = 0;i<20;i++)
' m( a8 t* }$ S) ~ - {
1 m) t. Q9 g" _% Z% w. t A - TIM_SetCompare2(TIM3,frequency);- o/ W9 b. A. ~" Q
- frequency--;
! J6 i! i2 [# k: ~) p - delay_ms(DELAYMIN);
) ^" m1 {9 o. P2 d$ k - }
2 ?1 q# T. l; x/ o - } ) y. l. V- R) J+ I
- delay_ms(1000); 1 k& z( w2 m: v9 P) ~% r
- }
. C1 e$ I; e2 W( M) S - EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志位 % F7 x6 r8 o" R& g: _ G% S
- }) {$ `: t3 c Q0 t6 t3 W
- void EXTI4_IRQHandler(void)//亮度在中间; a7 J6 Q1 x1 e/ ?
- {7 o0 A* r7 H7 h3 w
- delay_ms(10);//消抖
. [ v |1 V/ r/ Q6 a" B: |( o - if(KEY0==0) //按键KEY0
# Z! c) f8 w$ |2 b P7 B; C0 I6 _" E7 A - {% r* R) B+ M# i/ {" O
- for(i = 0;i<10;i++)% e1 s: M6 s" N4 f+ p) E# K/ O0 H
- {
4 n) t1 l' s3 F4 I - for(i = 0;i<20;i++)# n! a6 z$ k$ h& q; Z
- { H K* o: g+ [
- TIM_SetCompare2(TIM3,frequency);0 t$ W" J; r2 W
- frequency++;: ^' n8 l+ l% _4 A
- delay_ms(DELAYMIN);& h2 p4 T) n& y. O# @
- }3 x# q; h: k. Q; E! k3 f
- for(i = 0;i<20;i++)' G0 w, ^- Y# @; h# F O
- {
- C: }: I$ i0 D7 F - TIM_SetCompare2(TIM3,frequency);
. A" }$ }5 d* K# ?* r0 e( k) } - frequency--;( X) B7 g( V' w1 x( p( j
- delay_ms(DELAYMIN);- ~3 z$ V+ X, W3 g# J9 L
- }
# a# V* a# k5 A2 D - } : m+ J( {1 A' R3 E6 M; r. c
- delay_ms(1000); - b4 R9 I6 c, ^. U
- }
C) N, o9 {% h+ z1 g - EXTI_ClearITPendingBit(EXTI_Line4); //清除LINE4上的中断标志位
3 I6 A/ H! _2 d) N2 k i - }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
- #ifndef __KEY_H
- ?. V8 L- ~" W+ J" B( }" ~2 }: r - #define __KEY_H / q7 j# B1 ]4 }) V
- #include "sys.h" + P* S" S7 H3 F) ~' b
- / M5 i6 X" v7 Z- w& y: d
- #define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0+ Q. B8 T- B' k' V/ I9 m0 |; Z" \
- #define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1
: @. Z* h" V; \* ]& [7 X - #define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP) 2 m7 r4 h! G9 W- R, m7 v; L
- , N' h" A9 K u8 j; E. Z
- #define KEY0_PRES 1 //KEY0按下5 j- R5 j" @, U- v9 f) d* i; u
- #define KEY1_PRES 2 //KEY1按下. t: d0 S% f: F+ C. l- a/ \% ^
- #define WKUP_PRES 3 //KEY_UP按下(即WK_UP/KEY_UP)
4 R- n1 b, F% Q; z7 ?+ E4 {0 p# O! M - ) H" S4 I- _" D3 F9 L
- void KEY_Init(void);//IO初始化* f" B d5 M3 S6 C8 v/ A
- u8 KEY_Scan(u8); //按键扫描函数
! b9 K$ `& y8 U - #endif
复制代码
4 m" x% l0 p: s% o$ w+ y. Lkey.c
: A% M. x: ~+ H" ]) y8 Y9 c& w% B$ G9 Q. ]
- #include "stm32f10x.h"
( m; v$ c1 G' H M - #include "key.h"
# |! k! F, s6 l3 k2 k1 N - #include "sys.h"
/ [$ j7 z0 r" ~& g7 z" S0 F) e - #include "delay.h"
) \9 e1 }/ R' Z6 I8 o/ ]* }; Y -
3 L2 y. `7 R; g2 c$ _! ~ - //按键初始化函数5 R4 E6 B8 ?- k7 L7 T$ x9 O
- void KEY_Init(void) //IO初始化
, [ H, Q! c/ h' q* [ - { " R5 {! O# a5 T1 z* }
- GPIO_InitTypeDef GPIO_InitStructure;: a7 I5 Y n+ K2 Z# z( I
- - B6 e7 w F8 Z$ N, S2 F) m+ I2 T
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟
9 A/ [# S5 k( Z/ g7 w - 2 g3 U/ ?9 {3 n7 Q) R
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_3;//KEY0-KEY1
3 f: Z+ e; d' c - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入. ?3 `" h# Y6 R7 W0 t% m4 T
- GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE4,3
/ e& w2 Z4 y, j9 M. e
# } }( \" `# _" N- //初始化 WK_UP-->GPIOA.0 下拉输入
$ o2 f+ ?% `2 Z" ^" d: | - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
. N& L# j+ m$ M5 @# J - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉
; ~5 x; a& I- P2 r) o - GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0
" Y0 _' N' a- _ - }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- #ifndef __SYS_H. {% N, q- |/ _# l! [2 C
- #define __SYS_H 8 w2 U& \& C3 a7 ?, k. n+ C+ d0 x
- #include "stm32f10x.h"2 ~5 K' ]" G' k
2 E& B* n9 ?! }2 n6 Z5 A9 D+ a- //0,不支持ucos
: @$ D. k6 d# O - //1,支持ucos% r9 `1 I9 L! i1 N/ @( C- G
- #define SYSTEM_SUPPORT_OS 0 //定义系统文件夹是否支持UCOS
8 B7 l) o( N* ?7 G6 [& c - " U# N* c4 W- k- |6 N* u. h$ d
- ( s5 f* Y9 P# G% w5 y, j) v
- //位带操作,实现51类似的GPIO控制功能" a8 l' m" _$ Q+ p2 i# B% W
- //具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
" g3 ~: q! f$ A$ V- |2 g - //IO口操作宏定义
' x6 M7 j8 d# h8 ]- z# Q - #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) $ G. P- ~0 U7 D
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) 0 m5 K! |6 c' W; n0 l
- #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) 1 w1 O) S$ f T. B. Y
- //IO口地址映射# s+ j7 L9 A2 ^3 i' p3 A
- #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
. |, @( g7 n0 v/ U - #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
+ D, n: p8 S- P6 s: {( j- Y/ w: | - #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C $ s0 h: ^+ ` \. Y4 H
- #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
- ~) }2 O0 A5 S1 Q+ n! \, O7 O - #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C 2 H8 S5 P9 }& Z/ i4 t5 t
- #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
# x! J* q' \: }3 Y$ _) y - #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C , p2 U) A. S% M
) R7 |; w+ c7 i( B- #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 $ p2 D% w0 [8 c \- j: A
- #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
' b: `# h- i* j# `4 _" x2 @ X7 M - #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
8 E8 A5 ^( J7 K) ^. w - #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
$ B- R7 g% K8 k. f6 G3 |# ? - #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 5 O, P7 h$ J9 X i% v# X/ h
- #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 ( ]) s4 f! C# j/ V! r- U
- #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 4 u0 q; k* g' K+ R; S& n- D9 R
9 a1 d3 k I3 e) t6 L! d. \- //IO口操作,只对单一的IO口!% @: L& p. Y2 A2 a. Y
- //确保n的值小于16!
. w) B' Q. P h! u - #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
+ f( A: ?( W: ?+ w6 [* T - #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 ) ^ |7 O. ]6 B( }( ?0 A* [
, H. e/ o7 q+ x) ~' X$ ]8 ~- #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出 " k; ?1 p2 @8 w9 Y- t
- #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
2 w2 W* s( e! M
+ R- o3 H1 P; P8 ~ v# \- #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出 ' U' v: `( t) h& {& N+ ]8 M/ z
- #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 1 Y$ J2 x( v/ \0 S0 O
0 s: [" R7 o# G1 }1 s- #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出 ; k. d0 o+ O8 h) k* H
- #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 $ B6 p* L5 R5 D) [' v
5 R/ ^* V1 x- B* U/ S" h# Y- #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
$ g5 B6 r& J* o" Y1 G - #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
* m: {) R5 t1 f4 G% K* |9 d5 j
* p1 @0 y/ V6 w6 h. w- #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出 - t$ @6 I" \& z$ w0 p; S1 U$ w
- #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入# q) l( G- y) t/ `1 L
9 G* @. [" G9 a, K- #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出 % e- u; P0 }8 k. O$ L2 d |; r0 ~
- #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入% U/ y& s: ]. b' i `: ^
- 0 P% v9 g& y+ V9 e. _% t& i2 N/ d
- //以下为汇编函数
- i$ `; U8 e/ d. }8 Q& l - void WFI_SET(void); //执行WFI指令% P8 J+ n. M S- d9 j
- void INTX_DISABLE(void);//关闭所有中断
2 n/ f* M0 |6 @8 M" n, s - void INTX_ENABLE(void); //开启所有中断! [2 r/ `% M% m$ O" n
- void MSR_MSP(u32 addr); //设置堆栈地址" G/ X9 ?* X% F: d$ s
: v T- H9 |- d8 Y. _' W" }! u; Z- #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
- #include "sys.h"
! N( d3 m+ n9 K7 a
8 @/ w; C3 A. |+ B- //THUMB指令不支持汇编内联- s" o- E; A2 B8 ~9 O. R. \' C
- //采用如下方法实现执行汇编指令WFI 1 P7 j- D% o9 } N0 [# l9 m; [' I
- void WFI_SET(void)
$ k d9 u5 }8 {3 Z ^1 y5 c - {
9 T' X, ]& B7 C - __ASM volatile("wfi");
$ r" h! C0 z- |. r - }
7 _# x$ X# ~& w/ U - //关闭所有中断5 ~: h$ r2 }% w# X3 z
- void INTX_DISABLE(void)) e1 B3 ^- ]" f6 _# c
- { 5 r, e) R8 a: F) c
- __ASM volatile("cpsid i");
5 Q0 `. v, M. {/ ~7 ^+ w& B, Q& Z - }' H; C1 E' ^( Z' z }' J' j
- //开启所有中断, a' w* V8 e, D' G$ t
- void INTX_ENABLE(void)
5 h: r9 R& q/ A. O U - {; O1 z5 _; c4 J( C- |
- __ASM volatile("cpsie i"); O. r+ D2 b$ C% v4 \* L
- }
+ p: H5 ^& D4 b4 `. x1 x0 O f - //设置栈顶地址
3 c( M7 K3 E/ m1 ? - //addr:栈顶地址( J; s |$ c- [
- __asm void MSR_MSP(u32 addr)
/ ^( Q2 a1 j/ {9 Y - {& \+ H- C2 D$ y3 L3 `0 T6 Z
- MSR MSP, r0 //set Main Stack value
) w7 b7 o: N; W% |. B - BX r14
, S0 a' T7 l# a8 ]; B5 h - }! 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- #ifndef __DELAY_H
( d% n; P! D- [: @* h - #define __DELAY_H " K4 G: Z7 }. m2 c8 a K, H
- #include "sys.h"
1 A$ j3 S( Y+ e5 L -
* s# a7 N: V2 S; s' r% n - void delay_init(void);
( ?( q/ \4 c% ?- K- Z8 J - void delay_ms(u16 nms);, e+ I/ \# H; X9 Q2 L/ p5 m' U' O
- void delay_us(u32 nus);( R& x7 n9 t, U1 C4 e
; M$ `4 j" f- Q/ _6 s/ X- #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- #include "delay.h"
6 ^+ ] R+ c9 Z R' b+ L% K - // 9 P* v2 m# }5 m! j7 P
- //如果需要使用OS,则包括下面的头文件即可.* ^3 H3 _+ ~/ Y& K5 z' G; `% E
- #if SYSTEM_SUPPORT_OS7 w H+ ^+ h4 o
- #include "includes.h" //ucos 使用
2 a% _- o# _1 z9 W) W$ L3 d5 R - #endif
; [+ ]9 N3 Q, y4 X2 K& e( ]
2 B) a7 @/ l' f5 Z0 Z# p0 ?- static u8 fac_us=0; //us延时倍乘数 ) f4 q9 X: d/ N9 z1 [. @
- static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数/ n5 `$ U9 s5 b% K
-
% r3 n/ R* u; v/ E' V -
! K6 a5 i* N6 v$ p6 ?# @ - #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).) }( B6 h7 v) w
- //当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
5 G# a& R2 K; c, n; U - //首先是3个宏定义:, d% a L$ s2 T4 w. ^
- // delay_osrunning:用于表示OS当前是否正在运行,以决定是否可以使用相关函数: x9 M& `2 K1 V6 b
- //delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始哈systick' W) e" W# U: l2 p& ?
- // delay_osintnesting:用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行+ n5 o1 o+ ?4 j4 [8 P: F( I8 l
- //然后是3个函数:
( }0 |3 X0 w: b/ p' j3 n- O" f/ v - // delay_osschedlock:用于锁定OS任务调度,禁止调度
; a; W/ ~2 y# V7 Z% F' B& y7 v - //delay_osschedunlock:用于解锁OS任务调度,重新开启调度* A7 n1 d& a8 X
- // delay_ostimedly:用于OS延时,可以引起任务调度. z3 n+ s0 U# R8 D# ?' S
- / B& r& A* b$ k- k- F- F& B
- //本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考着移植
+ M( ~" \5 Z! R3 \8 P - //支持UCOSII" @" ?1 z3 ?3 h" ~% e
- #ifdef OS_CRITICAL_METHOD //OS_CRITICAL_METHOD定义了,说明要支持UCOSII ! H8 C3 }- {; ?! Y* _
- #define delay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行9 H' @5 |, N' b t0 m' z/ |# j
- #define delay_ostickspersec OS_TICKS_PER_SEC //OS时钟节拍,即每秒调度次数+ O9 s/ o6 n& a- U5 |. V
- #define delay_osintnesting OSIntNesting //中断嵌套级别,即中断嵌套次数' @. Q- E0 X4 A1 Q$ e3 C5 y8 X
- #endif. w- p* }+ R$ \& x
- 6 r5 c) N2 d, h: D7 R
- //支持UCOSIII
* j8 A* W% W) O3 R% R. D - #ifdef CPU_CFG_CRITICAL_METHOD //CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII + D, H0 p; K" d
- #define delay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行
, b9 z- Q {# H6 X# U. Z - #define delay_ostickspersec OSCfg_TickRate_Hz //OS时钟节拍,即每秒调度次数
8 k3 j. P$ R+ v+ @ - #define delay_osintnesting OSIntNestingCtr //中断嵌套级别,即中断嵌套次数
5 M& U# R# F- V - #endif
! Z( x `0 H: F% u* t. | - 3 ~5 ~6 v$ _& F5 u& U) v
3 h! a' ^2 |- y7 C9 j- //us级延时时,关闭任务调度(防止打断us级延迟) o5 I. L V r
- void delay_osschedlock(void)
/ }1 x, @. o2 s( n# T) a - {
$ G$ Z' G; m" v% j6 I8 a0 d( o - #ifdef CPU_CFG_CRITICAL_METHOD //使用UCOSIII5 K/ y8 [. m: U1 {: f1 N+ h, x
- OS_ERR err; ; F t. O- [: A* T# r9 ~: q) M1 A
- OSSchedLock(&err); //UCOSIII的方式,禁止调度,防止打断us延时' @5 L' _( W% \, S0 h& s4 P
- #else //否则UCOSII
% E7 i) f* {5 i! S/ d w - OSSchedLock(); //UCOSII的方式,禁止调度,防止打断us延时
* i# H! _& S, \3 F: x3 u/ v5 x9 F - #endif
K: A1 t' |2 l7 Q( q8 o1 W) W) c# ~) d - }6 n( p2 ]: }3 M8 Y c$ w Y
$ k$ u. G7 |5 v! {9 e# \2 T; j- //us级延时时,恢复任务调度
* X- ]. \3 t4 Q8 s - void delay_osschedunlock(void)
6 b) R5 o4 U K- E3 d - {
' S: J, \% m! U, ^4 i - #ifdef CPU_CFG_CRITICAL_METHOD //使用UCOSIII
2 g/ H- y5 z9 f$ `" g0 x# W% } - OS_ERR err; + x; w( o2 _) B) i6 }
- OSSchedUnlock(&err); //UCOSIII的方式,恢复调度, X9 d; S1 @0 m7 ]2 J
- #else //否则UCOSII
) X4 o& m S9 \* E* @6 _9 D - OSSchedUnlock(); //UCOSII的方式,恢复调度
/ P: @& _$ L. F' ^ - #endif4 R, W: _; M1 B7 ?' I5 |. e
- }
( m7 q& C" U) q9 z
" E1 s* }, N, P8 k- //调用OS自带的延时函数延时3 c0 S6 C+ X2 E4 D" T
- //ticks:延时的节拍数# f) x9 \7 K1 m
- void delay_ostimedly(u32 ticks)
8 F+ V5 ~3 T$ K4 L - {! k9 u- L* E6 |/ |% A
- #ifdef CPU_CFG_CRITICAL_METHOD
) n+ O1 _, z8 {. C8 T+ r- s- w - OS_ERR err; 9 G6 l% H; i) `
- OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err); //UCOSIII延时采用周期模式
( F* _) z( z9 H/ J! b - #else
0 ^. _6 `$ x) w" v; a7 W& r - OSTimeDly(ticks); //UCOSII延时
6 M( _/ N- m5 k+ M# n - #endif
) e7 n: i; y F9 m0 D" B - }
; k O/ g" ~7 c: V, Z
- |0 D# Y9 X8 B% X* u- //systick中断服务函数,使用ucos时用到+ U2 g7 p: O, @7 a
- void SysTick_Handler(void)$ B! }8 n( }6 T$ M1 @2 S0 C
- {
. \" E: Q/ y- f; | l+ z, Y" W - if(delay_osrunning==1) //OS开始跑了,才执行正常的调度处理2 J2 j' h4 y4 S
- {+ t( l* k. k5 Q' |
- OSIntEnter(); //进入中断2 I b9 r7 m% v+ {& e( Z' `
- OSTimeTick(); //调用ucos的时钟服务程序 1 b$ f' `9 `8 O% m7 A/ J7 a
- OSIntExit(); //触发任务切换软中断: ?4 D/ ]4 J, M( U) \; Q. [
- }1 Q6 M* C' S z% X0 g
- }6 w$ p" z; G5 D) ~+ R# t+ K
- #endif- P; q- o: \2 B9 i
2 T& v; r% e( j2 _ [% t- //初始化延迟函数9 i( i6 _5 w: u* Z' R
- //当使用OS的时候,此函数会初始化OS的时钟节拍
! b/ N# W8 \& v; A - //SYSTICK的时钟固定为HCLK时钟的1/8: k- I! u. Q2 X: Q
- //SYSCLK:系统时钟4 l) s2 p4 R O; T: Z; ?" P! f
- void delay_init()& B& ? }- @* i# O5 F+ m
- {$ z. w! x1 u; }' K. ?( U
- #if SYSTEM_SUPPORT_OS //如果需要支持OS.! A; }( U$ R2 |8 Y3 P# Y2 q7 g" L
- u32 reload;8 q% `* D8 R3 N$ Q7 }
- #endif4 j. d* u* {9 C
- SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8! h6 z) ]) K% D5 g/ W, ^
- fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
3 _( J a5 J0 \ - #if SYSTEM_SUPPORT_OS //如果需要支持OS.
/ K" |3 X+ l8 I @) S, M3 ^ - reload=SystemCoreClock/8000000; //每秒钟的计数次数 单位为K * e. i9 Y* @% P6 b
- reload*=1000000/delay_ostickspersec; //根据delay_ostickspersec设定溢出时间* n2 M5 Z" K# Q
- //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
& H8 E8 Y. r- n/ x - fac_ms=1000/delay_ostickspersec; //代表OS可以延时的最少单位
4 f4 a, n! n; B4 A% s) K - 4 K8 K5 x7 a' r; f( k5 l
- SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
8 u! Q4 N: u2 e3 j [) I - SysTick->LOAD=reload; //每1/delay_ostickspersec秒中断一次 # C ]/ ~; ?' }6 L0 o+ V
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK , q4 N7 H+ }# g4 F; A
- / u0 ]- [5 v. o$ M4 r8 |
- #else
9 Z6 o8 N# m8 ]2 e+ a - fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
0 P% @" o* W$ K - #endif$ o5 \) @1 H. G- l. D4 k$ R
- } 3 {. o5 j( ~( @1 R7 E1 O4 T/ r
b a s5 ? n1 N; c& `5 j- #if SYSTEM_SUPPORT_OS //如果需要支持OS.
# `& }6 D7 f0 N# b - //延时nus
$ o! b0 i [3 l+ K9 A* f - //nus为要延时的us数. ' I' D# J% H: P
- void delay_us(u32 nus)
% d$ K U% i6 j W+ e9 o - {
0 T8 t7 C% s2 S8 o0 V8 L1 @ - u32 ticks;
* L: N2 O: K; V! _) Q - u32 told,tnow,tcnt=0;' X6 w3 v5 c' a Y
- u32 reload=SysTick->LOAD; //LOAD的值 $ x# i6 |% ~ w( r1 h8 \
- ticks=nus*fac_us; //需要的节拍数 7 {! O5 h) N; k+ }1 a; L
- tcnt=0;. @1 e2 P+ h7 o$ m
- delay_osschedlock(); //阻止OS调度,防止打断us延时
" V- Q/ D$ O+ ^0 O1 j2 }$ x8 S7 T - told=SysTick->VAL; //刚进入时的计数器值
* Y( A; w3 V+ n' H6 t3 o, Q/ } - while(1)9 e1 u' m: q4 U" _, \* L5 o$ `
- {5 i/ l6 R( |0 W. W9 y' n
- tnow=SysTick->VAL;
/ [' }8 @! _' [' [! G+ \ - if(tnow!=told)
- ]% p9 x3 q+ S - { j1 B8 W* d: \0 G
- if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
; T. t0 k2 R' ?' r- U/ L$ a# Z1 f9 C - else tcnt+=reload-tnow+told; 5 D6 f$ [$ h9 ?7 W5 b7 P7 d
- told=tnow;
. V# p+ ~. R* C/ O: K9 _ - if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.2 v! P5 b: V8 ~; C& I w
- } ; b# e! p! M3 D$ g3 o
- };8 `8 J) h1 G% @
- delay_osschedunlock(); //恢复OS调度
. g1 l1 d6 }0 B6 g) G* T - }
% n% N0 l$ D& e/ f - //延时nms" g' R( O6 W0 w) U6 Q2 V
- //nms:要延时的ms数
~. m/ V& Y. Y, o: L1 y% | T - void delay_ms(u16 nms)
W6 }. E4 |. B5 b/ K) W - { . D8 s! f! t" D+ o+ i8 Y
- if(delay_osrunning&&delay_osintnesting==0) //如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)
. d( \& F3 P, h - {
; N% K2 ]! [4 T* y - if(nms>=fac_ms) //延时的时间大于OS的最少时间周期 6 @2 h: e/ [; s k4 s, I/ X
- {
7 J# l9 h6 F' e4 ~! q4 b - delay_ostimedly(nms/fac_ms); //OS延时
4 |# d& @3 g( p ~" J9 n& x' Q9 t - }
# n: f: H: Y4 P/ [ - nms%=fac_ms; //OS已经无法提供这么小的延时了,采用普通方式延时 ( F' J1 W& J( L8 i( t2 }
- }7 S7 [; L1 ], d* }
- delay_us((u32)(nms*1000)); //普通方式延时 % p8 ]1 G, ^- B* o6 R/ v% I0 H! X
- }9 z) w% A" T: N3 y9 W
- #else //不用OS时
# X+ d# f8 \; }( W7 z - //延时nus7 B, L! f9 q7 F* T
- //nus为要延时的us数.
3 H6 c a- j' u5 `# P$ K - void delay_us(u32 nus)+ C: B( @4 Z# X5 D) g1 b
- {
- K( z' b- W/ m0 ~ o# c - u32 temp;
3 Q. b1 ?6 b% l - SysTick->LOAD=nus*fac_us; //时间加载
6 u5 ~* p3 ?' J% z0 G - SysTick->VAL=0x00; //清空计数器* o' H; o! Y% {' U. B2 s$ g1 A
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
8 U3 N2 D8 v3 G5 f! w: C - do
7 \$ e, Q3 y" k/ {" X - {
: {1 R' N8 }+ s" s - temp=SysTick->CTRL;5 ?) \4 d _7 T0 F6 x/ ^
- }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
4 a8 x# T4 r: m+ d! m3 c! p - SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器1 o2 w, m/ z L3 E3 T0 ]
- SysTick->VAL =0X00; //清空计数器 2 o5 F& r$ `# \! g9 M8 Z
- }: D& Y7 V6 M- w
- //延时nms( @, T4 l0 S$ O$ [* f6 e/ n% i6 ~
- //注意nms的范围: E" ~ Y1 j+ u" }: L& ?/ R: g& U
- //SysTick->LOAD为24位寄存器,所以,最大延时为: C. F0 o: {; u( Z- s5 c1 l
- //nms<=0xffffff*8*1000/SYSCLK+ V! S* ]: J) p G$ v+ E* P3 ^
- //SYSCLK单位为Hz,nms单位为ms# A0 J) [+ k8 k! x( K/ e" g1 @3 Q
- //对72M条件下,nms<=1864 0 F& n6 z' [) J- n7 {
- void delay_ms(u16 nms), X+ v, B2 O8 `6 r
- { * I" I' P$ U1 j4 j' a5 x* g w
- u32 temp; : f `, s6 q' Y3 p! x# h
- SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit); [, `" m1 F% U. l2 D M- I. u6 [
- SysTick->VAL =0x00; //清空计数器
2 w4 c+ C" z9 @% p& ]& E - SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
4 q. B! t0 q. g) l1 D* g+ R, M; m - do3 @5 M, C5 u5 H* F) T+ l
- {
4 C% Z8 y, N0 m4 {2 E0 Z+ X" l - temp=SysTick->CTRL;* N5 c$ h2 `* x/ k
- }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 - }9 c' ^/ d# K& c. U$ m) e- c* r
- SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器7 p7 N( m f* z6 D/ O3 y
- SysTick->VAL =0X00; //清空计数器
" ^, K3 }- \' b# N( o Q! z - }
% ?# c! s. v" K, q G8 y5 j - #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- #ifndef __USART_H
- V8 l* W, x* e - #define __USART_H4 \( x1 ?1 T' L
- #include "stdio.h"
- Q6 D- e4 \- V) S - #include "sys.h" ( i7 b8 j8 l! q# r: ~
- 7 L' \: n# q9 P$ Q
- #define USART_REC_LEN 200 //定义最大接收字节数 200: g7 x+ S0 a& W, u: u2 C6 s$ d
- #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
1 v: ?2 v7 H4 D/ ~ -
0 e$ k8 X) ^- b - extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 7 C1 L* H/ _, ?9 W) I( A
- extern u16 USART_RX_STA; //接收状态标记
9 D1 {8 E& }" S) a/ z# F - //如果想串口中断接收,请不要注释以下宏定义( x' w: T( g b# z* a2 O! L
- void uart_init(u32 bound);
8 ^. o3 M' X% o - #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- #include "sys.h"
4 y7 U( Q: v' c3 A - #include "usart.h"
8 ]1 o# M/ }( Z; b! m+ O! W! j2 h - // ' x, q* G. \% C2 g6 i( S
- //如果使用ucos,则包括下面的头文件即可.
& r+ R, e' o$ n8 T - #if SYSTEM_SUPPORT_OS
1 d# h. U- F9 o6 D6 |$ Q - #include "includes.h" //ucos 使用 % A' Y4 W- m2 H$ B- Q8 D5 y' E' [
- #endif
2 z( J9 B8 a* F4 B - 8 t" ]7 H$ a" R4 k5 y7 `
- //加入以下代码,支持printf函数,而不需要选择use MicroLIB
* o' }. ]* u; h+ ]& Z+ ? - #if 1
7 g! x, {7 B& b W7 z - #pragma import(__use_no_semihosting)
( | V& `0 N5 K) p# V6 c - //标准库需要的支持函数
9 h( f: x( N" N, E' W. e" b - struct __FILE
' F' y0 z- ]. `$ d' H* w9 m+ n* l; G' Y) \ - {
$ {4 x1 n7 V' m3 [ - int handle; 2 H( R% l) T0 h$ m' k
- s$ Q4 e8 }3 C
- }; . K3 m! y0 z) h# N" Z& ^
- S# h2 Z: S9 Q
- FILE __stdout; 3 d- K% l. O& }1 r5 h. l& r. F
- //定义_sys_exit()以避免使用半主机模式
# x9 z6 r- O( ]: ?+ I - void _sys_exit(int x) 6 \- z# x( K% f. _+ t
- {
+ d' X2 [) ^" } - x = x; 1 ~; O7 t* s1 B: ^7 q. z$ u/ f
- }
9 `6 E3 J3 C4 ~ - //重定义fputc函数
- `" y7 ?6 ?* W" ?. S& t' f - int fputc(int ch, FILE *f)
1 ?" e% k) ]# R' u& [, | - { & @: r) k8 f ]$ u7 h A& G
- while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 8 e% |1 |1 v# t
- USART1->DR = (u8) ch; ! x# w1 r y9 I' x# N# M# r. V
- return ch;- N. W! R- N( M5 ?0 A6 k, ]5 u
- }: X) v7 B& I, B! W
- #endif
" G( }* O+ g( d, w - 0 A1 Q h) Q2 D% u5 O! G
- /*使用microLib的方法*/8 m1 V+ [% a% J' Y* V3 P! j
- /*
/ F7 W4 n ?+ N; g- h( @6 S- ^+ B - int fputc(int ch, FILE *f) u2 m7 D& T d2 o7 u4 N
- {! _; D: L$ `4 W
- USART_SendData(USART1, (uint8_t) ch); @6 a' e, R$ F) U6 ]) U9 A5 ?# J
* H" m# s. G/ B( S! e/ l- while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} 0 u2 y2 ^, }5 M6 t
- 4 n* `* E- \' e; ?# y( R
- return ch;
D) p/ ?% t* [- V - }
$ X* S6 q3 @3 ~ U7 y - int GetKey (void) {
/ F; A7 R# M5 {, \9 f - * U, Z. E9 M: E5 ^$ Q. z- m4 b' n, O
- while (!(USART1->SR & USART_FLAG_RXNE));% f; e+ z, `2 b5 r0 C* H
8 T% Y& \8 o$ ^1 r9 ?9 ~- return ((int)(USART1->DR & 0x1FF));/ \) o" D: ~0 a8 k, e4 H
- }
( L3 d+ B P( D# N) \ - */- L5 ~' a: W) N
- : B3 U& l: P! Q) f5 O0 F7 x9 h
- #if EN_USART1_RX //如果使能了接收. C* G* H* ?4 j' T
- //串口1中断服务程序2 w+ X! \. r f, n
- //注意,读取USARTx->SR能避免莫名其妙的错误
0 J2 g, r& r' B6 F5 g - u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
- B1 j$ \) H; U/ t9 a2 L* t: R - //接收状态
( g: p9 U; _% i7 c! { - //bit15, 接收完成标志- `9 H9 C3 ?' Y8 v/ ^8 ^7 P
- //bit14, 接收到0x0d
! u' _5 F. G! _ - //bit13~0, 接收到的有效字节数目: v \5 O: M. j2 R
- u16 USART_RX_STA=0; //接收状态标记 ; n% s% A) l! ?7 ~
- . A: H4 e; K6 k/ g
- void uart_init(u32 bound){2 f5 C F+ f7 e
- //GPIO端口设置7 X# B& Z6 D! z% z& v8 k
- GPIO_InitTypeDef GPIO_InitStructure;3 o! q# ~) q b
- USART_InitTypeDef USART_InitStructure;
4 {6 }3 u$ R4 y7 {- }* X - NVIC_InitTypeDef NVIC_InitStructure;% B' C' ]8 L6 ~) P/ ~
-
/ F3 p. d8 m/ d" y' { - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
# M% e! a" H9 p4 ^) E - 8 Y5 S1 l' C$ @' N% R. J
- //USART1_TX GPIOA.9- K e6 p4 Q4 G' y+ I
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9' F9 A ~$ g' i, V' W- y) h
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;" J& M+ C& o9 u5 z; `* E I9 ~
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出5 t; H6 _4 S! ?7 j. E( q: L8 q
- GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9- G; R8 M; X; P) a( ^& ^
/ ^+ t3 n+ K0 W- //USART1_RX GPIOA.10初始化2 \* T2 f% L7 P" \/ t6 W/ p: }
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
6 A$ V& z+ i6 d. F% |' S& A# L - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
0 P) [$ k' m/ u! O& r; a - GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
& r4 D; s5 N: a8 L ~* t. A5 w
+ T) s; Q. ?2 V% j3 g) ^- //Usart1 NVIC 配置" Q7 Y- O: G2 W( d. a6 h) L3 H
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
4 j. g, w( V- J - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
2 V) \+ u/ b& P* y/ U9 ] - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3; _+ P( ]6 `. u& p
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能& f! V3 O. W7 I/ Z0 O1 A
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
V4 c+ v Q4 ~) {) G6 J$ a* H
5 i8 m6 \( y* w, f0 y: \( @4 K- //USART 初始化设置
, c/ ]( t5 o0 _: Z& u - 3 Z" v. M" s/ T$ x. y
- USART_InitStructure.USART_BaudRate = bound;//串口波特率6 S7 I6 c5 d, C; X- E
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
- u( L8 m1 d/ \. K2 N - USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位+ {* S) m1 B# c; ]: ~
- USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位+ X$ Y# m1 k: X! }. a) ^- t
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
+ d6 ~- _: n$ u4 I - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
& F5 E. A& E, C - , j2 A2 T' k: u$ c- V
- USART_Init(USART1, &USART_InitStructure); //初始化串口1
+ N/ f# S9 I: T - USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断0 v3 O7 z" @$ S1 E
- USART_Cmd(USART1, ENABLE); //使能串口1 7 H4 Z% r( z- ?; ?+ i4 q w
- }! Y- _) m( k6 v5 C0 Z7 g5 C/ p* }
- # [6 F8 c3 G: Z1 Z
- void USART1_IRQHandler(void) //串口1中断服务程序
/ i0 W' k1 E4 y% |, c* k* ]2 I - {
0 [8 m: {8 n+ `3 Y- U0 m - u8 Res;
) K. l G$ N( u Q6 u - #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
% g" ?, _# U& a - OSIntEnter(); 4 T; j4 I% n6 V9 v8 r4 U7 f4 t5 N
- #endif
; l4 ] Q8 |8 ]; z. U - if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
: U: k2 j7 n7 _9 V+ a, K) \( |0 q - {
: }2 n) R" \( K+ m - Res =USART_ReceiveData(USART1); //读取接收到的数据9 M( e: G+ m" C* w8 C5 F
-
8 i: N/ _0 M" v8 D; ` - if((USART_RX_STA&0x8000)==0)//接收未完成
+ E; \ ~( L5 I - {
( D7 D- r4 o1 M - if(USART_RX_STA&0x4000)//接收到了0x0d
# n& ^& T, }0 ? - {
+ v8 Z$ W8 n8 v - if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始! n4 t# _* ~: G8 F, v
- else USART_RX_STA|=0x8000; //接收完成了
; [$ j& N, ]" S& j - }
6 ?7 V6 Y8 [' O4 A* r8 n - else //还没收到0X0D) |- Q% g i$ w9 Z. K
- { G- T& X7 c8 ?8 V1 Y) H# i* c
- if(Res==0x0d)USART_RX_STA|=0x4000;
# c; _, ~8 h) i- y - else" k+ r1 r4 |1 [9 c
- {
7 B2 F8 `0 F& N. m# x - USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;& h' Z& G# r5 x; w- P" @$ C
- USART_RX_STA++;
' ?6 L* ~' `2 _$ G- X - if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
2 K7 {( `4 i' q( k/ b& R, f6 u - }
/ x6 y9 U% L- k0 ] - }
6 N: w M* n! w - } * M9 p3 P2 g) P
- } / _. U5 R4 r: h8 g q) w
- #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
1 Y2 h* |3 n7 a' I2 w9 ^) ] - OSIntExit(); 8 E4 l* t+ Q1 X5 }5 Y! f' ~
- #endif
1 n. r j. u% X) T - } ' l7 H# K4 O% r" p8 H: t* ~
- #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
|