1 概述
5 y4 U+ v) U9 c实验的代码已经上传,无需积分。0 B' n# \$ }" `1 ]% l
# d3 D# p2 B7 V. G$ j) ~
1.1 资源概述
+ c' l6 e4 ^- h/ T8 _开发板:正点原子STM32F103 Nano开发板0 g- g4 |& f1 l6 O% y
CUBEMX版本:1.3.0
! b D7 Z! w* d7 ^) X9 j [MDK版本:5.27
1 s+ d+ O O9 @* P主控芯片型号:STM32F103RBT6
6 G6 X w0 {, |( a4 s6 r# _( D+ @5 s9 }
$ r0 K: _' {/ B
8 w" \! o+ i" }( L. g# G6 P0 x1.2 实现功能, r9 I$ [* S m0 e! t( T0 p# u# H
1,移植野火ADC使用DMA传输例程,实现读取B01的电压,并通过串口打印出来。野火的程序使用的RCT6芯片,引脚与RBT6相同,改动比较简单。
4 P- u, F7 W' [. |
% @2 f3 f) U# _! J/ j4 j2 D2 程序实现
7 S0 R& s- z0 x' w$ T* i* Z* Z; C7 t2.1主程序' p o3 d3 g; Y5 a* J
- ) b/ O% ?) R: K& I
- /* Includes ------------------------------------------------------------------*/
4 V; l) G7 V. A6 B - #include "main.h"
2 I; u) s7 \! s# H6 E- X' D2 K" A - #include "stm32f1xx.h"
: ?) u' m0 B8 w' P - #include "./usart/bsp_debug_usart.h"
' p. ~& a9 j$ p) ^: r$ |2 q - #include "./led/bsp_led.h"! u+ r; z2 V# L! y
- #include <stdio.h>0 n3 v# U9 w4 m9 a: Q6 z: w9 X
- #include "./adc/bsp_adc.h"
& g, [$ y! G+ w' \, Z8 m
! y6 t8 F+ G, t$ A- // ADC1转换的电压值通过MDA方式传到SRAM$ O, m& i: H3 D' [- |, _
- extern __IO uint32_t ADC_ConvertedValue;
5 r' Z( z* D3 \. X; A* c% g, S1 H* z- ]
1 d1 P( S/ x; \+ Q$ F- // 局部变量,用于保存转换计算后的电压值
. k7 I o. U: r% W+ ~# N - float ADC_Vol; , A/ a( s9 ~7 ^: S+ N9 w+ K4 S' a
2 ~& m, }9 Y3 s) o, M- static void Delay(__IO uint32_t nCount) //简单的延时函数
. t6 t( P5 L7 q - {
$ X/ j8 [; D- n4 a - for(; nCount != 0; nCount--);2 ?: u" W, l; S, Q6 ]1 a
- }5 m: [7 d) v" t+ f) J. q( r' `
- /**6 U, y7 h8 l) i9 O' ~; n U
- * @brief 主函数
+ Z$ T! l4 \- ~# M( g) ~- @& @ - * @param 无
9 {# v8 m' Q4 i; _ - * @retval 无! j$ d& J$ S) j# k
- */+ B" f2 Z A# L
- int main(void)
% k& F0 z2 C/ ~' L+ ?+ {+ C' d - { & i( l5 }- }0 Q3 ]- y9 ?' b
- /* 配置系统时钟为72 MHz */! m3 U5 F+ S0 V! y8 L7 s
- SystemClock_Config();' x0 X/ W' r& u" Z2 _( h: D& G* ^( O
" _$ Z7 o. p( z9 B: w; C( T- /* 初始化USART1 配置模式为 115200 8-N-1 */2 W% o1 a1 @2 }! D% F& s
- DEBUG_USART_Config();
4 |+ F+ l+ e) a5 Y0 v- x: d5 H - , J) @* `& B# k' [. F* l
- Rheostat_Init();" x) ]5 z& P% ^3 Q9 }
- while (1)" [+ `. ]7 R4 ^& {
- {; V# { S5 f3 C: h \, L2 I% n
- ADC_Vol =(float) ADC_ConvertedValue/4096*(float)3.3; // 读取转换的AD值
9 O$ R. e$ v- z1 D9 m7 k- x - printf("\r\n The current AD value = 0x%04X \r\n", ADC_ConvertedValue); * f0 U. R( N: ]6 V
- printf("\r\n The current AD value = %f V \r\n",ADC_Vol);
/ v( e) J9 W3 o1 K$ j/ p+ J - Delay(0x8fffff); 8 P$ x8 S# f0 Y& V
- }
, e; X6 [, M: f( w ~3 J- Z - }, J" ]* O/ W9 ?: g- q
- ' {( e' J. F% L, e2 w
- /**
9 x/ G8 t0 q6 m7 @ G7 c - * @brief System Clock Configuration
, u' z: h- f0 K' A - * The system Clock is configured as follow :
# N* d, G- ]" H8 s, z$ j/ _ - * System Clock source = PLL (HSE)7 l7 r* D! }8 a) ~3 [* d" F& `
- * SYSCLK(Hz) = 720000005 U ?9 h I0 G* o- u- W4 N+ K
- * HCLK(Hz) = 72000000 d9 ^# R8 Q+ Q$ J% v& M0 [( [
- * AHB Prescaler = 1
P& i/ U- Q6 {. D' B4 X - * APB1 Prescaler = 2
( b' R$ F! p! `0 C6 z: c - * APB2 Prescaler = 1- O: Q9 h: T0 a
- * HSE Frequency(Hz) = 8000000
. x: w' C# }! q7 O9 U - * HSE PREDIV1 = 1
2 z+ A7 ]% Y) f/ t1 f - * PLLMUL = 9# Z; E5 w K* c0 B& v0 S* W: c. p
- * Flash Latency(WS) = 2
( E' D5 F; b* k; _; A - * @param None, l' V6 }6 R3 C/ q3 ?" }: p
- * @retval None: u H4 k3 G+ O3 n
- */
* Y2 H2 e6 `4 }% q5 y% c- D - void SystemClock_Config(void)1 f" F$ r. [+ S! ?
- {
: ]: ]) a3 o, M* x" ^8 `6 M0 l+ V - RCC_ClkInitTypeDef clkinitstruct = {0};7 }0 D3 ]. t0 V" S5 T; Z4 p
- RCC_OscInitTypeDef oscinitstruct = {0};
' v8 ^* s4 j' _+ m% M - ' u& I' Y6 J1 s, e
- /* Enable HSE Oscillator and activate PLL with HSE as source */
# |( r Q6 b5 e5 O* P: k - oscinitstruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;- D; `% v E, d8 v& @9 S+ y
- oscinitstruct.HSEState = RCC_HSE_ON;
' I, h( G1 i, g" c( d& H8 ? - oscinitstruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;( }) o& A j: W
- oscinitstruct.PLL.PLLState = RCC_PLL_ON;6 }3 P5 p3 K9 I, D. [
- oscinitstruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
# E# a, M7 H' M1 ]/ J* J, E - oscinitstruct.PLL.PLLMUL = RCC_PLL_MUL9;+ A, g* ]( J4 m. b5 f5 @* _) l! }2 c
- if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK)
/ S( n2 m1 G- c0 v1 N* C" t" y - {" e8 Q4 S% H$ x" k6 X# U. {( O
- /* Initialization Error */+ m0 \" @1 H& Z- a8 u8 L
- while(1);
* |4 U( [! B7 c: v/ W \% C - }
" ]+ ]: _2 r! w+ Z$ t
. H* x5 G# q0 c0 ?' G. U- /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
/ t( H% H% r- Z; ?5 x* M - clocks dividers */9 H9 k. o) |9 B8 W
- clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);0 w+ g5 Y' U! v# `; {: b+ H4 a t
- clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ O8 |/ @0 u# [% S# ?0 e! e - clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
7 w8 k9 R* n% y/ f' f - clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
! L4 K7 O2 [, N/ {, v - clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2; + \* Z1 K1 ? C9 E0 G
- if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK)+ X0 l5 {2 g* n: N, J% _. `
- {9 P, b( N1 u7 l- @( S( W; S* n
- /* Initialization Error */
/ w$ |. r6 z3 L; W2 f+ R5 `8 N - while(1);
# ^" w8 D% F; U- e* F I - }
& a- r" w) @5 S' k8 ^. f1 {1 ` - }
复制代码 , f( [: f. p) m2 F$ r$ ~
2.2 ADC程序# o& G4 K! r) I' A
- #include "./adc/bsp_adc.h"
. l) f) P' o1 e+ K6 {6 @5 @
2 T( q- u4 _4 l- __IO uint32_t ADC_ConvertedValue;
8 r1 ?9 `% {9 j4 @( N3 p2 N - DMA_HandleTypeDef hdma_adcx;
/ y i8 g2 @* V* Z1 {6 v( C - ADC_HandleTypeDef ADC_Handle;) U) p. W" x" j! j7 y
- ADC_ChannelConfTypeDef ADC_Config;: V( Y$ X1 r8 r+ y$ V+ ^: ?
- ; `. F/ E/ {9 e# E7 M" B" S
- static void Rheostat_ADC_GPIO_Config(void)
+ D# y$ p$ t5 E% K - {
2 M0 C! ?" p1 Z# J - GPIO_InitTypeDef GPIO_InitStructure;1 N9 I2 R* n7 n9 o) p
6 X+ o: F/ D6 H1 X- RHEOSTAT_ADC_CLK_ENABLE(); . t" m. r, N: J# ^
- // 使能 GPIO 时钟
1 Q2 P5 \* ~6 w6 u% {7 S' B - RHEOSTAT_ADC_GPIO_CLK_ENABLE();
' C$ m: B) U. V* s3 r - ! y5 `4 l8 p$ e
- // 配置 IO H: k. j( F4 H# b4 `9 W
- GPIO_InitStructure.Pin = RHEOSTAT_ADC_GPIO_PIN;
. g7 y/ C* p* y, J* t - GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; 4 R3 t6 \; u, e0 x3 g$ d
- // GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉
. `+ W# W2 `5 l7 L7 v$ d( Z; B - HAL_GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure); 4 ^* ^: Y; @- n. \- ^
- }
8 [/ _ r! r2 M
" D" ]" B) o0 G" |; \- static void Rheostat_ADC_Mode_Config(void)
; D9 k& K: Y6 l3 e+ t6 j - {" Z% p, s! j3 Y
- // ------------------DMA Init 结构体参数 初始化--------------------------
# b w+ l& B7 K! L5 f6 ` - // 开启DMA时钟/ g4 L5 E+ e1 J' V, f& y
- RHEOSTAT_ADC_DMA_CLK_ENABLE();& T% y W- e, w- @* ~ q) Q
- // 数据传输通道
1 |3 M" ~( _# p+ f D0 L - hdma_adcx.Instance = RHEOSTAT_ADC_DMA_STREAM;- ~' }- U7 G! ^& J: {# o: x/ t
/ I. |6 w# c9 N5 s- hdma_adcx.Init.Direction=DMA_PERIPH_TO_MEMORY;; //存储器到外设
# R1 @( s0 I) ?/ ] - hdma_adcx.Init.PeriphInc=DMA_PINC_DISABLE; //外设非增量模式0 n9 v7 a' |) Q9 O1 _
- hdma_adcx.Init.MemInc=DMA_MINC_DISABLE; //存储器增量模式 4 {- h. g7 l- u# f1 R C
- hdma_adcx.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;//外设数据长度:16位$ ^. w. F* z1 y% _* T' ?
- hdma_adcx.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD; //存储器数据长度:16位,错误已经修改3 K; j# ^ K; d2 D1 K$ u. D; B
- hdma_adcx.Init.Mode= DMA_CIRCULAR; //外设普通模式9 P8 P3 z$ R& u( a3 T4 X. _' _
- hdma_adcx.Init.Priority=DMA_PRIORITY_MEDIUM; //中等优先级
9 k; _1 b5 K5 e
) L& E, G0 U D) O2 y- //初始化DMA流,流相当于一个大的管道,管道里面有很多通道
}/ ?2 Z' V) H4 T! } - HAL_DMA_Init(&hdma_adcx); 3 j" ]0 {, a+ w9 t' O
- e% S; A$ j# ]2 I- __HAL_LINKDMA( &ADC_Handle,DMA_Handle,hdma_adcx);0 Q" s6 Q# |- L& X L2 P0 l; V
! j8 V1 w6 X m! o$ w9 J+ \& o- //--------------------------------------------------------------------------- l$ t+ Q1 q: m
- RCC_PeriphCLKInitTypeDef ADC_CLKInit;
/ v& i, U% f. b1 ? - // 开启ADC时钟$ G8 b- k5 I; C- L5 w0 f
- ADC_CLKInit.PeriphClockSelection=RCC_PERIPHCLK_ADC; //ADC外设时钟7 k3 d. T ?3 r$ J x1 V4 P% z I
- ADC_CLKInit.AdcClockSelection=RCC_ADCPCLK2_DIV8; //分频因子6时钟为72M/8=9MHz+ E$ u% B8 Y1 [* H( I, ^* w2 Q
- HAL_RCCEx_PeriphCLKConfig(&ADC_CLKInit); //设置ADC时钟
& Y8 s: M6 x6 q$ t: k, g
) W7 g8 M+ M7 O; A* V* r5 H- ADC_Handle.Instance=RHEOSTAT_ADC;" J; E8 s6 x9 p0 z
- ADC_Handle.Init.DataAlign=ADC_DATAALIGN_RIGHT; //右对齐
8 ]# [" k U h4 C$ R - ADC_Handle.Init.ScanConvMode=DISABLE; //非扫描模式
8 K8 |: s' L* e5 y) m - ADC_Handle.Init.ContinuousConvMode=ENABLE; //连续转换" {, y9 X. ^9 m+ R( N
- ADC_Handle.Init.NbrOfConversion=1; //1个转换在规则序列中 也就是只转换规则序列1 5 U$ G! `( x* b, ^' M# S# @
- ADC_Handle.Init.DiscontinuousConvMode=DISABLE; //禁止不连续采样模式
0 U* B, D7 q2 C - ADC_Handle.Init.NbrOfDiscConversion=0; //不连续采样通道数为0% R8 n) F) _$ Q4 Q+ q, E) A
- ADC_Handle.Init.ExternalTrigConv=ADC_SOFTWARE_START; //软件触发2 q1 Z1 F. v2 m" L, L# p
- HAL_ADC_Init(&ADC_Handle); //初始化 ( J! ?) S2 _3 I% i6 W* ]
c0 x, m7 k0 \- //---------------------------------------------------------------------------1 F4 f9 ^1 L0 x: @0 g( v
- ADC_Config.Channel = RHEOSTAT_ADC_CHANNEL;
0 N8 h# t$ F- i" S - ADC_Config.Rank = 1;
- J; r1 m/ H. E1 H7 v - // 采样时间间隔
; Z2 }9 |! B8 y9 r! r8 [& S- N - ADC_Config.SamplingTime = ADC_SAMPLETIME_55CYCLES_5 ;
+ Q3 F/ R3 ?5 Y+ L1 v& l7 I! k - // 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期
/ w9 t& K, n& n! F - HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config);
/ T5 |8 O, I: q: Z6 z. o* @ - 8 W3 y7 N! [/ O
- HAL_ADC_Start_DMA(&ADC_Handle, (uint32_t*)&ADC_ConvertedValue, 1);
5 R1 N4 K- n6 V - }
u% X% c1 k- r' Z1 \ - void Rheostat_Init(void): [6 s3 f7 Z4 c7 `% o
- {9 n( a- N: N) X) G0 ~4 T7 a
- Rheostat_ADC_GPIO_Config();
& `' s1 i% l9 u1 A - Rheostat_ADC_Mode_Config();3 ^% M4 u. I- I' s
- }% m! [+ b$ B. X
复制代码
9 m$ S1 m/ H/ C4 `) R2.3 ADC头文件* P4 H7 h) C9 N1 ~" k5 w) I
调整端口定义与正点Nano保持一致,这里需要注意的是,GBIOB1对应的是ADC_IN9, 对应的DMA1_Channel1(通道1,而不是11)。" X. A% p* j. F5 ^: {4 {
1 C8 F1 T& }( P
- #ifndef __BSP_ADC_H
) {# H1 F) n1 `( }& ?3 l, l - #define __BSP_ADC_H% U. N4 }+ O2 I$ H
u, u( `+ D/ q) N0 n- #include "stm32f1xx.h"
" h$ M2 }' C/ e! E$ t - k" y0 Y- V/ V) C
- // ADC GPIO 宏定义0 \& V0 K% X# Z; P
- #define RHEOSTAT_ADC_GPIO_PORT GPIOB6 g" s: Z* x1 V; K
- #define RHEOSTAT_ADC_GPIO_PIN GPIO_PIN_1) r1 g) }& L3 \" t( X3 c
- #define RHEOSTAT_ADC_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
6 a7 P* \( K3 o2 m$ J
' A' Q' R5 N3 r4 e- // ADC 序号宏定义
/ c/ {1 v. g1 n! K8 Q1 Q5 ] - #define RHEOSTAT_ADC ADC1& F; o8 J6 V' P3 p( E% u
- #define RHEOSTAT_ADC_CLK_ENABLE() __HAL_RCC_ADC1_CLK_ENABLE();
# N% O6 ?1 `$ `! D6 F - #define RHEOSTAT_ADC_CHANNEL ADC_CHANNEL_9
3 y. P- l' w* ~/ a6 D. | - ' w& d1 R5 W7 S/ D3 A6 D
- // ADC DMA 通道宏定义,这里我们使用DMA传输& l/ B8 a6 [, T# T; _/ `) f; [7 U0 d
- #define RHEOSTAT_ADC_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE();
1 S$ C/ |: Y9 ~ - #define RHEOSTAT_ADC_DMA_STREAM DMA1_Channel1" L: f9 }0 A( F. ?
' T# s; }0 `. r2 b5 p( }. y- void Rheostat_Init(void);, e/ E) d- Q* f% f0 n/ ^
) x: @0 G0 ]4 j5 o: B) d- #endif /* __BSP_ADC_H */% i+ U7 r7 H, [% i
复制代码
- j* z. L; [$ q* y, P0 s; ^3 程序调试" Q/ O0 p/ U( C9 K
在程序调试过程中,串口打印一直无法输出正确的值,都是小于1的小数,而且调节滑动电阻时,数值会发生变化。由于是移植的例程,一直怀疑是我自己改程序导致的,但是经过换成别的开发板,而且ADC端口不改的情况下,还是不好用。如果开始了漫长的查找过程。路程如下:# i e4 i+ H6 f
1.使用CUBEMX生成一个ADC DMA传输的程序,正常运行没有错误;
4 k. G. p% V$ L, w7 p7 o: o, ]9 V! L2.将生成的程序,ADC以及DMA相关部分去掉,加入野火例程中的ADC相关文件;5 S( T4 W: Z& _; U9 d2 M5 `
3.将CUBEMX生成的ADC相关文件加到野火程序中,运行正常没有错误。
2 k! ~, [& P$ k& j1 o( Q4.运行调试发现不好用,只显示小数;
: L P# z7 V1 ^9 O$ s5.将原CUBEMX生成的函数,一块一块加到野火程序中去,替代旧的函数。最后发现在配置半字时出现问题。! c4 | L2 S6 k; C8 I; C
例程中错误的配置/ I" n; t2 ~* c- F7 `7 j8 _
- hdma_adcx.Init.MemDataAlignment=DMA_PDATAALIGN_HALFWORD; //存储器数据长度:16位
复制代码
c x) j9 |+ P" S3 K: W而正确的配置为(P改为M)
$ n0 w5 P9 [1 b5 r
0 }& S3 }: w$ r# O8 b2 }- hdma_adcx.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD; //存储器数据长度:16位
复制代码 , `; E! M* d5 @4 U6 Q
修改后程序调试OK,下面为更改后和更改前的结果,在错误的程序中,第三位的B丢失了。正确的位B37,错误的为37。
% A6 o% _, S" {6 f4 D6 c' E: v# h
8 W9 h, D; b, i+ F
% K: M+ B8 G3 M* q& P- |: N# T& Y+ w+ j; [( q- ]1 \
4 查找原因
! |) v6 w0 E, ?查看官方手册继续查找原因,将程序里边的定义一层层翻出来,结果如下。# s" S: g# o4 x0 Y
/ w$ t8 |. H2 B! k& s$ W1 {错误赋值函数
: ?+ |1 g+ Y9 e% E
5 V5 M0 u, K# ~& l5 e- hdma_adcx.Init.MemDataAlignment=DMA_PDATAALIGN_HALFWORD; //存储器数据长度:16位6 n- R9 B" {8 S" L
- - d4 z2 j; i, ], H0 T
- #define DMA_PDATAALIGN_HALFWORD ((uint32_t)DMA_CCR_PSIZE_0) /*!< Peripheral data alignment: HalfWord */
$ [& {7 h0 p; \8 ~$ L
. R) V1 H5 B. }4 V$ A- #define DMA_CCR_PSIZE_0 (0x1U << DMA_CCR_PSIZE_Pos) /*!< 0x00000100 */
: F+ t2 D9 Z. T* d+ D- B2 ^5 Q - ! H1 s7 a/ E& e" w0 Z
- #define DMA_CCR_PSIZE_Pos (8U) 2 J% G( o* v0 C c
- . G7 f. ^6 c# N7 ~
- STM32F1中文参考手册V10里边关于DMA配置寄存器的说明
# d, |# r* E3 p/ ? - 位9:8
, v, C m1 V& U6 l$ p$ w* w - PSIZE[1:0]:外设数据宽度 (Peripheral size) 这些位由软件设置和清除
/ E5 T, F; Z/ h6 a' H& p - 00:8位 ! A( V' ?7 k, _
- 01:16位 " Q3 y( i* l" U) {9 ~; q( Z4 X4 G5 m
- 10:32位
% O( d9 B8 K0 G0 ^6 \# Z- A2 P - 11:保留
6 `+ ]6 m5 J+ N" _& M3 H2 g8 [ - 这是错误的设置,导致外设的数据宽度设置了两次,而存储器保持默认00,即为8位,而ADC为12位右对齐,最高4位丢失。 7 ^1 e; O: i: B& [) {$ T5 X. a
复制代码 " X) R1 K- W3 ]! X' ~- f5 C8 m
正确赋值的函数8 u0 R3 M7 A) }3 ]/ ]$ g
! v5 O7 W. {4 c$ A2 |7 g
- hdma_adcx.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD; //存储器数据长度:16位+ r q4 x! u9 S! U; {1 H# F* r
- . J/ ]' A( r8 }8 W/ R
- #define DMA_MDATAALIGN_HALFWORD ((uint32_t)DMA_CCR_MSIZE_0) /*!< Memory data alignment: HalfWord */3 x6 r+ ]3 E' k' A) p& _( Z
- 5 U L% L* n4 S, T1 Y& B& T4 u
- #define DMA_CCR_MSIZE_0 (0x1U << DMA_CCR_MSIZE_Pos) /*!< 0x00000400 */
3 m6 V! C8 E- @! f. D - ( m% k M7 i, H" ]
- #define DMA_CCR_MSIZE_Pos (10U) $ [/ S T* ?! q" b, s9 S
- G% i+ t9 M1 J! S4 z. ~, ^( X- STM32F1中文参考手册V10里边关于DMA配置寄存器的说明
7 e1 ]; \7 _: ?! E0 I8 N8 l - 位11:10 * n; \% `+ y4 u
- MSIZE[1:0]:存储器数据宽度 (Peripheral size) 这些位由软件设置和清除
- w( y; _6 F# O, {' [: Y* M! Y - 00:8位
; ?( ^9 g/ H* K& `! H0 C+ ]; K: ] - 01:16位
2 D6 t: ?7 M( ?# L$ W& T - 10:32位
: A3 Y6 y0 l. y+ j, |; ~ - 11:保留' Q$ I8 d3 U) @8 I! {5 M
- 这是正确的设置,存储器设置位01,即为16位,最高4位不会丢失
4 J( I) S- ~: C/ l+ q
复制代码
" C, P- j6 B; T5 z6 x# \原因分析和实际情况一致。2 z7 p' T, W: w4 `3 r# t; B4 G2 v6 o
查看野火给的资料,发现里边的这个地方是错的,和程序保持了一致。这个程序应该是被误写(使用自动补全),然后编译后实际验证没有认真检查导致。8 w8 W2 o2 o2 y7 ^- j3 c- `0 K$ D
6 a: |5 w. |% s5 J& }4 | I! ?0 [% k8 j6 v& G* w8 |5 F7 ]
N) v8 u$ k g) @9 j# ~
|