當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀] 在單片機(jī)學(xué)習(xí)中,我們常常遇到這樣那樣的零星問題,這里我將我遇到的問題總結(jié)如下,都是個人見解,如果不對,萬望指出。(持續(xù)更新中)問題0001:51單片機(jī)下載失敗常見原因1.查看單片機(jī)是否插反了;2.下載軟件選擇正確

在單片機(jī)學(xué)習(xí)中,我們常常遇到這樣那樣的零星問題,這里我將我遇到的問題總結(jié)如下,都是個人見解,如果不對,萬望指出。(持續(xù)更新中)

問題0001:51單片機(jī)下載失敗常見原因

1.查看單片機(jī)是否插反了;

2.下載軟件選擇正確的單片機(jī)型號(注意STC89C52和STC89C52RC是不同的) ;

3.檢測是否連接了晶振 ,時候有晶振接觸不良的現(xiàn)象 ;

4.查看電腦com是否有多個,是否選錯了com口 (是否安裝了相應(yīng)的驅(qū)動);

5.單片機(jī)開發(fā)板是否重新上電了(下載單片機(jī)程序需要冷啟動過程) ;

6.注意是否有短路(比如開發(fā)板下面最好鋪一張紙,不要被短路) ;

7.下載軟件用的什么版本,舊版本可能需要設(shè)置最低、最高波特率,并且還會出現(xiàn)很多奇怪的現(xiàn)象,比如第一次燒寫用一個波特率,第二次就不行了,但是有時候卻一直可以(個人經(jīng)驗(yàn))。新版本不用設(shè)置,并且不用等待軟件提醒上電才可以上電,點(diǎn)擊下載后,直接重新上電即可,建議盡量使用新版 ;

8.如果使用的是CH340/CH341或者PL2302,檢測RXD/TXD是否連接反了。(注意PL2302,驅(qū)動,新版的驅(qū)動只支持正版芯片,這個一定要注意,很多人會沿用老版本驅(qū)動,不建議用PL2302)

9.換一個單片機(jī)試試看,驗(yàn)證單片機(jī)是否已損壞。

10.一部分人修改上一次工程代碼,然后直接編譯,下載無效果。可能是新的代碼編譯有錯(編譯有三個按鈕,請注意區(qū)別差異),導(dǎo)致目標(biāo)文件未生成,hex文件未更新,所以下載的還是上一次的程序。這里要注意。

11.STC-ISP軟件選擇hex文件后,要勾“每次下載前都重新裝置文件”,這樣有三大好處:(1)免去每次編譯都重新手動裝在hex文件(2)避免因忘記手動重新裝載hex文件,而導(dǎo)致下載的hex文件還是上一次的hex文件,代碼下載后現(xiàn)象和上一次一樣,誤以為還是程序問題(3)方便快速調(diào)試代碼。

12.連接線可以出現(xiàn)問題,比如接觸不良,線頭脫斷等。

13.芯片“鎖死”。STC-ISP軟件設(shè)置問題,上一次下載程序的時候,在STC-ISP可能勾選了“下次冷啟動時,P1.0 / P1.1為0/0才可以下載程序” , 這種情況,試著將此兩個IO拉低,下載程序試試看。

(其他原因后續(xù)更新中-------2016年2月2日最后更新此問題)

問題0002:學(xué)習(xí)單片機(jī)我們都需要什么軟件

最近看到群里面有很多人為了學(xué)習(xí)單片機(jī),下載了STC-ISP,然后又下載了串口軟件、單片機(jī)小精靈、定時器計算神器之類的,可謂五花八門,但是實(shí)際我們并不需要那么多的軟件。

大家注意到STC-ISP軟件已經(jīng)附帶了很多功能了,學(xué)會使用這些功能可以讓我們事半功倍。另外,STC手冊上有C語言和匯編語言程序,值得參考。下面在分析幾款常用軟件給大家:

keil4 : 點(diǎn)擊打開鏈接 (附帶我下載的兩個仿真插件,可以做很多仿真)

STC-ISP 下載方式:進(jìn)入www.stcmcu.comwww.stcmcu.com 然后CTRL+F搜索STC-ISP即可。

BCompare : 點(diǎn)擊打開鏈接 (快速比較文件差異,便于對比程序)

Proteus7.5 仿真:點(diǎn)擊打開鏈接 (文件中包含我錄制的破解過程,目前我的系統(tǒng)為W8.1暫時未發(fā)現(xiàn)使用問題)

Multisim 仿真 :點(diǎn)擊打開鏈接

Source Insight : 點(diǎn)擊打開鏈接(適合編寫代碼,非常方便)

SecureCRT7 :點(diǎn)擊打開鏈接 (免破解)

