这是一个综合的例子,演示了ADC模块、DMA模块和USART模块的基本使用。 我们在这里设置ADC为连续转换模式,常规转换序列中有两路转换通道,分别是ADC_CH10(PC0)和ADC_CH16(片内温度传感器)。因为 使用了自动多通道转换,数据的取出工作最适合使用DMA方式取出,so,我们在内存里开辟了一个u16 AD_Value[2]数组,并设置了相应的DMA模块,使ADC在每个通道转换结束后启动DMA传输,其缓冲区数据量为2个HalfWord,使两路通 道的转换结果自动的分别落到AD_Value[0]和AD_Value[1]中。 然后,在主函数里,就无需手动启动AD转换,等待转换结束,再取结果了。我们可以在主函数里随时取AD_Value中的数值,那里永远都是最新的AD转换结果。 如果我们定义一个更大的AD_Value数组,并调整DMA的传输数据量(BufferSize)可以实现AD结果的循环队列存储,从而可以进行各种数字滤波算法。 接着,取到转换结果后,根据V=(AD_Value/4096)*Vref+的公式可以算出相应通道的电压值,也可以根据 T(℃) = (1.43 - Vad)/34*10^(-6) + 25的算法,得到片内温度传感器的测量温度值了。 通过重新定义putchar函数,及包含"stdio.h"头文件,我们可以方便的使用标准C的库函数printf(),实现串口通信。 相关的官方例程,可以参考FWLib V2.0的ADC\ADC1_DMA和USART\printf两个目录下的代码。本代码例子是基于万利199的开发板EK-STM32F实现,CPU=STM32F103VBT6 % q/ T8 m7 P1 U% V
- 本文件实现ADC模块的基本功能 w1 @. C5 s, D% \/ `+ R$ y
- * 设置ADC1的常规转换序列包含CH10和CH16(片内温度传感器)' z+ l* N4 m# s# s0 S
- * 设置了连续转换模式,并使用DMA传输7 O3 [4 J, Z: o! \% d
- * AD转换值被放在了AD_Value[2]数组内,[0]保存CH0结果,[1]保存CH16结果8 r+ B; x- a( [# E7 ^( j
- * GetVolt函数计算[0]的值对应的电压值(放大100倍,保留2位小数)
! ^* |1 {+ N+ L* g3 e - * GetTemp函数计算[1]的值对应的温度值,计算公式在相应函数内有说明
' E8 N, _- L, e4 b- ? - * 作者:jjldc(九九)
1 f/ X: r) T- v; D. A9 H u - *******************************************************************************/. Q8 f g+ E2 u3 y
- ! Z/ G4 |' K& ?* h
- /* Includes ------------------------------------------------------------------*/' K0 g1 j& U. L2 B( w
- #include "stm32f10x_lib.h"" d0 ^' ^4 B; }4 P/ ?6 s( w
- #include "stdio.h"0 z; M/ X9 a( a( C! N1 _8 m. Y
) J/ z; Y6 x& ^: ^, l- /* Private typedef -----------------------------------------------------------*/
' j0 H7 U# r# @/ _: X5 r# u) |' B/ o - /* Private define ------------------------------------------------------------*/
7 G8 ?" ~- A; V X! y - #define ADC1_DR_Address ((u32)0x4001244C)
9 a2 O% I' k3 Q - /* Private macro -------------------------------------------------------------*/
- P. G2 `: p' c/ ]' n - /* Private variables ---------------------------------------------------------*/( x# T9 }+ Z U0 t
- vu16 AD_Value[2];
' q2 `, k9 s" R" D. t4 `* @ - vu16 i=0;
/ \' K' w2 G" }% {% F - s16 Temp;, r+ m9 P( n6 S/ g" L$ m. ?
- u16 Volt;
$ h, Y0 t. N; b1 [3 t) S7 K2 ^ - ( q( o) w4 q E$ R" f" m
- /* Private function prototypes -----------------------------------------------*/
7 m* l" |' b: K* o( i - void RCC_Configuration(void);
5 o5 s( ~& E9 L9 J - void GPIO_Configuration(void);
! c, B x1 ~+ e* I. T - void NVIC_Configuration(void);$ R6 Y; L4 x8 q& h0 v C
- void USART1_Configuration(void);
2 P7 E- Y& B- U a5 n5 {3 b0 s% Q - void ADC1_Configuration(void);
" Q( B9 p4 e5 B9 _/ c9 V3 X - void DMA_Configuration(void);
. H9 M5 O" U' R! e$ s
& H* `: k1 n4 B- int fputc(int ch, FILE *f); f1 Z! J$ k# I' Z
- void Delay(void);. i" I0 ?2 r5 \& [8 d9 K. @
- u16 GetTemp(u16 advalue);' {; c9 f& ?6 b, h! a# a- l$ M
- u16 GetVolt(u16 advalue);
4 x. G# o+ ]; O - /* Private functions ---------------------------------------------------------*/+ B) q( M8 }' N2 u9 u
- /*******************************************************************************
$ M" C) w# l$ I5 I/ r* f* X- v- i - * Function Name : main
& F8 i9 t7 p3 }. D& B7 Q2 R) I - * Description : Main program.+ b, |! ]! d, w6 u2 q+ ]
- * Input : None' _7 y. u: j1 q: M* b
- * Output : None/ Z" \* _! b' ]
- * Return : None8 \; S1 w. H3 y0 \% r& l
- *******************************************************************************/! X4 a- j, ~1 V' |- a
- int main(void)
$ ?+ M1 l' g# q$ Y - {: x* \( k8 z. F+ u$ [6 S3 p* U1 F) c
- RCC_Configuration();
; J. Q) }2 `) ^& ]5 `0 Z! _5 e - GPIO_Configuration();
' z0 g& C. @% N+ I% ^) J - NVIC_Configuration();
7 a: f* c" ~. k% V/ v5 O) V- Y - USART1_Configuration();4 S4 u. m0 w& A' ^
- DMA_Configuration();5 s- K0 c/ |! m* `! O
- ADC1_Configuration();
0 u5 }$ N- ]+ x3 b- b2 j, W - * [/ @. N& L; [3 @" s% c% M5 k3 ]
- //启动第一次AD转换$ A) @6 y: v( ]: m. A9 Y
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);$ o+ F. X b! _. J2 B7 Q
- //因为已经配置好了DMA,接下来AD自动连续转换,结果自动保存在AD_Value处 + D$ N" _" b# N/ ^0 A
- , D4 B, t: @, o
- while (1)7 P( H) a5 o7 u. ?! P: l% u
- {
* v( N9 P8 s! K- e# D - Delay();
9 Y2 A6 Q, I: x& _2 Z2 W2 n - Temp = GetTemp(AD_Value[1]);
( H2 a7 m5 c$ m - Volt = GetVolt(AD_Value[0]);
6 f9 }1 c7 k% ?. X8 Q7 G* Q" ^* a - USART_SendData(USART1, 0x0c); //清屏
# A; o- o, X( l2 d, k( W2 s+ X4 U9 a - //注意,USART_SendData函数不检查是否发送完成
8 F8 }$ c" R( o: O$ @* I1 ~ - //等待发送完成/ T0 X. R0 T! R( ~/ H
- while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
- ]& G+ g; u0 C# l! r
& G$ r$ W5 T+ g( ~2 r- printf("电压:%d.%d\t温度:%d.%d℃\r\n", \) K2 E$ U7 k3 f$ b1 R, \# a
- Volt/100, Volt%100, Temp/100, Temp%100);
) P7 x5 x! F& D7 z - ) h; O H) e" n# S* h& P" f; o" F; i
- }* y; q0 U0 R0 l4 C" @1 |8 N9 ~. T
- }
; A `) A! H4 p& D9 ~5 @: ] - 0 t8 d6 `# k4 f
- /*******************************************************************************
% o N, V# T4 V0 E, K - * Function Name : 重定义系统putchar函数int fputc(int ch, FILE *f)7 A2 F Z. y% f" ]8 X% G
- * Description : 串口发一个字节 g0 E) p0 H, v0 R
- * Input : int ch, FILE *f
6 x8 H- {- h7 g1 l - * Output :# \' P. e3 ^' V% J- A5 m% \
- * Return : int ch2 W- a2 ^3 t4 z/ I5 J* m% Y$ m; V
- *******************************************************************************/: K; }6 }7 N! a! W2 ]* m
- int fputc(int ch, FILE *f)
9 q& J. J. M) @* n( }, D% ^ - {6 ~5 _! c( t& } \4 l, u
- //USART_SendData(USART1, (u8) ch);! ?# }' B$ ?' r4 q$ i: w7 I( z. ~: m
- USART1->DR = (u8) ch;" A4 ~4 B% |* p6 A4 K {( c
- ; `' [3 V, R3 a" I B1 Q
- /* Loop until the end of transmission */6 M& A+ R% [/ F% \# S
- while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)8 r" `. N0 \! w( t* z& U# f) ~
- {
7 W. p! W; y$ x2 A5 ~7 E3 j - }. y( F5 U L) {# ~1 d
- 1 w, u8 I. q) A0 W
- return ch;
5 [2 ?* h1 h9 R: {& y4 \ - }6 M# m+ Z" l5 B9 C7 T' C
3 }7 F4 l& S. [/ i* W- /*******************************************************************************+ T+ [5 T% A: i( Q t3 A0 X$ A
- * Function Name : Delay3 P8 }; ^% z& |/ @' q: {
- * Description : 延时函数6 }" X) {3 Q- B2 H% l
- * Input : None
( M! L/ G Q, p+ z) A - * Output : None
* f4 a/ O! `' y. j8 V/ ^ - * Return : None
$ |: B* c: W% s8 @+ S - *******************************************************************************/
5 l9 T2 S" w4 v: {2 o9 A& S - void Delay(void)1 V& @/ r& L# P
- {
1 y. I9 d, L5 y* z! x2 \1 ^- z - u32 i;
! l! {& Z0 }# {4 ] C1 f5 n - for(i=0;i<0x4f0000;i++);* A* ]" S W+ {
- return;, \2 K; X% I1 X3 e7 m
- }
% \* K$ f# r' S9 g* |# D
3 z! T$ B* o- Q7 M4 ~* \+ o. h: d- /*******************************************************************************
4 t( r* r0 {8 x/ k# H - * Function Name : GetTemp8 W( B# d9 w) f' ]
- * Description : 根据ADC结果计算温度
( u4 E ?0 U4 ]* X( E/ } - * Input : u16 advalue; q. A5 F" h& ?4 l0 I
- * Output :
! Y" L5 w4 K% S! ]# y - * Return : u16 temp( s4 S( r% T5 ~, s1 ~ r
- *******************************************************************************/
5 A. Q" v9 \" i! m6 Z) \ - u16 GetTemp(u16 advalue)3 \4 |! w0 A$ G4 _- J6 c' }7 H
- {$ U5 Y* |( g( K3 W4 T% d2 p
- u32 Vtemp_sensor;
/ ^- t9 \! R9 k2 f8 w7 N y$ Y. a - s32 Current_Temp;
- l* L/ Z0 Q9 e) L - 6 `1 _1 h2 z/ Z/ V; r% U0 }) N- e3 F. k
- // ADC转换结束以后,读取ADC_DR寄存器中的结果,转换温度值计算公式如下:
; E4 B/ y- g8 ? - // V25 - VSENSE
6 J6 O* A8 L9 U - // T(℃) = ------------ + 25
( E4 P) Q' p( I, D! Z% |# x - // Avg_Slope; r3 E1 [* f6 @
- // V25: 温度传感器在25℃时 的输出电压,典型值1.43 V。
& H0 m! |; E9 G& N( r% S. Y - // VSENSE:温度传感器的当前输出电压,与ADC_DR 寄存器中的结果ADC_ConvertedValue之间的转换关系为:$ q' ~! j$ A( b ^# M; F0 Z
- // ADC_ConvertedValue * Vdd
* U( X: w4 b! o- S F& R. w2 V. y - // VSENSE = --------------------------
7 f9 |. \2 ?1 u - // Vdd_convert_value(0xFFF)
' Y" @# ~0 X& g6 z( Y- A8 o6 }+ ? - // Avg_Slope:温度传感器输出电压和温度的关联参数,典型值4.3 mV/℃。7 S1 @, y# y3 q4 S6 N6 q% x! C
- " c3 {( v: [5 B9 G/ o- j
- Vtemp_sensor = advalue * 330 / 4096;
: m' }. v& l9 e6 q - Current_Temp = (s32)(143 - Vtemp_sensor)*10000/43 + 2500;
9 o3 _7 e6 p( e8 a; w/ f; Y* |4 G - return (s16)Current_Temp;& L9 ^: L$ l7 L. Z. w5 A# f3 S
- }
; Q: U; M/ Z# { z# o
1 ]5 b- k: ?$ A- . y8 I6 l" m3 w# z( f
- /*******************************************************************************7 n( ^/ O2 m- `, B. F, s, `+ H
- * Function Name : GetVolt
: W, F! o x* B; }" s. i. v' w - * Description : 根据ADC结果计算电压
8 Y$ ]( z O2 }, P* W - * Input : u16 advalue
9 t- l$ x) f: d, z! |( I6 [1 o0 S - * Output :
) p$ [ u' ~2 d1 L& I3 G' Q - * Return : u16 temp
* A1 ^/ x$ Q+ y5 _2 W7 n* z/ T! y4 C - *******************************************************************************/4 r& h5 Y0 t5 v$ r4 X
- u16 GetVolt(u16 advalue)
: s; a3 V" l9 B- A- U: } - {
$ `8 S3 J5 R" T - return (u16)(advalue * 330 / 4096);% ~. A% A. |" g+ W
- }
9 p9 \ z* E2 \6 g0 ]1 J - 2 {# G# u9 s/ ^+ ]
- 2 U8 I' ]- p$ q2 B c- I
- /******************************************************************************** I3 [: r& R( z$ v: {& D
- * Function Name : RCC_Configuration0 z2 i. m, h9 z4 D, K) _
- * Description : 系统时钟设置
7 H/ R# C7 E" a9 Y$ `* B1 c! N - * Input : None8 v4 f. R. T0 V, E( J" Q9 Q
- * Output : None/ h- h8 a: J$ z |. t0 u: e( Z
- * Return : None% ?8 I3 X# ~. I* Q% Y0 g
- *******************************************************************************/, k8 X. w M0 A) g7 o. g
- void RCC_Configuration(void)* i! C4 ~9 g2 _+ X
- {
7 n, _1 t8 [# u4 L) L& w J) H - ErrorStatus HSEStartUpStatus;5 E% v+ a5 `( x) S9 }1 l, T$ @
4 N0 B2 V2 T# ?- //使能外部晶振
( _* N5 w7 ]3 L - RCC_HSEConfig(RCC_HSE_ON);
. g5 D# K4 j. t& ~' N - //等待外部晶振稳定
5 I( u0 d2 S# r& ^/ p; r7 R2 O- _ - HSEStartUpStatus = RCC_WaitForHSEStartUp();
" I" ~/ W7 N7 ^! E+ B7 a( ` - //如果外部晶振启动成功,则进行下一步操作
9 ?6 z# X( `# [1 g# A! c* i; T - if(HSEStartUpStatus==SUCCESS)5 h. t! i) k% h, c m- G' a) K5 ?% _ J
- {! G0 `5 e! [( u, u9 P8 C2 Y1 W
- //设置HCLK(AHB时钟)=SYSCLK
- |% G2 v0 _; R% v1 A - RCC_HCLKConfig(RCC_SYSCLK_Div1);
' P) W; B; _* A: Z4 h, e$ A7 ?
; b- H7 k6 F6 v$ N8 J- //PCLK1(APB1) = HCLK/22 O# I) [% b( R/ Z
- RCC_PCLK1Config(RCC_HCLK_Div2);
, ?1 A. O' ?% j/ ?* ?
* ?0 z" C7 t5 x9 F8 \- //PCLK2(APB2) = HCLK+ W1 b7 L7 h+ a
- RCC_PCLK2Config(RCC_HCLK_Div1);: C: Z5 M* H3 _
- ! c' ~8 d; B& z. D' ^
- //设置ADC时钟频率
3 b, o2 r1 h+ T+ n. G6 q - RCC_ADCCLKConfig(RCC_PCLK2_Div2);0 X) x6 q. r9 f. W& ^1 u
2 i k( e, B* s5 e- //FLASH时序控制! Y3 N, ^( S; ?3 y
- //推荐值:SYSCLK = 0~24MHz Latency=05 A. K+ k2 ] k* G4 D
- // SYSCLK = 24~48MHz Latency=1* W C7 F8 T5 J% P
- // SYSCLK = 48~72MHz Latency=2
2 L6 a; W1 j+ O0 C7 Q - FLASH_SetLatency(FLASH_Latency_2);
+ f5 c6 r4 ^9 U0 _3 c! @ - //开启FLASH预取指功能( v9 H7 }0 ?! \( Z& D
- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);% \4 L3 l& K8 f+ t) o% q3 N
- $ c1 K0 |. Y4 Z( ]
- //PLL设置 SYSCLK/1 * 9 = 8*1*9 = 72MHz& K2 z8 |) d1 d b2 p2 S
- RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);# Y, B$ ~) z2 t, f; K9 ?' ]" B
- //启动PLL
- A+ }4 c* q/ _- w - RCC_PLLCmd(ENABLE);! _, m4 F$ X! }% L5 r Z" Y9 J
- //等待PLL稳定
# x0 s% T. O* i) I2 _! k - while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
9 @( H5 p7 u( T% e% P. x( f - //系统时钟SYSCLK来自PLL输出$ M: t5 n% d5 r; J0 E! O; `
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
! X2 H: D) A% t. l3 s1 S* k0 Q - //切换时钟后等待系统时钟稳定
& m7 _0 J$ X0 J$ ~' l: L2 x6 { - while(RCC_GetSYSCLKSource()!=0x08);8 m4 T7 X! G8 M
- 8 D: O/ J5 K5 ?
-
) W( ?4 t: I/ G( z: U - }6 b" f7 H7 S5 q: r6 O/ @* P
- - K$ i8 C4 ^. v# E) P! m
- //下面是给各模块开启时钟
o' n2 o* }2 M; N - //启动GPIO
$ e) s' g+ m0 x. O. x - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | \6 t( t0 K& s r9 a0 o
- RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD,\
& W; N* Q2 H3 m8 j# F+ G - ENABLE);9 I8 f$ y' J, N9 k g
- //启动AFIO
7 n! b, _2 g, m* b - RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
( V: r2 [: x F Y: J8 b X# ~ - //启动USART1
" r/ A* x9 M7 U% Q$ h; N/ ~ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
$ K, G( b* \4 ` - //启动DMA时钟
* v6 _- M- A' W: q0 W - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
$ F3 Y, T6 z4 k+ k1 }2 Y# i - //启动ADC1时钟
2 Z3 a9 {1 G# v - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);0 c7 R! e8 G2 L* h+ W* Z. F/ z
4 Q5 ^7 D1 A4 f" Q% `7 H6 ~- i R- }2 [$ B- Z9 P, K& V( [5 A% X! J' K2 {
5 s: g+ B. D+ Q) t# R4 E( `- 1 o5 b9 G/ Q3 a9 @- p V
- /*******************************************************************************
& W3 B/ \ }& r9 U3 H - * Function Name : GPIO_Configuration5 g+ b7 E0 U( H4 \* ^
- * Description : GPIO设置
' ~6 m/ _' V! p: R; S: E - * Input : None) b5 ^: Y. g0 H6 i7 H2 Y
- * Output : None5 V3 n: `8 O/ n% Z0 d
- * Return : None
6 u! { P7 d# X3 b3 q" G - *******************************************************************************/% s. ]2 p' p6 g2 R% t# F) U; `
- void GPIO_Configuration(void), f; T, W4 c; W: I0 `5 c
- {
9 v5 W, \" t7 ^5 j' n - GPIO_InitTypeDef GPIO_InitStructure;
# v/ c7 G( F. c8 Y: V: T - ( H% u; C( }, @4 X% H
- //PC口4567脚设置GPIO输出,推挽 2M
( Z: ?) ?# q$ Z' P, H# \ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;: ^+ u+ Y; c; {! i0 ~2 ~( G
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;* Q$ Q4 F9 d) H. ^0 [$ v
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;* N1 L* v% K2 W* T: g6 u
- GPIO_Init(GPIOC, &GPIO_InitStructure);' { r5 T" o6 ^, t4 g
, i$ M( w9 L0 u# [- //KEY2 KEY3 JOYKEY& z! U9 b" Z n. u2 e: w& k
- //位于PD口的3 4 11-15脚,使能设置为输入* O. Y7 _% @5 H U6 c" g" Q9 E# } m' _
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_11 | GPIO_Pin_12 |\
: i1 q( U* `1 o$ g0 F) g& g& F - GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
% D# z( ~' f) F& Q2 Y0 L9 o - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;$ D" k& o" W, [0 t; ~0 ?
- GPIO_Init(GPIOD, &GPIO_InitStructure);
" X5 }5 K# N. Y/ k* w4 I) [& E' C
' R1 `/ d: S7 y/ g. @) `, Q- //USART1_TX
9 R, t) y/ a) q* q9 C - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;- _/ [4 C) E* g
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;% @9 y0 L; g7 C- K6 t) m
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;# w0 l2 }. V; f3 D1 V$ _7 i
- GPIO_Init(GPIOA, &GPIO_InitStructure);! J) A: l5 P1 j% u& T& `
-
6 h4 O5 K6 p! M - //USART1_RX
! e3 {- S9 a2 g \2 B" w - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;8 D$ g8 g1 M5 G1 T, D5 _4 p# W+ Y
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- _ V3 B. p' Z, M - GPIO_Init(GPIOA, &GPIO_InitStructure);' W& P% s( \2 q# r
- ( P9 s% g3 c6 K2 O& t% T
- //ADC_CH10--> PC0
3 O- Y p$ F$ q+ o) ]( H4 A3 t - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;5 @0 O" }. M4 o% c
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;& J- ~: i4 b7 _( {: I* u5 \9 x1 d0 R
- GPIO_Init(GPIOC, &GPIO_InitStructure); @$ F# o9 |$ d3 n3 F# g) c
- # M2 u1 ~$ I5 r# @* N: F
- }) m5 Q3 ]1 @9 d W/ y" b# _
- 7 j& A: k( A5 [$ `8 ^( v+ C$ e
n- {* t2 k& P/ y- + `/ d( `5 k2 L8 u3 U
- /*******************************************************************************
, y1 z) b! C1 C7 J s% l - * Function Name : NVIC_Configuration
3 U( J: }: I: R9 |, L* G - * Description : NVIC设置
6 k( T6 Z) x- x6 u8 t' M - * Input : None* ?, n- M' m8 G" R2 k! o. S
- * Output : None6 s( k# |* g' x* [; @) P6 X9 i
- * Return : None
" r2 d1 P; ?& h+ D* R - *******************************************************************************/
( j( h- z* |6 H# P - void NVIC_Configuration(void)
1 ~% }3 b, o& S" W* Z- z# U - {& v/ x1 i/ Q. @4 F
- NVIC_InitTypeDef NVIC_InitStructure;9 M+ U. a' e8 j4 q+ W# h! S
- # U: z- W7 S- K; h" l. f1 }; m
- #ifdef VECT_TAB_RAM
0 k# ^) j) M: _+ M - // Set the Vector Table base location at 0x20000000$ A; t g6 @6 g8 z
- NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);. x# G9 n7 B. @# \
- #else /* VECT_TAB_FLASH */
$ A, P" c5 F' @" d3 T9 r& s1 L - // Set the Vector Table base location at 0x08000000
, D: c* j; }8 }* M6 O8 { - NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
, W1 O% @. x3 i" H! s& Y2 S - #endif
8 q* r- m- c' S; T# Y5 j* S2 R
0 J) E" S" D: @- H/ l- //设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级! G! q" ?7 o: \4 I
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
0 r" ^5 e6 Z, I. { - //串口中断打开
; D& Q* d Z, p( S% b3 O! Y% e - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;( N/ D' k0 V) x, B' Z1 y
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;) x3 H, J5 h6 c; G! o8 J
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
, v+ ~* `+ L7 H+ A) ~+ j - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;: ] f2 s" N; l" g. z0 f: x! B8 T
- NVIC_Init(&NVIC_InitStructure);
5 O7 u% e- {* O - }
4 ^# W/ ^/ z" T - + v# I6 A" e/ l# T. ?
- 6 W0 C0 F, J+ {. M& Z
- /*******************************************************************************
1 l$ J" \# V0 E6 K# t+ F4 P, @ - * Function Name : USART1_Configuration$ w4 o' ~7 q! W+ r/ a
- * Description : NUSART1设置1 S7 Z4 I1 Q/ w
- * Input : None& f7 l' F% N3 H
- * Output : None$ z+ _, G" P& m
- * Return : None
- a6 a9 B% ~9 W$ q, U: a' T - *******************************************************************************/# j' \ E( |& a4 c+ o
- void USART1_Configuration(void)+ r; @+ B2 D3 c) P
- {" Z6 N7 g9 G$ m8 W5 m1 G L
- USART_InitTypeDef USART_InitStructure;$ t; y. y! @% V' b. ?0 K
-
% o. x6 i" Q0 D$ y9 N2 I9 }9 T - USART_InitStructure.USART_BaudRate = 19200;& b: c! _; i( c4 ]$ _. q
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;' G$ W( r; q- t
- USART_InitStructure.USART_StopBits = USART_StopBits_1;- z1 s6 }9 t8 @
- USART_InitStructure.USART_Parity = USART_Parity_No;
3 g* r8 Q, r \1 t6 O$ L - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;' ^7 J' ^6 `! E. n* v
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;% i& j6 t2 u! H; M. p! o! p5 v
- USART_Init(USART1, &USART_InitStructure);
) R! n9 G, Z$ l" K2 ? ~* p2 S+ r - ( g# t; N5 [3 U' A( L
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);% g* G5 Q2 e8 W/ U: s, E& B
-
( p, g/ q2 ~, ~' m; B - USART_Cmd(USART1, ENABLE);5 `& {) i: {: h9 x. k. G( r/ N
- }! G5 r4 \/ r+ M5 e- |- u' l" T
- 7 q9 `+ k9 h& F0 I0 p; {. Q
- /*******************************************************************************
5 _5 {/ \# u" q* B - * Function Name : ADC1_Configuration
. }4 i$ q& v8 B) H - * Description : ADC1设置(包括ADC模块配置和自校准)
4 X# g/ u, q1 t: R) k- n% R - * Input : None/ T9 u6 T+ J/ ?1 I& X
- * Output : None
2 e; H0 j, Q8 U' { - * Return : None8 F: L7 c( m* l) u& u
- *******************************************************************************/2 o$ j. s. q: G
- void ADC1_Configuration(void)
% m% j, C- z. w" [$ n: Z: P - {8 g7 k" g( e) {
- ADC_InitTypeDef ADC_InitStructure;2 i5 B0 z2 j: B" Y- r3 t/ W
( g% o2 f" q1 z6 h( h- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
7 E3 G; E. Z: u- Q; G( f3 t - ADC_InitStructure.ADC_ScanConvMode = ENABLE;
0 R9 C& ~; a. M) o. Q/ x - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换开启
' ~5 i) Z6 T* d5 t4 [; R$ P - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
: @9 A+ ~( {5 v- E7 I - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;$ R0 T' j# J+ R% l4 b/ ?! X3 E2 z
- ADC_InitStructure.ADC_NbrOfChannel = 2; //设置转换序列长度为26 q$ ]! d4 p5 t! N8 t. G5 k- P' F9 u
- ADC_Init(ADC1, &ADC_InitStructure);: V" n! _; F2 T' ]. Z
-
1 ^8 J1 d: _" U7 i/ P) W& x F - //ADC内置温度传感器使能(要使用片内温度传感器,切忌要开启它)
% G1 \5 B+ B- b7 S8 I. y - ADC_TempSensorVrefintCmd(ENABLE);/ Y8 C( x* K: Z
- ! @, }* e3 |' y$ E' V. l
- //常规转换序列1:通道103 d* H. L, F: g) [ h
- ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);# ?, H% ]3 K) H$ _: l& O8 M
- //常规转换序列2:通道16(内部温度传感器),采样时间>2.2us,(239cycles)
( x) s4 K! ]5 Y2 R9 D' ?$ l - ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_239Cycles5);) a0 W: z0 R. L/ H
-
+ N" R4 t/ ?' v - // Enable ADC1
. i( {( ?3 X& D' Z C - ADC_Cmd(ADC1, ENABLE);& K( }: U" \: U" Z9 T: `0 X8 r* }
- // 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)- U8 J. h# }3 o- C- U
- ADC_DMACmd(ADC1, ENABLE);
6 M Y; ]3 x) D) Z1 n, z' |! e - + m6 ]- k4 J: C0 i2 p
- // 下面是ADC自动校准,开机后需执行一次,保证精度- i0 F$ b' d+ B+ l L* ^* ?
- // Enable ADC1 reset calibaration register+ N4 A0 w0 g& U; I# y
- ADC_ResetCalibration(ADC1);$ |% }% j3 K6 j
- // Check the end of ADC1 reset calibration register
# ^% i5 i0 r4 j- M+ a# I' b - while(ADC_GetResetCalibrationStatus(ADC1));
4 S4 }9 X \6 q+ p) R5 u
: U$ {5 ]% X8 \" z- // Start ADC1 calibaration
" B' }1 x/ @, S# z/ W - ADC_StartCalibration(ADC1);, H2 {5 Q: J+ J8 L: n3 y' B
- // Check the end of ADC1 calibration
7 H$ S: t2 S& z& k9 m. Z% M9 D1 q - while(ADC_GetCalibrationStatus(ADC1));
1 g, g5 H, V) u/ x - // ADC自动校准结束---------------! M& @8 a3 N4 @9 G7 A, F
- & L) u3 e7 l& m J/ {" X1 Z
- }
2 e0 u2 |$ p: q/ g/ ~ - 7 N. Z' J; l7 ?# y, {
- /*******************************************************************************9 w* N0 o( L1 C5 v2 u. g8 x I8 P# ?& W
- * Function Name : DMA_Configuration2 \4 |4 |4 `) X
- * Description : DMA设置:从ADC模块自动读转换结果至内存
, |. K9 h; d! I2 O - * Input : None: G3 Q# ~1 F' x* g) H( E2 w
- * Output : None' B2 w+ R6 \2 I" J6 Q9 B
- * Return : None \6 b" h2 ~0 ^/ P/ c- I9 t
- *******************************************************************************/* d+ D: g) w1 {5 a, r8 ]
- void DMA_Configuration(void)
6 k* C7 d* }$ M; E! G$ x - {! p; f: ^3 g: j# {( _* ]
- DMA_InitTypeDef DMA_InitStructure;8 }4 e& g. c' Y- u$ B
- $ y% y) U4 j: a, D1 e- X: t
- DMA_DeInit(DMA1_Channel1);
- h3 P- a9 `/ y0 D - DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;0 w7 q, c3 B! E" `
- DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value;% o9 [9 [& ^/ P" ]0 P% G9 w/ P
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;- w4 q+ E, T: C1 f8 k
- //BufferSize=2,因为ADC转换序列有2个通道% @# k/ J% V3 f3 C7 s0 E
- //如此设置,使序列1结果放在AD_Value[0],序列2结果放在AD_Value[1]
' O4 w. g$ j% b& V - DMA_InitStructure.DMA_BufferSize = 2;
' x9 V& E; l" {- q2 F3 |. s - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;8 b8 ~9 b5 W) E* ~( ~0 Q
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
! a6 u. m- r8 a4 p" V - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
9 n2 _9 k. O; Z# ^5 S$ L* m - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
s+ J1 |, K8 [7 }; d" m/ r - //循环模式开启,Buffer写满后,自动回到初始地址开始传输
$ C- ]: \; e' h0 u; R% ]8 w( p# b - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
. T- M2 T4 ~ d/ Z - DMA_InitStructure.DMA_Priority = DMA_Priority_High;
5 o% D. Q3 k7 C7 ~' g - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;8 K$ v2 L! Q) W G
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);
( @3 H) f) I( X$ P - //配置完成后,启动DMA通道
2 [0 Q- B, r2 s1 c# D$ s8 E7 K - DMA_Cmd(DMA1_Channel1, ENABLE);
1 {( ?9 K1 D. u& ~9 [0 p+ C/ T - }
* j8 n: e; c: F; _3 U* G
复制代码
2 c9 v: I2 J8 Z3 l7 I2 k+ l4 `" u* A+ h$ P m
|