STM32U0系列微控制器中的ULP(Ultra Low Power)UART接口设计用于在低功耗应用中实现串行通信。
1 }( b+ i2 l5 e) w. K硬件特性:
1 }, v% P: X0 j# k- P9 ~2 x8 e, P 超低功耗模式支持:ULP UART具备在低功耗模式下保持唤醒源的能力,允许在微控制器处于低功耗状态下依然能够接收数据或触发中断,从而快速唤醒并处理通信事件,有助于降低系统平均功耗。0 Z2 v# A( r3 e( t! _( q
电源管理:ULP UART可能集成电源管理特性,如低电压检测、自动电源关断等,有助于在闲置时减少电流消耗。: c/ A' {# R1 j' l
专用低功耗引脚:某些型号的STM32U0可能提供专门针对低功耗优化的UART引脚,这些引脚在待机或睡眠模式下具有更低的漏电流,有助于降低整体系统功耗。
; [) a( C* e/ V4 N# g软件配置:' _6 f6 u# _( @4 s* t# M2 P
1 波特率设置:根据实际通信需求选择合适的波特率。ULP UART可能支持较低的波特率选项,有利于在低功耗模式下降低通信时的瞬态电流。
# u7 w9 u+ z+ U6 ?9 h2 数据格式:配置数据位(通常是8位)、停止位(1或2位)、奇偶校验(无、奇校验、偶校验)等参数,确保与通信伙伴的设置一致。
, W' s* E. l% v( s6 _3 中断与DMA:
* g; B; \$ F& d- G 中断:启用接收/发送中断,允许微控制器在数据准备好或传输完成时被唤醒,而非持续轮询,有助于节能。确保在中断服务程序中快速 处理事件并返回低功耗状态。DMA:如果ULP UART支持,可以使用DMA(Direct Memory Access)进行数据传输,无需CPU干预,进一步降低功耗。尤其在批量数据传输时,DMA可以显著减少CPU唤醒次数。0 w8 G! S6 C* Z+ Q* }0 h2 r r
4 低功耗模式切换:在进入低功耗模式前,确保正确配置UART的唤醒源(如空闲检测、接收数据可用等),并在唤醒后恢复正常的UART操作。8 `( N" O$ T1 g$ E9 O; I, F
功耗优化技巧:- W- d. C# ]. u; l) [& v
1 禁用未使用的功能:关闭不需要的UART功能(如硬件流控、校验等)以减少不必要的电流消耗。9 @ \9 G3 A6 A. R6 \ }
1 ]( E0 B$ f5 r% m; a/ C+ N7 B
2 节电模式:利用ULP UART的节电模式(如果支持),在数据传输间隙降低工作频率或电压,减小功耗。- P& W9 U9 z: B8 X
3 唤醒阈值调整:某些ULP UART允许设置唤醒阈值,调整阈值可以平衡灵敏度与功耗,避免因噪声引起的误唤醒。7 x% f3 _7 ~% l6 v- {, e
4 软件定时器:使用精确的软件定时器代替连续轮询,以定期检查UART状态或处理数据,减少CPU活动时间。
4 w6 [) B5 G, [
; A# H1 v& R0 m, q初始化:调用HAL_UART_Init()函数,设置UART参数(如波特率、数据格式等)。1 L% T$ k% `- f1 ?' U
中断配置:开启相关中断(如接收中断),并编写对应的中断服务程序。
- U. j3 O( @, Y$ R' X3 TDMA配置(如果使用):配置DMA通道,关联到UART,并设置传输参数。5 k3 A2 [) R- F0 H# I G
发送/接收:使用HAL_UART_Transmit()、HAL_UART_Receive()或DMA相关函数进行数据传输。
8 P5 R3 @/ q) n调试与测试:
2 z& S2 h5 I% G# N
) }% o; [% S$ K- [, ~& {5 ^& ^ a n
0 L5 V" o) k( e; F
6 Z) p& m, K, A1 \
MX_LPUART1_UART_Init初始化:$ G2 c P" A0 B/ m% {' h( v
. A" A* C* z1 ~) a5 n2 y
- static void MX_LPUART1_UART_Init(void)/ j' R+ d9 a9 w Z2 \4 }/ }( e
- {& p6 z& |% `0 v$ m
- : m* E) q* K3 ?; ?' f8 `2 |1 Q( U" t
- - P$ e1 G8 T9 E5 o
- hlpuart1.Instance = LPUART1;& c2 |* ^, s! ?# S0 u' L" V
- hlpuart1.Init.BaudRate = 115200;
; S$ ~0 O' S2 ?2 N+ g5 x4 f: z" H( o - hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;' G8 t3 q/ f& s. m$ D& o9 q+ D
- hlpuart1.Init.StopBits = UART_STOPBITS_1;$ v& r. v9 G6 E* v& c2 [
- hlpuart1.Init.Parity = UART_PARITY_NONE;
9 z' X* Y2 \$ E" D& { - hlpuart1.Init.Mode = UART_MODE_TX_RX;
/ n( D! n$ a: l3 S s$ | - hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
' T: ?; E$ K Z' H+ R - hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;) Y9 f2 i2 q# Y( e% {9 e
- hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;, a0 N" P! K. |. [1 `/ W2 G
- hlpuart1.FifoMode = UART_FIFOMODE_DISABLE;7 @2 W& `% p; L8 n
- if (HAL_UART_Init(&hlpuart1) != HAL_OK)
9 V, C# o0 a: h* w$ {$ i9 X$ V# X% T& ` - {0 h# x; I/ @ @, }2 `
- Error_Handler();, r9 |+ N7 C8 ]- F. i8 o
- }
2 l" v* }0 E0 q5 {0 h0 L - if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)' e _6 ^& ]$ H/ y, e: G
- {
4 w( c6 d6 K4 o# `% v$ L - Error_Handler();
9 h9 s9 _$ k; C/ \3 _( H* P2 ^" Y - }. h6 P, P# K- f' R
- if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)( h% m g4 s! W8 I3 ?- s: S# j
- {
5 z6 f5 l0 N7 L# L9 M* q. P$ K - Error_Handler();) X6 I. v4 I+ _( m! O3 n
- }- v4 R6 O! p' v& E( h
- if (HAL_UARTEx_DisableFifoMode(&hlpuart1) != HAL_OK)
) K4 s1 \" u2 k3 z0 s- E5 \) O - {: y. }2 B/ N) X1 Q6 R! `; F) l5 L1 v
- Error_Handler();
$ V; C( [- W* F1 e; l - }1 f0 ]; ~( _6 ^ w) Q3 b0 `" h+ C0 N, c
- 1 o3 z ~( u4 C2 H
- }
复制代码
" Z. g* i( B# b. J* p: N$ g# N: l# p4 r
- static void MX_LPTIM1_Init(void)/ }' u5 N- @' t6 H3 b
- {% f d. {) ]. [ m: O6 W# g
- l" y) P& R4 W1 j: W4 S9 z
- /* USER CODE BEGIN LPTIM1_Init 0 */
$ z D6 N2 O8 k$ n9 {" j - - Y$ \% x* D2 v2 q8 }4 U* O
- /* USER CODE END LPTIM1_Init 0 */ F& d1 K1 |2 a0 B& E. P
: h% c7 l9 r0 D- g$ G1 F# F- /* USER CODE BEGIN LPTIM1_Init 1 */
2 b! G3 U$ m- R8 l; h( {; y8 A - 9 J4 B" [! ?5 F+ |3 n3 w& ?
- /* USER CODE END LPTIM1_Init 1 */ }5 n5 m! V/ w$ `1 n
- hlptim1.Instance = LPTIM1;6 ~- U" m- `% {- s
- hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;3 }) I' {' R- U3 t3 M) V
- hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1;& ~9 Q* b- {; d: s* B/ N
- hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
* Q4 z/ b# C; L2 Y8 Q2 |. T3 A - hlptim1.Init.Period = 65535;
- ?+ g7 w/ ?. r- T - hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;+ b9 Z( E7 j8 P8 L: b0 o
- hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;% h" A" @( r0 E+ F5 V
- hlptim1.Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO;+ U `1 `* w8 p
- hlptim1.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO;: k+ s$ t# @5 F, @1 s8 h" d: s u
- hlptim1.Init.RepetitionCounter = 0;% O- d; g6 q+ C& t
- if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
$ B" v2 I A) a* `! s9 e" v - {
+ b7 T U( s& [" Z! _, D7 H' K5 n - Error_Handler();
: b9 A5 u/ u0 \$ a2 M! n6 g - } P5 t! M* A- ~. f
- /* USER CODE BEGIN LPTIM1_Init 2 */1 y* k/ r6 W# Z; q( }- ~
# H0 [3 n; T$ Y$ `1 J- z t% d- /* USER CODE END LPTIM1_Init 2 */
, z0 E5 v( ]8 c4 Q; \0 c - : Z4 }0 [/ v: x
- }
复制代码
; J, `* L$ R, `: @
) h: O: t2 e6 b( I4 q
! V! d& k, ?3 o这里可以选在HAL库 LL库: M& R& v# ]) `) ~* R* n* c5 p
8 Y: m/ }& t. O% i* F* W" h R0 j% T. n6 Q
- HAL_UART_Transmit_IT(&hlpuart1, (uint8_t*)aTxBuffer, TXBUFFERSIZE);3 t, J4 j6 S, T h0 L
6 d6 ?0 l6 ?' }7 Z* B% ?- HAL_Delay(1000);
复制代码
& d7 F# K. }) P' Y8 P8 D8 \. d% z' H8 Z, a( M! l7 |" M
" M. E! F) U7 y p9 ]+ l$ q
运行如下:
( F1 X1 W8 R4 e2 Q) U
- n- \/ |# u/ s4 k# z, ?
8 r( d% H1 ]/ U: G& [3 w
+ y, p) P& h; Z/ K, g% _7 E4 F
/ W/ f5 k1 f! M9 s
|