Altium Designer6.9 : 點(diǎn)擊打開鏈接

Altium Designer14.2.3 : 點(diǎn)擊打開鏈接

屏幕錄制專家: 點(diǎn)擊打開鏈接 (有時候交流溝通,錄制視頻更加簡單直接)

另外,單片機(jī)采用C語言編程的學(xué)生,有兩本書必須要度:

華為技術(shù)有限公司c語言編程規(guī)范.pdf :點(diǎn)擊打開鏈接

高質(zhì)量C編程指南—林銳.pdf : 點(diǎn)擊打開鏈接

問題0003:51類單片機(jī)需要冷啟動,但是一定要手動重啟開關(guān)一次嗎

51類單片機(jī)下載程序時必須冷啟動,這是大家都知道的。昨天,一個學(xué)生告訴我他是用的普中科技開發(fā)板,他用普中科技的下載軟件去下載程序,發(fā)現(xiàn)不是很好用。我告訴他STC-ISP下載軟件非常好用,他說STC-ISP軟件必須經(jīng)過手動重啟開關(guān)完成下載,而普中科技的開發(fā)板,可以完成全自動下載,只需點(diǎn)擊“下載”按鈕即可,無需手動重啟開關(guān),并且普中科技技術(shù)支持告訴他,只能使用他們的軟件才能夠完成全自動下載(我對此只能呵呵)。本人也是采用普中科技開發(fā)板,普中科技的自動下載功能確實(shí)存在,但是我使用過發(fā)現(xiàn)并不是很好用,而且需要結(jié)合它的開發(fā)板硬件才行。這里介紹一下我使用過的兩種“全自動”下載(可能方法還有很多,需要廣大網(wǎng)友的補(bǔ)充)

(1)硬件法:利用STC自動下載器,點(diǎn)擊下載后,模塊會自動重新上電,完成下載任務(wù),需要淘寶購買,約9~13元。

(2)軟件法:利用串口結(jié)合IAP功能,點(diǎn)擊下載,模塊自動完成下載,無需手動重啟。(版本古老的芯片無此功能)此方法可參考我的筆記:stc單片機(jī)“全自動下載”(程序版) http://blog.csdn.NET/yagnruinihao/article/details/21739665

問題0004:變量的定義與程序的執(zhí)行

為了簡化問題,這里把程序簡化為2行(先不要看變量i是否有意義)

 

在C語言方面,這是可以的(盡管這樣不是很規(guī)范),但是在keil4中,卻出現(xiàn)了問題,網(wǎng)上百度,說可能是有中文字符,但是我將程序刪除后,編譯沒有錯誤,切換輸入法,再次輸入圖片2的內(nèi)容,出錯,將int i=0 ; 剪切到第一行,錯誤消失。還有一個可能是軟件出錯(經(jīng)過測試,排除可能性)。

所以,在單片機(jī)編程中,最好將變量的定義放在執(zhí)行語句的前面。

問題0005:程序中的“死循環(huán)等待”正確嗎?

在單片機(jī)程序中,有時候會需要“死循環(huán)等待”,也就是等到某一條件我們才需要執(zhí)行下面的操作。這里以溫度傳感器DS18B20為例,主機(jī)首先需要發(fā)送一個存在檢測脈沖,如果DS18B20存在,則它會以60us至240us的電平來回應(yīng)主機(jī),這里就會需要一個“死循環(huán)等待”,我們必須等到DS18B20“回應(yīng)完成”,這時候主機(jī)才能繼續(xù)發(fā)送指令到DS18B20中去,這時候很多人會采用這樣的方式:(首先假設(shè)sbit ds18b20_io_bit = P3^7 ;)

則,while( !ds18b20_io_bit) ;

這樣的代碼其實(shí)是有問題的,在未連接DS18B20或者接觸不良時,DS18B20并不能回應(yīng)主機(jī),這樣的代碼就會有問題,尤其在大工程中,所以,為了安全,我通常的做法是:

第一步:

while( (!ds18b20_io_bit) ;

P1=0x01 ; //led

如果,P1口的led有變化,則表示我們“程序在邏輯上和時序上沒有問題”

第二步:

將上面的代碼修改為:

unsigned long i=0

while( ( (!ds18b20_io_bit) && (i++)) ;

然后打印 i ,

因?yàn)閕一般都很小,所以這時候我一般將unsigned long 修改為unsigned char 類型,然后最后修改為這樣

while( (!ds18b20_io_bit)&& (i++ <250)) ;

注意這里的250不是隨意寫的,是經(jīng)過測試的,經(jīng)過測試,我讀出的i值遠(yuǎn)小于250,我才這樣做的,如果在其他類似的地方,打印出來i是其他較大的值,那就重新定義i的類型為unsigned int 或者unsigned long ,根據(jù)具體情況而定。

上面的修改似乎意義不大,但是在大工程中,這樣不會因?yàn)镈S18B20的“不存在”而導(dǎo)致整個程序“死循環(huán)等待”。

