最近为了学习HAL库和熟悉STM32CUBEIDE软件,用手上STM32F407板子做了小工程,里面包含有串口1,串口2的使用,定时器中断,EXTI,DAC输出,ADC的DMA读取和用SPI驱动的TFT彩屏显示。
# U" d6 Z1 r4 |% H. t" z4 ^先放一张工程做好的图吧
~/ X; _) _/ q. E' P& v
/ D* z2 J& x# E# ] i% K程序很简单,用CUBEMX初始化后,只需要自己写回调函数和主函数的部分,先看一下外设的CUBEMX初始化;
: F. Z+ ^. u. t$ ^6 o/ H4 H1 N(1)USART1和USART2
7 D2 L& _$ m$ A; o; b
8 z$ d, C @5 S/ b$ A$ B
5 j; k2 \: X- F& n两个串口的初始化是一样的这是设置的NVIC中断不同,后面放出工程的NVIC配置。
, n! C; n0 f+ N: r! d; O- D(2)TIM31 W) u2 r' l4 {" k' M3 \1 `7 z
; o- X& a2 o& c* ^

+ `4 d! G, X3 N0 U2 ?- C/ C定时器的配置要多一点,但只用定时器则比较简单
. L# y. g; r; M' Y+ O(3)ADC6
$ i2 u8 D& Z' C' ]# `# }% c I# Q9 d " ]9 s1 n8 n* g! O: O
/ ^ e* \# q. q# V
; O. ^' {& e# [+ @0 j( [1 K0 D# F
$ Q! F1 `* d; _8 i, b$ R
ADC的DMA读取设置
5 _( {, X2 b g# g$ [3 J1 x
4 P% Q5 K& ^: \% B' v. @(4)DAC11 L+ k$ g1 {0 p r ~5 T8 e

6 L! V A+ y5 t6 }0 M(5)SPI2% Z @( W! P% A% W+ Q8 N2 `9 O5 `, q/ g
q, \2 _6 E9 H( f
(6)EXTI* R5 v' x' k) b
( s! h5 g" [2 `1 f' ^7 p; E2 P
(7)NVIC
- a9 n# G3 e3 T
# v+ t A& K& v7 W( a; R(8)GPIO' s$ z8 b# @( R2 ~/ D O* e2 S$ b

