04:ADC数据采样【MSP430F5529】

芯片引脚

数据手册:MSP430F552x、MSP430F551x 混合信号微控制器 datasheet (Rev. N) (ti.com.cn)

参考代码

TI官网资料提供例程:

#include <msp430.h>

int main(void)
{
    WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
    
    ADC12CTL0 = ADC12SHT02 + ADC12ON;         // Sampling time, ADC12 on
    ADC12CTL1 = ADC12SHP;                     // Use sampling timer
    ADC12IE = 0x01;                           // Enable interrupt
    ADC12CTL0 |= ADC12ENC;
    P6SEL |= 0x01;                            // P6.0 ADC option select
    P1DIR |= 0x01;                            // P1.0 output

    while (1)
    {
        ADC12CTL0 |= ADC12SC;                   // Start sampling/conversion

        __bis_SR_register(LPM0_bits + GIE);     // LPM0, ADC12_ISR will force exit
        __no_operation();                       // For debugger
    }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
#elif defined(__GNUC__)
void __attribute__  interrupt(ADC12_VECTOR)   ADC12_ISR (void)
#else
#error Compiler not supported!
#endif
{
    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:                                  // Vector  6:  ADC12IFG0
            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);   // Exit active CPU
            break;
        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;
    }
}

功能实现

在参考代码的基础上,实现功能:通过模拟数字转换器(ADC)采样输入电压V_Int,并使用OLED显示屏显示采样电压V_Int和计算后的输出电压V_Out。

定义全局变量和函数原型

  • results 数组用于存储采样结果。
  • sum 用于累加采样结果。
  • acom 和 com 用于计算滤波后的电压值。
  • cap 和 flag 用于中断服务函数中的计数和标志。
  • V_Int 和 V_Out 用于存储输入和输出电压值。

函数定义

  • CLK_Init:初始化时钟源,设置系统时钟。
  • ADC_Init:初始化ADC模块,配置ADC的相关参数。
  • ADC_date:从ADC读取数据并将其转换为电压值。
  • OLED_Flag:在OLED屏幕上显示电压值。
  • ADC12ISR:ADC中断服务函数,用于处理采样数据并计算滤波后的电压值。

main 函数

  • 首先关闭看门狗定时器。
  • 调用 CLK_Init 和 ADC_Init 函数进行时钟和ADC的初始化。
  • 调用 OLED_Init 函数初始化OLED显示屏。
  • 在无限循环中,调用 ADC_date 函数读取电压值,并通过 OLED_Flag 函数显示在OLED屏幕上。

CLK_Init 函数

  • 设置时钟源,包括PLL和晶振的相关配置。

ADC_Init 函数

  • 配置ADC模块,包括选择输入通道、设置采样时间、启动ADC转换等。

ADC_date 函数

  • 读取ADC寄存器的值,并将其转换为电压值。

OLED_Flag 函数

  • 将 V_Int 和 V_Out 的值显示在OLED屏幕上。

ADC12ISR 中断服务函数

  • 在ADC转换完成后被调用,存储采样结果到 results 数组。
  • 对数组中的值进行平均滤波,计算滤波后的电压值 com
  • 当采样次数达到10次时,关闭ADC中断,以便主函数可以继续执行。

完整main.c代码

//端口P6.6采样输入电压V_Int,未设置采样V_Out
//使用OLED显示采样电压

#include <msp430.h> 
#include <stdio.h>
#include <stdlib.h>
#include "oled.h"
#include "bmp.h"
#include <type.h>

u32 results[10];
u32 sum = 0, acom = 0, com = 0;
u32 cap = 0, flag = 0;

float V_Int, V_Out;  // 分别用于存储输入和输出电压值

// 函数原型声明
void CLK_Init(void);
void ADC_Init(void);
float ADC_date();
void OLED_Flag(void);

// 主函数
int main(void)
{
    // 关闭看门狗定时器
    WDTCTL = WDTPW | WDTHOLD;

    // 初始化时钟和ADC
    CLK_Init();
    ADC_Init();

    // 初始化OLED显示
    OLED_Init();

    // 在OLED屏幕上显示提示信息
    OLED_ShowString(7,4,"V_Int :  ",8);
    OLED_ShowString(7,6,"V_Out :  ",8);

    // 主循环
    while(1)
    {
        // 读取ADC采样值
        V_Int = ADC_date();
        // 调用OLED_Flag函数显示电压值
        OLED_Flag();
    }
}

// 时钟初始化函数
void CLK_Init(void)
{
    // 设置P2.2为时钟输出
    P2DIR |= BIT2;
    P2SEL |= BIT2;

    // 设置P7.7为时钟输出
    P7DIR |= BIT7;
    P7SEL |= BIT7;

    // 设置P5.2和P5.3为时钟选择
    P5SEL |= BIT2 + BIT3;

    // 选择不使用外部晶振
    UCSCTL6 &= ~XT2OFF;

    // 设置参考电压源
    UCSCTL3 |= SELREF_2;

    // 设置时钟频率选择
    UCSCTL4 |= SELA_2 + SELS_5 + SELM_5;

    // 等待时钟源稳定
    do
    {
        UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
        SFRIFG1 &= ~OFIFG;
    }
    while(SFRIFG1 & OFIFG);

    // 设置时钟输出驱动能力
    UCSCTL6 &= ~XT2DRIVE0;
}

// ADC初始化函数
void ADC_Init(void)
{
    // 设置P6.6为ADC输入
    P6SEL |= BIT6;

    // 初始化ADC12模块
    ADC12CTL0 = ADC12ON + ADC12SHT0_8 + ADC12MSC;

    // 设置ADC12的采样保持时间
    ADC12CTL1 = ADC12SHP + ADC12CONSEQ_2;

    // 设置ADC12的输入通道
    ADC12MCTL0 = ADC12SREF_0 + ADC12INCH_6;

    // 启动ADC转换
    ADC12CTL0 |= ADC12ENC;

    // 启动ADC12的采样转换
    ADC12CTL0 |= ADC12SC;

    // 使能ADC12中断
    _EINT();
}

// 采样数据转换函数
float ADC_date()
{
    // 启动ADC转换并等待完成
    ADC12CTL0 |= ADC12SC;
    // 读取ADC结果
    float date = ADC12MEM0;
    // 将ADC结果转换为电压值
    date = date * 3.3 / 4065;
    // 返回转换后的电压值
    return date;
}

// 显示电压值的函数
void OLED_Flag(void)
{
    // 在OLED屏幕上显示V_Int和V_Out的值
    OLED_ShowVI(65,4,V_Int,8);
    OLED_ShowVI(65,6,V_Out,8);
}

// ADC中断服务函数
#pragma vector = ADC12_VECTOR
__interrupt void ADC12ISR(void)
{
    // 静态变量用于存储采样次数
    static unsigned int m, count = 0;
    // 滤波系数
    float factor = 0.80566;

    // 存储当前采样值
    results[count] = ADC12MEM0;
    // 增加采样次数
    count++;

    // 累加所有采样值
    for(m = 0; m < 10; m++)
    {
        sum += results[m];
    }
    // 计算平均值
    sum /= 10;
    // 应用滤波系数
    sum = sum * factor;
    // 存储滤波后的值
    com = sum;

    // 如果采样次数达到10次
    if(count == 10)
    {
        // 重置采样次数
        count = 0;
        // 设置标志位
        flag = 1;
        // 关闭ADC中断
        ADC12IE = 0x00;
    }
}

OLED模块请见下一篇:05:OLED模块【MSP430F5529】_msp43o5529-CSDN博客

  • 7
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千城千景

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值