問題0006:指針能否指向特殊功能寄存器

特殊功能寄存器的尋址方式只有直接尋址和位尋址。沒有間接尋址方式。而指針卻是間接尋址方式,不能通過指向特殊功能寄存器的指針來操作特殊功能寄存器。

例:利用指向0x90的指針來操作P1口的LCD燈(高電平時LCD點(diǎn)亮)(P1口的地址是0x90,但是屬于特殊功能寄存器區(qū))

#include

#include "./stc/stc12c5a60s2.h"

void main(void)

{

unsigned char *p=0x90;

while(1)

{

*p=0x55;/*從這里看,似乎應(yīng)該是LCD每隔一個被點(diǎn)亮,但是事實(shí)卻并非這樣*/

}

}

問題0007:“判忙” 函數(shù)重要嗎

在某些芯片操作時,會有一些引腳或者寄存器或地址的數(shù)據(jù)被用來表明當(dāng)前芯片處于的狀態(tài)為忙碌狀態(tài)或者空閑狀態(tài),如果忙碌,單片機(jī)需要用輪詢的方式等待直到芯片空閑下來才繼續(xù)發(fā)送指令或數(shù)據(jù)。這里以1602液晶屏為例:

一個朋友用ST89C52操作1602液晶屏,操作成功,后來換了芯片STC12C5A60S2,同樣的程序,顯示出來的卻是“亂碼”,后來經(jīng)過測試,程序部門似乎沒有問題,于是,我在LCD1602的“寫命令”函數(shù)和“寫數(shù)據(jù)”函數(shù)中

加入了延時(只是為了快速測試),下載后,兩個芯片都運(yùn)行正常。其實(shí)對于LCD1602,一般都不需要“判忙”,它運(yùn)行時比較快的,但是如果將一個沒有“判忙”的1602液晶屏模塊封裝起來,在調(diào)試一個大工程時,這時候

因?yàn)閾Q了芯片,導(dǎo)致整體效果錯誤,這就是增加了調(diào)試難度。比如在利用LCD1602學(xué)習(xí)使用時鐘芯片DS1302時,如果顯示亂碼,這時候,因?yàn)槟愕腖CD1602是實(shí)驗(yàn)的基礎(chǔ)環(huán)節(jié),肯定是你之前就已經(jīng)封裝好了的,這時候

你肯定會懷疑DS1302環(huán)節(jié)操作出錯了,這就增加了調(diào)試的難度和時間。所以,“判忙”函數(shù)必不可少。這里,又有一個技巧,就是防止程序“卡死”,含義與本文中的問題0002類似。

起初LCD1602的核心操作為:

[cpp] view plain copy

do{

;

}while( (lcd1602ReadStatus()) & 0x80));

后來我變?yōu)?/p>

[cpp] view plain copy

unsigned long i=0 ;

do{

i++;

}while( (lcd1602ReadStatus()) & 0x80);

UartSendValue("i = " ,i) ;/*利用串口打印出i的值*/

打印出i的值為 “1”(基于芯片STC12C5A60S1,11.0592MHZ,其他型號的單品機(jī)可能打印出來的效果不同,甚至同樣的型號單片機(jī)、同樣的晶振、同樣型號的1602 操作打印出來的值也是不一樣的),又變化為:

[cpp] view plain copy

unsigned char i=0 ;/*同時,需要注意這里,修改了類型*/

do{

i++;

}while( ((lcd1602ReadStatus()) & 0x80) && (i<10)); /*經(jīng)過驗(yàn)證,10已經(jīng)可以滿足足夠的時間了*/

這樣做才是安全的。(尤其在大系統(tǒng)中,不會因?yàn)?602的”不存在“導(dǎo)致整個系統(tǒng)的運(yùn)行失敗,經(jīng)典案例如下)

(在2015年2月7日,我?guī)椭粋€大四學(xué)生調(diào)試畢設(shè)時,也發(fā)現(xiàn)了同樣的問題,此同學(xué)在1602液晶屏的寫命令、寫數(shù)據(jù)函數(shù)里面加入了判忙函數(shù),判忙核心代碼如下:

[cpp] view plain copy

do{

;

}while( (lcd1602ReadStatus()) & 0x80));

