|
使用Platformio平台的libopencm3开发框架来开发STM32G0,以下为串口中断的使用。
- E4 `- v0 j* A- N3 p+ f' ^+ w 1 新建项目建立uart项目 / A% I/ ~* `- l& k9 E) v8 b
在PIO的Home页面新建项目,项目名称uart,选择开发板为上一次建立的自定义开发板型号 MonkeyPi_STM32_G070RB,开发框架选择libopencm3; - 1upload_protocol = cmsis-dap
4 \( Q/ ~+ x7 M0 l0 X- ^9 j - 2debug_tool = cmsis-dap
复制代码
+ z; Q/ x+ T& d, z- I7 c/ K: y! |2 z
* P* M4 ~* N- B/ b \' n( B2 编写程序时钟设置
$ ?; p( d9 ?) U, H" ~# i9 S7 u
- 1//system clock
8 j0 a$ T( a8 y' X( w- b - 2rcc_clock_setup(&rcc_clock_config[RCC_CLOCK_CONFIG_HSI_PLL_64MHZ]);+ D/ H- r" Z O+ p/ |8 I4 b+ f
- 3
1 p# q) T1 `7 n0 V - 4//uart pin
8 E3 K' v5 p' d7 z- X( r - 5rcc_periph_clock_enable(RCC_USART1);3 h9 Q$ ]! K3 D, O" S% m d" |# {5 H
- 6rcc_periph_clock_enable(RCC_GPIOB);
复制代码 9 u, a: N5 n. X8 |5 _! U
! ^7 w! E5 [+ A+ P* v
先设置系统时钟为内部PLL生成64MHz,然后设置串口外设和串口引脚外设的时钟; - 1gpio_mode_setup(GPIOB,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO6|GPIO7);
1 ^, D3 p8 J: f/ N - 2gpio_set_af(GPIOB,GPIO_AF0,GPIO6|GPIO7);
复制代码
. }6 O$ ^$ R5 X9 d! j& Y
0 h9 q& I9 B* |( x根据芯片datasheet文档,使用USART1其引脚为PA9\PA10,复用功能AF1为串口功能;
2 v% L) [' K; i/ B; P+ r8 R. G+ }
- 1usart_set_baudrate(USART1,115200);" {# V) l0 ~$ F/ G' F9 ^6 t
- 2usart_set_databits(USART1,8);3 ~0 y) l7 D/ @# ^$ t$ g" j
- 3usart_set_stopbits(USART1,USART_STOPBITS_1);0 ~- }8 `/ h% X9 z5 l
- 4usart_set_parity(USART1,USART_PARITY_NONE);
# V/ U G$ R6 I - 5usart_set_flow_control(USART1,USART_FLOWCONTROL_NONE);2 v* a( j- O- K, c$ F
- 6usart_set_mode(USART1,USART_MODE_TX_RX);- b- p5 ]$ C2 S' L: W( ~2 Z' o9 y/ f7 A
- 71 b: I9 X# {3 ^6 p. p: U4 U a
- 8//uart isr
. | {9 M6 d; Q& h - 9nvic_enable_irq(NVIC_USART1_IRQ);
+ r5 p' u; D4 T7 p* \* ~ - 10, P+ L$ p- x% K A
- 11usart_enable(USART1);
5 s0 x- I2 i: | T5 Q4 X - 12
! a e, O6 q$ v6 \# C* c - 13usart_enable_rx_interrupt(USART1);
复制代码 + G) ~3 k" ^8 d) l/ c1 N
$ y7 G) Q+ }) H
先设置串口波特率、数据位数、停止位、校验、流控等设置,再开启串口中断,使能串口和其接收中断; ; D& I) O1 m! ]% Q# k( R0 D; h
串口发送 2 n6 L6 s2 ~( O, e$ X
- 1char buff[32] = "hello, makerinchina.cn\n";
9 p1 E+ z: s1 t! L$ h - 2for(int i=0; i<strlen(buff); i++){- F, x8 `% y O( S, C1 M
- 3 usart_send_blocking(USART1, buff[i]);
; n8 x# K. p& | O8 g! N8 j* q% s - 4}
复制代码
" e1 S( y' h# B( N Z2 @6 ~! k/ I
$ v6 h4 K3 L: U( ?% ?2 S发送直接使用 usart_send_blocking 接口发送一个字节数据;
& K# i5 S2 s+ C+ g
串口接收 3 ~/ q( W( ?, Z/ Y( l, r
- 1/**/ A Q. J B5 f% ?: G
- 2 * @brief uart1 isr function
) `. n: H; ]6 K! k' ? - 3 *
7 f( Y- N% ^! }" U& i! e6 ?) R- l - 4 */. D- _ ^8 ?6 }: l# y" j; l
- 5void usart1_isr(void)4 ?8 ?/ u* m, J
- 6{( r0 S& {( C8 j" j' r2 B& M$ a/ K
- 7 //receive interrupt$ z6 c0 k" K' Q' G0 P, H
- 8 if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&2 A$ f R1 A# ?* O0 D/ ]3 Q
- 9 ((USART_ISR(USART1) & USART_ISR_RXNE) != 0)) {0 N. l8 N* a9 L T2 d$ Q y/ [" c
- 103 S1 d" X- `$ \! }8 i/ P U; t0 d! n, K
- 11 if(recv_index < BUFF_SIZE){
3 u _( |; i8 W( @# I - 12 recv_buff[recv_index++] = usart_recv(USART1);* z; J0 ?2 Z/ L9 i- g% P
- 13 }else{. E1 @) {9 W4 j
- 14 recv_index = 0;! B$ w6 [: q" A8 |! i5 `: C8 R
- 15 }6 B. ]- d( U' Z9 |
- 16 }
2 D. i, A7 w/ @) z - 17}
复制代码
5 C( L1 I& M6 Z: U' L/ G9 U" i# }( H P# I8 E# l9 G
串口接收使用中断方式,接收到数据后将其存放的buff中,然后主程序中取出打印显示出来: - 1#include <libopencm3/stm32/usart.h>+ Q* p7 R. ~! i& X: M, l& z
- 2#include <libopencm3/stm32/rcc.h>: [8 _3 X- z0 ?5 _3 b
- 3#include <libopencm3/stm32/gpio.h>
! C: ~* i1 w: ]* W5 y* v8 h0 M - 4#include <libopencm3/cm3/nvic.h>9 a+ Y) A: }) f% | C
- 55 I' W6 Y# s4 Q
- 6#include <string.h>( | }: u* ]' N. i
- 7
9 ] s* T3 [$ _! {9 k - 8volatile uint8_t recv_index = 0;
- F- A: K2 F" Z$ p% ~: b - 9volatile uint8_t send_index = 0;" C6 H; y( q3 m
- 104 U" j, b( D2 k5 X7 [$ K& K
- 11#define BUFF_SIZE 64
8 x2 n+ ^& x' l, v$ | - 12uint8_t recv_buff[BUFF_SIZE] = {0};
W4 D1 S% t! l8 ^5 ^7 J- p1 F+ T2 n - 13
! h: c( H0 ?! d2 B) R - 14int main(void)" C( h4 V) T( `
- 15{
! I$ }9 c1 ?" Z! z* e - 16 ...
9 c i8 o1 R: R- \ - 17/ A6 o9 y1 U( y" U% [& A1 J- ?
- 18 while (1)5 g \- s% j4 U) a0 P, F% z
- 19 {
# Y, ^% {1 U* K% O; R+ V: u" y - 20
: v0 |& @/ }/ D9 F2 {- ?3 r - 21 if(recv_index != send_index){
4 f. `/ _2 \+ I G+ h7 }( C# k - 22
' M$ s& u8 h; p - 23 if(send_index < BUFF_SIZE){
8 J& E5 `" \9 }( N6 w" R - 24 usart_send_blocking(USART1, recv_buff[send_index++]);
# H- q% e+ G* U# e% e) s - 25 }else{# \3 r5 w2 ~) P4 b( y
- 26 send_index = 0;
a3 U/ F/ W5 y2 N. e! B7 M4 o - 27 }
$ u, ?) G6 f9 w/ [4 z - 28 }& e9 p3 @, ]& K, A* o/ B
- 29" k% N6 g' E* A8 y4 b9 H! ?0 \- `
- 30 }
: u/ M: Z+ p/ l - 31}
复制代码
: D; S1 V: H4 o6 n3 烧写测试点击 platformio:Upload按钮或快捷键 Ctrl+Alt+U即可完成编译、烧写过程,打开串口工具,可以看到发送的数据和接收数据一样; $ v% ^" S) `$ @& z, r8 P ]) u3 B2 L
4 printf使用如果要使用printf功能,需要定义如下函数,将串口重定向: - 1/*& C; t9 [: g0 C4 X
- 2 * Called by libc stdio fwrite functions4 Y7 [& O6 o3 Q' k4 @
- 3 */
9 ^; m* V! ^$ Q$ P" ~1 w+ w - 4int
5 W C7 Z5 j7 z E- C - 5_write(int fd, char *ptr, int len)
: d0 t8 v: l$ \% p; X: C' `% @) | - 6{
- F- Z# ^9 u0 U4 F$ K - 7 int i = 0;) L# h) j0 i3 [& Z0 R" s3 z
- 8
+ Z/ U& L- c7 `8 Q - 9 /*% a2 N! |. O4 k! W2 L2 Q* a% G) Q9 D8 N
- 10 * Write "len" of char from "ptr" to file id "fd"$ W9 F, ~/ |$ N* k- [
- 11 * Return number of char written.$ f$ b% I$ E3 P) |
- 12 *
' c3 U+ a9 c; ]- n" i - 13 * Only work for STDOUT, STDIN, and STDERR' @6 h- Y1 c( E3 K
- 14 */
; Z6 \; z0 V5 r/ i1 B' U( d# U - 15 if (fd > 2) {6 e' R" i7 h8 ? s6 }
- 16 return -1;
' ]5 V& J/ P* N7 @ - 17 }- I4 ~1 n- I( S! C3 C) N$ s4 _
- 18 while (*ptr && (i < len)) {
6 C! F5 v, U$ ?1 q - 19 usart_send_blocking(USART1, *ptr);" c& ?; S4 R' h% w& H: t' R! R
- 20 if (*ptr == '\n') {
5 w. }( M% }; f7 F) b; Y: ]; u8 M - 21 usart_send_blocking(USART1, '\r');
9 q9 E6 q2 [0 m/ D7 A) L - 22 }, I; Z8 i/ E1 N
- 23 i++;- h4 Z2 C% p( W5 x& Y
- 24 ptr++;
; H1 \1 x; }6 e8 H7 i - 25 }7 k. S3 G. Z. R) a# l: F
- 26 return i;
, F- u: [$ _0 R+ C* l' F - 27}
复制代码 ) B: S0 S4 x2 K
现在就可以直接使用printf函数进行打印显示到串口设备; ; t, R* j0 l+ k4 r/ B6 p
转载自:MakerInChina.cn
& r9 K0 @# f; R' b |