2019-12-28 11:27:55 WideMouth
我的第二篇博客,其實我是一個純物理專業的本科生,學習的是物理主流的力熱電光原,陰差陽錯的玩起了電子和編程(當然,也是興趣所驅),考慮過轉專業,但是迫於學校各種各樣的因素,還是免了吧,就這樣寫寫屬於自己的博客,覺得挺好的。
一開始做藍牙通信是在上一學期(大一下學期),那時對電子特別感興趣,剛上手了51單片機,想玩點高級點的,想到了藍牙和語音,然后去問電信專業的一個學長(現在是我的好哥們啦),貌似電信專業的都沒玩過這個,很驚訝,那就只能自己玩啦,問了一個挺牛的大三學姐,她也沒做過,然后給我講了一些特別復雜懵逼的原理,不過給了我幾篇博客,那我就帶着這幾篇博客自主搞啦,那時學姐那剛好有一塊HC-06模塊,說是撿的,還不知道能不能用,那就隨便玩玩啦。嘻嘻!!!還是能玩的,雖然出了各種各樣的狀況,不過還是基本實現了藍牙通信啦,那是還只能單字符(其實那時也用不到字符串),后來就自己買模塊玩,HC-08、HC-12、LD3320語音模塊。都上手成功啦。不過后來由於焊工不太好,燒了一塊語音芯片(好幾十塊,心疼),加上玩電子實戰要焊板子,一來二去不如編程來得方便,就改手編程了。一台筆記本電腦即可,無任何成本,實戰快,不過電腦是初中買的Lenovo G40-70m(2900塊),自己加了塊內存條和固態,嘻嘻!!!就喜歡搞這些。由於自己對電腦比較熟悉,感覺自己電腦比同學花好幾千新買的高配置電腦還好用。自豪!!!
好啦,下面開始分享啦!!!
先上完整代碼:
1 2 /*----------------------------------------------------------------------------- 3 * 實 驗 名 : WideMouth 51單片機字符串收發 4 * 實驗說明 : 單片機串口收發數據控制燈亮滅 5 * 實驗模塊 : STC89C52RC單片機最小系統、HC-06藍牙模塊 6 * 連接方式 :藍牙模塊RXD、TXD端分別連接單片機TXD、RXD端,藍牙正負極連接單片機正負極 7 * 注 意 : 單片機晶振使用的是11.0592 8 *******************************************************************************/ 9 10 #include<reg52.h> 11 #include<string.h> //字符串處理函數包 12 #include<intrins.h> 13 14 #define uchar unsigned char // 宏定義 51單片機內存資源有限 15 #define uint unsigned int //需考慮內存資源問題,故使用無符號類型 16 17 18 uchar receive_data[8]; 19 uint bytes=0; 20 uint bytes_old; 21 22 //--定義使用的IO--// 23 24 sbit Led301=P2^0; 25 sbit Led302=P2^3; 26 27 //--聲明全局函數--// 28 void uart_init(); 29 void Delay_1ms(uint i); 30 void SendChar(uchar character); 31 void SendString(uchar *p); 32 33 /******************************************************************** 34 * 名稱 : Com_Int() 35 * 功能 : 串口中斷函數(接受和發送數據時都會調回此函數) 36 ***********************************************************************/ 37 void Com_Int(void) interrupt 4 38 { 39 EA = 0; 40 if(RI==1) //此句判斷不能省略,否則發送數據時也會執行此語句,造成字符串錯誤!!!(RI為接收數據標志,當接收到數據自動置為1) 41 { 42 RI=0; 43 receive_data[bytes] = SBUF;//接收到的數據 44 bytes++; 45 } 46 EA = 1; 47 } 48 49 /******************************************************************************* 50 * 函 數 名 : main 51 * 函數功能 : 主函數(程序入口) 52 *******************************************************************************/ 53 54 void main() 55 { 56 bytes_old=0; 57 uart_init();//初始化串口 58 while(1) 59 { 60 while(1) 61 { 62 bytes_old=bytes; 63 64 Delay_1ms(30); //如果單片機接收來自藍牙模塊不少於1字節的串口數據,一定要加延時后再判斷是否,延時時間自己可按情況而定 65 //接收數據中斷一定發生在這30ms內 66 if(bytes_old==bytes) //如果在這30ms內無數據接收,說明字符串已接收完畢,這樣才能完整的接收一幀串口數據 67 { 68 receive_data[bytes]=0; //字符串末尾加結尾標志0(對應/0) 69 if(bytes) break; //跳出循環,執行相應邏輯操作 70 } 71 } 72 73 SendString(receive_data); //將接收到的完整數據返回給發送端 74 75 //想干啥干啥吧 76 if(strcmp(receive_data,"3011")==0) //strcmp(str1,str2)字符串比較函數. 參數 str1 和 str2 是參與比較的兩個字符串。 77 { //若str1=str2,則返回零; 78 Led301=0; //若str1<str2,則返回負數; 79 } //若str1>str2,則返回正數。 80 if(strcmp(receive_data,"3010")==0) 81 { 82 Led301=1; 83 } 84 if(strcmp(receive_data,"3021")==0) 85 { 86 Led302=0; 87 } 88 if(strcmp(receive_data,"3020")==0) 89 { 90 Led302=1; 91 } 92 bytes_old=0; //將bytes_old、bytes置為初始化值,等待接收下一字符串 93 bytes=0; 94 } 95 96 97 } 98 99 /******************************************************************************* 100 * 函 數 名 : uart_init() 101 * 函數功能 : 初始化配置串口 102 * 備注 :可直接復制 103 *******************************************************************************/ 104 105 void uart_init() //直接復制即可 106 { 107 SCON=0X50; //設置為工作方式1,8位數據,可變波特率 108 TMOD=0X20; //設置計數器工作方式2 109 PCON=0X00; //波特率不加倍 110 TH1=0XFd; //計數器初始值設置,9600@11.0592MHz 111 TL1=0XFd; 112 TR1=1; //打開計數器 113 ES = 1; //開串口中斷 114 EA = 1; //開總中斷 115 } 116 117 /******************************************************************** 118 * 名稱 : Delay_1ms() 119 * 功能 : 延時子程序,延時時間為 1ms 120 * x * 輸入 : x (單位為毫秒) 121 ***********************************************************************/ 122 void Delay_1ms(uint i) //1ms延時,直接復制即可 123 { 124 uint x,j; 125 for(j=0;j<i;j++) 126 for(x=0;x<=148;x++); 127 } 128 129 /******************************************************************** 130 * 名稱 : SendChar(uchar character) 131 * 輸入 :單個字符 132 * 功能 : 發送單個字符 133 ***********************************************************************/ 134 135 void SendChar(uchar character) 136 { 137 SBUF=character; //發送單個字符 138 while(!TI);TI=0; //發送完成標志 139 } 140 141 /******************************************************************** 142 * 名稱 : SendString(uchar String[]) 143 * 功能 : 發送字符串 144 * 輸入 :字符串 145 ***********************************************************************/ 146 147 void SendString(uchar String[]) 148 { 149 uchar *p=String; 150 while(*p) //若指針指向的地址為空,則跳出循環 151 { 152 SendChar(*p); //指針第一次默認指向首地址 153 Delay_1ms(2); //延時,作用為提高發送准確度 154 p++; 155 } 156 }
用的工具都是最簡單的,編譯軟件是Keil C51,單片機是STC89C52RC,一塊HC06藍牙模塊,很容易上手。程序中,uart_init()和Delay_1ms(uint i) 對於51單片機藍牙通信都是通用的,復制即可,然后最后兩個發送數據函數,第一個發送字符比較簡單,第二個需要一點C語言基礎,但邏輯很簡單。程序最核心的是中斷函數Com_Int(void)和主函數main(),中斷函數比較簡單,就是把接收的字符賦值給字符串,但是要注意的是必須要加上if(RI==1)判斷,否則發送數據時也會執行賦值語句,造成字符串錯誤(RI為接收數據標志,當接收到數據自動置為1)!!!之前就是省了這一句,導致字符串老是重復,大家好奇的可以試一試,便於理解。然后最核心的是main函數中關於接收字符串的整理邏輯,從而得到一個完整的字符串數據,處理的巧妙之在於加了一行延時語句Delay_1ms(30); 函數里的時間可按情況設定,大家在這里需要花點時間好好理解一下里面的循環語句,弄明白他的處理機制,代碼中有詳細的備注便於你去理解。
現在單片機程序部分就完結了哦,現在需要你動手去實戰啦!!!這時還需要最后一步,來生成單片機燒錄的Hex文件。點擊工具欄的“魔法棒”,在Target欄修改晶振頻率為11.0592,Output欄勾選Creat Hex File,然后在主界面點擊ReBuild編譯生成Hex文件。在Build窗口出現creating hex file from " "...說明生成Hex文件成功啦!
附圖:
現在輪到你去燒錄啦,這里就不展示啦,需要你自己動手完成。加油,好運哦!!!大家如果需要源文件,可在評論區留言。
大功告成!!! @WideMouth
推薦:一款美觀實用的藍牙串口通信APP,內含多種自定義擴展按鈕,需要的朋友可前往下載(附鏈接):https://www.coolapk.com/apk/com.WideMouth.bluetooth20