,最后因在系統(tǒng)設(shè)計時,暫時用了1602顯示,后來為了做上位機(jī),就用了串口通信代替1602, 拔掉了1602液晶屏,但是沒有屏蔽掉主函數(shù)中關(guān)于1602的操作,導(dǎo)致了程序卡死在判忙函數(shù)中,因?yàn)槿绻麤]有硬件連接,通過數(shù)據(jù)口讀取到的1602狀態(tài)數(shù)據(jù)是0xff,然后0xff&0x80,這樣得到的結(jié)果永遠(yuǎn)是1(除非再次插上液晶屏或者手動將數(shù)據(jù)最高bit對應(yīng)的IO口拉低),導(dǎo)致程序卡死在這里,而且這些功能都是封裝好的,所以就更加加大了難度,導(dǎo)致一周沒有調(diào)試出來,后來,我給他指出兩種方法(1)在主函數(shù)中屏蔽所有關(guān)于1602液晶屏的函數(shù),實(shí)驗(yàn)后,系統(tǒng)運(yùn)行正常(2)修改判忙函數(shù),因?yàn)橐粍谟酪?,試?yàn)后,運(yùn)行正常,即使主函數(shù)中沒有屏蔽1602相關(guān)函數(shù),1602硬件暫時取下,也是可以成功運(yùn)行的)

另外,還有很多同學(xué)運(yùn)用了延時的方法去操作,似乎大部分人都得到了滿意的結(jié)果,那么,這里有出現(xiàn)了兩個問題:(1)延時的結(jié)果有三種:延時太小、延時正好、延時太大,對于大家來說,延時正好、延時太大都是可以完成系統(tǒng)的設(shè)計的,但是,你又如何保證你的延時不會小呢?大部分人想,這非常簡單,把延時設(shè)計的非常大就好了,那么,就引出了問題(2)延時太大,不利于系統(tǒng)整體設(shè)計,導(dǎo)致了效率太低 。 何去何從,大家可以想一想。

問題0008:調(diào)試程序之“窮途末路”

有時候,在調(diào)試程序時,明明都是嚴(yán)格按照datasheet的說明和時序圖編寫的代碼,就是沒有效果,然后借鑒別人的代碼,代碼相同,但還是沒有效果 。 這時候,先要懷疑硬件,如果硬件沒有問題,有可能還會有一個原因,那就是單片機(jī)的問題(或者是keil軟件的問題,這個不得而知了)。我之前遇到過編寫一個代碼,沒有效果,最后把全部代碼屏蔽掉,只在main函數(shù)中,點(diǎn)亮了LED,但還是失敗了,后來,復(fù)制代碼,重新新建工程,粘貼代碼,就好了。(這里不是噴STC,其實(shí)STC在國內(nèi)做的較好,但是總會有一些奇葩的時候),這里分享一下,僅個人經(jīng)歷。

問題0009:如何一步步測試編寫代碼

單片機(jī)程序測試調(diào)試似乎對于剛?cè)腴T的同學(xué)有一定難度,但是入門之后我們快速調(diào)試程序呢?很多人寫代碼一氣呵成,然后在main函數(shù)中調(diào)用10幾個子函數(shù),然后直接通過液晶屏或者其他的手段觀察效果是正確,這樣的方法對嗎 ?以下是常用方法:

1.借助于網(wǎng)上的視頻講解或源代碼,(對于32位的MCU尚可理解,但是51、PIC.MSP430單片機(jī)使用者如果入門后還是同樣的方法,你就OUT了),但只適用于部分網(wǎng)上資料較多的芯片。

2.借助"邏輯分析儀"儀器去分析(這種神器我也是通過網(wǎng)上資料介紹,有所了解,但是并沒有使用過,不過好像非常好用的),通過邏輯分析儀可以分析我們的時序是否存在問題,但是個人感覺比較適用于菜鳥和破解單片機(jī)程序的高手,對于大多數(shù)用戶,沒有必須花錢購買

3.利用程序本身去驗(yàn)證程序,編寫一個函數(shù),測試一個函數(shù),操作簡單,屢試不爽,這里以大家熟知的51類單片機(jī)STC12C5A60S2和數(shù)字溫度傳感器DS18B20為例(單總線協(xié)議通信)。

下圖為DS18B20的“復(fù)位”時序,因?yàn)槊看尾僮鞫夹枰狹CU發(fā)送一個復(fù)位信號,所以,“復(fù)位”函數(shù)相當(dāng)重要。

我們知道,當(dāng)DS18B20存在時,紅色部分的時間內(nèi),總線將會被DS15B20拉低,呈現(xiàn)低電平 ; 如果DS15B20不存在,則在單片機(jī)使用總線(藍(lán)色)后,紅色部分仍然是高電平。

假設(shè)我們有以下定義:

[cpp] view plain copy

typedef unsigned char UB8 ;

typedef unsigned short int UW16 ;

