該MCU是由德州儀器TI生產(chǎn)的16位低功耗單片機
主要分以下型號:
- 專注低功耗的1xx通用型,配備1KB-60KB FLASH、512B-10KB RAM,工作時耗電僅達200uA/MIPS,RAM保持模式耗電0.1uA,RTC模式耗電0.7uA;可在6us之內(nèi)快速喚醒。搭載10/12位斜率SAR ADC,集成模擬比較器、DMA、硬件乘法器、BOR、SVS、12位DAC
- 能耗比高的F2xx通用型,性能16MIPS@3.3V,配備1-120KB FLASH,8-128KB RAM,工作耗電220uA,配備10/12位斜率SAR ADC,集成16位Σ-ΔADC,基本上等于1xx的升級版
- 性價比高的G2xx經(jīng)濟型,性能16MIPS@3.3V,對標友商stm32l,主打模擬外設(shè)和低功耗
- 面向計量和智能電網(wǎng)的AFE2xx專用型:性能略低于以上兩個2xx系列,但是集成了1-3個獨立的24位Σ-ΔADC,一個16位定時器、一個16位硬件乘法器、USART控制器、看門狗和GPIO
- 停產(chǎn)的老型號3xx
- 面向低功耗多媒體的4xx控制型,8-16MIPS處理性能,配備LCD控制器、FLL、SVS,針對低功耗測量和醫(yī)療應(yīng)用,功耗和1xx相近,4-120KB FLASH、8-256KB RAM,引腳豐富最多可達80Pin,配備10/12位斜率SAR、16位Σ-ΔADC,同樣集成了12位ADC、DMA、硬件乘法器、運放、USCI模塊等
- 超高能耗比的5xx超低功耗型,能達到25MIPS@3.3V,工作模式功耗165uA/MIPS,RTC模式2.5uA,RAM保持模式可達1uA,待機喚醒時間極短,小于5ms,配備256KB FLASH、18KB RAM,額外集成了USB、模擬比較器
- 高性能、低功耗的6xx系列旗艦型,達到25MIPS@3.3V,配備功耗優(yōu)化的創(chuàng)新電源管理模塊和USB控制器,配備LCD控制器,有256KB FLASH、18KB RAM,74Pin引腳,功耗與5xx系列相同,還額外集成了電壓管理模塊
- 基于FRAM技術(shù)的FRxx系列,和主要的F系列差別在于使用了FRAM存儲技術(shù),能夠達到更快的FLASH訪問速度并在所有功率模式下實現(xiàn)零功率狀態(tài)保持,即使發(fā)生功率損耗的情況也可以保證寫入操作,寫入壽命能達到100M個周期,不再需要EEPROM
- 低電壓C、L系列,兩個謝列都可以在0.9-1.65V電壓范圍內(nèi)工作并提供4MIPS的性能
- 集成射頻基帶的CC無線系列,具有低于1GHz的片上射頻收發(fā)器,工作電壓為1.8-3.3V,處理性能20MIPS
- 特殊系列:面對車規(guī)應(yīng)用、電容觸摸、超聲波測量、DSP等等特殊用途的系列設(shè)備
綜合來看MSP430具有以下特點:
-
超低功耗
使用1.8-3.6V低電壓供電,RAM數(shù)據(jù)保持方式下耗電僅為0.1μA/MIPS,活動模式下耗電也僅僅為250μA/MIPS,IO輸入端口漏電流僅為50mA,相比之下只有stm8和stm32l0系列能夠達到同等級的低功耗水準。普通的8051則遠遠落后
-
能效比高,針對算法加速
MSP430基于RISC架構(gòu),采用了一般DSP才有的16位多功能硬件乘法器、硬件乘-加功能、DMA等架構(gòu),可以高效實現(xiàn)如FFT、DFT、FIR濾波等數(shù)字信號處理算法
-
模擬外設(shè)技術(shù)高
MSP430片內(nèi)集成多種模擬外設(shè),包括液晶驅(qū)動器和ADC、DAC等,具體外設(shè)由型號決定
-
外設(shè)寄存器直接按位尋址
外設(shè)寄存器可以直接進行賦值、按位操作
msp430系列使用了馮諾依曼架構(gòu),并構(gòu)建了MAB(存儲器地址總線)、MDB(存儲器數(shù)據(jù)總線)兩個總線協(xié)議,其中RAM、FLASH共用同一個地址空間,程序被下載到FLASH,設(shè)備復(fù)位后自動讀取并執(zhí)行程序指令,局部變量存儲在RAM,BSS段變量存儲在FLASH,F(xiàn)LASH掉電不丟失
設(shè)備內(nèi)部時鐘至少具有3套時鐘源:
- LFXT1CLK:低頻時鐘,32.768kHz
- XT2CLK:高頻時鐘,8MHz
- DCOCLK:片內(nèi)數(shù)字控制RC振蕩器,經(jīng)常用作系統(tǒng)和外設(shè)時鐘信號,其穩(wěn)定性由FLL與硬件控制
三套時鐘源可以被設(shè)備單獨選用,時鐘通過片內(nèi)總線提供給設(shè)備;有些型號還具有更多類型的時鐘源
DMA可以直接接管總線以提高傳輸效率(不同于AMBA總線的仲裁,MAB、MDB總線只采用主控設(shè)備-從設(shè)備的方式)
CPU則采用了雙總線位寬的靈活處理方式,分為16位尋址的CPU和20位尋址的CPUX。CPU采用RISC架構(gòu),配備27條指令和7種統(tǒng)一的尋址模式,尋址空間64KB;CPUX尋址空間為1MB,采用面向控制的結(jié)構(gòu)和指令系統(tǒng),集成了計算分支、表處理等特性,可以在不分頁的情況下處理1MB的地址范圍,屬于RISC正交指令集(正交:指令集的絕大多數(shù)指令格式相同、長度相同,所有寄存器的尋址可以替換;而指令的操作碼、尋址方式、操作數(shù)寄存器字段的取值相互獨立),可以實現(xiàn)MTM(內(nèi)存到內(nèi)存)傳輸,不需要經(jīng)過中間寄存器,一并對16位CPU實現(xiàn)了兼容。
外圍電路設(shè)計
供電
MCU部分模擬外設(shè)和FLASH、RAM對于電源要求較高,但是MCU數(shù)字部分對于電源要求較低,因此采用雙電源——模擬/數(shù)字的方式為MCU供電。模擬-數(shù)字電源之間采用磁珠跨接3.3V和地除雜波,同時需要使用10uF、100nF電容并聯(lián)進行濾波,10uF用于濾除低頻雜波,100nF則用于旁路
復(fù)位
RST引腳低電平有效,因此和一般單片機的復(fù)位電路一樣即可
晶振
需要使用兩個晶振接入來保證電源穩(wěn)定,XT1接低頻32.768kHz,XT2接高頻晶振,一般為4MHz,因為內(nèi)部電容不足以起振,所以同時需要單獨配備20-30pF的匹配電容,一般使用22pF電容
USB
f5529具有USB控制器,能夠使用4芯電纜:5V、D+、D-、GND,并可以兼容USB OTG的ID線。
編譯燒錄
MSP430支持JTAG和SBW(Spy-Bi-Wire,TI指定的兩線調(diào)試接口,信號叫為SBWTCK和SBWTDIO)
同時也支持BSL(BootStrap Loader),或者說BootLoader加載程序燒錄可以通過USB、UART等對單片機進行ISP燒錄,在PUR引腳和USB D+之間跨接1.4k電阻,下連1M電阻到地,并通過一個加了限流電阻(一般為100Ω)的微動開關(guān)連接到VCC即可實現(xiàn)USB的BSL燒錄
MSP430的開發(fā)環(huán)境是TI基于eclipse開發(fā)的Code Composer Studio,簡稱CCS,在其中使用專用的MSP430 Compile與Linker即可實現(xiàn)C程序編譯鏈接
關(guān)鍵字和內(nèi)聯(lián)函數(shù)
同時CCS支持了一些擴展關(guān)鍵字,列舉如下:
同時P7.7、P2.2、P1.0分別能夠?qū)ν廨敵鯩CLK、SMCLK、ACLK時鐘
這里用最為復(fù)雜的DCO配置說明整個時鐘系統(tǒng)的配置流程
需要注意:msp430f5529的XTIN和XTOUT引腳默認為GPIO功能,并在上電情況下不會啟動,需要額外進行軟件設(shè)置
但是并不是所有系列都支持這些工作模式,對于f5529來說,不支持LPM3.5
使用以下指令來進入和退出低功耗模式0-4
定時器的基本模式如下:
通過配置TASSEL可以選擇時鐘來自ACLK、SMCLK、TAxCLK(外部輸入)或INCLK(定時器級聯(lián))
-
__asm
用于C語言內(nèi)嵌匯編,這個和keil一樣 -
示中斷函數(shù),一般和#pragma指令共用__interrupt
放在函數(shù)前指 -
#pragma vector=UART0RX_VECTOR __interrupt void UART_ISR(void) { }
-
上例指示了一個串口0接收中斷,#pragma指令讓中斷向量表中的地址位重定向了
-
__monitor
放在函數(shù)前,在執(zhí)行到函數(shù)時自動關(guān)閉全局中斷,類似__atom指令 -
__no_init
放在全局變量錢讓程序啟動時不被變量賦初值 -
__raw
關(guān)閉中斷服務(wù)函數(shù)的恢復(fù)現(xiàn)場能力,這會導(dǎo)致中斷服務(wù)函數(shù)無法返回 -
__regvar
聲明變量為寄存器變量,注意不能使用指針指向寄存器變量,并且必須搭配使用__no_init禁止初始化 -
sfrb
用于聲明單字節(jié)IO數(shù)據(jù)類型對象,和51一樣用于定義寄存器地址 - 除了關(guān)鍵字外,CCS還包含了許多內(nèi)聯(lián)函數(shù),常見的幾個摘錄如下:
-
__no_operation();//空指令,相當于NOP __enable_interrupt();//打開全局中斷 __disable_interrupt();//關(guān)閉全局中斷 __delay_cycles(unsigned long __cycles);//延時__cycles個主時鐘(MCLK)周期 __set_SP_register(unsigned short);//為堆棧指針寄存器SP賦值
預(yù)定義寄存器
-
CCS中還預(yù)置了一些單片機常用的寄存器和配置,如下所示
-
端口定義,其中x表示端口號
PxIN:端口輸入寄存器
PxOUT:端口輸出寄存器
PxDIR:端口方向控制寄存器
PxSEL:端口復(fù)用寄存器
注意:MSP430不支持位操作,一般通過屏蔽位的方法實現(xiàn)位操作,這是它和51開發(fā)方面最大的不同,如下所示
-
#define BIT0 00000001b #define BIT1 00000010b #define BIT2 00000100b #define BIT3 00001000b #define BIT4 00010000b #define BIT5 00100000b #define BIT6 01000000b #define BIT7 10000000b P1OUT |= BIT0; //這樣可以實現(xiàn)P1.0輸出 P1OUT |= BIT4; //這樣可以實現(xiàn)P1.0和P1.3同時輸出 P1OUT &= ~BIT1; //這樣可以取消P1.0的輸出
低功耗模式的進入和退出
CCS預(yù)定義了一些宏指令用來實現(xiàn)低功耗模式
-
LPM3;//進入低功耗模式 LPM3_EXIT;//退出低功耗模式
-
其中數(shù)字可以寫0-4,分別對應(yīng)四種低功耗模式
-
外設(shè)寄存器
各種片上外設(shè)的寄存器都被定義為了宏,可以通過
|=
與&=~
的方式進行按位控制 -
部分常用代碼
-
_dint(); //等效于__disable_interrupt _EINT(); //等效于__enable_interrupt _NOP(); //空指令 _OPC(x); //在指令流中插入一個常熟,對與參數(shù)對應(yīng)的任何指令進行編碼 _SWAP_BYTES(x); //將無符號16位整數(shù)的高8位和低8位交換 monitor //關(guān)鍵字__monitor的宏定義 no_init //關(guān)鍵字__no_init的宏定義
綜上所述,MSP430的開發(fā)和8051的開發(fā)非常類似,并沒有stm32的庫封裝,而是直接操作寄存器。這不僅僅是由于MSP430的性能較低,也是由于這樣的編程方式寫出的代碼更加簡潔、指令量更少,能突出體現(xiàn)MSP430低功耗的優(yōu)勢
-
片上外設(shè)開發(fā)
- MSP430的片上外設(shè)寄存器具體配置和51單片機的很像,但是有一些功能更加復(fù)雜,和stm32的寄存器接近,同時也提供了簡化操作的庫函數(shù)
-
GPIO
-
f5529一共有80個引腳,和stm32的gpio結(jié)構(gòu)類似,并且也具有復(fù)用功能。除此之外某些引腳具備基本的電源功能,分別能夠為MCU的片上數(shù)字電路和模擬電路供電,一般情況下可以共用一個電源,但在某些高精度測量場合需要雙電源隔離供電。msp430還具有一個USB電源,可以直接輸出5V供電,經(jīng)過片上LDO后能在端口VBUS處輸出穩(wěn)定的3.3V電壓供單片機和外設(shè)使用,最大驅(qū)動電流60mA
其中P1、P2端口IO都具有外部中斷能力,分別對應(yīng)P1IV中斷向量和P2IV中斷向量。端口可單獨配置強驅(qū)動和弱驅(qū)動模式,強驅(qū)動模式下全片最大輸出電流100mA,單端口最大電流15mA;弱驅(qū)動模式下全片最大輸出電流48mA,單端口最大電流6mA
-
寄存器操作可以通過上面介紹過的屏蔽位法,也可以通過分別操作寄存器高8位和低8位的方法實現(xiàn)
-
//使用三種方法將P1.1和P2.2配置為輸出功能 P1DIR |= 0x02; //0x02 == 00000010b P2DIR |= 0x04; //0x04 == 00000100b PADIR_L |= 0x02; //DIR寄存器低8位,代表P1 PADIR_H |= 0x04; //DIR寄存器高8位,代表P2 PADIR |= 0x0402; //直接操作DIR寄存器,將其視作uint16_t
端口配置
如下配置端口為輸入狀態(tài)并配置內(nèi)部上拉
-
P1DIR &= ~BIT1; //BIT1 == 0x00000010b,設(shè)置P1.1為輸入模式 P1REN |= BIT1; //使能上下拉電阻 P1OUT |= BIT1; //P1.1配置上拉電阻
通過配置PxDIR.n |= 1可以將相應(yīng)的IO口配置為輸出狀態(tài),在輸出狀態(tài)下,PxREN、PxIN無效。
-
P1OUT |= BIT1; //P1.1輸出高電平 P1OUT &= ~BIT1; //P1.1輸出低電平 P1DS.1 &= ~BIT1; //配置P1.1為弱驅(qū)動輸出 P1DS.1 |= BIT1; //配置P1.1為強驅(qū)動輸出
端口復(fù)用配置
基本每個IO都有端口復(fù)用功能,通過配置PxSEL.n把對應(yīng)的IO口配置為復(fù)用功能
使用以下代碼配置P1.0為定時器A0時鐘輸入
P1DIR &= ~BIT0; //設(shè)置P1.0為輸入狀態(tài) P1SEL |= BIT0; //將P1.0復(fù)用為定時器A0時鐘輸入
相關(guān)配置需要按照datasheet中的端口復(fù)用表選擇
-
時鐘系統(tǒng)與低功耗
-
msp430f5529具有5種時鐘源(XT1CLK、XT2CLK、VLOCLK、REFOCLK、DCOCLK)和3種時鐘信號(MCLK、SMCLK、ACLK)
時鐘系統(tǒng)可以軟件配置成不需要外部晶振、需要一個外部晶振、需要兩個外部晶振、外部時鐘輸入等方式,最極端的情況下單片機內(nèi)部具有自身振蕩器可以為CPU及片上外設(shè)提供系統(tǒng)時鐘
時鐘系統(tǒng)的安全性比較重要,msp430配備了緊急保護系統(tǒng),在外部時鐘故障時會自動選擇內(nèi)部時鐘源REFOCLK或VLOCLK作為時鐘信號,并產(chǎn)生響應(yīng)故障信號(可選中斷)
系統(tǒng)時鐘大致分為兩級,信號生成級和信號分配級,中間通過MUX連接。信號生成級別分為三個模塊基本的OSC模塊可以通過晶振旁路、內(nèi)部REFO或VLO直接輸出XT1CLK、VLOCLK、REFOCLK三種信號;可選的XT2模塊直接輸出XT2晶振的4MHz時鐘作為XT2CLK;可以通過晶振旁路和FLL(Frequency Locked Loop鎖頻環(huán))進行晶振時鐘倍頻和分頻,信號源(即FLLREFCLK反饋時鐘)通過MUX直接引用XT1CLK、REFOCLK、XT2CLK之一,經(jīng)過多個倍頻分頻器后輸出為DCOCLK和DCOCLKDIV。所有信號分別輸出到信號分配級,通過MUX分配給ACLK、MCLK、SMCLK
XT1CLK:外部低頻或高頻時鐘源,默認關(guān)閉,需要接入外部晶振并通過軟件使晶振起振后再使用,一般使用32.768kHz的低頻晶振,但是也可以使用4-32MHz的外部高頻時鐘源,端口P5.4、P5.5
使用下面的代碼對時鐘源進行配置
-
P5SEL |= BIT4 | BIT5; //配置P5.4、P5.5為XT1復(fù)用功能 UCSCTL6 |= XCAP_3; //配置匹配電容為12pF UCSCTL6 &= ~XT1OFF; //使能XT1,使外部晶振起振 while(SFRIFG1 & OFIFG) { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); //清除三類時鐘故障標志位,等待起振 SFRIFG1 &= ~OFIFG; //清除震蕩器故障標志位 }
XT2CLK:和XT1CLK類似,但只能接4-32MHz的高頻晶振,一般接入4MHz晶振,需要額外加匹配電容方便起振。端口P5.2、P5.3
需要注意的是在配置SMCLK和MCLK為XT2CLK時鐘源之前需要先修改ACLK和REFCLK的時鐘源,因為它們的時鐘源默認為XT1CLK,但這里并沒有啟動,所以會導(dǎo)致沒有必要的XT1CLK始終故障,會影響判斷XT2是否起振,實現(xiàn)代碼如下
P5SEL |= BIT2 | BIT3; //配置P5.2、P5.3為XT2復(fù)用功能 UCSCTL6 &= ~XT2OFF; //使能XT2 UCSCTL4 = UCSCTL4 & (~(SELA_7)) | SELA_1; //將ACLK配置為VLOCLK UCSCTL3 |= SELREF_2; //將REFCLK配置為REFOCLK while(SFRIFG1 & OFIFG) { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); //清除三類時鐘故障標志位,等待起振 SFRIFG1 &= ~OFIFG; //清除震蕩器故障標志位 }
VLOCLK:內(nèi)部低功耗、低頻時鐘源,頻率10kHz,精度較低,會隨電源電壓和溫度產(chǎn)生較大漂移,用于不需要精準時鐘基準的系統(tǒng)控制,被使用時自動開啟、不使用時自動關(guān)閉,低功耗喚醒模式下回優(yōu)先使用該時鐘源作為系統(tǒng)和看門狗時鐘
配置UCSCTL4選擇
-
REFOCLK:內(nèi)部修整低頻參考時鐘源,精度較高,32.768kHz,和VLOCLK一樣不需要配置寄存器進行起振,若未使用外部晶振,系統(tǒng)會自動選擇該時鐘源作為ACLK和DCOCLK鎖頻環(huán)參考時鐘源
-
DCOCLK:內(nèi)部數(shù)字控制時鐘源,具有寬工作頻率,最高可產(chǎn)生25MHz時鐘頻率,可以和FLL配合控制參考時鐘,也可以引入其他時鐘源反饋進行時鐘分頻/倍頻,但是需要額外配置
這是f5xx中最常用的時鐘源,類似于stm32的PLL時鐘(它的內(nèi)部也是類似的PLL)
其頻率計算公式如下
D C O C L K = D × ( N + 1 ) × R E F C L K n D C O C L K D I V = ( N + 1 ) × R E F C L K n DCOCLK = D \times (N+1) \times \frac{REFCLK}{n} \\ DCOCLKDIV = (N+1) \times \frac{REFCLK}{n} DCOCLK=D×(N+1)×nREFCLK?DCOCLKDIV=(N+1)×nREFCLK?
REFCLK來源見上文n為輸入時鐘分頻,通過UCSCTL3中的FLLCLKDIV設(shè)定,查找該寄存器介紹可知其取值0-7,對應(yīng)n取值2p,默認為0,不分頻
D通過UCSCTL2中的FLLD設(shè)對,可取值0-7,對應(yīng)D取值2p,默認為1,即D=2,二分頻
N可以通過UCSCTL2中的FLLN設(shè)定,取值0-1023,當FLLN=0時,N=1,除此之外N=FLLN,默認為31,即N=31
如果系統(tǒng)復(fù)位后不進行任何設(shè)置,DCOCLK=2097152Hz,DCOCLKDIV=1048576Hz
MCLK和SMCLK都默認選擇DCOCLKDIV作為時鐘源。
通過配置DCORSEL、DCOx、MOD來選擇DCO的頻率設(shè)置范圍(最小值和最大值)
詳細內(nèi)容參考datasheet
MODOSC:內(nèi)部模塊振蕩器,是UCS時鐘模塊下屬的振蕩器,能產(chǎn)生4.8MHz的MODCLK時鐘,用于FLASH、ADC等片上外設(shè)
MCLK:為CPU和片上外設(shè)提供主時鐘,默認使用DCOCLKDIV
通過配置DIVM選擇MCLK分頻系數(shù)為1、2、4、8、16、32
-
UCSCTL4 = UCSCTL4 & (~SELM_7) | SELM_0; //XT1CLK時鐘源 UCSCTL4 = UCSCTL4 & (~SELM_7) | SELM_1; //VLOCLK時鐘源 UCSCTL4 = UCSCTL4 & (~SELM_7) | SELM_2; //REFOCLK時鐘源 UCSCTL4 = UCSCTL4 & (~SELM_7) | SELM_3; //DCOCLK時鐘源 UCSCTL4 = UCSCTL4 & (~SELM_7) | SELM_4; //DCOCLKDIV時鐘源 UCSCTL4 = UCSCTL4 & (~SELM_7) | SELM_5; //XT2CLK時鐘源 UCSCTL5 = UCSCTL5 & (~DIVM_7) | DIVM_0; //MCLK不分頻 UCSCTL5 = UCSCTL5 & (~DIVM_7) | DIVM_1; //MCLK 2分頻 UCSCTL5 = UCSCTL5 & (~DIVM_7) | DIVM_2; //MCLK 4分頻 UCSCTL5 = UCSCTL5 & (~DIVM_7) | DIVM_3; //MCLK 8分頻 UCSCTL5 = UCSCTL5 & (~DIVM_7) | DIVM_4; //MCLK 16分頻 UCSCTL5 = UCSCTL5 & (~DIVM_7) | DIVM_5; //MCLK 32分頻
ACLK:輔助時鐘,專用來為外圍模塊提供信號。默認使用XT1CLK時鐘源,如果未起振,則使用REFOCLK。配置方法和MCLK完全一致
SMCLK:子系統(tǒng)主時鐘,和MCLK基本一致,只是不為CPU提供時鐘
上電復(fù)位后,UCS默認配置如下:
- ACLK選擇XT1為時鐘源,如果未起振則使用REFOCLK并生成時鐘故障標志
- MCLK選擇DCOCLKDIV
- SMCLK選擇DCOCLKDIV
-
需要注意:msp430f5529的XTIN和XTOUT引腳默認為GPIO功能,并在上電情況下不會啟動,需要額外進行軟件設(shè)置
同時P7.7、P2.2、P1.0分別能夠?qū)ν廨敵鯩CLK、SMCLK、ACLK時鐘
這里用最為復(fù)雜的DCO配置說明整個時鐘系統(tǒng)的配置流程
-
#include <msp430f5529.h> #include <stdint.h> void SetVcoreUp(uint_32_t level); //提升核心電壓以提升工作頻率 void XT1_ON(void); //啟動XT1 void DCO__16MHz(void); //使用DCO將XT1倍頻到16MHz void main(void) { WDTCTL = WDTPW + WDTHOLD; P1SEL |= BIT0; //P1.0 ACLK輸出 P1DIR |= BIT0; P2SEL |= BIT2; //SMCLK輸出 P2DIR |= BIT2; P7SEL |= BIT7; //MCLK輸出 P7DIR |= BIT7; P7DIR |= BIT0; //P7.0 LED驅(qū)動輸出 P1OUT |= BIT0; XT1_ON(); DCO__16MHz(); while(1) { __delay_cycles(8000000); //每0.5s P7OUT ^= BIT0 ;//LED狀態(tài)翻轉(zhuǎn)一次 } } void SetVcoreUp(uint_32_t level) { PMMCTL0_H = PMMPW_H; //解鎖PMM寄存器,允許寫入 SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level; //設(shè)置SVS/SVM高側(cè)到新的等級 SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level; //設(shè)置SVS低側(cè)到新的等級 while((PMMIFG & SVSMLDLYIFG) == 0); //等待SVM穩(wěn)定 PMMIFG &= ~(SVMLVLRIFG + SVMLIFG); //清除已經(jīng)置位的標志 PMMCTL0_L = PMMCOREV0 * level; //設(shè)置VCORE到新的等級 if((PMMIFG & SVMLIFG)) //等待達到新的電壓等級 { while((PMMIFG & SVMLVLRIFG) == 0); } //設(shè)置SVS/SVM低側(cè)到新的水平 SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level; PMMCTL0_H = 0x00; //鎖住PMM的寫入路徑 } void XT1_ON(void) { P5SEL |= BIT4 |BIT5; //配置XT1引腳 UCSCTL6 |= XCAP_3; //配置電容為12pF UCSCTL6 &= ~XT1OFF; //使能XT1 while(SFRIFG1 & OFIFG) { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); //清除三類時鐘錯誤標志位 SFRIFG1 &= ~OFIFG; //清除時鐘錯誤標志位 } } void DCO__16MHz(void) { SetVcoreUp(1); //一級一級提升核心電壓,不能跨級 SetVcoreUp(2); /* 配置寄存器使DCOCLK=4.9MHz,DCOCLKDIV=2.45MHz */ __bis_SR_register(SCG0); //關(guān)閉FLL庫函數(shù) UCSCTL0 = 0x0000; //清零寄存器值,F(xiàn)LL運行時系統(tǒng)會自動配置該寄存器 UCSCTL1 = DCORSEL_5; //選擇DCOCLK頻率范圍 6-23.7MHz //FLLD=0,則D=1;FLLN=487,則N=487;N在UCSCTL3寄存器,默認值為1,則DCOCLK=1*(487+1)*32768=15.990784MHz //DCODIVCLK=(487+1)*32768=15.990784MHz UCSCTL2 = FLLD_0 + 487; __bic_SR_register(SCG0); //開啟FLL控制回路 __delay_cycles(76563); //延時等待時鐘穩(wěn)定 while(SFRIFG1 & OFIFG) //檢測時鐘錯誤并等待時鐘穩(wěn)定 { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); SFRIFG1 &= ~OFIFG; } }
低功耗配置
msp430一共有8種工作模式
- 活躍模式(AM)
- 低功耗模式(LPM)0
- 低功耗模式1
- 低功耗模式2
- 低功耗模式3
- 低功耗模式3.5
- 低功耗模式4
- 低功耗模式4.5
-
但是并不是所有系列都支持這些工作模式,對于f5529來說,不支持LPM3.5
使用以下指令來進入和退出低功耗模式0-4
-
/* 開總中斷并進入低功耗模式 */ __bis_SR_register(LPMn_bits + GIE); /* 退出低功耗模式 */ LPMn_EXIT; //其中n可以換成數(shù)字0-4
需要注意:低功耗模式喚醒都需要使用外部中斷,所以需要在進入低功耗模式同時開啟總中斷
在最高級別LPM4.5低功耗模式下,RAM中內(nèi)容會直接丟失,所以在從LPM4.5喚醒后需要重新配置寄存器和相關(guān)設(shè)置
-
中斷
低功耗模式喚醒使用的指令實際上是通過直接修改SR寄存器的值,清除休眠標志,它內(nèi)聯(lián)到以下函數(shù)
_bic_SR_register_on_exit(LPM3_bits);//退出LPM3
MSP430和arm一樣都具有系統(tǒng)中斷、不可屏蔽中斷和可屏蔽中斷三種,其中系統(tǒng)中斷和不可屏蔽中斷優(yōu)先級最高;可屏蔽中斷可以通過狀態(tài)寄存器SR中的GIE位來屏蔽和開啟
大致的中斷作用與arm類似,而使用方式與51類似
下面主要介紹外部中斷
-
初始化端口時要清空中斷標志位
-
P1IFG &= ~(BIT0); //清空中斷標志位
使用
PIES
寄存器選擇觸發(fā)邊沿(0為上升沿,1為下降沿)并使用PxIE
寄存器使能中斷 -
P1IES &= ~BIT0; //P1.0上升沿觸發(fā) P1IES |= BIT1; //P1.1下降沿觸發(fā) P1IES |= BIT2; //P1.2下降沿觸發(fā) P1IE |= BIT0; //使能P1.0中斷 P1IE |= BIT1; //使能P1.1中斷 P1IE |= BIT2; //使能P1.2中斷
開總中斷
-
__bis_SR_register(GIE);
編寫中斷服務(wù)函數(shù)
-
#pragma vector = 中斷向量地址 __interrupt void ISR_function(void) { //中斷服務(wù)函數(shù) }
在中斷函數(shù)內(nèi)部清零中斷標志位
-
__even_in_range(P1IV, 16); //用于查詢P1的所有中斷標志位并自動清零,使用該函數(shù)可以實現(xiàn)將所有P1的外部中斷放在同一個函數(shù)內(nèi)解決的功能,如下所示 switch(__even_in_range(P1IV, 16)) { case 0: //無中斷 break; case 2: //P1IFG.0 /* 中斷處理函數(shù) */ break; case 4: //P1IFG.1 /* 中斷處理函數(shù) */ break; case 6: //P1IFG.2 /* 中斷處理函數(shù) */ break; case 8: //P1IFG.3 break; case 10: //P1IFG.4 break; case 12: //P1IFG.5 break; case 14: //P1IFG.6 break; case 16: //P1IFG.7 break; default: //出錯情況 break; }
此外,msp430還支持手動的嵌套中斷
示例程序如下所示(TI的七段數(shù)碼管驅(qū)動示例程序)
-
#include <msp430.h> const unsigned char SEVENSEG_OUTPUT[10] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; unsigned char loopCounter; unsigned char timeCounter1; unsigned char timeCounter2; unsigned char timeCounter3; int main(void) { WDTCTL = WDTPW | WDTHOLD; //關(guān)閉看門狗 PADIR = 0x03ff; // P1, P2.0 and P2.1 output, P2.6 and P2.7 input PAOUT = 0xc03f; P2REN = 0xc0; // P2.6 P2.7 上拉電阻使能 P2IES = 0x3f; // P2.6 P2.7 配置中斷為上升沿 P2IE = 0xc0; // P2.6 P2.7 interrupt enabled PM5CTL0 &= ~LOCKLPM5; // 關(guān)閉GPIO高阻抗模式 RTCMOD = 50; // 設(shè)置RTC重裝計數(shù)值為50 // 64/32768 * 51 = ~0.1 sec. SYSCFG2 |= RTCCKSEL; // Source = ACLK = REFO,64分頻,選擇ACLK作為RTC時鐘 RTCCTL = RTCSS_1 | RTCSR | RTCPS__64; P2IFG = 0; // 清除P1.3中斷標志位 __bis_SR_register(GIE); //開全局中斷 while(1) { PAOUT |= (BIT9 | SEVENSEG_OUTPUT[timeCounter3]); // 按順序顯示七段數(shù)碼管數(shù)字 __delay_cycles(100); PAOUT = 0xc000; // 清除引腳 PAOUT |= (BIT8 | SEVENSEG_OUTPUT[timeCounter2]); __delay_cycles(100); PAOUT = 0xc000; P1OUT |= (BIT7 | SEVENSEG_OUTPUT[timeCounter1]); __delay_cycles(100); P1OUT = 0; } } //RTC中斷服務(wù)函數(shù) #pragma vector=RTC_VECTOR __interrupt void RTC_ISR(void) { __bis_SR_register(GIE); // 允許嵌套中斷 RTCIV = 0; timeCounter1++; // timeCounter1代表0.1s, timeCounter2代表1s,timeCounter3代表10s,經(jīng)典延時操作 if(timeCounter1 > 9) { timeCounter1 = 0; timeCounter2++; if(timeCounter2 > 9) { timeCounter3++; timeCounter2 = 0; } if(timeCounter3 > 9) { timeCounter3 = 0; } } } //P2中斷服務(wù)函數(shù) #pragma vector=PORT2_VECTOR __interrupt void Port_2(void) { __bis_SR_register(GIE); // 允許嵌套中斷 if(P2IFG & BIT6) { P2IFG &= ~BIT6; // 清除P2.6中斷標志位 // 第一次按下按鈕時開啟定時器;第二次按下時停止定時器 if(loopCounter == 0) { loopCounter++; //開啟一輪循環(huán) RTCCTL |= RTCIE; //開啟定時器 } else { RTCCTL &= ~RTCIE; //關(guān)閉定時器 loopCounter = 0; //循環(huán)清零 } } if(P2IFG & BIT7) { P2IFG &= ~BIT7; // 清除P2.7中斷標志位并復(fù)位秒表 RTCCTL &= ~RTCIE; //關(guān)閉定時器 loopCounter = 0; //復(fù)位所有變量 timeCounter3 = 0; timeCounter2 = 0; timeCounter1 = 0; } }
實現(xiàn)中斷嵌套需要注意以下幾點:
msp430默認關(guān)閉中斷嵌套,一定要中斷嵌套的話,就必須在中斷服務(wù)程序中打開總中斷
msp430的指令中,_DINT()和_EINT()分別指關(guān)和開總中斷
當進入中斷服務(wù)程序時,只要不在中斷服務(wù)程序中再次開中斷,則總中斷是關(guān)閉的,此時來中斷不管是比當前中斷的優(yōu)先級高還是低都不執(zhí)行
若在中斷服務(wù)程序A中開了總中斷,則可以響應(yīng)后來的中斷B(不管B的優(yōu)先級比A高還是低),B執(zhí)行完再繼續(xù)執(zhí)行A
注意:進入中斷服務(wù)程序B后總中斷同樣也會關(guān)閉,如果B中斷程序執(zhí)行時需響應(yīng)中斷C,則此時也要開總中斷,若不需響應(yīng)中斷,則不用開中斷,B執(zhí)行完后跳出中斷程序進入A程序時,總中斷會自動打開
若在中斷服務(wù)程序中開了總中斷,后來的中斷同時有多個,則會按優(yōu)先級來執(zhí)行,即中斷優(yōu)先級只有在多個中斷同時到來時才起作用,中斷服務(wù)不執(zhí)行搶先原則
對于單源中斷,只要響應(yīng)中斷,系統(tǒng)硬件會自動清除中斷標志位。對于TA/TB定時器的比較/捕獲中斷,只要訪問TAIV/TBIV,標志位就會被自動清除;對于多源中斷要手動清標志位,比如P1/P2口中斷,要手工清除相應(yīng)的標志。如果在這種中斷里用
_EINT();
開中斷,而在打開中斷前沒有清標志,就會有相同的中斷不斷嵌入,導(dǎo)致堆棧溢出引起復(fù)位,所以在這類中斷中必須先清標志再打開中斷開關(guān) -
常用中斷向量表
-
#define BASICTIMER_VECTOR (0 * 2u) /* 0xFFE0 Basic Timer */ #define PORT2_VECTOR (1 * 2u) /* 0xFFE2 Port 2 */ #define USART1TX_VECTOR (2 * 2u) /* 0xFFE4 USART 1 Transmit */ #define USART1RX_VECTOR (3 * 2u) /* 0xFFE6 USART 1 Receive */ #define PORT1_VECTOR (4 * 2u) /* 0xFFE8 Port 1 */ #define TIMERA1_VECTOR (5 * 2u) /* 0xFFEA Timer A CC1-2, TA */ #define TIMERA0_VECTOR (6 * 2u) /* 0xFFEC Timer A CC0 */ #define ADC12_VECTOR (7 * 2u) /* 0xFFEE ADC */ #define USART0TX_VECTOR (8 * 2u) /* 0xFFF0 USART 0 Transmit */ #define USART0RX_VECTOR (9 * 2u) /* 0xFFF2 USART 0 Receive */ #define WDT_VECTOR (10 * 2u) /* 0xFFF4 Watchdog Timer */ #defineCOMPARATORA_VECTOR (11 * 2u) /* 0xFFF6Comparator A */ #define TIMERB1_VECTOR (12 * 2u) /* 0xFFF8 Timer B CC1-6, TB */ #define TIMERB0_VECTOR (13 * 2u) /* 0xFFFA Timer B CC0 */ #define NMI_VECTOR (14 * 2u) /* 0xFFFC Non-maskable */ #define RESET_VECTOR (15 * 2u) /* 0xFFFE Reset [HighestPriority] */
定時器
-
msp430有四個基本定時器,外加一個RTC定時器,部分定時器具有PWM輸出功能
計數(shù)器核心是一個計數(shù)寄存器,對輸入的時鐘信號進行計數(shù),可以配置其捕獲跳變沿種類和分頻系數(shù),使用寄存器TAxR獲取當前計數(shù)值。定時器主要分成兩部分:主計數(shù)器和捕獲比較器模塊。捕獲比較器模塊與主計數(shù)器模塊通過TAxR連通,主計數(shù)器會根據(jù)輸入的信號跳變沿遞增/遞減寄存器TAxR/TBxR的值,捕獲比較器會根據(jù)收到的比較值對寄存器的值進行檢查,根據(jù)當前模式不同做出不同反應(yīng),因為計數(shù)寄存器被共用,所以可以將其分成多個通道。一般當捕獲比較器滿足設(shè)置的條件時就會產(chǎn)生中斷,存儲計數(shù)值或輸出相應(yīng)的信號。只需要主計數(shù)器即可完成定時工作,捕獲比較器的作用則在于配合主計數(shù)器完成更多擴展功能
-
Timer_A:16位定時器(最大值65535),具有7個捕獲比較器,支持多路捕獲比較、PWM輸出、間隔定時功能
F5529中包含兩個Timer_A模塊,記作Timer_A0、Timer_A1、Timer_A2,三個模塊的主計數(shù)器在結(jié)構(gòu)上完全相同,單捕獲比較器的數(shù)量不相同:Timer_A0有7個,Timer_A1和Timer_A2各有3個。
- Timer_B:16位定時器(最大值65535),具備Timer_A的所有功能,但它還具備雙緩沖比較鎖存與同步加載功能
-
捕獲器模式
觸發(fā)信號到來時捕獲器將計數(shù)寄存器的值復(fù)制到捕獲比較器的計數(shù)值寄存器TAxCCRn/TBxCCRn,并產(chǎn)生中斷請求
-
比較器模式
需要程序向計數(shù)值寄存器TAxCCRn/TBxCCRn中寫入初值,當主計數(shù)器的計數(shù)寄存器TAxR/TBxR計數(shù)值達到寄存器中存儲的初值后定時器模塊就會向CPU請求中斷
-
輸出模式
傳統(tǒng)的定時器通過標志位判斷來觸發(fā)事件,但msp430配備了專用的輸出模塊,使用輸出模塊寄存器OUTMODEx可以快速輸出PWM信號或其他控制信號
-
定時器中斷
-
定時器A具有兩個中斷源,捕獲比較器0中斷獨立,其他所有中斷(定時器溢出中斷、捕獲比較器1中斷、捕獲比較器2中斷等等)共用中斷源,通過TAxIV來確定具體觸發(fā)中斷的中斷源
使用步驟如下:
-
設(shè)置主計數(shù)器時鐘TA0CTL = TASSEL_1;
-
TA0CTL = TASSEL_1;
-
設(shè)置分頻
-
TA0EX0 = TAIDEX_7 //8分頻
初始化CCR寄存器(設(shè)置初值)并使能中斷
-
TA0CCR0 = 9000; //設(shè)置初值 TA0CCTL0 = CCIE; //使能TA0CCR0中斷
設(shè)置捕獲比較器模式
-
TA0CTL |= MC_2 + TACLR; //清除TA0R,啟動定時器,選擇連續(xù)計數(shù)模式
也可以使用下面的代碼啟用其他模式
-
MC_1 增模式 MC_3 減增模式
開總中斷
-
__bis_SR_register(GIE);
配置中斷服務(wù)函數(shù)
-
#pragma vector = TIMER0_A0_VECTOR //TA0CCR0中斷 __interrupt void TA0CCR0_ISR(void) { TA0CCR0 += 16384; //添加偏置 /* 中斷處理函數(shù) */ }
定時器B
在捕獲比較器和比較器之間加入的比較鎖存器可以分組控制比較值載入的時刻,實現(xiàn)同步更新數(shù)據(jù)
在Timer_B中可以通過配置寄存器TBxCCTLn來選擇TBxCCRn載入TBxCLn的時刻,在Timer_B中起到比較作用的是比較鎖存器TBxCLn而不是CCR寄存器,當TBxR的值達到TBxCLn時,相應(yīng)的中斷標志位置位,產(chǎn)生比較器中斷請求,TBxCCRn的值會在寄存器設(shè)置的時間點載入TBxCLn,從而實現(xiàn)比較延時更新
輸入捕獲
使用定時器的外部計數(shù)功能來測量脈沖個數(shù),可用于測速、編碼器驅(qū)動等場合
基本使用方式和上面的定時器中斷類似,但是需要以下額外語句
-
配置外部時鐘源,使能溢出中斷
-
TA0CTL = TASSEL_0 + TAIE;
清除TAxR、啟動定時器并工作于連續(xù)模式
-
TA0CTL |= TACLR + MC_2;
在定時器中斷服務(wù)函數(shù)內(nèi)遞增全局計數(shù)變量用于獲取輸入捕獲的脈沖數(shù)
-
uint8_t counter; uint8_t loop; #pragma vector = TIMER0_A1_VECTOR __interrupt void TA0_ISR(void) { counter++; if(counter>10) { loop++; counter=0; } }
PWM輸出
msp430可以實現(xiàn)在不占用CPU資源的情況下輸出PWM信號,程序如下所示
-
#include <msp430f5529.h> void main(void) { WDTCTL = WDTPW | WDTHOLD; //關(guān)閉看門狗 P1DIR |= BIT2 | BIT3; P1SEL |= BIT2 | BIT3; //設(shè)置為定時器復(fù)用 TA0CCR0 = 512-1; //PWM周期,頻率=32768/512=64 TA0CCTL1 = OUTMODE_7; //CCR1輸出模式7 TA0CCR1 = 384; //CCR1 PWM占空比設(shè)置為384/512=75% TA0CCTL2 = OUTMODE_7; //CCR2輸出模式7 TA0CCR2 = 128; //CCR2 PWM占空比設(shè)置為128/512=25% //開啟定時器 TA0CTL = TASSEL_1 + MC_1 + TACLR; //定時器時鐘設(shè)置為32768Hz的ACLK,配置為增模式,清空TA0R while(1) { /* 可實現(xiàn)在P1.2上輸出75%占空比,在P1.3上輸出25%占空比,頻率都是64Hz的PWM信號 */ } }
總線協(xié)議
msp430f5529中配備了通用串行通信接口模塊USCI,它支持了多種通信模式,UART、SPI、IIC都可以使用該外設(shè)進行處理
使用方法很類似,僅給出示例代碼
-
UART
- 串口接收并復(fù)讀數(shù)據(jù)
-
#include <msp430f5529.h> void main(void) { WDTCTL = WDTPW + WDTHOLD; /* 初始化UART */ P4SEL |= BIT4 + BIT5; //配置P4.4、P4.5為USCI_A1 Tx、Rx UCA1CTL1 |= UCSWRST; //復(fù)位USCI_A1 UCA1CTL1 |= UCSSEL_2; //SMCLK 無校驗位 8字符長度 1個停止位 UCA1BR0 = 9; //低8位=9 UCA1BR1 = 0; //高8位=0,調(diào)制后波特率約為115200bps UCA1MCTL |= UCBRS_1 + UCBRF_0; //調(diào)制器UCBRSx=1,UCBRFx=0 UCA1CTL1 &= ~UCSWRST; //啟動USCI_A1 UCA1IE |= UCRXIE; //使能USCI_A1接收中斷 __bis_SR_register(LPM0_bits + GIE); //使能全局中斷 while(1); } #pragma vector=USCI_A1_VECTOR __interrupt void USCI_A1_ISR(void) { switch(__even_in_range(UCA1IV, 4)) { case 0: //無中斷 break; case 2: //接收中斷RXIFG UCA1TXBUF = UCA1RXBUF; //復(fù)讀 break; case 4: //發(fā)送中斷TXIFG break; default: break; } }
UCA1TXBUF:串口發(fā)送寄存器
UCA1RXBUF:串口接收寄存器
UCA1IE:串口中斷控制寄存器,可以選擇接收中斷、發(fā)送中斷
-
IIC
-
需要注意,msp430的IIC無法內(nèi)部上拉,所以必須在外部接入4.7k的上拉電阻到VCC(3.3V)
下面的代碼僅說明如何將USCI配置成IIC驅(qū)動模式
-
#include <msp430.h> P4SEL |= BIT1 + BIT2;//初始化引腳復(fù)用功能 /*初始化USCI,并配置傳輸速率*/ UCB1CTL1 |= UCSWRST; //復(fù)位USCI_B1 UCB1CTL0 |= UCMST + UCMODE_3 + UCSYNC; //配置為IIC主機,同步模式 UCB1CTL1 = UCSSEL_2 + UCSWRST; //SMCLK,保持UCSWRST置位 UCB1BR0 = 12; //fscl=SMCLK/12=100kHz UCB1BR1 = 0; /*設(shè)置從機地址*/ 這里假設(shè)從機地址是0x48*/ UCB1I2CSA = 0x48; //從機地址0x48 /*啟動外設(shè)*/ UCB1CTL1 &= ~UCSWRST; //清除復(fù)位標志,外設(shè)開始運行 /*編寫中斷控制函數(shù)*/ uint8_t IIC_RXByte; uint8_t IIC_TXByte; uint8_t *PRxData; //接收緩存 uint8_t *PTxData; //發(fā)送緩存 #pragma vector=USCI_B1_VECTOR __interrupt void USCI_B1_ISR(void) { switch(__even_in_range(UCB1IV, 12)) { case 0: //無中斷 break; case 2: //ALIFG break; case 4: //無響應(yīng)中斷NACKIFG break; case 6: //STTIFG break; case 8: //停止位中斷STPIFG break; case 10: //接收中斷RXIFG IIC_RXByte--; //遞減字節(jié)計數(shù)變量 if(IIC_RXByte) //如果沒有接收完畢 { *PRxData++ = UCB1RXBUF; //接收剩下的數(shù)據(jù)到緩存區(qū) if(IIC_RXByte == 1) //檢查是否只剩一個字節(jié)未接收 { UCB1CTL1 |= UCTXSTP; //發(fā)送停止條件 } } else //已經(jīng)接收完畢 { *PRxData = UCB1RXBUF; //將最后一字節(jié)數(shù)據(jù)存儲到緩存區(qū) UCB1IE &= ~UCRXIE; //禁用接收中斷 __bic_SR_registe_on_exit(LPM0_bits); //退出LPM0,進入活躍模式 } break; case 12: //發(fā)送中斷TXIFG if(IIC_TXByte) //如果沒有發(fā)送完畢 { UCB1TXBUF = *PTxData; //IIC發(fā)送數(shù)據(jù) IIC_TXByte--; //遞減字節(jié)計數(shù)變量 } else //已經(jīng)接收完畢 { UCB1CTL1 |= UCTXSTP; //置位發(fā)送停止條件位 UCB1IFG &= ~UCTTXIFG; //清除發(fā)送中斷標志位TXIFG UCB1IE &= ~UCTXIE; //禁用發(fā)送中斷 __bic_SR_registe_on_exit(LPM0_bits); //退出LPM0,進入活躍模式 } break; default: break; } }
編寫相關(guān)驅(qū)動
-
TxData[8] = { 0}; //發(fā)送緩存區(qū) RxData[8] = { 0}; //接收緩存區(qū) uint8_t IIC_RXByte; uint8_t IIC_TXByte; uint8_t *PRxData; //接收緩存 uint8_t *PTxData; //發(fā)送緩存 void main(void) { /* 這里省略初始化部分 */ disable_WDG(); init_iic(); while(1) { /* 發(fā)送設(shè)置 */ PTxData = TxData; IIC_TXByte = 8; while(UCB1CTL1 & UCTXSTP); //確保停止條件已發(fā)送,總線空閑 UCBCTL1 |= UCTR; //設(shè)置主機工作在發(fā)送機模式 UCBCTL1 |= UCTXSTT; //發(fā)送開始條件并發(fā)送有“寫標志位”的地址 UCB1IE |= UCTXIE; //使能發(fā)送中斷 __bis_SR_register(LPM0_bits + GIE); //進入LPM0,使能全局中斷 /* 接收設(shè)置 */ PRxData = RxData; IIC_RXByte = 8; while(UCB1CTL1 & UCTXSTP); //確保停止條件已發(fā)送,總線空閑 UCBCTL1 &= ~UCTR;//設(shè)置主機工作在接收機模式 UCBCTL1 |= UCTXSTT; //發(fā)送開始條件并發(fā)送有“讀標志位”的地址 UCB1IE |= UCRXIE; //使能接收中斷 __bis_SR_register(LPM0_bits + GIE); //進入LPM0,使能全局中斷 } }
SPI
- 使用以下代碼設(shè)置SPI
-
/* 這里省略端口復(fù)用設(shè)置 */ UCB0CTL1 |= UCSWrST; UCB0CTL0 |= UCMST + UCSYNC; //設(shè)置為三線SPI主機模式,8位數(shù)據(jù)位 UCB1CTL1 = UCSSEL_2; //時鐘設(shè)置為SMCLK UCB1BR0 = 0xFF; //UCB0CLK = SMCLK / 0xFFF UCB1BR1 = 0x0F; //一般來說可以選擇100kHz以上的頻率,通常使用4MHz頻率 UCB1CTL1 &= ~UCSWRST; //清除復(fù)位標志,外設(shè)開始運行
中斷和驅(qū)動編寫部分和IIC基本一致,不再贅述
-
片上模擬外設(shè)
msp430集成了12位ADC/DAC和模擬比較器外設(shè)
-
ADC
f5529配備了SAR架構(gòu)的ADC12_A模塊,支持12位ADC,具有16個模擬輸入通道、16個獨立的轉(zhuǎn)換和存儲單元,可在脫離CPU情況下完成ADC轉(zhuǎn)換,最高200ksp(千次采樣/每秒)
基本配置流程如下:
-
配置核心控制寄存器,選擇時鐘、轉(zhuǎn)換模式、啟動參考電壓生成器
ADC12_A內(nèi)部具有獨立的REF模塊,可以提供1.5V、2V、2.5V參考電壓。通過REF模塊的REFMSTR位選擇參考電壓:置1時(默認狀態(tài))使用REF模塊控制參考電壓;置0時使用ADC12_A的參考電壓模塊控制參考電壓
使用ADC12REF2_5V控制參考電壓大小,ADC12REFON控制是否開啟電壓生成器,ADC12REFOUT控制是否輸出參考電壓
ADC使用ADC12CLK時鐘用來控制采樣和轉(zhuǎn)換的時間和周期,時鐘源可選擇SMCLK、MCLK、ACLK和ADC12OSC(UCS模塊的MODCLK的5MHz內(nèi)部振蕩器),時鐘源使用ADC12DIV控制的預(yù)分頻器和ADC12SSELx控制的分頻器進行分頻,可選擇1-32分頻
基本配置程序如下
-
ADC12CTL0 = ADC12ON+ADC12SHT0_8+ADC12MSC; //開啟ADC12,設(shè)置采樣時間,設(shè)置采樣模式(這里使用了多采樣轉(zhuǎn)換)
-
ADC具有4種模式,通過CONSEQx位選擇
- 單通道模式:單通道只采樣和轉(zhuǎn)換一次,當ADC12SC置位時觸發(fā)一次采樣轉(zhuǎn)換操作,持續(xù)一段時間后自動復(fù)位
- 序列通道(自動掃描)模式:使用CSTARTADDx位選擇開始轉(zhuǎn)換的第一個ADC1MCTLx,指定后序列啟動指針會自動遞增,被它指向的通道會自動開始轉(zhuǎn)換,轉(zhuǎn)換完成后自動復(fù)位,操作一直繼續(xù)直到處理到ADC12EOS=1的ADC12MCTLx才會停止,ADC12EOS作為序列結(jié)束的標志,只在序列轉(zhuǎn)換模式下使用
- 重復(fù)單通道模式:一個單獨的通道會被不斷采樣轉(zhuǎn)換,可以設(shè)置完成中斷來讀取轉(zhuǎn)換結(jié)果
- 重復(fù)序列通道(自動重復(fù))模式:一序列通道會被重復(fù)采樣和轉(zhuǎn)換,使用CSTARTADDx定義第一個ADC12McTLx,序列再檢測到ADC12EOS(序列結(jié)束標志)置位后會自動結(jié)束,下一個觸發(fā)信號將重新開始序列
- 保持其處于禁用狀態(tài),ADC12ENC=0
-
配置引腳復(fù)用
將GPIO復(fù)用為ADC輸入引腳
-
PxSEL |= 0x0n; //選擇Px.n引腳復(fù)用為ADC輸入
注意:只有能接入ADC的對應(yīng)IO口才能復(fù)用
-
配置采樣定時器
一次轉(zhuǎn)換由一個采樣信號SHI的上升沿引起,可通過SHSx位來選擇,可以選為直接由ADC12SC位控制或使用定時器來控制
- ADC12SHP=0,使用擴展采樣模式,SHI信號直接控制SAMPCON并定義采樣周期長度;SAMPCON=1時采樣活躍,SAMPCON的下降沿會在同步ADC12CLK信號后啟動轉(zhuǎn)換
- ADC12SHP=1,使用脈沖采樣模式,SHI信號用于觸發(fā)采樣定時器,采樣定時器在同步AD12CLK后將SAMPCON保持在高電平并持續(xù)一個可編程的間隔 t s a m p l e t_{sample} tsample?,整個采樣時間就是 t s a m p l e + t s y n c t_{sample}+t_{sync} tsample?+tsync?
-
可單獨配置每個通道的參考電壓和輸入源
使用ADC12MCTLx(x為0-15)控制轉(zhuǎn)換存儲單元,通過ADC12SREF和ADC12INCH分別選擇參考電壓和模擬信號的輸入通道
在單通道單轉(zhuǎn)換模式中,復(fù)位ADC12ENC立刻停止一個轉(zhuǎn)換且會導(dǎo)致轉(zhuǎn)換結(jié)果不可預(yù)知,一般來說需要使用以下語句停止單通道轉(zhuǎn)換
-
while(ADC12BUSY != 0) { delay(); } ADC12ENC = 0; //等待ADC12BUSY = 0后才能停止單通道轉(zhuǎn)換
-
重復(fù)單通道模式下,復(fù)位ADC12ENC會在當前轉(zhuǎn)換結(jié)束時停止轉(zhuǎn)換器
序列通道或重復(fù)序列通道中,復(fù)位ADC12ENC會在序列結(jié)束時停止轉(zhuǎn)換器
任何模式中都可以通過清零ADC12CONSEQ并復(fù)位ADC12ENC位來立刻停止,但這樣會導(dǎo)致轉(zhuǎn)換結(jié)果不可預(yù)知
-
可以使能集成溫度傳感器或配置轉(zhuǎn)換完成中斷
ADC可以直接連接內(nèi)部的溫度傳感器(這是參考電壓生成器的一部分)來獲取內(nèi)部溫度,計算公式如下
T = ( A D C r a w ? C A L _ A D C _ T 30 ) × ( 85 ? 30 C A L _ A D C _ T 85 ? C A L _ A D C _ T 30 ) + 30 T=(ADC_{raw} - CAL\_ADC\_T30) \times (\frac{85-30}{CAL\_ADC\_T85 - CAL\_ADC\_T30}) + 30 T=(ADCraw??CAL_ADC_T30)×(CAL_ADC_T85?CAL_ADC_T3085?30?)+30
其中T是精確溫度值, A D C r a w ADC_{raw} ADCraw?是數(shù)模轉(zhuǎn)換結(jié)果,兩個 C A L _ A D C _ T CAL\_ADC\_T CAL_ADC_T為溫度矯正參數(shù),需要通過地址進行訪問調(diào)用,每個設(shè)備的矯正參數(shù)都不同,該參數(shù)會被使用TLV(Tag-Length-Value)的方式寫入單片機,地址調(diào)用形式如下 -
*((unsigned int*)0x1A1A) //具體地址需要根據(jù)電壓和設(shè)備的不同來確定,詳細內(nèi)容參考datasheet即可
ADC12_A具有18個中斷,共用一個中斷源
可單獨配置某通道完成中斷、ADC12MEMx溢出中斷、ADC12_A計時溢出中斷,所有中斷通過唯一的中斷向量寄存器來配置,也就是說只使用一個中斷服務(wù)函數(shù)
注意:任何對于ADC12IV的讀寫操作都會自動復(fù)位ADC12OV或ADC12TOV,如果中斷服務(wù)函數(shù)在訪問ADC12IV寄存器時有ADC12OV和ADC12IFGx中斷生成,那么ADC12OV中斷條件會自動復(fù)位,在中斷服務(wù)函數(shù)返回后緊接著處理其他中斷,因此應(yīng)避免中斷執(zhí)行時間過長導(dǎo)致ADC中斷占用前臺應(yīng)用
使用下面的程序來開啟ADC中斷
-
ADC12IE = 0x01;
將ADC12ENC=1來使能設(shè)備
-
ADC12CTL0 |= ADC12ENC; ADC12CTL0 |= ADC12SC;
- 通過讀取ADC12MCTLx對應(yīng)的ADC12MEMx來獲取轉(zhuǎn)換結(jié)果
-
單通道單次轉(zhuǎn)換示例如下(測量引腳電壓高于參考電壓則指示燈亮)
-
#include <msp430.h> int main(void) { WDTCTL = WDTPW + WDTHOLD; //停止WDG ADC12CTL0 = ADC12SHT02 + ADC12ON; //設(shè)置采樣時間并開啟ADC12_A ADC12CTL1 = ADC12SHP; //使用采樣定時器 ADC12IE = 0x01; //使能中斷 ADC12CTL0 |= ADC12ENC; //使能轉(zhuǎn)換通道 P6SEL |= 0x01; //配置P6.1復(fù)用為ADC輸入 P1DIR |= 0x01; //配置P1.0信號指示輸出 while (1) { ADC12CTL0 |= ADC12SC; //開始依次采樣 __bis_SR_register(LPM0_bits + GIE); //進入LPM0,開啟全局中斷 __no_operation(); //用于調(diào)試器打斷點的空指令 } } /* ADC中斷服務(wù)函數(shù) */ #pragma vector = ADC12_VECTOR __interrupt void ADC12_ISR(void) { switch(__even_in_range(ADC12IV,34)) { case 0: break; // Vector 0: No interrupt case 2: break; // Vector 2: ADC溢出中斷 case 4: break; // Vector 4: ADC超時中斷 case 6: // Vector 6: ADC12IFG0 /* 測量P1引腳 */ if (ADC12MEM0 >= 0x7ff) // ADC12MEM = A0 > 0.5AVcc? P1OUT |= BIT0; // P1.0 = 1 else P1OUT &= ~BIT0; // P1.0 = 0 __bic_SR_register_on_exit(LPM0_bits); //退出LPM0模式 case 8: break; // Vector 8: ADC12IFG1 case 10: break; // Vector 10: ADC12IFG2 case 12: break; // Vector 12: ADC12IFG3 case 14: break; // Vector 14: ADC12IFG4 case 16: break; // Vector 16: ADC12IFG5 case 18: break; // Vector 18: ADC12IFG6 case 20: break; // Vector 20: ADC12IFG7 case 22: break; // Vector 22: ADC12IFG8 case 24: break; // Vector 24: ADC12IFG9 case 26: break; // Vector 26: ADC12IFG10 case 28: break; // Vector 28: ADC12IFG11 case 30: break; // Vector 30: ADC12IFG12 case 32: break; // Vector 32: ADC12IFG13 case 34: break; // Vector 34: ADC12IFG14 default: break; } }
多通道重復(fù)轉(zhuǎn)換示例如下(連續(xù)讀取P6.0、P6.1、P6.2、P6.3的ADC值)
-
#include <msp430.h> #define Num_of_Results 8 volatile unsigned int A0results[Num_of_Results]; volatile unsigned int A1results[Num_of_Results]; volatile unsigned int A2results[Num_of_Results]; volatile unsigned int A3results[Num_of_Results]; int main(void) { WDTCTL = WDTPW+WDTHOLD; //關(guān)閉WDG P6SEL = 0x0F; //使能ADC復(fù)用引腳(P6的低四位0、1、2、3進行復(fù)用) ADC12CTL0 = ADC12ON+ADC12MSC+ADC12SHT0_8; //開啟ADC、擴展采樣時間避免結(jié)果溢出 ADC12CTL1 = ADC12SHP+ADC12CONSEQ_3; //使用采樣定時器,設(shè)置為多通道重復(fù)采樣模式 /* 設(shè)置0、1、2、3通道的參數(shù) */ ADC12MCTL0 = ADC12INCH_0; // ref+=AVcc, channel = A0 ADC12MCTL1 = ADC12INCH_1; // ref+=AVcc, channel = A1 ADC12MCTL2 = ADC12INCH_2; // ref+=AVcc, channel = A2 ADC12MCTL3 = ADC12INCH_3+ADC12EOS; // ref+=AVcc, channel = A3 ,設(shè)置ADC結(jié)束標志 ADC12IE = 0x08; //使能ADC12IFG.3中斷 ADC12CTL0 |= ADC12ENC; //使能轉(zhuǎn)換通道 ADC12CTL0 |= ADC12SC; //開始轉(zhuǎn)換-軟件觸發(fā) __bis_SR_register(LPM0_bits + GIE); //進入LPM0并開啟全局中斷 __no_operation(); //用于調(diào)試器打斷點 } #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR (void) { static unsigned int index = 0; switch(__even_in_range(ADC12IV,34)) { case 0: break; // Vector 0: No interrupt case 2: break; // Vector 2: ADC overflow case 4: break; // Vector 4: ADC timing overflow case 6: break; // Vector 6: ADC12IFG0 case 8: break; // Vector 8: ADC12IFG1 case 10: break; // Vector 10: ADC12IFG2 case 12: // Vector 12: ADC12IFG3 A0results[index] = ADC12MEM0; // Move A0 results, IFG is cleared A1results[index] = ADC12MEM1; // Move A1 results, IFG is cleared A2results[index] = ADC12MEM2; // Move A2 results, IFG is cleared A3results[index] = ADC12MEM3; // Move A3 results, IFG is cleared index++; // 保存到結(jié)果緩存區(qū) if (index == 8) { (index = 0); } case 14: break; // Vector 14: ADC12IFG4 case 16: break; // Vector 16: ADC12IFG5 case 18: break; // Vector 18: ADC12IFG6 case 20: break; // Vector 20: ADC12IFG7 case 22: break; // Vector 22: ADC12IFG8 case 24: break; // Vector 24: ADC12IFG9 case 26: break; // Vector 26: ADC12IFG10 case 28: break; // Vector 28: ADC12IFG11 case 30: break; // Vector 30: ADC12IFG12 case 32: break; // Vector 32: ADC12IFG13 case 34: break; // Vector 34: ADC12IFG14 default: break; } }
DAC
msp430f5529配備了DAC12_A模塊,模塊組成結(jié)構(gòu)如下:
-
核心
可以通過修改DAC12RES的值將DAC12_A配置為8位或12位模式;配置DAC12IR和DAC12OG位可以將滿標度輸出配置為所選參考電壓的1倍、2倍或3倍;配置DAC12DF位選擇輸入的數(shù)據(jù)格式是原碼還是補碼。
-
端口
大多數(shù)DAC復(fù)用的端口都有其他復(fù)用功能,但是當DAC12AMPx>0時,DAC12_A會忽略PxSEL.y和PxSEL.x的值,自動配置端口為DAC12_A輸出復(fù)用功能
每個DAC通道都能輸出到兩個不同的端口,通過DAC122OPS選擇,詳細參數(shù)需要查閱datasheet
-
參考電壓
使用DAC12SREFx選擇DAC12_A參考電壓,該值從AVCC、外部電壓輸入、內(nèi)部1.16V參考電壓、內(nèi)部REF模塊提供1.5V、2V、2.5V參考電壓之一選擇
-
參考輸入和電壓輸出緩沖區(qū)
參考輸入和電壓輸出緩沖區(qū)通過寄存器配置來平衡建立時間和功耗,通過配置DAC12AMPx來選擇組合,其值越小、建立時間越長、緩沖區(qū)上的電流消耗越小
-
數(shù)據(jù)格式
使用原碼或補碼形式都可以設(shè)置DAC,使用DAC12_xDAT(取值范圍0800h(輸出0V)-07ffh(輸出標度),另外取值0000h時輸出標度的一半)控制
-
相關(guān)示例程序如下
-
/* 輸出固定電壓 */ void main(void) { WDTCTL = WDTPW+WDTHOLD; //關(guān)閉WDG //設(shè)置無增益,參考電壓AVCC,啟動DAC校準 DAC12_0CTL0 = DAC12IR + DAC12SREF_1 + DAC12AMP_5 + DAC12CALON; DAC12_0CTL0 |= DAC12ENC; //使能DAC12_A //需要注意這里的輸出值是12位 DAC12_0DAT = 0x000; //DAC輸出0V //和上面一樣的流程 DAC12_1CTL0 = DAC12IR + DAC12SREF_1 + DAC12AMP_5 + DAC12CALON; DAC12_0CTL0 |= DAC12ENC; //使能DAC12_A DAC12_0DAT = 0x700; //輸出1.4V __bis_SR_register(LPM4_bits); //進入LPM4,DAC會自動輸出 } /* 輸出波形 */ //以FLASH換內(nèi)存 static?int?Sin_tab[100]?=?{ ? 1638,1740,1843,1944,2045,2143,2240,2335,2426,2515, 2600,2681,2758,2831,?2899,2962,3020,3072,3119,3160, 3195,3224,3246,3262,3272,3272,3263,3247,3224,3196, 3161,3120,3074,3021,2964,2901,2833,2760,2683,2602, 2517,2429,2337,2243,2146,2047,1947,1845,1743,1640, 1537,1435,1333,1233,1134,1037,943,851,762,677,596, 519,446,378,314,256,204,157,116,81,52,29,13,3,0,2, 12,28,50,78,113,154,200,252,310,373,440,513,590, 671,756,756,844,936,1030,1127,1225,1326,1427,1529}; void main(void) { WDTCTL?=?WDTPW?+?WDTHOLD; //??撮T狗 ? INIT_XT2(); //開啟時鐘??? ? P5SEL = 0XFF; ? ADC12CTL0?=?REFON; //參考電壓為內(nèi)部2.5v?? /* 配置DMA,直接將Sin_tab數(shù)據(jù)傳輸?shù)紻AC */ ? DMA0SA?=?(int)?Sin_tab; //源地址寄存器 ? DMA0DA?=?DAC12_0DAT_; //目的地址寄存器 DMA0SZ?=?100; //傳輸基本單元的個數(shù) ? DMACTL0?=?DMA0TSEL_5; //?DAC12_0CTL的DAC12IFG標志 ? DMA0CTL =?DMADT_4?+?DMASRCINCR_3?+?DMAEN;?//DMADT_4:重復(fù)的塊傳輸方式 /* 使用內(nèi)部1.5V參考電壓,無增益,使能DAC12_A校準并使能DAC12_A */ DAC12_0CTL?=?DAC12LSEL_2?+?DAC12IR?+?DAC12AMP_5?+?DAC12IFG?+?DAC12ENC;?//配置DAC /* 強制輸出第一個中斷 */ ? CCTL1?=?OUTMOD_3;?//設(shè)置并復(fù)位 CCR1?=?1; //?PWM?Duty?Cycle??? CCR0?=?8-1; //1kHz頻率 TACTL?=?TASSEL_2?+?MC_1; //使用SMCLK時鐘源,向上計數(shù)模式?? __bis_SR_register(LPM0_bits); //進入LPM0,DMA和DAC都在工作,會自動輸出 }
可編程比較器
f5529配備了Comp_B模塊,支持精密線性數(shù)模轉(zhuǎn)換、電源電壓監(jiān)控、外部模擬信號電壓監(jiān)測功能
其中核心是一個精密電壓比較器,同相端比反相端電壓高,則輸出高電平,否則輸出低電平,使用CBON位打開/關(guān)閉比較器
使用CBCTL0寄存器控制外部輸入端口,CBIPEN和CBIMEN分別控制同相端和反相端;使用CBIMSEL和CBIPSEL控制端子連接的GPIO,應(yīng)選擇P6的端口,以這兩個寄存器控制端口號
可以使用CBSHORT短路正反相輸入,可用來建立簡單的采樣-保持機制,一般來說設(shè)置采樣時間為3-10τ,3τ可以將采樣電容充電到95%的輸入信號電壓值,5τ可以將采樣電容充電到99%,10τ可以滿足12位的精度
使用CBF控制位控制輸出信號的輸出濾波器
使用參考電壓生成器來生成VREF,可以應(yīng)用于比較器輸入端,使用CBREF0x和CBREF1xl來控制
使用CBPWRMD來選擇比較器功耗模式,默認為00——最大功耗、最快速度;可以調(diào)節(jié)到11來使用最低功耗、最低速度
使用CBCTL3來控制比較器的端口是否禁用;使用CBIPSEL或CBIMSEL來控制對應(yīng)端口的輸入緩沖區(qū)
比較器也可以開啟中斷
對于可編程電壓比較器而言,一般使用滯后比較來讓參考電壓根據(jù)輸出值變化,可以讓比較器輸出更加穩(wěn)定,降低噪聲
代碼如下
-
void main(void) { WDTCTL?=?WDTPW?+?WDTHOLD; //停看門狗 P1DIR |= BIT6; //P1.6作輸出 P1SEL |= BIT6; //復(fù)用為比較器輸出CBOUT P7DIR |= 0xFF; //P7設(shè)置為輸出,用來驅(qū)動LED顯示當前比較器結(jié)果 CBCTL0 |= CBIPEN + CBIPSEL_0; //比較器施恩那個,設(shè)置輸入通道CB0為P6.0 CBCTL1 |= CBPWRMD_0; //設(shè)置為高速模數(shù) CBCTL2 |= CBRSEL; //使用VREF作為反相端的參考電壓 /* 設(shè)置高低兩個閾值電壓 */ CBCTL2 |= CBRS_1 + CBREF13; //以VCC為參考電壓,CBREF1=8,VREF=VCC/4 CBCTL2 |= CBREF04 + CBREF03; //VREF0=VCC * 3/4 CBCTL3 |= BIT0; //打開Comp_B CBCTL1 |= CBON; //使能比較器 __delay_cycles(75); //等待比較器內(nèi)部參考電壓達到穩(wěn)定 while(1) { if(CBCTL1 & CBOUT) //如果CBOUT為高電平 { P7OUT = 0x00; //LED點亮 } else { P7OUT = 0xFF; //LED熄滅 } } }
以上代碼在輸入電壓大于VREF0=3/4 VCC時CBOUT輸出高電平,LED點亮;輸入電壓小于VREF0=1/4 VCC時CBOUT輸出低電平,LED熄滅;當電壓在二者之間時,CBOUT狀態(tài)不變,起到了穩(wěn)定輸出的作用
同樣的比較器也可以產(chǎn)生中斷信號,在檢測到設(shè)定的跳變沿(上升沿或下降沿)后觸發(fā)中斷,進入對應(yīng)的中斷服務(wù)函數(shù),可以在其中判斷比較器輸出的電平,避免了輪詢
-
CBCTL1 |= CBPWRMD_1 + CBF + CBFDLY_3; //普通模式,選擇中斷邊壓,使用輸出濾波 /* 在中間設(shè)置其他比較器參數(shù) */ /* 等待一定時間來讓參考電壓穩(wěn)定 */ CBINT &= ~(CBIFG + CCBIIFG); //清除錯誤中斷標志 CBINT |= CBIE + CBIIE; //使能比較器輸出中斷和輸出反相中斷 __bis_SR_register(LPM0_bits + GIE); //開啟全局中斷 #pragma vector=COMP_B_VECTOR __interrupt void Comp_B_ISR(void) { switch(__even_in_range(CBIV, 4)) { case 0: //無中斷 break; case 2: //中斷CBIFG if(CBCTL1 & CBOUT) //判斷是否輸出高電平 { } break; case 4: //反相中斷CBIIFG if(!(CBCTL1 & CBOUT)) //反相端需要相反的判斷 { } break; default: break; } }
這里僅列出中斷服務(wù)函數(shù)和其開啟方式
-
DMA
msp430的DMA最多有8個通道,但是msp430f5529只有3個通道
基本使用方法和stm32的DMA完全一樣,四種模式、單傳輸、塊傳輸、連續(xù)傳輸都和stm32的傳輸方法類似,但設(shè)置更為簡單
一個使用DMA進行UART傳輸?shù)睦尤缦滤荆?/p>
-
#include <msp430.h> #include <stdint.h> static uint8_t String1[] = { "Hello World\r\n"}; void main(void) { WDTCTL?=?WDTPW?+?WDTHOLD; //??撮T狗 /* 端口配置 */ P4SEL = BIT4 + BIT5; //配置P4.4、P4.5為Tx、Rx端口 /* 配置USCI_A1為UART模式 */ UCA1CTL1 = UCSSEL_1; //使用ACLK為時鐘源 //控制分頻器設(shè)置波特率為9600 UCA1BR0 = 0x03; //分頻器高八位 UCA1BR1 = 0x0; //分頻器低八位 UCA1MCTL = UCBRS_3 + UCBRF_0; //調(diào)制器UCBRSx = 3 UCA1CTL1 &= ~UCSWRST; //啟動設(shè)備 /* 配置DMA */ DMACTL0 = DMA0TSEL_1; //以定時器TA0CCR0 CCIFG為觸發(fā)源 __data16_write_addr((uint16_t)&DMA0SA, (uint32_t)String1); //源地址:String1字符串 __data16_write_addr((uint16_t)&DMA0DA), (uint32_t)&UCA1TXBUF); //目標地址:UART發(fā)送緩存區(qū)域 DMA0CTL = DMADT_4 + DMASRCINCR_3 + DMASBDB +DMAEN; //重復(fù)單傳輸,遞增模式,字節(jié)到字節(jié),并使能DMA /* 配置定時器 */ TA0CCR0 = 8192; //字符傳輸頻率=32768/8192=4 字節(jié)/s TA0CTL = TASSEL_1 + MC_1; //使用ACLK作為時鐘源,采用增模式 __bis_SR_register(LPM0_bits); //進入LPM3 }
這個程序會連續(xù)向外以9600波特率發(fā)送串口數(shù)據(jù)
-
電源管理
msp430f5529的電源管理模塊PMM由監(jiān)督器SVS和監(jiān)視器SVM組成
SVS是強制要求的,用于保障設(shè)備穩(wěn)定運行
SVM是寬松可編程的,用于進行一些低功耗控制和安全保障文章來源:http://www.zghlxwxcb.cn/news/detail-555298.html
可以通過對SVM編程提高VCORE來支持更高的MCLK,也就是所謂的超頻文章來源地址http://www.zghlxwxcb.cn/news/detail-555298.html
到了這里,關(guān)于MSP430F5529學習筆記的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!