呵呵,怎么著也算是用過很久的msp430系列的單片機(jī)了,畢設(shè)用的是149,在公司用過2系列、4系列的。也算是有點(diǎn)經(jīng)驗(yàn)了。想想也遇到過好多很2的問題,不知道有沒有用,能想起來的就寫的,有人看了可能會(huì)有幫助,也許有人會(huì)覺得這些問題都是本就該知道的或者看完后不出山人所料的感覺,那就權(quán)當(dāng)小弟的一篇嬉鬧之作,博君一笑而已。
1.外設(shè)共享寄存器的問題。 初學(xué)者經(jīng)常會(huì)想不開,datesheet上明明就標(biāo)著芯片里I2C、SPI、UART都有,用戶手冊看上去每個(gè)都是單獨(dú)模塊,但是事實(shí)上用起來卻不是那么回事,仔細(xì)對比其寄存器,忽然發(fā)現(xiàn),尼瑪,他們就是一個(gè)玩意兒,而且,一次只能用一個(gè),而而且,他們和在一起叫UART!或者usi或者usci!而而而且,通常一款芯片只有一個(gè)UART或者usi或者usci!也就是一次只能也僅有一個(gè)串行口可以用。!我草,坑爹啊,TI你要不要這么無恥啊……頓時(shí)會(huì)有種菊花被人*操*弄但是又無法掙扎的感覺。
(哦,好吧,濕太了。。。平復(fù)一下心情~~~~~~~)
也許你這也就不能不懷疑了,為何430會(huì)這么低功耗,因?yàn)橥降腎2C和SPI的主模式還有異步的UART,它們的開啟都是需要時(shí)鐘的,當(dāng)你同時(shí)開啟多個(gè)外設(shè)的時(shí)候,就會(huì)有多個(gè)時(shí)鐘在工作,外設(shè)的各個(gè)寄存器分明,占用的資源也就多了,功耗自然就上去了。而430卻限制你一次只能用一個(gè),而且其寄存器非常簡單,我不知道這和430的低功耗會(huì)不會(huì)真的有大的關(guān)系,但是當(dāng)我使用了業(yè)內(nèi)唯一敢叫板430低功耗的pic之后,居然發(fā)現(xiàn)它TMD也這么干。
世界上兩個(gè)半導(dǎo)體大公司,TI和microchip分別編織了兩個(gè)謊言:低功耗和強(qiáng)抗干擾,誆大伙去買,然后抬高價(jià)格,其實(shí)用過的人都知道,430寄存器及其簡單,外設(shè)寄存器共享,完全沒有AVR和STM8那么嚴(yán)謹(jǐn)各個(gè)外設(shè)功能分明,而是能省則省。pic單片機(jī),14位寬的程序存儲(chǔ)器,蛋疼的ram分頁,蛋疼的外設(shè)操作(特別是定時(shí)器操作,想起來頭皮發(fā)麻~)……而事實(shí)上怎么樣,只有用的人心里知道了,反正一個(gè)愿打一個(gè)愿挨,工程師能忍就忍,芯片廠家廣告出去了,還不是掙得瓢滿缽滿的。。。
2.定時(shí)器問題。 430的定時(shí)器很給力,以前官網(wǎng)的選型表會(huì)寫出Capture/Compare Register的個(gè)數(shù),而弱化了Timer的概念,當(dāng)然現(xiàn)在不會(huì)了。這個(gè)CCR是啥呢?就是捕獲比較寄存器,當(dāng)你看到CCR的個(gè)數(shù)有3~5個(gè)的時(shí)候,你是否很興奮?我草,那你就悲劇了!真相就是大多數(shù)的430定時(shí)器就1個(gè),尼瑪,最普通的51都有兩個(gè)。
最典型的CCR是有三個(gè)。一般情況下,TAR(或者TBR)是計(jì)數(shù)寄存器,它負(fù)責(zé)計(jì)數(shù)。其實(shí)說穿了也就是同步用的,當(dāng)開啟比較模式的時(shí)候,CCR0是被用來做周期寄存器的,而CCR1和CCR2是在CCR0的范圍內(nèi)與TAR(或者TBR)進(jìn)行比較。其實(shí)比較一般也就是為了得到一個(gè)好的pwm模式,有了這樣的一種定時(shí)器機(jī)制,寄存器簡單,使用起來也很方便,可以隨意更改占空比和周期,將CCR0修改即可修改周期,將CCR1或者CCR2修改即可修改占空比。定時(shí)器up模式下,產(chǎn)生的就是avr中所言的快速pwm,up/down模式則是相位修正pwm。雖然430定時(shí)器操作簡單,但不可否認(rèn)它比avr的定時(shí)器靈活得多,avr沒有專門的周期寄存器,它并不能靈活的修改pwm的頻率,只有在特定的幾種模式下可以。
很重要的一點(diǎn),430的定時(shí)器CCR的修改都是及時(shí)更新的,并不像avr一樣是下個(gè)周期更新或者像stm8或者stm32一樣可以選擇更新方式,更沒有重裝載寄存器。所以想要用430做spwm的朋友請注意了,如果想要得到正確的spwm波,更新CCR的時(shí)候一定要選擇CCR0中斷的時(shí)候。
說到中斷,又有一個(gè)比較糾結(jié)的問題了,呵呵,一個(gè)定時(shí)器有兩個(gè)中斷向量,以TA0為例
TIMER0_A1_VECTOR
TIMER0_A0_VECTOR
TIMER0_A1_VECTOR是比較中斷1~4,還有溢出中斷。也就是說當(dāng)不操作CCR的時(shí)候,也就是沒有啟用比較捕獲的時(shí)候,單純想要使用TAR計(jì)數(shù)計(jì)到0xffff溢出,會(huì)觸發(fā)的中斷,會(huì)進(jìn)到這個(gè)中斷,當(dāng)然一般也就是剛從51轉(zhuǎn)過來,大腦還沉浸在51快樂時(shí)光里的犯2的人才會(huì)這么做。CCR1~CCR4的比較捕獲中斷也是進(jìn)這個(gè)中斷。而CCR0是進(jìn)到TIMER0_A0_VECTOR,所以做spwm的朋友要開啟這個(gè)中斷。一般情況下比較模式也就是PWM模式有7種,而只開啟CCR0不開啟其他CCR的時(shí)候,只能用四種,常用一般也就三種,set強(qiáng)制拉到有效,toggle扳機(jī)也就是翻轉(zhuǎn),reset強(qiáng)制拉到無效。
3.ADC的功耗隱藏任務(wù)問題。 想要低功耗,那就別用ADC,這個(gè)隱藏的功耗殺手,會(huì)不經(jīng)意間給你來那么一下。當(dāng)你進(jìn)去深度睡眠的時(shí)候,想要測一下功耗卻發(fā)現(xiàn)測出來的功耗與電氣特性表上標(biāo)明小于1uA相差了幾百uA正要大罵TI坑爹的時(shí)候,你看看你的ADC關(guān)了木有~~~DC關(guān)了木有~~~C關(guān)了木有~~~關(guān)了木有~~~了木有~~~木有~~~有~~~(這是肥音)
ADC開啟的時(shí)候會(huì)消耗將近200uA的電流,和深度休眠的差了200倍!!所以最好在使用完ADC之后,將其寄存器全部清空。哦,對了,不小心插一句,AVR有硬件模擬比較器,這個(gè)默認(rèn)是打開的,為了節(jié)省功耗你可以每次上電都將ACSR寄存器的ACD置位。每個(gè)使用430的ADC的孩紙上輩子都是折翼的天使,而且掉下來都是腦袋先著地的,傷不起啊~
4.LCD外接電阻問題。
看到這里,很多人可能都會(huì)覺得我有點(diǎn)吹毛求疵,不見得大家都不明白,即便這個(gè)問題也一樣,說來話長估計(jì)大家都明白。那我就長話短說。很多人使用lcd的時(shí)候都喜歡在R33、R23、R13、R03之間接上大電阻,貌似為了符合用戶手冊上的指示,其實(shí)只是為了求心安的一個(gè)表現(xiàn)罷了,實(shí)際上會(huì)有多少人會(huì)把REXT置一呢?因?yàn)?font color="#ff0000">REXT置一才是使用外部電阻啊。!我看過很多人的程序,沒有看到啊,包括代理發(fā)給我的程序。我很負(fù)責(zé)的告訴你,你TMD就是犯賤,知道在這里加上3、4個(gè)外部電阻給你的PCB布線帶來多大的煩惱么?這就是坑爹的安排!因?yàn)镽EXT置一之后液晶會(huì)顯示不正常,這個(gè)是要調(diào)的!所以當(dāng)你對于液晶對比度的調(diào)節(jié)要求要求不高的時(shí)候(Rx可以調(diào)節(jié)液晶對比度),直接將外面的電阻舍去,使用內(nèi)部電阻,方便布線。 5.存儲(chǔ)器的問題。 這個(gè)問題是一個(gè)很嚴(yán)肅的問題。如果說ADC是功耗的隱藏任務(wù),那么這個(gè)就是動(dòng)搖你的整個(gè)程序結(jié)構(gòu)基礎(chǔ)的隱藏boss,要么你遇不到,遇到了你就over了,因?yàn)檫@個(gè)不是打怪升級。我們先來看看一個(gè)warning:
也許這個(gè)問題有人一輩子都遇不到的,這個(gè)問題很蛋疼。神馬叫做訪問了奇地址???這個(gè)問題和電腦上的暴力訪問內(nèi)存某地址有著異曲同工之妙。當(dāng)時(shí)我遇到這個(gè)問題的時(shí)候,有種蛋蛋被人捏在手里的感覺。不過幸好有mc_wangbo這位高人指點(diǎn)。 首先要確定這個(gè)地址在什么地方。由于430是馮諾依曼結(jié)構(gòu)的所以程序存儲(chǔ)器和數(shù)據(jù)存儲(chǔ)器是一起的。按上用戶手冊上所說,0x0200以上是RAM,當(dāng)然是看大小。因?yàn)楫?dāng)時(shí)我使用的是msp430f4152,RAM為512B,也就是0x0200~0x0400為RAM區(qū),0x0400以上是code區(qū),那么也就是code區(qū)有問題。 然后再解釋奇地址的問題。下面是截自用戶手冊的一段關(guān)于存儲(chǔ)器組織的一段話: 上面的意思是說,字節(jié)數(shù)據(jù)可以位于奇地址和偶地址,而字?jǐn)?shù)據(jù)只能位于偶地址。!什么意思呢?msp430是16位單片機(jī),它的一個(gè)字就是2個(gè)字節(jié),雖然它是16位單片機(jī),它還是按照半字方式進(jìn)行存儲(chǔ),它的一個(gè)地址對應(yīng)的其實(shí)是一個(gè)字節(jié),而不是一個(gè)字。。∫簿褪钦f它的存儲(chǔ)方式還是8位的(這種存儲(chǔ)方式的好處是不會(huì)浪費(fèi)RAM),只是一次可以處理2個(gè)8位的數(shù)據(jù)而已...所以地址才要區(qū)分奇偶!又由于其存儲(chǔ)方式是小端存儲(chǔ),16位數(shù)據(jù)高8位存在高地址低8位存在低地址,但是低地址必須是偶地址。! 那么情況就大概明了了。編譯器編譯的結(jié)果,一般單純的指令是不會(huì)存在這種漏洞的,唯一的可能性就是,定義在code區(qū)的常量出問題了,也就是前面加了const的變量。! 為什么呢?因?yàn)榫幾g器還沒有那么智能,假設(shè)你定義的常量變量是一串unsigned char型的數(shù)組,帶著const,如x[4]={0x12,0x34,0x56,0x78};編譯器看你是定義的8位,它會(huì)使用MOV.B(半字指令)來將這串?dāng)?shù)組常量存儲(chǔ),假設(shè)存儲(chǔ)在0xc120,0xc121,0xc122,0xc123這4地址上。這個(gè)本來就無可厚非,但是如果你在程序中將這4個(gè)數(shù)強(qiáng)制轉(zhuǎn)換為一個(gè)unsigned char、一個(gè)unsigned int和一個(gè)unsigned char型的結(jié)構(gòu)體(別說不可以,指針是個(gè)很奇妙的東西),那么隱藏的boss就如死神一樣揮起收割靈魂的鐮刀,在使用這個(gè)結(jié)構(gòu)體的時(shí)候單片機(jī)先使用MOV.B來調(diào)用第一個(gè)unsigned char數(shù)也就是0xc120上的0x12,然后再用MOV.W來調(diào)用第二個(gè)unsigned inti型的數(shù)也就是0xc121和0xc122上的數(shù)連起來是0x5634,但是實(shí)際上就出錯(cuò),因?yàn)榈偷刂繁淮嬖诹?xc121這個(gè)奇地址上!。!MOV.W無法訪問奇地址!!也就是說實(shí)際上單片機(jī)根本就不會(huì)去訪問0xc121這個(gè)地址,而是跳過了0xc121直接從0xc122開始取出數(shù)據(jù),取出來的是0x7856。!坑爹了吧!!而且這個(gè)警告在編譯的時(shí)候不會(huì)出錯(cuò)。。∠碌絾纹瑱C(jī)里面也不會(huì)出錯(cuò),還能運(yùn)行!!只有在軟件仿真的時(shí)候編譯器會(huì)出錯(cuò)。。! 最好的解決方法,就是別這么干,編譯器不會(huì)出錯(cuò),它也不會(huì)故意這么分配地址,所以當(dāng)你定義半字?jǐn)?shù)組,而在程序中又要強(qiáng)制轉(zhuǎn)換類型的時(shí)候,就要特別注意。如果你想要把每個(gè)數(shù)組都定義到偶地址,可以在定義完數(shù)組之后在數(shù)組后面加上@0xc120,這樣數(shù)組就會(huì)定義到這個(gè)地址開始的地方。
|