typedef unsigned long UL32 ;

typedef char SB8;

typedef short int SW16 ;

typedef long SL32 ;

#define HIGH_LEVEL 1

#define LOW_LEVEL 0

sbit ds18b20_io_bit = P1^7 ;/*根據(jù)硬件選擇*/

#define DS18B20_EXISTENCE 0 /*存在DS18B20*/

#define DS18B20_NOT_EXISTENCE -1/*不存在DS18B20*/

然后編寫“復(fù)位函數(shù)”

[cpp] view plain copy

/******************************************************

Function :ds18b20Init

Input :N/A

Output :N/A

Return :DS18B20_EXISTENCE或者DS18B20_NOT_EXISTENCE

Description :N/A

Note :經(jīng)過測試在11.0592MHZ和12.00MHZ條件下都可以

檢測到ds18b20的存在。

******************************************************/

SB8 ds18b20Init(void)

{

SB8 existenceFlag ;

UB8 i=0 ;

ds18b20_io_bit = HIGH_LEVEL ;

_nop_() ;

_nop_() ;

/*master transmit the reset pulse */

ds18b20_io_bit = LOW_LEVEL ;

delay720usForDs18b20();

/*rising edge*/

ds18b20_io_bit = HIGH_LEVEL ;

/*ds18b20 wait 15us to 60us then transmit a presence pulse by

pulling the 1-wire low for 60us to 240 us */

delay15usForDs18b20();

delay15usForDs18b20();

delay15usForDs18b20();

delay15usForDs18b20();

if( ! ds18b20_io_bit)

{/*ds18b20 eixstence*/

existenceFlag = DS18B20_EXISTENCE;

}

else

{/*no ds18b20*/

existenceFlag = DS18B20_NOT_EXISTENCE;

}

while((!ds18b20_io_bit) && (i<250))

{

i++;/*wait*//*暫時,具體見調(diào)試*/

/*經(jīng)過測試,這里的250對于11.0592MHZ和12MHZ都遠(yuǎn)遠(yuǎn)足夠了*/

}

return existenceFlag ;

}

然后,我們驗(yàn)證此函數(shù)是否可以成功完成“復(fù)位功能”:(時序不再詳細(xì)分析)

[cpp] view plain copy

#include

#include "ds18b20.h"

void main(void)

{

SB8 flag = -3 ;

P1=0x00;//連接leds,高電平點(diǎn)亮

flag = ds18b20Init();

if( flag == DS18B20_EXISTENCE) //檢測結(jié)果:存在,0

{

P1 = 0x01 ;

}

else if(flag == DS18B20_NOT_EXISTENCE)//檢測結(jié)果:不存在,-1

{

P1=0x02;

}

else

{

P1 = 0x04 ;

}

while(1) ;

}

這樣,我們通過LED就可以驗(yàn)證函數(shù)了:

(1)正常連接DS18B20,結(jié)果如果是P1的第一個燈亮了(P1=0x01),則表示單片機(jī)可以檢測到DS18B20的存在,說明函數(shù)可能對了(可以檢測到DS18B20的存在);

(2)拔掉DS18B20,結(jié)果如果是P1的第二個燈亮了(P1=0x02),則表示單片機(jī)未檢測到DS18B20的存在,說明函數(shù)完全正確。(可以同時檢測到DS18B20的存在和不存在)

注意:只有當(dāng)(1)(2)都正確后,才表示此“復(fù)位”函數(shù)編寫正確了。然后繼續(xù)進(jìn)行下面的函數(shù)編寫。

同樣的,對于很多芯片,我們使用51單片機(jī)驅(qū)動時,都會涉及到“讀操作”和“寫操作”,在編寫讀寫函數(shù)時,通常嚴(yán)格按照時序編寫“寫”函數(shù)和“讀”函數(shù),然后向芯片的內(nèi)部RAM寫入一個數(shù)據(jù)(這個數(shù)據(jù)最好不是0xff,因?yàn)楫?dāng)芯片未連接時,單片機(jī)讀出的數(shù)據(jù)就是0xff,這時候如果我們寫0xff,然后讀取,因?yàn)榻Y(jié)果肯定是0xff,所以并不能證明我們的讀寫函數(shù)書寫正確),然后讀出該地址的數(shù)據(jù),驗(yàn)證數(shù)據(jù)是否相同,如果相同,表明讀寫操作正確,但是這里同時需要注意一個問題:讀/寫操作周期為多少?即需要隔多長時間MCU才可以繼續(xù)讀/寫此芯片,因?yàn)閷τ谛酒?,我們讀寫一次后,可能需要過一段時間才可以繼續(xù)讀寫,如果沒有注意這個問題,就可能導(dǎo)致:編寫的代碼好像沒錯,但是在后期我們連續(xù)對芯片進(jìn)行讀/寫操作時,沒有注意這個延時等待啊,就會出現(xiàn)很奇怪的問題(通常這種錯誤導(dǎo)致的結(jié)果是隨機(jī)的),這時候反過來調(diào)試過程可能就繁瑣了,如果連續(xù)操作間隔較長,安全的做法是:在每一次讀/寫操作后,都加一個延時,這樣就保證肯定OK了。

