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