|
概述 本章通过使用模数转换器(ADC),通过轮询方式采集多个ADC通道电压。
* {" E8 {7 w( M$ S0 b- C硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:
/ e7 H- B, g6 h; n! h ) { o/ b+ s m4 H, [6 ?* F
& h' i% x' k' E/ P1 ?4 e& u. o8 p
选择芯片型号 使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
, c9 P& d7 i1 u& M" T& @# \( q3 h
' z6 E* v& h8 [( u
配置时钟源 HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:; \9 X, w: @8 T+ k& w
+ W3 D! T7 S$ j
: S. ~1 |6 t V9 m& s5 S3 E5 l配置时钟树 STM32F0的最高主频到48M,所以配置48即可:
- E5 _3 R( X0 q% A & N1 a( ~) n4 d6 }5 m
$ k+ d& d4 o( Q4 o/ j串口配置 本次实验使用的串口1进行串口通信,波特率配置为115200。
- _& D. F' k+ K
& }( Y0 s8 p8 Y% g' Z7 A( a! b( g$ Q$ A+ x9 @5 v
5 x( ~5 p, @ f' P+ G! ?ADC配置 STM32f030中,有一个ADC(模拟/数字转换器),每个 ADC 有 12 位、 10 位、 8 位和 6 位可选,每个ADC有16个外部通道、2个内部通道和一个VBAT 通道的信号。 本文将开ADC的IN0、IN1、IN15一共三个通道,来分别读取ADC,由于串口2和IN2,IN3复用,故不使用IN2、IN3。配置如下:
6 ?7 `( g* i- d. {4 v- ?& ? 生成工程设置 注意在生产工程设置中不能出现中文,不然会报错。7 v, {# h- n6 Z. }" ^0 }0 ~
! A* g5 Q8 r5 A
4 }7 V, [" Z0 `# n! F! m* `
生成代码, i2 X) q5 A. @0 y9 T# U+ U# M
9 X7 r" l/ {( G( Z* ^% A, e
) D0 X8 t6 {1 u9 |" d; s
配置keil
9 B' j8 b% g, U* D; ~2 ?0 O) [2 p( F7 L- a
$ ^, q, L6 [! v% I" ?& w 在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。 - /* USER CODE BEGIN Includes */+ {: e: @ Q# |! L& H
- #include "stdio.h"
, |8 v8 Z4 K q3 Z# N - /* USER CODE END Includes */
复制代码 % C: Q" k- K& e% x/ P3 E W
函数声明和串口重定向: - /* USER CODE BEGIN PTD */) q& g$ O+ Z6 q+ U; W6 V. _; s
- #ifdef __GNUC__
, ]+ W' T6 g1 @% U+ q* t - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
7 L6 s# ~% `% R' }' D( C6 x* E* @ - #else$ D& w1 f! L0 W9 ` j" e! d" e& Y
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f). J2 }% k% |8 ^# I* Z# C$ ?: B
- #endif /* __GNUC__ */0 R9 G$ Y; Y t: L/ B
- 0 ?0 Y" m4 k) ]( v) a
- 1 b1 n! v |, t4 U: Z$ D+ ~
- PUTCHAR_PROTOTYPE
, E7 l1 c6 _+ e# z# w/ x! M n - {! l9 `" ?2 R, A8 B' k
- HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
6 h+ u( k- J/ z; \ - return ch;
' D. N/ R! X* w - }' w( L% d7 s. v
- /* USER CODE END PTD */
复制代码
, w; e. v, G1 `# [2 L 变量定义: - /* USER CODE BEGIN 0 */
" n4 A7 r; r; W* [& U7 b - uint8_t i;8 E1 j, e B& E/ J& d) d
- uint16_t adcBuf[3];//存放ADC) z4 l; W* V' b. L9 ?: L, ]- _
- /* USER CODE END 0 */
复制代码 1 Q t! [5 Q5 C0 p3 ?) d' }
主循环: - /* USER CODE BEGIN WHILE */8 P& K/ n2 O {8 q. H; g! w1 t
- while (1)
9 h" ^$ W! w1 ]% E( ~. l% a - {1 ~6 K* c! _. Z: P. x
- /* USER CODE END WHILE */ x- q/ B4 D: {. |) G
- 4 ~# g! f3 u/ F- {* k8 V; `# Y
- /* USER CODE BEGIN 3 */9 ~# T, Q, _: I
- i=0; . Q2 V2 a+ [3 L! ~5 M: L
- while(i<3)
# C4 j# A$ ~% p! O# _ - {/ B9 G1 J0 R# W; I8 ~1 P
- HAL_ADC_Start(&hadc);//启动ADC
) _1 E& {, |' k Q Y - HAL_ADC_PollForConversion(&hadc,0xffff);//表示等待转换完成,第二个参数表示超时时间,单位ms.
. }/ U+ q9 I4 }3 V( k/ j2 v - //HAL_ADC_GetState(&hadc1)为换取ADC状态,HAL_ADC_STATE_REG_EOC表示转换完成标志位,转换数据可用。
. Q/ O$ I0 G4 ~+ H' g! P/ ]8 B - if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc),HAL_ADC_STATE_REG_EOC))//就是判断转换完成标志位是否设置,HAL_ADC_STATE_REG_EOC表示转换完成标志位,转换数据可用
8 I r$ \7 L5 g - {) W% B. `1 O9 y. W5 P
- //读取ADC转换数据,数据为12位。查看数据手册可知,寄存器为16位存储转换数据,数据右对齐,则转换的数据范围为0~2^12-1,即0~4095., l5 [2 T1 Y: D' @/ C0 L
- adcBuf[i]=HAL_ADC_GetValue(&hadc);$ {) ~* a; F& Y; t7 @6 H* F
- printf("\nadc%d=%4.0d,电压=%1.4f",i,adcBuf[i],adcBuf[i]*3.3f/4096);2 b& E8 l) r9 W9 ~0 ^) b, w- M
- i++;
5 y% K' m" D% d$ a8 d9 N* e* X - }
5 H4 A7 V5 c( [/ I - }! D0 J+ R4 M" D9 p
- 4 |8 p H0 k3 \' Q$ u% u1 l) A; e! F
- HAL_ADC_Stop(&hadc);8 E- A7 ^- R, f1 u4 ]
- HAL_Delay(500); a: t3 y, H$ T( _/ b1 h
- }
; _* j. `2 w8 i6 S# L9 O b- O: j, y - /* USER CODE END 3 */
复制代码
/ W* m. v6 v! Q3 g1 b, U" W2 y% i$ Z) h9 G- t
演示效果 设定adc0口接3.3V,adc1口接GND,adc3口接1.5V,输出如下。; c) q" ]1 Y0 [' R( c) ]
0 O% {' l7 O$ l Y: Z6 C+ a
4 D1 ^( X' S, X' F5 I# B5 k
( @% O6 N: H/ f# a. h) K+ F* j
- `5 S0 {0 \, X: S
4 n+ p& `) m! E: ^, x, q7 c' l3 f. K9 y4 \; V1 T. ]6 V1 B
|