問題0010:藍(lán)牙串口模塊使用的正確步驟

很多人現(xiàn)在都開始使用藍(lán)口模塊,利用手機(jī)藍(lán)牙或者PC藍(lán)牙進(jìn)行控制單片機(jī)系統(tǒng)。但是很多人一上來就直接把藍(lán)牙模塊和單片機(jī)相連接,然后編寫程序,效果實(shí)現(xiàn)不了,就不知該如何了。藍(lán)牙模塊很多都是結(jié)合了串口通信的,通常拿到模塊,需要經(jīng)過一下步驟(自己總結(jié),可做參考):

(1)首先,需要藍(lán)牙模塊和PC的硬件連接,這里有兩種方法:

把你的開發(fā)板的單片機(jī)取下來,然后從開發(fā)板引出電源線VCC和GND,還有P30、P31接口,連接藍(lán)牙模塊的四個端口(注意RXD和TXD不要反接了)

如果你有USB-TTL模塊,可以直接連接藍(lán)牙模塊,無需單片機(jī)開發(fā)板轉(zhuǎn)接過去。

(2)通過PC的串口軟件(比如STC-ISP軟件自帶的串口),設(shè)置好軟件的波特率和通信數(shù)據(jù)格式,通過串口軟件發(fā)送AT命令(通常購買時賣家提供了),看是否有返回數(shù)據(jù),如果沒有返回,有可能是P30、P31接口需要換過來,如果發(fā)送命令,有返回信息且不是亂碼,表示藍(lán)牙模塊和PC可以串口通信了。

(3)手機(jī)下載軟件“藍(lán)牙串口”,通過此軟件連接藍(lán)牙模塊(藍(lán)牙的名稱和配對密碼可通過 AT命令設(shè)置),然后給藍(lán)牙模塊供電,PC打開串口軟件,手機(jī)發(fā)送任意字符到藍(lán)牙模塊,會發(fā)現(xiàn)PC串口軟件接收到了信息,這表示藍(lán)牙可以正常工作。

(4)編寫單片機(jī)程序,此時需要分為兩步:

先不連接藍(lán)牙模塊,編寫程序,單片機(jī)接收到串口數(shù)據(jù),做出相應(yīng)動作,寫好后下載,然后打開PC的串口軟件,發(fā)送命令,檢驗(yàn)現(xiàn)象是否正確,如果正確,開始第二步

把藍(lán)牙模塊連接到單片機(jī),手機(jī)藍(lán)牙連接模塊,手機(jī)發(fā)送命令,此時只要步驟現(xiàn)象經(jīng)過反復(fù)驗(yàn)證沒有問題,第二步肯定沒問題。(如果第二步不對,那就返回去做第一步)

(5)其他。如果需要用PC的藍(lán)牙進(jìn)行控制,還需要購買藍(lán)牙適配器,也就是模塊發(fā)送信息到電腦時,需要一個接收器。如果不是很必要,就用手機(jī)藍(lán)牙軟件就好了,省錢省事。

問題0011:不知道遙控器的編碼協(xié)議,如何解碼

不同的遙控器,其協(xié)議也不同.

要看你的目的是什么 , 分兩種情況:

(1)你只是想單純的解碼出來而已 :可以查看一下你用的遙控器類型,然后百度一下試試看 , 然后結(jié)合示波器觀看。

(2)你想解碼出來后,用到其他設(shè)計上去 :這里有兩種方法

較為嚴(yán)格 : 就是參考(1)的思路去實(shí)驗(yàn),但是花時太多。

