|
这是一个综合的例子,演示了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
! b; K4 D9 `6 x2 x) F- 本文件实现ADC模块的基本功能! |3 r; ?6 l \9 Q
- * 设置ADC1的常规转换序列包含CH10和CH16(片内温度传感器)
$ P6 E0 t/ V s* U0 { s. ~ - * 设置了连续转换模式,并使用DMA传输
* Y% g; @9 [/ l0 ^! e - * AD转换值被放在了AD_Value[2]数组内,[0]保存CH0结果,[1]保存CH16结果
0 l2 y" M/ `$ {; i2 H5 U0 I# ]+ D5 S - * GetVolt函数计算[0]的值对应的电压值(放大100倍,保留2位小数)
: B( ~& _+ U8 H! i9 p0 F - * GetTemp函数计算[1]的值对应的温度值,计算公式在相应函数内有说明/ G& J/ D0 p. y1 g/ H1 y7 {7 m
- * 作者:jjldc(九九)
5 j% v- j6 }* f6 U g% { - *******************************************************************************/
9 b. e7 b/ P3 D5 `2 o V
) H0 ]% _. [7 x9 n- /* Includes ------------------------------------------------------------------*/) z; s0 r# I, q" J
- #include "stm32f10x_lib.h"4 D! @7 f# D3 ]9 b5 N7 m2 f
- #include "stdio.h"
' }/ M* m8 Q9 z r
# N9 B& F1 Y* Y- M- /* Private typedef -----------------------------------------------------------*/
1 `* M" I1 W; p1 [: b - /* Private define ------------------------------------------------------------*/
4 E' Q) c5 m* }2 u% P$ X3 A - #define ADC1_DR_Address ((u32)0x4001244C)' j' \% ^5 r z7 s8 D: \! O
- /* Private macro -------------------------------------------------------------*/
. {! c0 W; V4 s* |; l+ c - /* Private variables ---------------------------------------------------------*/6 W) W1 X7 } j/ X
- vu16 AD_Value[2];6 v8 c! W8 ]6 c2 [) T& J8 l: {
- vu16 i=0;/ I. r, d7 E8 N. Y1 q
- s16 Temp;6 n/ K" Q! X! ]0 J! m+ {3 H
- u16 Volt;
6 N6 e; j& d, @9 `1 f* @. {
" N5 k7 M2 U' a. U$ Q- /* Private function prototypes -----------------------------------------------*/
1 r3 l9 \9 W2 W, S( M- O6 N1 s, @ - void RCC_Configuration(void);
8 F9 ?% k( _8 h - void GPIO_Configuration(void);1 L, y( O' z* c( q, L9 Y7 `3 k
- void NVIC_Configuration(void);5 c: i6 |, y8 D) c4 p& F1 p1 y
- void USART1_Configuration(void);
5 S, ?4 \$ Z4 q - void ADC1_Configuration(void);5 [8 b$ U6 c4 D! ~6 V% i
- void DMA_Configuration(void);
$ }$ V9 o. f( y% w7 y - . U: B1 e+ R2 g$ k1 d3 `( x
- int fputc(int ch, FILE *f);
( ?. `' V2 _8 h8 r - void Delay(void);- L# Y9 O% ?! F$ S
- u16 GetTemp(u16 advalue);- ?; x0 E* f5 q9 g: E9 x
- u16 GetVolt(u16 advalue);6 E) ]. t+ {! ?: {
- /* Private functions ---------------------------------------------------------*/0 ]7 {1 V! S3 L. `0 F4 X
- /*******************************************************************************$ ]% L+ K" I! R% r( G1 Z) P5 H3 [. t
- * Function Name : main
" u/ A3 { z2 Y8 A, I$ g6 a W - * Description : Main program.. e+ q) J2 ~7 }8 `4 w
- * Input : None
6 o) O/ X8 o2 g0 {. Z - * Output : None
) ]* L9 Y% R( |4 E9 F5 g - * Return : None
( ?: {* [1 b3 {7 @6 |. e - *******************************************************************************/
9 G, U( e' T! O1 n, a/ e) l - int main(void)- f1 W! q3 P- c+ e) I d- e5 u
- {! j9 \, |! O# W9 I" S1 @6 B+ |
- RCC_Configuration();
' h& P n9 D2 {) n: y. p - GPIO_Configuration();: d7 v, G2 K# O; L
- NVIC_Configuration();
7 m& g3 U1 u) r8 f7 Q: K2 \ - USART1_Configuration();
2 r7 t/ |" v1 F' y6 V r9 t - DMA_Configuration();
) u A6 ~# Q4 V+ e - ADC1_Configuration();
& w" v6 _0 P$ J) F9 e2 J -
* r9 ?# j) T7 U# r7 c2 i1 } - //启动第一次AD转换* B( O- ~9 L+ b) p" ?: H' R, G
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);
3 `' L; r" Z' @% D4 D0 I5 M - //因为已经配置好了DMA,接下来AD自动连续转换,结果自动保存在AD_Value处 9 @! E) a: Y/ a& e7 X
-
! a. P( A4 e9 x3 Z/ i - while (1), y w5 K* Y' U& P, I
- {" q1 B6 \3 M6 `. L' |
- Delay();
$ R( S, j& f) H0 C2 ~+ D9 y - Temp = GetTemp(AD_Value[1]);" c! L# R K/ c! p D
- Volt = GetVolt(AD_Value[0]);
9 D' X" S$ K j - USART_SendData(USART1, 0x0c); //清屏
$ }2 F1 d% |3 j - //注意,USART_SendData函数不检查是否发送完成
9 W+ A2 R F3 n2 X5 \3 @7 R" m, F! ^ - //等待发送完成
1 n: Y& m( [! u0 r& E" W9 H7 o% _ - while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
; o% k' l$ S/ A9 K- m) c7 g - ]1 }* _- \. w, k. ?/ N
- printf("电压:%d.%d\t温度:%d.%d℃\r\n", \
8 C4 C1 ?- f. K1 ] - Volt/100, Volt%100, Temp/100, Temp%100);) S* R8 P( \: f/ U# P
-
. [4 C7 S- v7 L$ U - }& z" K2 A4 |8 t) e/ i: c9 [& d m
- }
( l' H2 S+ @2 U, X' Z
, s! @8 ^# T0 S# q6 ^0 `. X2 S- /*******************************************************************************
% P% c) r" O) [& t - * Function Name : 重定义系统putchar函数int fputc(int ch, FILE *f)3 g0 [$ P( H( v: h9 ~# K; B
- * Description : 串口发一个字节
, b x" J! M- y, _0 \$ a, l% E& [ - * Input : int ch, FILE *f
3 F: u' Y, [2 p. l& q+ e2 b# { - * Output :
- P' A* b/ l! E+ S - * Return : int ch" \- D; s0 v, ~
- *******************************************************************************/: m R# R) \$ B. r4 w% z
- int fputc(int ch, FILE *f)% n w* F$ B; n2 [: I1 U
- {
/ p0 g& f4 t# e) X( A$ o7 G! ] - //USART_SendData(USART1, (u8) ch);3 O% }+ ^; A9 F6 A' E% q" `
- USART1->DR = (u8) ch;
" K* Z# O B3 l; f- g$ I - 1 E0 b6 I# G& V0 s1 T, |7 ^6 {5 F
- /* Loop until the end of transmission */2 o' {( o7 O4 H* `& f( F9 C3 l
- while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
+ z. r5 u$ w- j - {
. O) J1 l s* R - }( C" K) U2 n9 b# S/ j: W
- $ t- \6 L& O/ x% {
- return ch;
. L& B8 g8 s1 O7 M9 m - }
8 F) q; A3 n0 j: g* H* z" ~ - o* I8 ~- _7 z. |1 i; h L7 G
- /*******************************************************************************
" P. x6 g% Q3 K5 P( C& U - * Function Name : Delay
1 F. W# l; R4 `* {" L0 a! i - * Description : 延时函数
]; S7 T6 t7 X+ z$ t0 W. c - * Input : None
! P. i7 d; \& g4 O8 W. U' N1 I - * Output : None6 ~8 o' V* K7 ~7 [% f
- * Return : None6 X7 j, Q- Y1 v# X
- *******************************************************************************/
$ E. N4 }1 R% q3 C l E - void Delay(void)/ N! u1 V1 D% d4 ^* L! s6 \/ h% z7 r
- {
7 {! m; ^8 @" h4 { - u32 i;
$ I% _1 i/ B) g* M - for(i=0;i<0x4f0000;i++);
, L" g) [0 V X& P, [ - return; [5 A0 A7 ?7 P
- }
+ |7 |& H2 W' T2 L - , w0 f) r j. ~, ]
- /*******************************************************************************
& J% d, I5 |- u l9 W" X1 d - * Function Name : GetTemp
. V. z2 H* F) {7 L) J1 E: O' X. E - * Description : 根据ADC结果计算温度 I' K' t9 y K5 T% y
- * Input : u16 advalue9 G- C4 x. c9 c2 } `. C* T/ n
- * Output :7 P( y2 z) C) H; v8 j
- * Return : u16 temp! q% c, @- s" a4 x: {8 d
- *******************************************************************************/" F) c4 b( j; i( w+ p
- u16 GetTemp(u16 advalue)( y! H) h: P9 i, S. _' V
- {3 N- a- c3 u! K
- u32 Vtemp_sensor;
2 A4 P! j3 c$ ], } - s32 Current_Temp;
- ^- P: [9 j1 j# X2 c' R- z0 } - 5 A" p1 i1 `$ h4 ?' i$ o2 G
- // ADC转换结束以后,读取ADC_DR寄存器中的结果,转换温度值计算公式如下:9 N. R) b6 r7 A# i( M% X* B
- // V25 - VSENSE) ~& ^$ |1 ~. Y. x" p% r
- // T(℃) = ------------ + 25- d6 t; ]& \: s1 s6 S
- // Avg_Slope
+ |, J1 K% G/ w1 c6 L5 S - // V25: 温度传感器在25℃时 的输出电压,典型值1.43 V。
# ^0 T8 L8 Y& ` d - // VSENSE:温度传感器的当前输出电压,与ADC_DR 寄存器中的结果ADC_ConvertedValue之间的转换关系为:
+ r! a9 `$ B1 F - // ADC_ConvertedValue * Vdd
5 B/ ]* o" h0 I6 c - // VSENSE = --------------------------6 c* P/ a0 E. t( W
- // Vdd_convert_value(0xFFF)/ q" R1 @$ p: N; f$ p
- // Avg_Slope:温度传感器输出电压和温度的关联参数,典型值4.3 mV/℃。7 f" l# {; ~! O! n4 q9 h! ~
- ( t8 N- g- d( I3 E1 N5 j; g1 c* E, I" x
- Vtemp_sensor = advalue * 330 / 4096;% F: y9 m$ _ n6 ]3 S8 R
- Current_Temp = (s32)(143 - Vtemp_sensor)*10000/43 + 2500;- S5 T: d! w6 X2 R2 l2 D
- return (s16)Current_Temp;, w+ `# F: h& x5 ~( Q" E
- }
$ q( v& u7 m( h0 o' P$ J$ u+ P
4 Z) I0 ]/ k) M' {. ~% q9 b
5 n4 b0 L6 y) o7 B; G! c- /*******************************************************************************6 V' H6 S1 m0 q4 `- j, [0 i; J
- * Function Name : GetVolt8 A V' O" A+ P! b7 \8 ^ t
- * Description : 根据ADC结果计算电压
1 m& e4 _& o# ?1 Z( g; l5 R( f - * Input : u16 advalue
3 x) {( Y" ?6 O+ f - * Output :
3 T/ `* V, G8 D! B - * Return : u16 temp- I$ `- c/ f7 h! u
- *******************************************************************************/
/ _& z. v/ v' E( [; W4 h+ z' T - u16 GetVolt(u16 advalue)# h2 C; T* `5 i4 \1 }6 d
- {
) n6 E- |# m4 w- x/ v3 |) x( ] - return (u16)(advalue * 330 / 4096);8 {9 r% y4 O2 ~/ O/ m
- }
/ a1 o2 m3 Y2 G! Z1 ]! ?0 y! r/ M -
0 H' L9 E8 h( p9 I* ]( g! M - $ _, g9 I! \: P
- /*******************************************************************************" E- l! V/ f j: s4 x5 u' v/ T' l
- * Function Name : RCC_Configuration
: q5 ~) v O7 m5 |. f7 K - * Description : 系统时钟设置
1 L/ q, p3 \3 x9 D - * Input : None8 n$ D) ]3 |1 \2 M- R$ n' R, F
- * Output : None
1 ?6 d+ J1 N5 S+ r4 W - * Return : None) j& Z! q' |+ h# b T9 B
- *******************************************************************************/
5 o2 S, k$ O& @' B - void RCC_Configuration(void)
" @7 v7 y4 D8 o* Y: ] - {, F ?+ M; C. A1 s0 ^2 b: V9 S1 Q
- ErrorStatus HSEStartUpStatus;' Z, }, x; ?9 n- x1 ]2 N& W/ s2 Z. M" t
- ' \ Y+ K: T7 g' `/ A' E$ U
- //使能外部晶振8 ?; c, ]3 ?( j2 r+ ?! y+ p& m
- RCC_HSEConfig(RCC_HSE_ON);* {; j- a/ L0 E$ h i9 `8 [7 ^
- //等待外部晶振稳定
0 \# F3 R$ W0 t" P" T3 W3 x' U% a - HSEStartUpStatus = RCC_WaitForHSEStartUp();
2 o" a6 v, U( n" i* m - //如果外部晶振启动成功,则进行下一步操作' O/ c+ A Z# d: y2 V8 b( v9 b7 |
- if(HSEStartUpStatus==SUCCESS)
+ i+ {* G5 R0 \; c" j A- m - {
8 c" p+ H K' r+ E - //设置HCLK(AHB时钟)=SYSCLK
, K5 g( b) r/ _; g5 ~- d - RCC_HCLKConfig(RCC_SYSCLK_Div1);
* b- J. A# ]( E' ?" O" V7 b6 `4 {
" a1 B* P' x3 X8 h2 J7 A- //PCLK1(APB1) = HCLK/2
: ?5 V9 }) R' `1 w/ t( W - RCC_PCLK1Config(RCC_HCLK_Div2);
3 s# d5 C, p9 N& ~% X; L& ^) }
4 V7 y! ^$ N `+ T- //PCLK2(APB2) = HCLK3 r9 q4 b" j/ a" u8 D
- RCC_PCLK2Config(RCC_HCLK_Div1);
# J, Y) B! s7 g$ v$ ^! s! f) h - + e: O) d3 u& T$ } B" b& A+ l
- //设置ADC时钟频率. O6 R: x( Q' {% g, `" G. }: J
- RCC_ADCCLKConfig(RCC_PCLK2_Div2);
5 V0 h5 u& }+ e5 W% ` - $ `9 y( u' e. H) q" j: O
- //FLASH时序控制
- e$ } S- f* t - //推荐值:SYSCLK = 0~24MHz Latency=07 m+ B4 ?. M" L. L ]
- // SYSCLK = 24~48MHz Latency=1- I5 }3 ]3 K: ?/ o3 C0 u
- // SYSCLK = 48~72MHz Latency=2
* ^" G* d0 x- A! y, u$ a - FLASH_SetLatency(FLASH_Latency_2);
k6 q4 Q' n( N. E7 ~. e4 P - //开启FLASH预取指功能& N0 G' Q: @: ]+ a
- FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);5 ]$ _9 U+ s5 d9 Q5 X% ]
- + B( y/ T( I. f1 {
- //PLL设置 SYSCLK/1 * 9 = 8*1*9 = 72MHz# W, D5 H7 {3 m9 p5 v& j9 G
- RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);/ G j6 V# ^( t1 F$ e
- //启动PLL
5 [: O2 |- ~! T - RCC_PLLCmd(ENABLE);8 y S# ~. y9 |
- //等待PLL稳定
, u2 J' H# C+ F' ?- n% ~ - while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);, X- d& [! `7 C/ S" b
- //系统时钟SYSCLK来自PLL输出
5 j( C, T/ [$ ?' A: a - RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
9 t9 L" T& P3 J/ b9 m - //切换时钟后等待系统时钟稳定
, U; y9 E7 w" p, u4 W - while(RCC_GetSYSCLKSource()!=0x08);. ^8 w3 m0 {, f x/ I5 \
- ) b8 n. u. c" ?3 K4 _
-
h/ I$ e( E6 B# t& G7 u - }( r' U: e$ Q5 U3 a
- 0 i" B5 S2 ^) m0 _1 V" Q
- //下面是给各模块开启时钟
4 H4 j. K8 ?* D& i4 Y! { - //启动GPIO
$ ^$ q7 y( { i* e% `. J4 R - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | \! R, U" a! u% C* r
- RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD,\
/ S1 ^. r: L' S) m2 R* | \- n - ENABLE);& j' a. q5 y7 P: v% c- n7 a' R
- //启动AFIO
3 J# b3 Z7 K E% L( D& v: ~7 L6 p - RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
& `1 B! `. N2 s# v4 u, O0 t - //启动USART1
( n& a' m' |* @ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
' H$ P. \5 q6 a* {' A - //启动DMA时钟
, ^1 n1 Q2 V0 R- s - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
! h8 f W( O* p1 c9 d7 M1 q - //启动ADC1时钟5 F0 Q h8 e; h/ A
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
7 E0 P, \, v" c9 S - 2 s3 w" y: X, v* T( r
- }6 B$ N5 {# {( R9 M
- ) E1 T- d$ T! ~& X
- . g, H$ p; N7 i! a) K4 j: d* `$ h5 [- v
- /*******************************************************************************
, \8 d a% I# S6 t, r# M - * Function Name : GPIO_Configuration
b0 a+ I" v; [ - * Description : GPIO设置$ U0 U, y P# z' q- i3 x: Q3 j
- * Input : None7 o# x4 z u( V) @, M$ n
- * Output : None
3 a# {2 H* B5 u& U" k2 x! Y* W4 O - * Return : None
3 i( p6 F( j( S7 g, c - *******************************************************************************/2 y9 ~. }+ H6 K( \
- void GPIO_Configuration(void)
# T$ {- d' O# r8 c' S2 O/ I+ B3 ] - {# d ]2 ]( w- D) E U ~. x
- GPIO_InitTypeDef GPIO_InitStructure;
* o! L& L5 `6 q9 s9 C: R - " x/ g D/ u0 t8 }1 Q/ S6 l7 T: H& r
- //PC口4567脚设置GPIO输出,推挽 2M0 ]/ d& x. O+ \2 \$ y2 t C8 i$ J
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
. Z: t4 U" ^( w9 a - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;7 T0 o, N6 }3 Z3 t
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; O1 |$ j# M. y. a" ^
- GPIO_Init(GPIOC, &GPIO_InitStructure);
0 B3 ]$ k4 M- { - 9 t- x q, r& j3 ~- ^
- //KEY2 KEY3 JOYKEY( Y+ I" m+ s8 H2 Z
- //位于PD口的3 4 11-15脚,使能设置为输入
' W( U( ?6 ^8 l9 N& {8 B2 r2 E - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_11 | GPIO_Pin_12 |\: q. A- o6 A$ ^( ^
- GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
# `1 A* C# a* t. a - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;$ i$ P3 ^5 k" g6 q1 c8 O+ a
- GPIO_Init(GPIOD, &GPIO_InitStructure);
5 Z1 n; P+ w' ]: g - * G0 L+ R$ `- b
- //USART1_TX
& }# K! ~0 F, o! y, F - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;; X. x" C$ L% G4 u) Y6 k% S
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
9 |$ w. n. h6 O9 T! Q - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
) E& Z$ l1 V% Q! v - GPIO_Init(GPIOA, &GPIO_InitStructure);
' O8 o" a7 c& \7 k; f - 5 S* s2 P; K3 p
- //USART1_RX
8 C+ n% z# v, D9 w2 Y- e$ { - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;8 @/ n) z- D* V' j
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;- J1 c8 x1 J, {& h4 t. n( _& t" o% V
- GPIO_Init(GPIOA, &GPIO_InitStructure);
) e6 i0 c) t* _ - , P! ?2 c" D" ]6 v2 |# C
- //ADC_CH10--> PC0
# Y/ m; V, e: |; h - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
/ b: h" u$ h ?: e8 Y, V - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;! |. S, m& I- g: w
- GPIO_Init(GPIOC, &GPIO_InitStructure);. y# O5 v% [: a. I6 g9 F* E
- : y; f' _' ?1 y& C+ K
- }1 s/ S6 w& a* {1 \& V- T! o
) z" G/ v" m& C. t) P
' i# ~4 E- y" P4 d, `8 `! T- * Z4 `; Y7 s! q/ d" V
- /*******************************************************************************
( a0 t' I3 ?! V! R( W- U' C - * Function Name : NVIC_Configuration
. T4 F- w, v% p& F) Y - * Description : NVIC设置
6 f3 O) c% m7 z M: u, j& B - * Input : None
! |4 M# M/ j) R5 \ - * Output : None
* ~0 N; m' }; H( Q$ |" @: S" o6 i - * Return : None) e4 Z/ i1 [! y& [6 }" p
- *******************************************************************************/
6 }9 j) u8 k g' I - void NVIC_Configuration(void)
" _$ O( E9 x7 L$ t - {7 o/ y Y1 W$ G8 ~
- NVIC_InitTypeDef NVIC_InitStructure;$ s( O. F! T* \3 N. w. S
3 v5 {" z- ]' A- #ifdef VECT_TAB_RAM% P* ^' u# B# c8 p
- // Set the Vector Table base location at 0x20000000( _, B6 T0 I5 z9 o4 n. T! S
- NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
$ z2 d2 d+ w! M! P4 a* T- Y - #else /* VECT_TAB_FLASH */# a) I# m9 y# [8 y7 F
- // Set the Vector Table base location at 0x08000000& o2 P5 O c9 P2 W: B
- NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
* I# l& m, b, b' r' D- s0 y - #endif. z: [& a) U2 E+ E5 W, Z! b" x
! B, B8 v8 `% N" p y- //设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级6 A) A8 b) ~; y
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);1 E2 w. M3 h& o1 X
- //串口中断打开
3 O% g+ q# W/ U, d; ]8 I - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;; x% d$ J( g$ u4 v5 g. F
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
# u! f3 f1 t. z) y4 |7 D - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
& ]5 D. `% O4 R+ o# O - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
3 ~9 `2 B K5 D* Q, O8 Y# Q - NVIC_Init(&NVIC_InitStructure);
3 m- V& ^0 j0 t2 c( O4 { - }8 r& O( I2 @- Q# l2 d! B
6 T9 V" E/ R" f7 g! Q6 C1 _5 l- D, T$ }9 _- w M* T6 m
- /*******************************************************************************
2 T) D8 F& t$ v: A8 z - * Function Name : USART1_Configuration
7 U) P) j# F% J. F% X& | - * Description : NUSART1设置
. | X, _1 h- l( b" m" X# D0 j - * Input : None
- T5 H5 Z9 j; f, h4 F* s9 F - * Output : None; B- c7 R. G `) s; l8 u9 T
- * Return : None4 i! O) G( a, c9 R+ o
- *******************************************************************************/7 J2 O6 c/ s! z, L
- void USART1_Configuration(void)
- f. q& d" s7 Y4 J. | - {
% P+ N( _) |5 f0 n( g" d9 w - USART_InitTypeDef USART_InitStructure;
' W! ^, B7 p/ i3 J6 C- f/ l - 9 ~0 A) Q; B. R' G; e- z4 C# F
- USART_InitStructure.USART_BaudRate = 19200;" h1 M$ d' k! |- W5 N' }8 Z
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
# Z( S8 j+ j5 r% `/ r( b - USART_InitStructure.USART_StopBits = USART_StopBits_1;$ z' S8 J1 \3 b' |7 m `: Y
- USART_InitStructure.USART_Parity = USART_Parity_No;
L D; a2 ^9 A& d, n! ]; P9 q - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;% R) B' T/ V- w* B1 k
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
- H& z0 T# }7 i3 F. x - USART_Init(USART1, &USART_InitStructure);
' V$ e9 j0 D& H9 w - 7 X% R* x/ ~6 i& j+ E9 j( q7 z" ? m! @
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
( K4 _& w3 M3 ^* [" |$ ~ - " W+ X5 z) X& W; ~9 C
- USART_Cmd(USART1, ENABLE);
. E$ {" m* o, W' | l* O, J - }
+ F: o% |, o( E5 o- W p. f
+ E4 }) c5 w9 ]/ m- /*******************************************************************************4 w0 a8 c1 l- w- I! B
- * Function Name : ADC1_Configuration+ ~. p& G2 ~& N& T. p' P: a
- * Description : ADC1设置(包括ADC模块配置和自校准)
" O5 N) N0 R! o - * Input : None3 o5 s ]. Z; ]' X1 ~8 s" z# j
- * Output : None
* _* w+ K0 G6 R: k4 N% t8 [: } - * Return : None9 R1 B. C9 G; E3 u
- *******************************************************************************/
/ H* p; V% r; q9 E+ q1 v3 U7 x - void ADC1_Configuration(void)3 y) Y j& y' b; _( N" k
- {/ l: E. o1 N; t; C" o6 Y
- ADC_InitTypeDef ADC_InitStructure;$ ]" y) ^! y: y0 B8 z; F' P5 A3 n6 ]
- ) _0 t+ o. q5 u. n
- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
( `$ t5 [* u' L$ b - ADC_InitStructure.ADC_ScanConvMode = ENABLE;' s$ J6 Q& c- n& T: R' v% h& G ]
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换开启
3 {# N; p# ?0 i; _$ V; W - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
. d8 Q& ]1 A: T9 a" l2 U - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
( a8 C% m: @4 p8 b$ u5 G. b+ b; P - ADC_InitStructure.ADC_NbrOfChannel = 2; //设置转换序列长度为2
# F2 P. D2 _. B2 B% [4 h/ x* C - ADC_Init(ADC1, &ADC_InitStructure);
, M: M- N# ~. W6 n* z3 f -
) J( G4 G$ T- g; q( v4 G - //ADC内置温度传感器使能(要使用片内温度传感器,切忌要开启它)+ b/ F! D9 g- X) l& }! _
- ADC_TempSensorVrefintCmd(ENABLE);6 |: b7 T" a _7 o7 R
-
5 h' p' c2 }" l& R) _ B+ N - //常规转换序列1:通道10
$ @" t1 q4 b( V& m8 g$ k' x - ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);# {, d) _# _& }2 r$ U
- //常规转换序列2:通道16(内部温度传感器),采样时间>2.2us,(239cycles)) C' A6 m9 ~+ Z9 A' B0 V% \# s) L' U
- ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_239Cycles5);% q2 ^6 t$ C8 v. r2 T
- + }5 `& ~$ L/ }: M4 T
- // Enable ADC14 I5 z8 u: I# v* O) B! d5 i; p
- ADC_Cmd(ADC1, ENABLE);
8 |( N9 H; A+ n% f3 ]. p - // 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)4 C/ e9 q* @5 G: u
- ADC_DMACmd(ADC1, ENABLE);+ o$ g* S g: a9 A
-
7 o3 G6 A- H4 c - // 下面是ADC自动校准,开机后需执行一次,保证精度
0 a9 |6 P9 k% h" h - // Enable ADC1 reset calibaration register/ y0 C, I2 r4 a
- ADC_ResetCalibration(ADC1);
' i% V. ^! M0 b( s- m' w; D& O - // Check the end of ADC1 reset calibration register( F* N3 [ Q6 @+ O7 B7 M
- while(ADC_GetResetCalibrationStatus(ADC1));. v) m: ~' s E" t2 c( z
- e0 G$ u" S" C/ o
- // Start ADC1 calibaration' l, l- K# M! l1 k0 J+ O
- ADC_StartCalibration(ADC1);
) y6 j7 h1 B+ s; Y - // Check the end of ADC1 calibration
& `( J4 L5 _" F, O5 e( v ?- L* l: E - while(ADC_GetCalibrationStatus(ADC1));! L1 h( o+ ]9 j" a* [
- // ADC自动校准结束---------------# j, h" C: V1 T5 |0 c5 L& B+ i4 n
- ; _; {% f U) f L+ [9 N) K, @
- }! X6 c6 m2 h8 p/ }4 [
* w; u7 v3 ]4 z) d- /*******************************************************************************
0 B7 G* L% V5 }5 n2 M - * Function Name : DMA_Configuration% j6 |3 A3 @1 `2 s! O" ?' a
- * Description : DMA设置:从ADC模块自动读转换结果至内存: |5 F0 Y! w& ~% D
- * Input : None4 D4 q$ k. @. K9 g
- * Output : None& a6 G; u- `$ v6 k W3 E
- * Return : None# q3 l/ a( s" f* D9 j* i
- *******************************************************************************/, v" F3 ?; S0 s* y! N0 _
- void DMA_Configuration(void)$ y3 ^2 p% h8 G; b; b
- {, S) ]7 x1 a& r/ h( y( ?7 \
- DMA_InitTypeDef DMA_InitStructure;
( l# f4 d |7 S0 x0 l - 2 o$ Q3 u1 ^% T9 |! a3 v8 t
- DMA_DeInit(DMA1_Channel1);; |: r/ X% \+ Y7 c" Z3 Q6 R
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
" b2 _1 u: u, J: ?/ Z8 A - DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value;
" i2 D1 Z9 |" w4 O& g4 g - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
! a) O" o+ \ r5 Z1 O5 L+ @ - //BufferSize=2,因为ADC转换序列有2个通道
. {9 c: ]" G+ C% c - //如此设置,使序列1结果放在AD_Value[0],序列2结果放在AD_Value[1]
2 |1 x' E9 U( l( } [6 ~. J0 o - DMA_InitStructure.DMA_BufferSize = 2;
- U. ?) w0 g5 \6 h3 G! R - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
. o# W @8 b( P* l: X - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
. o' l7 o( ~% J0 J0 H2 R - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; @* W- n. j; }3 u# \7 H2 D
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; d9 d& p- w& J1 u) Q
- //循环模式开启,Buffer写满后,自动回到初始地址开始传输
8 C) Y. v+ x) w2 d$ E" r - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;4 i5 D4 B& S" }1 ~3 c
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;5 f" L8 Q& j, J
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
( G6 W, R1 f) g% N9 z - DMA_Init(DMA1_Channel1, &DMA_InitStructure);: L0 m" ~, ?8 U, r! ]1 e
- //配置完成后,启动DMA通道
+ p! X% W: l- A# G/ ?4 G6 H - DMA_Cmd(DMA1_Channel1, ENABLE);& R- H; U8 }' g+ X
- }
7 ]9 }7 h2 t6 z2 f2 K
复制代码
- Q" B/ k& M5 b: L% R, ?3 F
1 x3 q' p p9 Q |