|
使用Platformio平台的libopencm3开发框架来开发STM32G0,以下为串口中断的使用。 / u9 Q7 C- a7 F: D
1 新建项目建立uart项目
( c* g$ \ K, `+ x
在PIO的Home页面新建项目,项目名称uart,选择开发板为上一次建立的自定义开发板型号 MonkeyPi_STM32_G070RB,开发框架选择libopencm3; - 1upload_protocol = cmsis-dap( S7 O# C' c/ J9 n8 J
- 2debug_tool = cmsis-dap
复制代码
9 @9 b$ N* K1 E* H- R
( Y) \/ U- F4 ]% V2 编写程序时钟设置 ) B$ j4 V/ a* S, T# [) z3 ~
- 1//system clock- ^3 j$ }, m4 S. Q
- 2rcc_clock_setup(&rcc_clock_config[RCC_CLOCK_CONFIG_HSI_PLL_64MHZ]);
9 _7 P, T& C1 V0 ^) c: T1 T3 v* T - 39 ^; \6 r, A* h" ]
- 4//uart pin
/ ^! F( t. S1 j9 k/ [3 O - 5rcc_periph_clock_enable(RCC_USART1);
1 i: x7 Z( f! M! ]& @6 e% o7 R% E' L - 6rcc_periph_clock_enable(RCC_GPIOB);
复制代码 + O. ^. {1 D2 Z9 W6 O8 X+ L0 I/ w
5 r. `1 E- n$ U. s, P+ |
先设置系统时钟为内部PLL生成64MHz,然后设置串口外设和串口引脚外设的时钟; 引脚复用功能设置 * c1 @% z+ W; \) s- G2 `( s
- 1gpio_mode_setup(GPIOB,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO6|GPIO7);2 J5 \) R @" S8 R5 n1 o2 n" n: M
- 2gpio_set_af(GPIOB,GPIO_AF0,GPIO6|GPIO7);
复制代码
2 r- x7 H8 W* I8 M+ o
2 n2 E4 {8 K E0 D+ G- z( y8 \根据芯片datasheet文档,使用USART1其引脚为PA9\PA10,复用功能AF1为串口功能;
9 \8 j6 ^$ x; ^% }$ W
- 1usart_set_baudrate(USART1,115200);. E) R6 q0 i: ]- S/ T" |# ?# x6 b
- 2usart_set_databits(USART1,8);- o) c3 _3 m% Y) C
- 3usart_set_stopbits(USART1,USART_STOPBITS_1);* l$ j0 ?5 C- s e+ d! p9 L* d
- 4usart_set_parity(USART1,USART_PARITY_NONE);4 w% Q# [1 T0 v9 f: r: x- S
- 5usart_set_flow_control(USART1,USART_FLOWCONTROL_NONE);- a/ L0 g g& L; F& L% F
- 6usart_set_mode(USART1,USART_MODE_TX_RX);* ^# Q* H. B" k8 H' I+ N* U
- 7
1 s/ R# s/ @/ _4 G$ N' m2 d - 8//uart isr. h6 L/ r2 B, k+ I) _1 V! N7 i
- 9nvic_enable_irq(NVIC_USART1_IRQ);
( \! |/ S- o9 Z& U: N y& t - 109 J* r6 G! v( M4 H
- 11usart_enable(USART1);
$ i9 I; I* H4 X) z1 S2 L - 12
0 r7 c$ @1 a( B$ [ - 13usart_enable_rx_interrupt(USART1);
复制代码 . B1 P7 q8 z8 \, q" z5 @
9 I/ R. {) Z+ f% Z* h/ S- D! k先设置串口波特率、数据位数、停止位、校验、流控等设置,再开启串口中断,使能串口和其接收中断; * Q# T. K: c# I: u/ x
串口发送
2 O5 R7 g* _3 ~4 h \
- 1char buff[32] = "hello, makerinchina.cn\n";
9 w& H" }5 p& u& T& h, C- U - 2for(int i=0; i<strlen(buff); i++){
( k$ Q( a9 f: [% p% y - 3 usart_send_blocking(USART1, buff[i]);
* x( K7 l! I4 u* w8 Z - 4}
复制代码
& D) D1 n+ `/ h- [# ]5 p( ?2 f
! U$ u! n9 y* n% [发送直接使用 usart_send_blocking 接口发送一个字节数据; & Z6 j3 v& _ P2 K) P' D
- 1/**- \$ Z! _1 L* I: Y- I0 W
- 2 * @brief uart1 isr function0 U8 j" q3 h3 l2 [; Z2 n
- 3 * & m) D; F1 E* K7 y+ `: Y
- 4 */
5 {7 X6 X+ ]6 n3 ~7 J1 s - 5void usart1_isr(void)0 y5 D( Q5 A* C3 h& Z% \+ u
- 6{
5 p5 \- O- |" L, } - 7 //receive interrupt
4 O9 l& k) I, r7 ~% b* E - 8 if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
v3 l" s5 K5 @( C - 9 ((USART_ISR(USART1) & USART_ISR_RXNE) != 0)) {
; H2 Y8 A% r! \0 p B; n9 q& ` - 10
1 h) x4 L& d4 ] B3 m- b - 11 if(recv_index < BUFF_SIZE){
" v+ L) Y7 e* q: D( N" @/ ` - 12 recv_buff[recv_index++] = usart_recv(USART1);$ C* _4 A5 @5 P& v0 x- X
- 13 }else{- p* _0 {" G+ n% i% Y1 m- C- |6 x
- 14 recv_index = 0;& R9 r! a, k& \; l |! k2 q* C
- 15 }5 H6 B$ o/ s& |
- 16 }
1 f- z; V$ Z+ @4 O* V) C9 U - 17}
复制代码
* H# g& L* A; a2 w( b% |# R4 w6 F' ^
串口接收使用中断方式,接收到数据后将其存放的buff中,然后主程序中取出打印显示出来: - 1#include <libopencm3/stm32/usart.h>/ u2 u9 B; b( a
- 2#include <libopencm3/stm32/rcc.h>
" z6 p# A7 U& F; K) m) j - 3#include <libopencm3/stm32/gpio.h>
7 p2 M2 f s! k/ x - 4#include <libopencm3/cm3/nvic.h>; K3 w. B# I, [! I5 @% t
- 5
3 e* T' w: C0 C; [& Q9 |# U - 6#include <string.h>$ y3 T1 \5 Y: D+ F+ {
- 7
9 z* V S, x# h9 Y) g. e - 8volatile uint8_t recv_index = 0;& r, N- C6 l# A( Q5 x
- 9volatile uint8_t send_index = 0;
' m1 e. J( D! }2 h0 q5 p- {& g j - 10' {$ }& B1 E l5 C4 r' x( h) m
- 11#define BUFF_SIZE 64% A* V: \' V+ j
- 12uint8_t recv_buff[BUFF_SIZE] = {0};4 I% {2 B0 s% d
- 13
$ G7 v& [. V i* M& b& u* z: h4 v - 14int main(void) B- e6 n2 Z6 S( E+ y: A
- 15{
; T3 V5 V- D# c# q& X: \6 ` - 16 ...4 k& ]4 C" q E0 E+ v" h
- 17
# F) r9 T$ P, C, J - 18 while (1)
" v. \8 ^/ \' l ] - 19 {! b8 N, i2 t4 N
- 20
$ E* V# E0 `: F- g! M- c - 21 if(recv_index != send_index){
7 S6 m% q$ Q& A( U, e - 22" n( n& O3 d8 G' p# w
- 23 if(send_index < BUFF_SIZE){& L8 r5 ?3 i3 \; Q
- 24 usart_send_blocking(USART1, recv_buff[send_index++]);
7 t: K F" d" T) b) s% A, s4 m - 25 }else{; `1 l8 l _3 B! s
- 26 send_index = 0;
; U* l. m+ g; j6 O9 ~ - 27 }
. Y1 ]1 {5 T! n P) Y d. | - 28 }3 Z3 l5 e" a9 g' W& E, y
- 29 }, `) G& C* z9 n
- 30 }. m0 y6 w9 M; Z& W: S8 H
- 31}
复制代码 3 K$ j' `$ s& P; ^5 L9 X3 ~# }. q" Q4 P
3 烧写测试点击 platformio:Upload按钮或快捷键 Ctrl+Alt+U即可完成编译、烧写过程,打开串口工具,可以看到发送的数据和接收数据一样;
* R, |# N% Y; l, B; ^+ e 4 printf使用如果要使用printf功能,需要定义如下函数,将串口重定向: - 1/*
2 A( ~9 u3 x' M8 F! L% z& O8 n - 2 * Called by libc stdio fwrite functions2 L2 U6 ~" l x. z
- 3 */
7 [" l/ F4 L" J9 u* t' T - 4int
Z. y# N+ E4 J( W/ Y. J - 5_write(int fd, char *ptr, int len)
* X$ }! e/ q* g/ g# ~: o - 6{6 c$ D% F5 \6 q9 M& a& y
- 7 int i = 0;! W3 e: S! s. {0 V
- 8
# [# }9 F4 G# _; {5 T. `7 T+ Z - 9 /*
* O& S/ R% ~$ D) m: p0 D - 10 * Write "len" of char from "ptr" to file id "fd"% s y' l+ l3 H5 l: y2 R' i9 H
- 11 * Return number of char written.
$ ~5 N; L3 W+ A- s2 ^& X V - 12 *8 G4 n: l0 d! B( M9 _8 Y4 K5 b
- 13 * Only work for STDOUT, STDIN, and STDERR
) ~* ~0 t9 x M* W - 14 */
, ?* \5 b' f8 I- K i - 15 if (fd > 2) {
* k) ?; y0 R/ o! V- x1 K$ K- b - 16 return -1;
& U& C5 F$ \9 n9 b8 A" C0 H - 17 }
t/ {) a6 [2 Z( U8 C - 18 while (*ptr && (i < len)) {! Y, s2 a2 o) I* N. m4 B5 g/ p0 I# e
- 19 usart_send_blocking(USART1, *ptr);
9 c5 }6 I0 H/ f4 o3 g, s8 \ - 20 if (*ptr == '\n') {
- N1 c6 u$ Z6 H# N) v - 21 usart_send_blocking(USART1, '\r');( h" M p' o) k
- 22 }
! O: l, p5 E/ x6 c* X7 [% E - 23 i++;
& G; k: ~$ D) p& @ - 24 ptr++;
0 F* p0 a% b% Z! H3 {& V, [# d - 25 }
; U; E3 V3 Q& ` N6 u3 Y1 V - 26 return i;1 @# h: a$ P! J- n7 P. j
- 27}
复制代码 ( n$ I3 \' f2 u3 T
现在就可以直接使用printf函数进行打印显示到串口设备; , b" r- A# q9 A! V8 l6 ]3 S1 Y
转载自:MakerInChina.cn
+ k" Y5 y' \' _) \) c |