<2>不是很嚴(yán)格,但是很實(shí)用 : 先在網(wǎng)上看一個紅外遙控器的協(xié)議,然后根據(jù)它的協(xié)議去解碼,然后,查看解碼的是否正確(通過原碼和反碼初步驗(yàn)證) , 然后把按下每一個按鍵,去記錄下他的編碼,然后下一設(shè)計要用到它的時候,你就把上次記錄的編碼,做一個數(shù)組,然后自己去定義每一個編碼對應(yīng)的功能即可。(因?yàn)閷?shí)際上很多類型的編碼,無非是引導(dǎo)碼的時間不同,當(dāng)然我們可以不關(guān)心引導(dǎo)碼 ,還有就是0和1的定義不同,再或者就是先傳輸?shù)氖歉呶贿€是低位 , 就是以上三點(diǎn)不同---->個人理解,可能有所偏差,但是對于我們,我們可以不關(guān)心解碼得到的是對的,還是不對的--->這里的“不對”是指是否和其真實(shí)的編碼相同,而不是解碼失敗。我們只需要關(guān)注,接收到的信息是否和數(shù)組里面的一樣,如果一樣,就完成某種功能。 當(dāng)然,這里有更加簡單的方法,就是無需每次記錄,用一個薄碼開關(guān),去選擇學(xué)習(xí)模式和工作模式,這時候定義一個數(shù)組,然后先進(jìn)入學(xué)習(xí)模式下,將接收到的信息放在數(shù)組中,然后進(jìn)入工作模式,工作模式下只是對比此次接受的編碼和數(shù)組當(dāng)中的編碼,如果相同,則完成一定的任務(wù)就可以了)

問題0012:Proteus仿真的那點(diǎn)事

越來越多的人,問我以下問題

(1)為什么我的程序在Proteus中可以運(yùn)行,但在實(shí)物上卻運(yùn)行失敗。

(2)為什么我的程序在實(shí)物上可以運(yùn)行,但是Proteus中卻運(yùn)行失敗。

現(xiàn)在在這里做統(tǒng)一解答 : (1)Proteus仿真和實(shí)物有差異,在Proteus中成功的代碼不一定可以用于實(shí)物,反過來,實(shí)物上已經(jīng)成功的代碼也不一定可以用于Proteus。如果出現(xiàn)了一方成功,一方失敗,那么很大的就是延時。(當(dāng)然不排除其他可能性,但這個延時問題可能最大)

(2)如果軟件仿真和硬件實(shí)驗(yàn),只有一方可以成功,而另一方失敗。 那么表明你的邏輯上沒有錯誤。參照第一條,稍做修改即可 。

問題0013:程序的嚴(yán)格性

程序的嚴(yán)格性似乎總是被很多人遺忘,在編寫程序時,一定要把隱患消滅掉,否則后患無窮。這里以1602液晶屏為例,希望可以作為一個切入點(diǎn),但是要通過問題表象,看到問題本質(zhì),而不僅僅局限于1602液晶屏,思想更加重要。大家都知道1602液晶屏的數(shù)據(jù)口是8位數(shù)據(jù)口,但是實(shí)際上還有一種模式,就是4位數(shù)據(jù)口,實(shí)質(zhì)上很簡單,就是利用4位數(shù)據(jù)口傳送數(shù)據(jù),傳送兩次而已,其他無差別,但這不是這里討論的關(guān)鍵。下面看一下網(wǎng)友的代碼(只放關(guān)鍵部分):

[cpp] view plain copy

#define DataPort P0

void LCD_Write_Data(unsigned char Data)

{

//while(LCD_Check_Busy()); //忙則等待

DelayMs(5);

RS_SET;

RW_CLR;

EN_SET;

DataPort= Data;

_nop_();

EN_CLR;

EN_SET;

DataPort= Data<<4;

_nop_();

EN_CLR;

}

其中,我們之關(guān)心兩句話,就是DataPort= Data; 和DataPort= Data<<4; 這兩句話什么意思呢 ? 就是通過P0端口的高4個Bit,把數(shù)據(jù)傳送兩次,使用的是P04,P05,P06,P07。這里的實(shí)驗(yàn)網(wǎng)友成功了,他認(rèn)為這個代碼沒有問題,但是這里的隱患確實(shí)非常明顯的,如果不該掉,可能導(dǎo)致這樣的情況發(fā)生:在1602的液晶屏4位數(shù)據(jù)口模式的獨(dú)立實(shí)驗(yàn)中成功了,但是在一個復(fù)雜的系統(tǒng)設(shè)計中,卻出現(xiàn)了很多意料之外的情況。實(shí)際上,問題較為突出,比如第一句DataPort= Data ; 從上面我們看出,對于1602而言,他只關(guān)心和他的4位數(shù)據(jù)口連接的 P04,P05,P06,P07的狀態(tài),但是上面的復(fù)制,卻影響到了P00,P01,P02,P03,這里明顯不行的,比如P00,P01,P02,P03連接了LED或者其他設(shè)備,這時候會影響到他們的運(yùn)行。所以我的建議是,修改為:

[cpp] view plain copy

第一次傳送:

DataPort &= 0x0f ; /*P0高4位清零,準(zhǔn)備傳送數(shù)據(jù)*/

DataPort |= (temp & 0xf0) ;/*P0傳送數(shù)據(jù)temp的高4位,P0的低4位不受影響*/