$ k, X$ A1 F9 i& L, n6 }% n& E所有的外设初始化配置完成了;' A& _ X" T$ F- i7 f. `
8 A8 C1 Z N2 M p# Q/ I9 ]
下面看一下中断相应的回调函数,在HAL库中,写中断处理函数和标准库不同,我个人认为现在只需要在回调函数里写内容就行了,我们看一下HAL库里面的IRQ函数,比如HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)- void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
" Y K& p. d7 x0 C+ ^ - {
. ~/ I& f, U6 d% ? A3 Y - /* EXTI line interrupt detected */
- Y4 V0 a/ f F. e0 @- T% e1 Q9 f - if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
: _9 C* f0 W+ y. ]* a - {- F( }' U) H1 @6 W( x
- __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);( D4 n; G( f6 G
- HAL_GPIO_EXTI_Callback(GPIO_Pin);# |- A8 h& a! b5 d8 n+ H7 o8 Q
- }5 g7 F' x3 b% c7 I, N" w, ~7 _
- }$ _4 o( A r) O! R% y5 x& D) X+ [
" ^" V$ M% W: [: z2 | H" Q- t- /**( ^! u: @' v1 T, q
- * @brief EXTI line detection callbacks." d2 _4 n: b& ]* J, S3 x6 E& X) e
- * @param GPIO_Pin Specifies the pins connected EXTI line) i' z2 e. m7 J
- * @retval None
- P0 u' u- Y# y - */
. @) B% n, `0 @. P/ T - __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
, A' b# _1 o8 Z1 p+ T - {/ S8 S) p& X* N+ |) I
- /* Prevent unused argument(s) compilation warning */- ^. g0 D0 B: I' W; L
- UNUSED(GPIO_Pin);: ~5 V6 `1 `7 l4 ]) N6 x# H
- /* NOTE: This function Should not be modified, when the callback is needed,* E0 G. K$ `6 V$ U3 B
- the HAL_GPIO_EXTI_Callback could be implemented in the user file5 @8 L" f, ~& F2 ]4 U9 a+ | X
- */+ [* r" k8 W, |9 A9 F2 c( }( u
- }
复制代码 HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)里面会调用 HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)函数,而 HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)是需要自己编写。
2 H7 M9 T5 z3 w( v' ~* n& h; {, P. R. p2 l
(1)串口
7 h; M' m. V* @& h& d3 T, |% ?9 _0 T, P, B# D; G7 a- i
- uint8_t RX_buff[RX_len];2 V o9 @1 N; y, ?% r0 ?2 ^
- uint8_t RX_temp=0;- q1 \/ q: D1 C! U0 E/ q- N( f+ S
- uint8_t RX_i=0;
/ h. _% W5 e: h* j" \, _4 I! [ - uint8_t RX2_temp=0;
) P+ k3 I7 M. r5 y; b0 \5 k
, s8 i a+ l: L& P) U7 ^4 \- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)! O. K$ F# }+ E5 n. E2 ]4 m" P# c
- {$ S( m2 u7 c: C- \/ ?8 @' }+ t
- // uint8_t buff[10];+ i4 G/ K! j$ V' p+ D2 v5 u
- if(huart->Instance==USART1)
. Y. @5 r7 g. M: v0 F) `3 E - {
2 ^; Z" I n+ p$ e8 N, Q - //HAL_UART_Transmit(&huart1, &RX_temp, 1, 1);3 K9 I# E6 w; A, f5 A- S" T
- if(RX_i>=RX_len)! y! d0 V+ }4 ~
- {* h( Q3 F$ D4 D; r- I. z
- RX_i=0;. w R/ E* Z0 p/ `9 V& w% e B
- HAL_UART_Transmit(&huart1, send_buff, sizeof(send_buff), 1);
% O6 v) p8 d6 ?& m - memset(RX_buff,0,sizeof(RX_buff));
1 N/ C" Y G$ Z7 u" h8 U* `3 P4 g - }
! o$ ?. y3 D# K& Y1 |$ l# q* I( b - else
' I( ^. ~9 k/ N( h; j# f' b - {# O+ b9 o& s8 a
- RX_buff[RX_i++]=RX_temp;' @5 X4 w1 k. ?; c v, W. A: l* |
- if((RX_buff[RX_i-1]=='\n')||(RX_buff[RX_i-2]=='\r'))/ ]3 |* x" F" I* @
- {
9 ^6 q0 K, x0 C( d+ e - HAL_UART_Transmit(&huart1, RX_buff, strlen(RX_buff), 10);//Timeout 不能太小,也不能太长1 X" l$ v9 _! f* {% d1 k
- memset(RX_buff,0,sizeof(RX_buff));
) \* ^; }# H# i- |0 m9 V% ] - RX_i=0;& X+ Z/ a- a' o# U' g
- }: Y [! [' f) o; p
- }
& i9 c6 M1 T( I( ~ [& _0 t - HAL_UART_Receive_IT(&huart1, &RX_temp, 1);
! [& k4 j% ~* B+ L. c$ N - }
) Q* l) t9 x ~, d' F
: W: B# _% d1 s- {- if(huart->Instance==USART2)/ b* o4 F" O$ H v8 f ]) T
- {
) V) C7 C5 [7 p8 {5 l - HAL_UART_Transmit(&huart2, &RX2_temp, 1, 10);
. V0 `4 }/ ^7 i0 |& z5 Z7 D+ x Z - HAL_UART_Receive_IT(&huart2, &RX2_temp, 1);
( m4 P! u, \, P0 c9 R - }- {9 p# }2 z, @1 Y
- }
复制代码 (2)TIM3定时器中断
" `3 S7 _8 A# Q; i& j- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim). n' N( X( \" C+ e M
- {
8 B b: K9 }1 I4 S - if(htim->Instance=htim3.Instance)
2 g4 V' Y& Z0 t( T, u2 h - {' V4 `( p1 e: H; E% o0 q
- HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);! J- W3 i+ V* {0 K1 U3 P6 g( H3 E& X
- }
# ?) @( ^; H$ w' a' Z - }
复制代码 (3)EXTI中断
: V& a R/ {. R v, H- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)+ d9 ^2 J# M% D
- {+ [, N+ x5 ?+ ?7 e+ }
- HAL_Delay(100);
) e2 P" y4 a( \0 M1 e* G$ d - 0 P5 g5 C1 t$ s
- switch(GPIO_Pin)5 h9 B$ M. D! `# m" @+ P
- {! [# ]6 ~5 d% X9 _$ x
- case WK_UP_Pin:* p: h" S3 H' U* _
- if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) == 1)& o) u5 @7 ?3 W: [* V' a
- {# n" |/ h& q6 z% I4 N" k
- HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);! r9 T5 b5 P$ z1 Q
- DAC_Value=3299;$ z% a$ M9 G; b& d# k+ S
- }2 a) w) \6 E- j6 k+ A
- break;
& W$ @% y! M) D8 B3 e0 i - 1 f7 H* s# j/ E
- case GPIO_PIN_2:0 ?% _ a" z1 L1 i @7 H5 P+ \3 h% g
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2) == 0)1 K; d4 U; b3 i/ K
- {4 q2 c6 X) F' m, W+ ?
- HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);' V, J Z: C) {# J
- if(DAC_Value<3200) DAC_Value+=100;6 U0 g0 s; v1 q% z3 m
: K7 o, y+ C' M1 b- }* H' @- D8 L* S' `3 g4 t5 m
- break;8 ]. {# |5 v6 s* }
- 4 w$ \- R* b: J( b
- case GPIO_PIN_3:
& ^0 t' s& ?0 K1 { - if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3) == 0) q6 o, ^+ b" x; m/ S5 r7 v X
- {' m5 s9 p/ p, D7 M0 p
- HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
8 w1 Y0 r7 m" }: k! U D ^- P - if(DAC_Value>=100) DAC_Value-=100;+ Q2 b9 F ~( k3 s* T3 n
- }1 ?' P9 }1 x" ]" ]' \6 x
- break;3 F( W4 m: z! ~& ?0 j/ k3 @( j
- 5 z9 U+ K* y6 H! H& S
- case GPIO_PIN_4:+ n# ]* Y$ [0 \2 R3 v- v* ~6 C
- if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4) == 0)4 j& m# i4 @; i6 Y2 y* J j7 h
- {
0 Y9 X+ P- Q' @' P" i - HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);) R* x, Q+ u3 ~: x" i/ X
- DAC_Value=0;
2 I3 @8 V G, P3 V. h( V8 U - }6 p( |" o/ z: u) P6 G; Q4 J, a
- break;9 I5 R |/ s5 _2 g! C
- }4 B8 G/ h9 z4 Q* A* |
- }
复制代码 再看一下用SPI往LCD里面写数据的程序# G1 }* L1 [6 T0 G
- uint8_t SPI_WriteByte(uint8_t Byte)
: j I. j7 Z* K4 ^3 u( D - {
9 t% U6 k; g) {1 N' x# r4 i - HAL_SPI_Transmit(&hspi2, &Byte, sizeof(Byte), 10);
u$ H- G9 r0 d+ h" O - }
复制代码 下面看一下主函数; L# H S7 P' I9 r6 Y0 }8 {5 f
- int main(void)4 M! i# s+ h2 F% G
- {
. l/ ], j/ `0 ?6 \1 _1 z% L - /* USER CODE BEGIN 1 */
" j$ T" d$ h: n# ^: h% e - uint8_t buff[50];
1 ?0 n* M( v2 B; k
% R* V' d0 f8 Q1 D+ d- /* USER CODE END 1 */" H1 z1 j5 D, ? w+ r' R
-
. {7 f* {6 @( C* Q6 o5 J1 @3 _ - 4 l& P, _1 N0 h) s( m x5 t" b; {
- /* MCU Configuration--------------------------------------------------------*/" |5 y2 t, C: _% g, P$ f
5 s6 ?: M( V0 L* V7 r. z- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */( a3 p+ F/ `. K3 w
- HAL_Init();
0 x3 ]6 w- q' _ - 3 y2 |. ?* B7 `, N; U
- /* USER CODE BEGIN Init */
# A5 Z- G0 o8 H1 n: r; r# ] - 8 N% H4 N4 J( F4 d/ }
- /* USER CODE END Init */
- n, Y- G+ n8 c+ u
% g$ B; a# v$ @2 K: J8 I! d- /* Configure the system clock */
; `: D8 p5 ^ z% z. _1 X5 T - SystemClock_Config();- ^" g5 C3 L1 N
& w: H8 ~7 V) q: A- /* USER CODE BEGIN SysInit */
S6 t6 y8 t! Y% }$ [* w. Q* j
2 `1 ^* e6 ?: s( a1 \- /* USER CODE END SysInit */
: M* w# x5 p) g. c, n
( S" }1 c0 v' f: v- /* Initialize all configured peripherals */! ]' L' J l$ I6 M. [
- MX_GPIO_Init();8 Z( w- L5 ]* V0 e* @- u9 x! a
- MX_DMA_Init();9 L, I( T4 U; S9 Y z
- MX_USART1_UART_Init();
. X" P- t8 r. ~ - MX_TIM3_Init();
4 L% [9 ~1 K# e( G k - MX_ADC1_Init();
5 A6 L7 k: i, d$ V: { - MX_DAC_Init();
4 Q. \3 J7 H0 M% F- A1 x6 C" f - MX_SPI2_Init();
9 V. W" A* X! I/ e0 J1 t% X - MX_USART2_UART_Init();. W* Y: d7 L+ U* A
- /* USER CODE BEGIN 2 */- b0 s, p- i$ Y. q w
- 2 F3 Q8 S* u& R0 Y: |& j% U* Y+ A9 o
- LCD_Init();' m) q; X# l/ ~" F9 ^
- POINT_COLOR=RED;! b" \' y1 n2 v
- LCD_ShowString(10, 50, 16, "Welcome come to My world",0);
" G/ R# g2 ^. z m3 B6 I; J - ; v. I$ [* s& v7 ]9 t
- //LCD_BL_SET;( v2 }3 z5 b: {* t) z6 z
- memset(RX_buff,0,RX_len);
" z2 `; u+ q" n8 }4 f) o - HAL_UART_Receive_IT(&huart1, &RX_temp, 1);
% D: r- o6 i3 @& [ R0 Q, f& B9 x- T/ P - HAL_UART_Receive_IT(&huart2, &RX2_temp, 1);5 E5 R% `5 J, w6 k0 a! s- k
- ! O6 d. b/ b/ ^) ^9 J1 G% {) m. F
- HAL_TIM_Base_Start_IT(&htim3);' g# E" o. ?+ b! | P
- ) `; Q1 E/ M( }& H7 z7 a! e
- HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
9 I$ Z+ _/ G, F6 B1 P7 k! j - HAL_ADC_Start_DMA(&hadc1, ADC_val, ADC_length);
1 M# r% _) F; T/ S - % ?7 y+ Q8 ?7 X% A7 i/ _; Z
- //HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0x100);
; V" ^1 E5 ? C. T: U - DAC1_Set_Vol(DAC_Value);/ S! o: W! o$ n4 D9 A/ O# q
- /* USER CODE END 2 */% q0 S+ A- N8 M% U5 V# o1 T) A" x
/ |" T! l$ k, H4 z& `- /* Infinite loop */% ]4 C ?# T+ w4 v( f
- /* USER CODE BEGIN WHILE */) P# P9 K9 U# n* r7 D
- while (1)) Q6 P3 Z! c j
- {
. \' R* x# H I: Y. ~- I+ x$ A - /* USER CODE END WHILE */# y! x* b2 M& X$ Y1 k2 }5 q
- . w2 u: G H& V% U6 d' \) g3 w+ ^
- /* USER CODE BEGIN 3 */
/ m8 c# Y' {. N3 T - HAL_Delay(500);& I2 k9 R/ V! n( L T6 ~/ S
- DAC1_Set_Vol(DAC_Value);5 K( B6 n1 ~: D, z4 E. n
- sprintf(buff,"S:ADC: %1.2f DAC:%4d\r\n",Get_ADC(),DAC_Value);
) r& y/ h2 E2 |" @+ m: J. M; t5 W0 B - LCD_ShowString(10, 70, 16, buff, 0);9 k# r6 S. D" c, J% m! y8 m
D5 _" E+ X o$ O0 Q- E. ^7 v- sprintf(buff,"S:DACG:%5d\r\n",HAL_DAC_GetValue(&hdac,DAC_CHANNEL_1));: o G' c6 n+ Q& ^1 W- c
- LCD_ShowString(10, 90, 16, buff, 0);
% n( {4 l' _9 `, D. B - HAL_UART_Transmit(&huart1, buff, strlen(buff), 10);
5 E2 x6 ^1 O# e0 K2 j - }
2 ]' _) u4 d+ \# F - /* USER CODE END 3 */6 j4 n% ~" a7 \ E; s' J a
- }
复制代码 在STM32CUBEIDE中,想要调用sprintf()和printf()程序的话要在软件里设置一下
5 n+ |# [* N# A+ O9 Z6 u8 W$ { ! l# D, f' t# K
(PS:软件里面也要选Debug模式,Release模式好像编译不了这两个函数)& I3 l+ O6 _8 h* H, ~
工程:Pro5.zip' }: A! u5 E1 D" O
% f w b# Z3 v5 U3 X9 v! g+ B( @' L
|
感谢分享