STM32串口通訊
1、基於寄存器與基於固件庫編寫的差別
固件庫編寫方式,特色是簡單易於理解,資料多。新手適合用這種方式入門。
寄存器的可移植性強,更貼近底層,要求對外設的工做原理和運行機理有更深的理解。
編程
2、stm32串口通訊實戰
1.燒錄方式
我使用的是stm32f103指南者,從電腦中下載程序到stm32有兩種方式:
1.使用仿真線下載程序;(須要仿真線)
2.使用串口下載程序;(已經快被淘汰了,因爲只須要一根USB線,因此在沒有仿真線的狀況下,仍是實用)
ubuntu
接下來我使用的是第二種方法。
先下載圖中圈出的三個壓縮包
windows
連接: 野火STM32F103指南者開發板.
提取碼:pmf1
失效了就去這裏找到stm32f013指南者點進去下:
連接: 野火全部產品資料下載連接.
函數
而後用usb線把stm32開發板和電腦相鏈接,stm32端鏈接的 ‘usb轉串口’這個接口,再打開stm32開關,能夠看到紅色的小燈亮起。
開發板上有黃色的跳帽,是至關於導線的做用,此處要求BOOT0和BOOT1接地,RXD接A9,TXD接A10,開發板買來默認就是這樣接的,因此不須要改動。
測試
鏈接事後打開CH341SER.EXE,點擊安裝,顯示安裝成功便可。
而後打開串口下載助手mcuisp
按以下方式配置:①搜索串口,設置波特率 115200(儘可能不要設置的過高) ,②選擇要下載的 HEX 文件、③校驗、編程後執行、④DTR 低電平復位,RTS 高電平進入 bootloader、⑤開始編程。(前4步必定要調試正確,不然可能鏈接不上)
ui
2.代碼及效果圖
該處串口通訊實現如下功能:
1)設置波特率爲115200,1位中止位,無校驗位。
spa
2)STM32系統給上位機(win10)連續發送「hello windows!」,.net
3)當上位機給stm32發送「Stop stm32!」後,stm32中止發送。3d
此處的代碼在野火的代碼模板上改動。
先在前面的百度雲連接中下載模板
解壓後打開第21個串口通訊文件中的USART1接發中的工程文件
而後把其中stm32f10x_it.c文件的串口中斷服務函數部分改成以下:
指針
int i=0; uint8_t ucTemp[50]; void DEBUG_USART_IRQHandler(void) { if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET) { ucTemp[i] = USART_ReceiveData(USART1); } if(ucTemp[i] == '!') { if(ucTemp[i-1] == '2'&&ucTemp[i-2] == '3'&&ucTemp[i-3] == 'm'&&ucTemp[i-4] == 't'&&ucTemp[i-5] == 's'&&ucTemp[i-6] == ' ') if(ucTemp[i-7] == 'p'&&ucTemp[i-8] == 'o'&&ucTemp[i-9] == 't'&&ucTemp[i-10] == 's') { printf("ÊÕµ½£¡"); while(1); } } i++; }
而後把main.c函數改成
#include "stm32f10x.h" #include "bsp_usart.h" void delay(uint32_t count) { while(count--); } int main(void) { USART_Config(); while(1) { printf("hello windows 10!\n"); delay(5000000); } }
而後就能夠編譯生成hex文件了,按照上面的方式把hex文件燒錄到stm32中,而後打開最開始下載的串口調試助手,點擊打開串口,便可以看到stm32發給電腦的信息
最終效果以下(中止命令中的感嘆號是英文狀態下的):
3、C語言程序裏全局變量、局部變量、堆、棧等概念
看如下代碼:
#include <stdio.h> #include <string.h> #include <stdlib.h> char g_buf[16]; char g_buf2[16]; char g_buf3[16]; char g_buf4[16]; int main() { printf("g_buf: 0x%x\n", g_buf); printf("g_buf2: 0x%x\n", g_buf2); printf("g_buf3: 0x%x\n", g_buf3); printf("g_buf4: 0x%x\n", g_buf4); return 0; }
該代碼定義了4個全局變量並輸出它們的地址,
它們儲存到了全局區裏,地址依次遞增。
再看如下代碼
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char l_buf[16]; char l_buf2[16]; char l_buf3[16]; printf("l_buf: 0x%x\n", l_buf); printf("l_buf2: 0x%x\n", l_buf2); printf("l_buf3: 0x%x\n", l_buf3); }
定義了4個局部變量,並輸出它們的地址
它們的地址也是遞增的,暫時不知道儲存到了哪裏。(我在ubuntu定義的全部變量地址都是遞增,多是cpu的關係)
4、stm32的堆、棧、全局變量的分配地址
仍然使用以前野火的串口通訊模板,把main.c(分別在stm32中定義了全局變量和局部變量,並把它們的地址返回給windows)改成以下:
#include "stm32f10x.h" #include "bsp_usart.h" char global1[16]; char global2[16]; char global3[16]; int main(void) { char part1[16]; char part2[16]; char part3[16]; USART_Config(); printf("part1: 0x%p\n", part1); printf("part2: 0x%p\n", part2); printf("part3: 0x%p\n", part3); printf("global1: 0x%p\n", global1); printf("global2: 0x%p\n", global2); printf("global3: 0x%p\n", global3); while(1) { } }
生成hex文件後,燒錄到stm32中,打開串口調試助手,點擊打開串口,而後點擊stm32上的reset按鈕,就能夠看到以下結果。
前3個part變量爲局部變量,它們儲存到了棧中,地址依次減少。
後三個global爲全局變量,它們儲存到了靜態區,地址依次增長。
再試試如下函數(定義了靜態變量和指針),
#include "stm32f10x.h" #include "bsp_usart.h" #include <stdlib.h> int main(void) { static char st1[16]; static char st2[16]; static char st3[16]; char *p1; char *p2; char *p3; USART_Config(); printf("st1: 0x%p\n", st1); printf("st2: 0x%p\n", st2); printf("st3: 0x%p\n", st3); p1 = (char *)malloc(sizeof(char) * 16); p2 = (char *)malloc(sizeof(char) * 16); p3 = (char *)malloc(sizeof(char) * 16); printf("p1: 0x%p\n", p1); printf("p2: 0x%p\n", p2); printf("p3: 0x%p\n", p3); while(1) { } }
前三個靜態變量儲存到了靜態區,地址依次增長。
後三個指針儲存到了堆中,地址依次增長。(堆棧具體知識請看參考博客)
結合兩次結果看(針對於測試的3個區域),能夠大概看出棧在頂層(地址最大),而後依次是堆,靜態區。對比如下地址分配圖,大體符合。
參考博客:
C語言中,局部變量、全局變量、靜態變量、堆、棧的內存地址.
C/C++程序內存的各類變量存儲區域和各個區域詳解.