本章選擇了一些簡單的C語言程序例題,這些程序的結構簡單,編程技巧不多,項目雖然 簡單,但是非常適合入門單片機的學習者學習MSP430單片機的C 語言編程。 如下列出了C語言例題運行的MSP430F149實驗板硬件資源環境,熟悉這些硬件資源,對 于理解程序非常重要。 (1)數碼管: 左側數碼管與P5口相連,a~g,h對應P5.0~P5.7 右側數碼管與P4口相連,a~g,h對應P4.0~P4.7 (2)發光二極管 8 個發光二極管與P3 口連接 (3)按鈕: 左側8個按鈕與P2口相連,引腳號標在按鈕上方 右側8個按鈕與P1口相連,引腳號標在按鈕上方 (4)P2.3引腳還是模擬比較器輸入 (5)P6.0,P6.1引腳連接模擬量電位器,用于模擬量實驗
9.1 通過 C 語言編程例入門 MSP430C 語言編程
如下例子都在MSP430F149實驗板上通過驗證。 例1:使與P3口的P3.0引腳連接的發光二極管閃爍。 #include <msp430x14x.h> //聲明庫 void main(void) //主函數 { unsigned int i; //變量聲明 WDTCTL=WDTPW+WDTHOLD; //關掉看門狗 P3DIR |=BIT0; //設置P3.0為輸出,這里BIT0=0x0001 while(1) //無限次while循環 { for(i=0;i<20000;i++) //for語句,i為循環變量,i每次循環加1,當i<20000時, //循環延時 P3OUT=0x00; //使P3.0輸出低電平,發光二極管亮,(低電平使發光二極管亮) for(i=0;i<20000;i++) //再次循環延時 P3OUT=0x01;//使P3.0輸出高電平,發光二極管滅,(高電平使發光二極管滅) } } 例2:8個發光二極管 1、3、5、7與 2、4、6、8交替發光的例子 #include <msp430x14x.h> void main(void) { unsigned int i; WDTCTL=WDTPW+WDTHOLD; P3DIR=0XFF; //設置P3口為輸出 while(1) { for(i=0;i<20000;i++) P3OUT=0X55; //使發光二極管1、3、5、7 滅,2、4、6、8亮 for(i=0;i<20000;i++) P3OUT=0XAA;//使發光二極管1、3、5、7亮,2、4、6、8滅 } } 例 3:定時器控制的發光二極管閃爍。這里使用了 MSP430F149芯片的 32768Hz低頻晶體振蕩器作為時鐘 源。用定時器 A定時 1s,發光二極管滅 0.5s,亮.0.5s。 #include <msp430x14x.h> void main (void) { WDTCTL= WDTPW + WDTHOLD; //設置看門狗控制寄存器,關看門狗 TACTL = TASSEL0 + TACLR; // 設置定時器A控制寄存器, //TASSEL0=0x0100,選擇輔助時鐘ACLK, //TACLR=0x0004,清除定時器A計數器 CCTL0 = CCIE; //設置捕獲/比較控制寄存器,CCIE=0x0010,使能捕獲比較中斷 CCR0 =16384; //設置捕獲/比較寄存器,初始值為16384,對于32768Hz的頻率,相當于0.5s P3DIR |=BIT7; //P3.7為輸出 TACTL |= MC0; //設置定時器A控制寄存器,MC0=0x0010,使計數模式為增計數 _EINT(); //使能中斷,這是一個C編譯器支持的內部過程。 while(1); //無限次while循環 }
interrupt[TIMERA0_VECTOR] void Timer_A(void) //定時器A的CC0中斷處理程序 //TIMERA0_VECTOR=6*2,等于基地址0xFFE0+12=0xFFEC { P3OUT ^= BIT7; //將P3.7引腳取反,就是使發光二極管閃爍 }
例 4:選擇不同的時鐘源,使 P3.7 連接的發光二極管閃爍。 (1)使用 XT2時鐘源,8MHz頻率,用定時器 A分頻,產生 1s脈沖,使 P3.7引腳的發光二極管閃爍。 #include <msp430x14x.h> #define XTOFF 0x40; void main (void) { WDTCTL= WDTPW + WDTHOLD; //關閉看門狗 BCSCTL1 &= ~XT2OFF; //基礎時鐘控制寄存器BCSCTL1的第7位置0,使XT2啟動 BCSCTL2 = SELS + DIVS1 + DIVS0; //基礎時鐘控制寄存器BCSCTL2設置,第3位置1,選擇 //XT2CLK作為SMCLK時鐘;將第2和第1位置1,使分頻比為8 TACTL =0x02D4; //定時器A控制寄存器設置,第2位置1:清除;第4、5位置1、0:加計數模式 //加計數至CCR0,然后重新開始;第6、7位1、1,所以是8分頻;第8、9位是 //0、1,所以TA使用SMCLK時鐘。 CCTL0 = CCIE; //CCIE=0x0010,使能定時器A中斷 CCR0 =62500; //設置計數器CCR0的初值,((8MHz/8)/8)/2=62500,相當于0.5s的時間 P3DIR |=BIT7; //將P3.7設置為輸出 _EINT(); //調用C430編譯器內部函數,使能中斷 while(1); //無限次循環 } interrupt[TIMERA0_VECTOR] void Timer_A(void) //定時器A中斷函數 { P3OUT ^= BIT7; //P3.7位取反 } (2)使用32768Hz晶體產生1s信號的程序如下: #include <msp430x14x.h> void main (void) { WDTCTL= WDTPW + WDTHOLD; TACTL =TASSEL0+TACLR+MC0; CCTL0 = CCIE; CCR0 =16384; P3DIR |=BIT7; _EINT(); while(1); } interrupt[TIMERA0_VECTOR] void Timer_A(void) { P3OUT ^= BIT7; } (3)看門狗使輸出 P3.7 引腳連接的發光二極管每秒閃爍一次的例子: #include <msp430x14x.h> void main (void) { WDTCTL= WDTPW + WDTTMSEL+WDTSSEL; IE1|=WDTIE; P3DIR |=BIT7; _EINT(); while(1); } interrupt[WDT_VECTOR] void WDT_interrupt(void) { P3OUT ^= BIT7; } 例 5: P4和 P5輸出口連接的數碼管顯示 1和 2。 #include <msp430x14x.h> void main(void) { unsigned char seg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //定義七段譯碼的共陽數碼管顯示數組 // hgfg dcba //0=1100 0000 //1=1111 1001 //2=1010 0100 //…… //9=1001 0000 WDTCTL=WDTPW+WDTHOLD; //關閉看門狗,以便于調試 P4DIR=0XFF; //設置P4口為輸出 P5DIR=0XFF;//設置P5口為輸出 P4OUT=seg[1];//向P4口輸出數組的第1個元素,數字1的段碼 P5OUT=seg[2];//向P5口輸出數組的第2個元素,數字2的段碼 } 例6:與 P5 口連接的數碼管加 1計數,與 P4口相連的數碼管顯示數字8。 #include <msp430x14x.h> void main(void) { inti,x; //聲明數據類型 unsigned char seg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; WDTCTL=WDTPW+WDTHOLD;//關看門狗 P4DIR=0XFF; //P4口為輸出,連接有共陽極數碼管 P5DIR=0XFF; //P5口為輸出,連接有共陽極數碼管 P4OUT=seg[8]; //P4輸出數字8 P5OUT=seg[0]; //P5輸出數字0 while(1) //無限次While循環 { for(i=0;i<=9;i++) //循環變量I從0到9循環 for(x=0;x<20000;x++) //沒有循環體的for循環,用于延遲時間 P5OUT=seg; //按照循環變量i的數值,取出相應的數組元素 } } 例7:使用定時器輸出精確的秒信號。從0開始計時,數碼管顯示0~60秒,每隔10秒使數碼管 更換顯示,并順序點亮發光二極管。 #include <msp430x14x.h> #define XTOFF 0x40; unsigned int i=0,j=0; //聲明數據類型 unsigned charseg_7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //數碼管字型碼數組 unsigned intbit[8]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080}; //發光二極管點亮順序數組 void main (void) { WDTCTL= WDTPW + WDTHOLD; //關看門狗 TACTL = TASSEL0 + TACLR; // 設置定時器A控制寄存器, //TASSEL0=0x0100,選擇輔助時鐘ACLK(32kHz) //TACLR=0x0004,清除定時器A計數器 CCTL0 = CCIE; //使能定時器A捕捉與中斷功能,CCIE=0x0010 CCR0 =32768; // 設置計數器CCR0初值 TACTL |= MC0; //設置定時器工作模式為加計數到CCR0初值 P3DIR = 0XFF; //P3口為輸出 P4DIR = 0XFF; //P4口為輸出 P5DIR = 0XFF; //P5口為輸出 P3OUT = 0X7E; //P3口輸出為0111 1110 _EINT(); 調用C430編譯器內部函數使能中斷 while(1); //沒有循環體的無限次while循環 } interrupt[TIMERA0_VECTOR] void Timer_A(void) //定時器A的中斷函數 { i+=1; i每次循環加1 if (i==10) //如果i=1 { i=0; //使i=0 j+=1; j每次加1 P3OUT ^= bit[j]; //數組的第j個元素取反后從P3口輸出,使發光二極管順序點亮 if(j==6) //如果j=6 { j=0; 使j=0 } } P4OUT =seg_7;//數碼管字型數組中取第i個元素,送到P4口輸出 P5OUT = seg_7[j]; //數碼管字型數組中取第j個元素,送到P5口輸出 } 例8:連接在P1.0 口的按鍵控制數碼管顯示數值,數碼管顯示按動次數。 #include <msp430x14x.h> //聲明庫文件 char Key_Pressed(void); //聲明被調用函數 void main(void) { unsigned char seg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //共陽數碼管字型碼數組 unsigned int i=0; //聲明數據類型 WDTCTL = WDTPW + WDTHOLD; //關看門狗 P1DIR &= ~BIT0; //P1.0引腳設置成輸入,該引腳連接的按鍵按下時,按鍵輸出低電平 P4DIR =0xff; //P4口設置為輸出,連接共陽數碼管 P4OUT=seg[8]; //P4口輸出數字8 while (1) //無限次while循環 { if(Key_Pressed()) //調用按鍵函數,如果按鍵函數返回1,
Page 6 of 21 基于模擬前端信號處理與控制技術的專業論壇、網站 P4OUT=seg[i++]; // 則數碼管字型數組下標加1,選擇相應的七段字型從 //P4口輸出 if(i>9) //如果i大于9,則使i=0 i=0; } } char Key_Pressed(void) //按鍵函數 { unsigned int i; //聲明變量i while(!(P1IN&BIT0));//當P1輸入寄存器P1IN的第0位為0時,開始while循環 for(i=0;i<8000;i++);//延時一段時間,消除按鍵抖動 if(!(P1IN&BIT0)) //如果P1輸入寄存器P1IN的第0位還是0,則返回1,表示按鍵按下 return 1; else //否則認為按鍵未按下,返回0 return 0; } 例9:將P6口輸入的模擬電壓AD轉換后,從P4、P5口連接的數碼管輸出。 使用AD單通道多次轉換,采集P6.0輸入的模擬電壓值(變化范圍:0~3.3V),轉換為數字量。 建立二維數組和通過順序查表的方法得出采集回來的電壓值。然后通過數碼管顯示當前電壓值,顯 示跟隨輸入的模擬電壓的變化。由于只有兩位數碼管,故顯示電壓值精確到小數點后一位,如當前 輸入電壓2.37V,則顯示2.4V。可用萬用表檢測顯示是否準確。 #include "msp430x14x.h" 聲明庫 void Init(void);//聲明初始化函數 interrupt [ADC_VECTOR]void ADC12(void); //聲明AD轉換中斷函數 unsigned int Result; 聲明變量 unsigned int Table[4][10] = { {0x040,0x0BC,0x138,0x1B4,0x230, 0x2AC , 0x328 , 0x3A4 , 0x420 ,0x49C}, {0x518 , 0x594 , 0x610 , 0x68C ,0x708 , 0x784 , 0x800, 0x87C ,0x8F8,0x974 }, {0x9F0 , 0xA6C , 0xAE8 , 0xB64 , 0xBE0 , 0xC5C , 0xC08 , 0xD54 , 0xDD0,0xE4C }, { 0xEC8 , 0xF44 , 0xFC0 , 0xFFF } }; //該數組元素用于與AD轉換的電壓數值相比較,如果某個數組元素稍大于等于AD轉換后的電壓數 //值,則將此元素輸出 void main(void) //主函數 { P4DIR = 0XFF; //P4口設置為輸出 P5DIR = 0XFF; //P5口設置為輸出 Init(); //調用初始化函數 _EINT(); //使能中斷 ADC12CTL0 |= ENC+ADC12SC; //設置轉換控制寄存器ADC12CTL0,ENC=0x002使轉換允許位為1, //意味著可以啟動轉換,同時ADC12TL0中的低電平位可以被修改。 //ADC12SC=0x001使采樣/轉換控制位為1,如果采樣信號SAMPCON由 //采樣定時器產生(SHP=1),則ASC12SC=1將產生一次轉換 while (1); //無限次的while循環 } void Init(void) //初始化函數 { WDTCTL = WDTPW+WDTHOLD; //關看門狗 P6SEL |= 0x01; // 設置P6口的P6.0引腳為外圍模塊AD轉換器的模擬信號輸入引腳 ADC12CTL0 &= ~ENC; //復位轉換允許位 ADC12CTL0 = ADC12ON + SHT0_2 + REFON + REF2_5V; // Turn on and set up ADC12 //設置轉換控制寄存器ADC12CTL0,ADC12ON=0x010,使ADC12內核工作 //SHT0_2=2*0x100,確定采樣周期為4×tADC12CLK×4 //REFON=0x020,內部參考電壓打開 //REF2_5V=0x040,選擇內部參考電壓發生器的電壓為2.5V ADC12CTL1 = SHP + CONSEQ_2 ; // 設置AD轉換控制寄存器ADC12CTL1 //SHP=0x0200 設置SAMPON來自采樣定時器,采樣信號上升沿觸發采樣 //CONSEQ_2=2*2 設置工作模式為單通道、多次轉換模式 ADC12MCTL0 = SREF_0; //設置通道0的轉換存儲控制寄存器ADC12MCTL0, //SREF_0=0*0x10 選擇參考電壓為VR+=AVCC,VR-=AVSS ,因此輸入模擬信號 //范圍是3.3V~0V。 ADC12IE |= BIT0; //設置中斷允許寄存器ADC12IE,將第0位置1,使通道A0轉換后產生中斷 } interrupt[ADC_VECTOR] void ADC12 (void)//AD轉換中斷函數 { unsigned charseg_7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //聲明無小數點顯示的數碼管七段字型碼數組 unsigned char seg_8[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //聲明有小數點顯示的數碼管七段字型碼數組 unsigned i,j; //聲明變量數據類型 ADC12CTL0 &= ~ENC; //設置AD轉換控制寄存器ADC12CTL0,ENC=0x002,~ENC=0xFFD,停止AD轉換 for( i=0 ; i<4 ;i++) //掃描Table 數組行下標 { for(j=0; j<10; j++) //掃描Table 數組列下標 {if (ADC12MEM0<=Table[j]) goto xxx; //如果Table數組元素大于轉換數值,則轉到標號 xxx } } xxx: {P4OUT = seg_7[j]; //P4 口輸出 P5OUT = seg_8; } //P5 口輸出 ADC12CTL0 |= ENC+ADC12SC; // 使能再次轉換 }
例10: 模擬比較器實驗 接電位器于端口P2.3, 用來輸入模擬電壓值 (0~3.3V)。 參考電壓選取0.5VCC, 待測電壓由P2.3 端輸入,如果待測電壓大于參考電壓,P1.0端口的LED點亮,反之熄滅。 注意:順時針調節電位器,輸入的模擬電壓值增大。 #include <msp430x14x.h> void main (void) { WDTCTL=WDTPW+WDTHOLD; P3DIR |= BIT0; //P3口的第0引腳為輸入 CACTL1 =CARSEL + CAREF1 + CAON;//設置控制寄存器CACTL1, //CARSEL=0x40,設置內部參考電壓,當CAEX=0時參考電平加在(-)端 //CAREF1=0x20,選擇0.5×VCC作為參考電壓 //CAON=0x08, 打開比較器 CACTL2 = P2CA0; //設置控制寄存器CACTL2, //P2CA0=0x04,設置外部引腳信號連接在比較器輸入端 while (1) //無限次循環 { if ((CACTL2 & CAOUT )== CAOUT)//CAOUT=0x01,如果比較器輸出為1 //若CACTL2寄存器的第0位為1,則表示輸入電壓 //大于參考電壓 P3OUT &= ~BIT0; //則P3的第0引腳輸出低電平,相連的發光二極管亮 else P3OUT |= BIT0; //否則,P3的第0引腳輸出高電平,相連的發光二極管滅 } } |