第二次傳送:

DataPort &= 0x0f ; /*P0高4位清零,準(zhǔn)備傳送數(shù)據(jù)*/

DataPort |= ((temp & 0x0f)<<4) ;/*P0傳送數(shù)據(jù)temp的低4位,P0的低4位不受影響*/

這里,希望新手可以通過這表象,看到問題的本質(zhì),將隱患扼殺在搖籃,否則簡單的1602的4位數(shù)據(jù)口模式,會成為你調(diào)試復(fù)雜系統(tǒng)調(diào)試的噩夢。

問題0014:液晶如何顯示小數(shù)并且小數(shù)自動四舍五入

液晶顯示數(shù)據(jù)的小小技巧:(主要針對液晶顯示浮點(diǎn)型數(shù)據(jù))

我們在使用液晶屏的時候,無論是1602/12864、NOKIA、J2004A還是其他的,常常遇到需要顯示一個變量(尤其是小數(shù)),那么顯示變量又有一些小小的技巧,這里把我的一些使用方法,給新手介紹一下,歡迎新人學(xué)習(xí),更加歡迎高手拍磚(但不能總是拍,得讓我知道為什么被拍)

(1)首先,我們需要先做一些預(yù)備知識:如何進(jìn)行四舍五入:

[cpp] view plain copy

float temp = 2.376 ;

我們需要保留兩位小數(shù),也就是2.38(四舍五入后的結(jié)果)

在程序中,我們只需要一句話:temp = (unsigned int)((temp*100)+0.5) / 100 ;就完成了這個功能,得到的結(jié)果就是2.38(不信可以試試看額)

(2)液晶如何顯示小數(shù)

使用以下代碼:

[cpp] view plain copy

#include

#include

#include "lcd1602.h"

void main(void)

{

float a = 182.376 ;

lcd1602Init();

lcd1602WriteCommand(0X0C);

/*顯示原來的數(shù)字,非重點(diǎn)*/

lcd1602AddressWriteByte(LCD1602_ROW0,0,((unsigned long)a)%1000/100+'0') ;

lcd1602AddressWriteByte(LCD1602_ROW0,1,((unsigned long)a)%100/10+'0') ;

lcd1602AddressWriteByte(LCD1602_ROW0,2,((unsigned long)a)%10+'0') ;

lcd1602AddressWriteByte(LCD1602_ROW0,3,'.') ;

lcd1602AddressWriteByte(LCD1602_ROW0,4,(unsigned long)(a*10)%10+'0') ;

lcd1602AddressWriteByte(LCD1602_ROW0,5,(unsigned long )(a*100)%10+'0') ;

lcd1602AddressWriteByte(LCD1602_ROW0,6,(unsigned long )(a*1000)%10+'0') ;

lcd1602AddressWriteByte(LCD1602_ROW0,8,0x7e) ;

/*重點(diǎn)部分*/

/*顯示,百位這里我一直最高是百位,所以沒有判斷更加位,實(shí)際操作時,應(yīng)該添加其他機(jī)制,使其更加智能*/

lcd1602AddressWriteByte(LCD1602_ROW0,10,((unsigned long)a)%1000/100+'0') ;

/*顯示十位*/

lcd1602AddressWriteByte(LCD1602_ROW0,11,((unsigned long)a)%100/10+'0') ;

/*顯示各位*/

lcd1602AddressWriteByte(LCD1602_ROW0,12,((unsigned long)a)%10+'0') ;

/*顯示小數(shù)點(diǎn)*/

lcd1602AddressWriteByte(LCD1602_ROW0,13,'.') ;

/*顯示小數(shù)點(diǎn)后第一位*/

lcd1602AddressWriteByte(LCD1602_ROW0,14,(unsigned long)(a*10)%10+'0') ;

/*顯示小數(shù)點(diǎn)后第二位,此時需要四舍五入計算*/

lcd1602AddressWriteByte(LCD1602_ROW0,15,(unsigned long )(a*100+0.5)%10+'0') ;

lcd1602AddressWriteString(LCD1602_ROW1,0,"QQ:279729201") ;

while(1);

}

下載程序后效果如下圖所示:

如果此時修改數(shù)據(jù)temp為182.372,則顯示為下圖:

發(fā)現(xiàn)液晶不僅顯示了數(shù)據(jù),而且有了四舍五入的心結(jié)果。實(shí)際上,這里為了實(shí)驗(yàn)效果,部分代碼并沒有做很好的處理,主要是為了凸顯出重點(diǎn),網(wǎng)友們可以在我的基礎(chǔ)上不斷修改,希望大家可以通過點(diǎn),看到面,不要局限于這一個方式。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