【MSP430系列电赛:GPIO、LED、按键、时钟、中断、串口、定时器、PWM与ADC】

文章目录

  • MSP430
  • 一、GPIO
  • 二、点亮LED
  • 三、按键控制LED
  • 四、更改主时钟
  • 五、串口通信
  • 六、串口中断
  • 七、外部中断
  • 八、定时器
  • 九、定时器中断
  • 十、PWM
  • 十一、ADC

  • MSP430

    MSP430 是德州仪器(TI)一款性能卓越的超低功耗 16 位单片机,自问世以来,MSP430 单片机一直是业内公认的功耗最低的单片机。除采用先进的制造工艺使芯片的静态电流尽可能降低外,MSP430 的独立可配置的时钟系统是其低功耗的基石之一。在追求绿色能源的今天,MSP430 超低功耗微控制器正以其超低功耗的特性,以及丰富多样化的外设受到越来越多设计者们的青睐。

    一、GPIO


    MSP430G2553共有两个通用数字端口P1和P2。

    端口P1和 P2具有输入/输出\中断和外部模块功能,这些功能可以通过它们各自的7个控制寄存器的设置来实现。

  • 1. PxDIR输入/输出方向寄存器
  • 相互独立的8位分别定义了8个引脚的输入/输出方向.8位在PUC后都被复位。使用时先根据需要定义端口的方向以满足设计者要求。
    0 : I/O引脚被切换成输入模式;
    1 : IO引脚被切换成输出模式。

  • 2. PxIN输入寄存器
  • 输入寄存器是CPU扫描IO引脚信号的只读寄存器。通过读取该寄存器的内容获取IO端口的输入信号。此时引脚的方向必须选定为输入。读出时,该引脚的方向寄存器必须设置为输入模式。

  • 3. PxOUT输出寄存器
  • 该寄存器为IO端口的输出缓冲寄存器。其内容可以像操作内存数据一样写入,以达到改变IO口状态的目的。在读取时输出缓存的内容与引脚方向定义无关。改变方向寄存器的内容,输出缓存的内容不受影响。

  • 4. PxIE中断使能寄存器
  • 该寄存器的各引脚都有一位用以控制该引脚是否允许中断,该寄存器中0 :禁止该位中断;
    1 :允许该位中断。

  • 5. PxIES 中断触发沿选择寄存器
  • 如果允许Px口的某个引脚中断,还需定义该引脚的中断触发沿。该寄存器的8位分别定义了Px口的8个引脚的中断触发沿。
    0:上升沿使相应标志置位;
    1:下降沿使相应标志置位。

  • 6. PxIFG中断标志寄存器
  • 该寄存器有8个标志位,它们含有相应引脚是否有待处理中断的信息,即
    相应引脚是否有中断请求。如果Px的某个引脚允许中断,同时选择上升沿,则当该引脚发生由低电平向高电平跳变时,PxFG的相应位就会置位,表明在该引脚上有中断事件发生。
    0 :没有中断请求;1 :有中断请求。

  • 7. PxSEL功能选择寄存器
  • Pl和P2两端口还有其他片内外设功能,考虑减少引脚,将这些功能与芯片外的联系通过复用P1和P2引脚的方式来实现.PxSEL用来选择引脚的IO端口功能与外围模块功能。
    0 :选择引脚为I/O端口;
    1 :选择引脚为外围模块功能。

    以下我以msp430g2553为例,解析GPIO的使用。

    二、点亮LED


    由上方电路图可读:

  • LED灯为P1.0和P1.6引脚,与下方GND相连,则为高电平驱动。
  • 按键为P1.3引脚,默认为悬空状态,当按键按下时与GND相连,为低电平状态。
  • #include <msp430.h> 
    
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// 关闭看门狗
    	
    	/*初始化LED2为输出*/
    	P1DIR |= BIT6;
    
    	/*初始化LED2为低电平,熄灭*/
    	P1OUT &= ~BIT6;
    
    	/*初始化KEY P1.3为输入*/
    	P1DIR &= ~BIT3;
    	/*使能P1.3口的上拉电阻*/
    	P1REN |= BIT3;
    	P1OUT |= BIT3;
    
    	while(1)
    	{
    	    if(P1IN & BIT3) /*如果P1.3口为高电平,证明按键没有被按下*/
    	    {
    	        P1OUT &= ~BIT6; //熄灭LED2
    	    }
    	    else
    	    {
    	        P1OUT |= BIT6;  //点亮LED2
    	    }
    	}
    	return 0;
    }
    
    

    三、按键控制LED

    #include <msp430.h> 
    
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	
    	/*初始化LED2为输出*/
    	P1DIR |= BIT6;
    
    	/*初始化LED2为低电平,熄灭*/
    	P1OUT &= ~BIT6;
    
    	/*初始化KEY P1.3为输入*/
    	P1DIR &= ~BIT3;
    	/*使能P1.3口的上拉电阻*/
    	P1REN |= BIT3;
    	P1OUT |= BIT3;
    
    	while(1)
    	{
    	    if(P1IN & BIT3) /*如果P1.3口为高电平,证明按键没有被按下*/
    	    {
    	        P1OUT &= ~BIT6; //熄灭LED2
    	    }
    	    else
    	    {
    	        P1OUT |= BIT6;  //点亮LED2
    	    }
    	}
    	return 0;
    }
    

    四、更改主时钟

    #include <msp430.h> 
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    
        /*设置MCLK频率1,8,12,16*/
        DCOCTL = CALDCO_16MHZ;
        BCSCTL1 = CALBC1_16MHZ;
    
        /*初始化LED2所在的IO口P1.6设置为输出*/
        P1DIR |= BIT6;
        /*初始化LED2 为低电平*/
        P1OUT &= ~BIT6;
    
        while(1)
        {
            P1OUT ^= BIT6;
            __delay_cycles(500000);
        }
        return 0;
    }
    

    五、串口通信

    #include <msp430.h> 
    #include "stdint.h"
    /*
     * @fn:    void InitSystemClock(void)
     * @brief: 初始化系统时钟
     * @para:  none
     * @return:none
     * @comment: 初始化系统时钟
     */
    void InitSystemClock(void)
    {
        /*配置DCO为1MHZ时钟*/
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
    
        /*配置SMCLK的时钟源为DCO*/
        BCSCTL2 &= ~SELS;
        /*SMCLK的分频系数置为1*/
        BCSCTL2 &= ~(DIVS0 | DIVS1);
    }
    
    /*
     * @fn:    void InitUART(void)
     * @brief: 初始化串口,包括设置波特率,数据位,校验位等
     * @para:  none
     * @return:none
     * @comment: 初始化串口
     */
    void InitUART(void)
    {
        /*复位USCI_Ax*/
        UCA0CTL1 |= UCSWRST;
    
        /*设置为异步模式*/
        UCA0CTL0 &= ~UCSYNC;
    
        /*配置UART时钟源为SMCLK*/
        UCA0CTL1 |= UCSSEL1;
    
        /*配置波特率为9600*/
        UCA0BR0 = 0x68;
        UCA0BR1 = 0x00;
        UCA0MCTL = 1 << 1;
    
        /*配置端口,使能端口复用*/
        P1SEL   |= BIT1 + BIT2;
        P1SEL2  |= BIT1 + BIT2;
    
        /*清除复位位,使能UART*/
        UCA0CTL1 &= ~UCSWRST;
    }
    
    /*
     * @fn:    void UARTSendString(uint8_t *pbuff, uint_8 num)
     * @brief: 初始化串口发送字符串
     * @para:  pbuff:指向要发送字符串的指针
     *         num:要发送的字符个数
     * @return:none
     * @comment: 初始化串口发送字符串
     */
    void UARTSendString(uint8_t *pbuff, uint8_t num)
    {
        uint8_t cnt = 0;
        for(cnt = 0; cnt < num; cnt++)
        {
            /*判断是否有数据正在发送*/
            while(UCA0STAT & UCBUSY);
            UCA0TXBUF = *(pbuff + cnt);
        }
    }
    
    /*
     * @fn:    void PrintNumber(uint16_t num)
     * @brief: 初始化串口发送数字
     * @para:  num:变量
     * @return:none
     * @comment: 初始化串口发送数字
     */
    void PrintNumber(uint16_t num)
    {
        uint8_t cnt = 0;
        uint8_t buff[6] = {0,0,0,0,0,'\n'};
    
        for(cnt = 0; cnt < 5; cnt++)
        {
            buff[4 - cnt] = (uint8_t)(num % 10 + '0');
            num /= 10;
        }
        UARTSendString(buff,6);
    }
    
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    
        InitSystemClock();
        InitUART();
    
        while(1)
        {
            PrintNumber(23456);
            __delay_cycles(500000);
        }
    
        return 0;
    }
    

    六、串口中断

    #include <msp430.h> 
    #include "stdint.h"
    
    uint8_t combuff[20] = {0};  //长度为20的命令缓冲区,用于保存串口接收到的命令
    uint8_t iscomend = 0;   //命令结束标志位
    /*
     * @fn:    void InitSystemClock(void)
     * @brief: 初始化系统时钟
     * @para:  none
     * @return:none
     * @comment: 初始化系统时钟
     */
    void InitSystemClock(void)
    {
        /*配置DCO为1MHZ时钟*/
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
    
        /*配置SMCLK的时钟源为DCO*/
        BCSCTL2 &= ~SELS;
        /*SMCLK的分频系数置为1*/
        BCSCTL2 &= ~(DIVS0 | DIVS1);
    }
    
    /*
     * @fn:    void InitUART(void)
     * @brief: 初始化串口,包括设置波特率,数据位,校验位等
     * @para:  none
     * @return:none
     * @comment: 初始化串口
     */
    void InitUART(void)
    {
        /*复位USCI_Ax*/
        UCA0CTL1 |= UCSWRST;
    
        /*设置为异步模式*/
        UCA0CTL0 &= ~UCSYNC;
    
        /*配置UART时钟源为SMCLK*/
        UCA0CTL1 |= UCSSEL1;
    
        /*配置波特率为9600*/
        UCA0BR0 = 0x68;
        UCA0BR1 = 0x00;
        UCA0MCTL = 1 << 1;
    
        /*配置端口,使能端口复用*/
        P1SEL   |= BIT1 + BIT2;
        P1SEL2  |= BIT1 + BIT2;
    
        /*清除复位位,使能UART*/
        UCA0CTL1 &= ~UCSWRST;
    
        /*接收中断启用*/
        IE2 |= UCA0RXIE;
        /*清空接收中断标志*/
        IFG2 &= ~UCA0RXIFG;
    }
    
    /*
     * @fn:    void UARTSendString(uint8_t *pbuff, uint_8 num)
     * @brief: 初始化串口发送字符串
     * @para:  pbuff:指向要发送字符串的指针
     *         num:要发送的字符个数
     * @return:none
     * @comment: 初始化串口发送字符串
     */
    void UARTSendString(uint8_t *pbuff, uint8_t num)
    {
        uint8_t cnt = 0;
        for(cnt = 0; cnt < num; cnt++)
        {
            /*判断是否有数据正在发送*/
            while(UCA0STAT & UCBUSY);
            UCA0TXBUF = *(pbuff + cnt);
        }
    }
    
    /*
     * @fn:    void PrintNumber(uint16_t num)
     * @brief: 初始化串口发送数字
     * @para:  num:变量
     * @return:none
     * @comment: 初始化串口发送数字
     */
    void PrintNumber(uint16_t num)
    {
        uint8_t cnt = 0;
        uint8_t buff[6] = {0,0,0,0,0,'\n'};
    
        for(cnt = 0; cnt < 5; cnt++)
        {
            buff[4 - cnt] = (uint8_t)(num % 10 + '0');
            num /= 10;
        }
        UARTSendString(buff,6);
    }
    
    /*
     * @fn:    void Execute(uint8_t *combuff)
     * @brief: 串口命令执行函数
     * @para:  combuff:指向串口命令缓冲区的指针
     * @return:none
     * @comment: 串口命令执行函数
     */
    void Execute(uint8_t *combuff)
    {
        const uint8_t charbuff[5][10] = {"王龙","米雷龙","班长","LED1 ON!","LED1 OFF!"};
        if(combuff[0] == charbuff[0][0] && combuff[1] == charbuff[0][1])
        {
            UARTSendString("aa",2);
        }
        else if(combuff[0] == charbuff[1][0] && combuff[1] == charbuff[1][1])
        {
            UARTSendString("bb",2);
        }
        else if(combuff[0] == charbuff[2][0] && combuff[1] == charbuff[2][1])
        {
            UARTSendString("cc",2);
        }
        else if(combuff[0] == charbuff[3][0] && combuff[6] == charbuff[3][6])
        {
            UARTSendString("Yes,LED ON!",11);
            P1OUT |= BIT0;
        }
        if(combuff[0] == charbuff[4][0] && combuff[6] == charbuff[4][6])
        {
            UARTSendString("Yes,LED OFF!",12);
            P1OUT &= ~BIT0;
        }
    }
    
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    
        InitSystemClock();
        InitUART();
        P1DIR |= BIT0;
        P1OUT &= ~BIT0;
        __bis_SR_register(GIE);//打开总中断
        while(1)
        {
           if(iscomend)
           {
               iscomend = 0; //清除标志位,防止重复执行
               Execute(combuff);
           }
        }
    
        return 0;
    }
    
    #pragma vector = USCIAB0RX_VECTOR
    __interrupt void UART_Receive_ISR(void)    //Port1_ISR(void)   中断服务函数
    {
        static uint8_t cnt = 0;
        if(IFG2 & UCA0RXIFG)//检测是否是USCI_AO的接收中断,USCI_AO和USCI_BO的接收中断共享同一向量
        {
    
            IFG2 &= ~UCA0RXIFG; //清空接收中断标志
            combuff[cnt++] = UCA0RXBUF; //保存命令
            cnt %= 20;  //防止cnt大于20,导致缓存区溢出
            if(combuff[cnt - 1] == '\n')
            {
                cnt = 0;    //复位计数器
                iscomend = 1;   //命令接收完毕标志
            }
        }
        /*清空接收中断标志*/
        IFG2 &= ~UCA0RXIFG;
    }
    
    

    七、外部中断

    #include <msp430.h> 
    
    
    /**
     * main.c
     */
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    
        /*初始化LED2为输出*/
        P1DIR |= BIT6;
    
        /*初始化LED2为低电平,熄灭*/
        P1OUT &= ~BIT6;
    
        /*初始化KEY P1.3为输入*/
        P1DIR &= ~BIT3;
        /*使能P1.3口的上拉电阻*/
        P1REN |= BIT3;
        P1OUT |= BIT3;
    
        /*打开P1.3口的中断*/
        P1IE |= BIT3;
        /*设定为下降沿触发*/
        P1IES |= BIT3;
        /*清除中断标志位*/
        P1IFG &= ~BIT3;
        /*打开全局中断*/
        __bis_SR_register(GIE);
    
        while(1)
        {
        }
        return 0;
    }
    
    #pragma vector = PORT1_VECTOR
    __interrupt void Port1_ISR(void)    //Port1_ISR(void)   中断服务函数
    {
        if(P1IFG & BIT3)   //判断是否P1.3产生中断
        {
            P1OUT ^= BIT6;
            P1IFG  &= ~ BIT3;   //清除标志位
        }
    }
    

    八、定时器

    #include <msp430.h> 
    #include "stdint.h"
    
    int main(void)
    {
        uint8_t cnt = 0;
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	/*配置DCO为1MHZ时钟*/
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
    
       P1DIR |= BIT0 ;
    
       /*配置时钟源为SMCLK*/
       TA1CTL |= TASSEL_2;
       /*设置工作模式为Up Mode*/
       TA1CTL |= MC_1;
       /*设置定时时间间隔*/
       TA1CCR0 = 49999;     //0.05s
    	while(1)
    	{
    	    if(TA1CTL & TAIFG)
    	    {
    	        cnt++;
    	        TA1CTL &= ~TAIFG;   //清除标志位
    	        if(cnt == 20)
    	        {
    	            P1OUT ^= BIT0;
    	            cnt = 0;
    	        }
    	    }
    	}
    
    	return 0;
    }
    

    九、定时器中断

    #include <msp430.h> 
    #include "stdint.h"
    
    uint32_t currenttime = 40500;   //用来保存时间的变量,初值代表11:15:00
    uint8_t flag = 0;
    /*
     * @fn:    void InitSystemClock(void)
     * @brief: 初始化系统时钟
     * @para:  none
     * @return:none
     * @comment: 初始化系统时钟
     */
    void InitSystemClock(void)
    {
        /*配置DCO为1MHZ时钟*/
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
    
        /*配置SMCLK的时钟源为DCO*/
        BCSCTL2 &= ~SELS;
        /*SMCLK的分频系数置为1*/
        BCSCTL2 &= ~(DIVS0 | DIVS1);
    }
    
    /*
     * @fn:    void InitUART(void)
     * @brief: 初始化串口,包括设置波特率,数据位,校验位等
     * @para:  none
     * @return:none
     * @comment: 初始化串口
     */
    void InitUART(void)
    {
        /*复位USCI_Ax*/
        UCA0CTL1 |= UCSWRST;
    
        /*设置为异步模式*/
        UCA0CTL0 &= ~UCSYNC;
    
        /*配置UART时钟源为SMCLK*/
        UCA0CTL1 |= UCSSEL1;
    
        /*配置波特率为9600*/
        UCA0BR0 = 0x68;
        UCA0BR1 = 0x00;
        UCA0MCTL = 1 << 1;
    
        /*配置端口,使能端口复用*/
        P1SEL   |= BIT1 + BIT2;
        P1SEL2  |= BIT1 + BIT2;
    
        /*清除复位位,使能UART*/
        UCA0CTL1 &= ~UCSWRST;
    
        /*接收中断启用*/
        IE2 |= UCA0RXIE;
        /*清空接收中断标志*/
        IFG2 &= ~UCA0RXIFG;
    }
    
    /*
     * @fn:    void UARTSendString(uint8_t *pbuff, uint_8 num)
     * @brief: 初始化串口发送字符串
     * @para:  pbuff:指向要发送字符串的指针
     *         num:要发送的字符个数
     * @return:none
     * @comment: 初始化串口发送字符串
     */
    void UARTSendString(uint8_t *pbuff, uint8_t num)
    {
        uint8_t cnt = 0;
        for(cnt = 0; cnt < num; cnt++)
        {
            /*判断是否有数据正在发送*/
            while(UCA0STAT & UCBUSY);
            UCA0TXBUF = *(pbuff + cnt);
        }
    }
    
    /*
     * @fn:    void PrintTime(uint32_t time)
     * @brief: 初始化串口发送字符串
     * @para:  pbuff:指向要发送字符串的指针
     *         num:要发送的字符个数
     * @return:none
     * @comment: 初始化串口发送字符串
     */
    void PrintTime(uint32_t time)
    {
        uint8_t charbuff[] = {0,0,':',0,0,':',0,0,'\n'};
        charbuff[7] = (uint8_t)((time % 60) % 10) + '0';    //得到当前秒个位
        charbuff[6] = (uint8_t)((time % 60) / 10) + '0';    //得到当前秒十位
        charbuff[4] = (uint8_t)((time % 3600) / 60 % 10) + '0';    //得到当前分个位
        charbuff[3] = (uint8_t)((time % 3600) / 60 / 10) + '0';    //得到当前分十位
        charbuff[1] = (uint8_t)((time / 3600) % 10) + '0';    //得到当前时个位
        charbuff[0] = (uint8_t)(time / 3600 / 10) + '0';    //得到当前时十位
        UARTSendString("当前时间:",10);
        UARTSendString(charbuff,9);
    }
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
        /*配置DCO为1MHZ时钟*/
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
    
        InitSystemClock();
        InitUART();
    
        P1DIR |= BIT0 ;
    
        /*配置时钟源为SMCLK*/
        TA1CTL |= TASSEL_2;
        /*设置工作模式为Up Mode*/
        TA1CTL |= MC_1;
        /*设置定时时间间隔*/
        TA1CCR0 = 49999;     //0.05s
    
        /*打开定时器TAIFG中断*/
        TA1CTL |= TAIE;
        /*打开全局中断*/
        __bis_SR_register(GIE);
    
        while(1)
        {
            if(flag == 1)
            {
                flag = 0;
                P1OUT ^= BIT0;
                PrintTime(currenttime);
            }
        }
    
        return 0;
    }
    
    #pragma vector = TIMER1_A1_VECTOR
    __interrupt void Timer_Tick(void)
    {
        static uint8_t cnt = 0;
        switch(TA1IV) //读取的话无需手动清零标志位
        {
        case 0x02:
            break;
        case 0x04:
            break;
        case 0x0A:
            cnt++;
            if(cnt == 20)
            {
                cnt = 0;
                flag = 1;   //1s时间到了
                currenttime ++; //时间加1
                currenttime %= 86400;   //一天24小时,防止溢出
            }
            break;
        default:
            break;
        }
    }
    
    

    十、PWM

    #include <msp430.h> 
    
    int main(void)
    {
        unsigned int cnt = 0;
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	
    	/*配置DCO为1MHZ时钟*/
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
    
        /*初始化P1.6为输入*/
        P1DIR &= ~BIT6;
    
        /*设置时钟源为SMCLK*/
        TA1CTL |= TASSEL_2;
        /*设置工作模式为Up & Dowm*/
        TA1CTL |= MC_0 | MC_1;
        /*设置TA1CCR0为0x00ff*/
        TA1CCR0 = 0x00FF;
        /*设置TA1CCR2为0x00ff*/
        TA1CCR2 = 0x00FF;   //占空比 = (TACCR0 - TACCR2)/ TACCR0 频率 = SMCLK / (TACCR0+1)/2
    
        /*设置为比较模式*/
        TA1CCTL0 &= ~CAP;
        TA1CCTL2 &= ~CAP;
        /*设置比较输出模式*/
        TA1CCTL2 |= OUTMOD_6;
        /*设置IO复用*/
        P2SEL |= BIT5;
        P2DIR |= BIT5;
    
        while(1)
        {
            for(cnt = 0;cnt < 0x00FF; cnt++)
            {
               TA1CCR2 =  cnt;
               __delay_cycles(5000);
            }
    
            for(cnt = 0x00FF;cnt > 0; cnt--)
            {
               TA1CCR2 =  cnt;
               __delay_cycles(5000);
            }
        }
    
    	return 0;
    }
    

    十一、ADC

    #include <msp430.h> 
    #include "stdint.h"
    
    /*
     * @fn:    void InitSystemClock(void)
     * @brief: 初始化系统时钟
     * @para:  none
     * @return:none
     * @comment: 初始化系统时钟
     */
    void InitSystemClock(void)
    {
        /*配置DCO为1MHZ时钟*/
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
    
        /*配置SMCLK的时钟源为DCO*/
        BCSCTL2 &= ~SELS;
        /*SMCLK的分频系数置为1*/
        BCSCTL2 &= ~(DIVS0 | DIVS1);
    }
    
    /*
     * @fn:    void InitUART(void)
     * @brief: 初始化串口,包括设置波特率,数据位,校验位等
     * @para:  none
     * @return:none
     * @comment: 初始化串口
     */
    void InitUART(void)
    {
        /*复位USCI_Ax*/
        UCA0CTL1 |= UCSWRST;
    
        /*设置为异步模式*/
        UCA0CTL0 &= ~UCSYNC;
    
        /*配置UART时钟源为SMCLK*/
        UCA0CTL1 |= UCSSEL1;
    
        /*配置波特率为9600*/
        UCA0BR0 = 0x68;
        UCA0BR1 = 0x00;
        UCA0MCTL = 1 << 1;
    
        /*配置端口,使能端口复用*/
        P1SEL   |= BIT1 + BIT2;
        P1SEL2  |= BIT1 + BIT2;
    
        /*清除复位位,使能UART*/
        UCA0CTL1 &= ~UCSWRST;
    
        /*接收中断启用*/
        IE2 |= UCA0RXIE;
        /*清空接收中断标志*/
        IFG2 &= ~UCA0RXIFG;
    }
    
    /*
     * @fn:    void UARTSendString(uint8_t *pbuff, uint_8 num)
     * @brief: 初始化串口发送字符串
     * @para:  pbuff:指向要发送字符串的指针
     *         num:要发送的字符个数
     * @return:none
     * @comment: 初始化串口发送字符串
     */
    void UARTSendString(uint8_t *pbuff, uint8_t num)
    {
        uint8_t cnt = 0;
        for(cnt = 0; cnt < num; cnt++)
        {
            /*判断是否有数据正在发送*/
            while(UCA0STAT & UCBUSY);
            UCA0TXBUF = *(pbuff + cnt);
        }
    }
    
    /*
     * @fn:    void PrintNumber(uint16_t num)
     * @brief: 初始化串口发送数字
     * @para:  num:变量
     * @return:none
     * @comment: 初始化串口发送数字
     */
    void PrintNumber(uint16_t num)
    {
        uint8_t cnt = 0;
        uint8_t buff[6] = {0,0,0,0,0,'\n'};
    
        for(cnt = 0; cnt < 5; cnt++)
        {
            buff[4 - cnt] = (uint8_t)(num % 10 + '0');
            num /= 10;
        }
        UARTSendString(buff,6);
    }
    
    /*
     * @fn:    void PrintFloat(float num)
     * @brief: 初始化串口发送浮点型数字
     * @para:  num:浮点型变量
     * @return:none
     * @comment: 初始化串口发送浮点型数字
     */
    void PrintFloat(float num)
    {
        uint8_t buff[] = {0,'.',0,0,0,'\n'};
        uint16_t temp = (uint16_t)(num * 1000);
        buff[0] = (uint8_t)(temp / 1000) + '0';
        buff[2] = (uint8_t)((temp % 1000) / 100) + '0';
        buff[3] = (uint8_t)((temp / 100) / 10) + '0';
        buff[4] = (uint8_t)(temp % 10) + '0';
        UARTSendString(buff,6);
    }
    
    /*
     * @fn:    void InitADC(void)
     * @brief: ADC初始化
     * @para:  none
     * @return:none
     * @comment: ADC初始化
     */
    void InitADC(void)
    {
        /*设置ADC时钟MCLK*/
        ADC10CTL1 |= ADC10SSEL_2;
        /*ADC 2分频*/
        ADC10CTL1 |= ADC10DIV_0;
        /*设置ADC基准源*/
        ADC10CTL0 |= SREF_1;
        /*设置ADC采样保持时间64CLK*/
        ADC10CTL0 |= ADC10SHT_3;
        /*设置ADC采样率200k*/
        ADC10CTL0 &= ~ADC10SR;
        /*ADC基准选择2.5V*/           /* ADC基准选择1.5V */
        ADC10CTL0 |= REF2_5V;         /* ADC10CTL0 &= ~REF2_5V; */
        /*开启基准*/
        ADC10CTL0 |= REFON;
        /*选择ADC输入通道A0*/
        ADC10CTL1 |= INCH_0;
        /*允许A0模拟输入*/
        ADC10AE0 |= 0x0001;
        /*开启ADC*/
        ADC10CTL0 |= ADC10ON;
    }
    
    /*
     * @fn:    uint16_t GetADCValue(void)
     * @brief: 进行一次ADC转换并返回ADC转换结果
     * @para:  none
     * @return:ADC转换结果
     * @comment: ADC转换结果为10bit,以uint16_t类型返回,低10位有效数据
     */
    uint16_t GetADCValue(void)
    {
        /*开始转换*/
        ADC10CTL0 |= ADC10SC|ENC;
        /*等待转换完成*/
        while(ADC10CTL1 & ADC10BUSY);
        /*返回结果*/
        return ADC10MEM;
    }
    
    int main(void)
    {
        float voltage = 0.0;
        uint16_t adcvalue = 0;
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	InitSystemClock();
    	InitUART();
    	InitADC();
    	
    	while(1)
    	{
    	    adcvalue = GetADCValue();
    	    voltage = adcvalue * 2.5 / 1023;
    
    	    UARTSendString("ADC10转接结果为:",17);
    	    PrintNumber(adcvalue);
    	    UARTSendString("相应电压值为:",14);
    	    PrintFloat(voltage);
            __delay_cycles(300000);
    	}
    	return 0;
    }
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 【MSP430系列电赛:GPIO、LED、按键、时钟、中断、串口、定时器、PWM与ADC】

    发表评论