This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/MSP430F5529:控制 LED 和 LDR

Guru**** 1993015 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/904294/ccs-msp430f5529-control-of-led-and-ldr

器件型号:MSP430F5529

工具/软件:Code Composer Studio

大家好、我已经制作了两个由3.3V 外部电压供电的分压器、并将一个 LDR 串联到一个电阻器上。 我还使用了 LED 来显示 LDR 内部电阻器的变化。 我的目的是、通过改变施加到 LDR 的光、改变连接到带有计时器的每个 LDR 的 LED 的 PWM 占空比。 例如、如果没有光照、两个 LED (每个 LDR 一个)将会亮起以补偿这种不存在光照的情况。  

我将代码粘贴到这里。 如果有人认为有任何问题,我将不胜感激。 顺便说一下、谢谢!

为了更好地通过焊盘和所有这些材料读取它、我还将相同的代码和粘贴到这里: https://pastebin.com/htjSHBX9

#include
#include
#include

uint16_t ADC_A0[8]={0};//数组参数、用于存储总共8个初始化为0的 A0值
uint16_t ADC_A1[8]={0};//数组参数、用于存储 A1初始化为零的总共8个值
uint8_t buffer_lleno = 0;
volatile uint8_t end_conversion = 1;//变量可确定转换是否已完成
uint16_t valor_promedio_A0 = 0;//存储 A0通道平均值的变量
uint16_t valor_promedio_A1 = 0;//存储 A1通道平均值的变量

void Inicializacion_Relojes (void){

_bis_SR_register (SCG0);//禁用 FLL 控制循环
UCSCTL0 = 0x0000;// Ponemos el DCOx y MODx al 最小可接受
UCSCTL1 = DCORSEL_5;//选择范围取消 operación DEL DCO 范围去16MHz
UCSCTL2 = FLLD_0 | 487;// Poniendo FLLD_0 hacemos tomamos como 1 el dividesde la frecuencia de entrada del crustal de cuarzo y 487 es el valor multiplicador de FLLN
//(N + 1)*(FLLRef/n)= Fdco
//(487 + 1)*(32768/1)= 16MHz
UCSCTL3 = 0;// FLL SELREF = XT1CLK y 除数 de FLL = 1 (FLLREFDIV = FLLREFCLK/1)
UCSCTL4 |= SELA_0 | SELM_4 | SELM_4;// tomamos ACLK = XT1CLK (Cuarzo extern DE 2^15位);SMCLK = MCLK = DCOCLKDIV (DCO interno de 16MHz)
// UCSCTL5 |= DIV_0 | DIVS_0;// Divisor para SMCLK =f (SMCLK)/1;ACLK =f (ACLK)/1 --没有必要的 ES 要求,不需要 Son los valores POR defecto
_BIC_SR_register (SCG0);//启用 FLL 控制环路

void Inicializacion_LEDs (void){
P1SEL |=(BIT2 | BIT3);// LED 的替代功能
P1DIR |=(BIT2 | BIT3);// LED 作为输出

void TimerA0_PWM (void){
TA0CCR0 = 2000-1;// Tperíodo del PWM:2000 milisegundos
TA0CCTL1 |= OUTMOD_3;// Modo CCR1:设置/复位。
TA0CCR1 = 0;//占空比官方值:0%
TA0CCTL2 |= OUTMOD_3;// Modo CCR1:设置/复位。
TA0CCR2 = 0;//占空比官方值:0%
TA0CTL |= tassel_2 | ID_3 | MC_1 | TACLR;// Reloj SMCLK、Frecuencia:16MHz。 莫多向上。 Precalador:8.

// Funcion 参数配置 el ADC:

void ConfiguracionADC (void){
P6SEL |= BIT0 | BIT1;//使用 P6.0 y P6.1作为通道 A0和 A1的条目
ADC12CTL0 |= ADC12SHT0_5 | ADC12MSC | ADC12ON;// ADC12ON:Activamos el ADC;ADC12SHT0_5:64 ciclos de muestreo del S & H
ADC12CTL1 |= ADC12SSEL_3 | ADC12DIV_7 | ADC12CONSEQ_3 | ADC12SHP;// ADC12SSEL_3:SMCLK;ADC12DIV_7:Precalador DE 8;ADC12CONSEQ_3:多通道中的多个样本
ADC12MCTL0 |= ADC12SREF_0 | ADC12INCH_0;// ADC12SREF_0:VR+= AVcc+且 VR-= AVss;ADC12INCH_0:通道 A0
ADC12MCTL1 |= ADC12SREF_0 | ADC12INCH_1 | ADC12EOS;// ADC12INCH_1:通道 A1;ADC12EOS:序列结束
__DELAY_CYCLES (30);//等待电压基准的稳定
ADC12CTL0 |= ADC12ENC;// ADC12ENC:启用转换
ADC12IE |= BIT1;//启用 ADC12IFG.1

void main (void){
uint8_t cont;//在数组中迭代的变量
uint16_t value1、value2;
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
Inicializacion_Relojes();
iniciacion_LEDs();
TimerA0_PWM ();
ConfiguracionadC();
_enable_interrupt ();
while (1){
if (end_conversion = 1){//如果转换已完成
ADC12CTL0 |= ADC12SC;// ADC12SC:您可以启动另一个转换
end_conversion = 0;

if (buffer_lleno = 1){
对于(CONT=0;CONT<8;CONT++){
valor_promedio_A0 += ADC_A0[续];
valor_promedio_A1 += ADC_A1[CONT];

valor_promedio_A0 >=3;//除以8 (向右移位3位)
valor_promedio_A1 >>= 3;
Value1 =(TA0CCR0*(valor_promedio_A0))/(4096);
TA0CCR1 = Value1;
Value2 =(TA0CCR0*(valor_promedio_A1))/(4096);
TA0CCR2 =值2;
valor_promedio_A0 = 0;//复位 A0的值
valor_promedio_A1 = 0;//复位 A0的值
Buffer_lleno = 0;
end_conversion = 1;


#pragma vector = ADC12_vector
_interrupt void ADC12_ISR (void)

静态无符号 int 索引= 0;
switch (__evo_in_range (ADC12IV、34))

情况0:中断;//向量0:无中断
情况2:中断;//矢量2:ADC 溢出
情况4:中断;//矢量4:ADC 时序溢出
案例6:中断;
案例8://向量8:ADC12IFG1
ADC_A0[索引]= ADC12MEM0;
ADC_A1[索引]= ADC12MEM1;
索引++;
if (index =8){
Buffer_lleno = 1;
索引= 0;
ADC12CTL0 &=~ADC12SC;
end_conversion = 0;

否则{
end_conversion = 1;

情况10:中断;//向量10:ADC12IFG2
情况12:中断;//向量12:ADC12IFG3
案例14:中断;//矢量14:ADC12IFG4
情况16:中断;//向量16:ADC12IFG5
情况18:中断;//向量18:ADC12IFG6
情况20:中断;//向量20:ADC12IFG7
情况22:中断;//向量22:ADC12IFG8
情况24:中断;//向量24:ADC12IFG9
情况26:中断;//向量26:ADC12IFG10
情况28:中断;//向量28:ADC12IFG11
情况30:中断;//向量30:ADC12IFG12
情况32:中断;//向量32:ADC12IFG13
案例34:中断;//矢量34:ADC12IFG14
默认值:break;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    它现在有什么作用?

    --------

    > while (!(ADC12IFG & BIT1));//等待数据准备就绪

    这可能会永远旋转、因为 ISR 会在您看到 IFG 之前将其清除。 一种解决方案是声明 buffer_lleno"并将其更改为:

    > while (buffer_lleno =0);  //等待数据准备就绪

    --------

    > value1 =(TA0CCR0*(valor_promedio_A0))/(4095);

    TA0CCR0大约为2^11、valor_promedio_A0最多可以为2^12、因此乘法运算将溢出的可能性很大(2^23)。 此外、除法实际上应该是/4096、因为这是范围的"宽度"。 尝试:

    > value1 =(TA0CCR0*(unsigned long) valor_promedio_A0)/(4096);

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢你的帮助。 我将新代码与您告诉我的更改一起粘贴。 问题是、我逐步分析程序、看起来运行良好、但当它以良好的方式首次计算平均值时、它直接进入 while (buffer_lleno = 0)、并像 forerver 一样留在那里、因此它不能计算更多的值。

    #include
    #include
    #include

    uint16_t ADC_A0[8]={0};//数组参数保护雷达8价、以消除认证的 A0无效性
    uint16_t ADC_A1[8]={0};//数组参数保护雷达8价、用于 A1 iniciizados a cero
    volatile uint8_t buffer_lleno = 0;
    uint16_t valor_promedio_A0 = 0;//可变的保护罩 valor promedio de A0
    uint16_t valor_promedio_a1 = 0;//可变的保护罩 valor promedio de a1

    void Inicializacion_Relojes (void){

    _bis_SR_register (SCG0);//禁用 FLL 控制循环
    UCSCTL0 = 0x0000;// Ponemos el DCOx y MODx al 最小可接受
    UCSCTL1 = DCORSEL_5;//选择范围取消 operación DEL DCO 范围去16MHz
    UCSCTL2 = FLLD_0 | 487;// Poniendo FLLD_0 hacemos tomamos como 1 el dividesde la frecuencia de entrada del crustal de cuarzo y 487 es el valor multiplicador de FLLN
    //(N + 1)*(FLLRef/n)= Fdco
    //(487 + 1)*(32768/1)= 16MHz
    UCSCTL3 = 0;// FLL SELREF = XT1CLK y 除数 de FLL = 1 (FLLREFDIV = FLLREFCLK/1)
    UCSCTL4 |= SELA_0 | SELM_4 | SELM_4;// tomamos ACLK = XT1CLK (Cuarzo extern DE 2^15位);SMCLK = MCLK = DCOCLKDIV (DCO interno de 16MHz)
    // UCSCTL5 |= DIV_0 | DIVS_0;// Divisor para SMCLK =f (SMCLK)/1;ACLK =f (ACLK)/1 --没有必要的 ES 要求,不需要 Son los valores POR defecto
    _BIC_SR_register (SCG0);//启用 FLL 控制环路

    void Inicializacion_LEDs (void){
    P1SEL |=(BIT2 | BIT3);// Pines GPIO
    P1DIR |=(BIT2 | BIT3);// LED COMO SALIDAS
    P1OUT &=~(BIT2 | BIT3);// LED 触点

    void TimerA0_PWM (void){
    TA0CCR0 = 2000-1;// Tperíodo del PWM:2000 milisegundos
    TA0CCTL1 |= OUTMOD_3;// Modo CCR1:设置/复位。
    TA0CCR1 = 0;//占空比官方值:0%
    TA0CCTL2 |= OUTMOD_3;// Modo CCR1:设置/复位。
    TA0CCR2 = 0;//占空比官方值:0%
    TA0CTL |= tassel_2 | ID_3 | MC_1 | TACLR;// Reloj SMCLK、Frecuencia:16MHz。 莫多向上。 Precalador:8.

    // Funcion 参数配置 el ADC:

    void ConfiguracionADC (void){
    P6SEL |= BIT0 | BIT1;// Habilitamos P6.0 y P6.1 como canales de entrada del A/D
    ADC12CTL0 |= ADC12SHT0_5 | ADC12MSC | ADC12ON;// ADC12ON:Activamos el ADC;ADC12SHT0_5:64 ciclos de muestreo del S & H
    ADC12CTL1 |= ADC12SSEL_3 | ADC12DIV_7 | ADC12CONSEQ_3 | ADC12SHP;// ADC12SSEL_3:SMCLK;ADC12DIV_7:Precalador de 8;ADC12CONSEQ_3:多路复用器和多路复用器
    ADC12MCTL0 |= ADC12SREF_0 | ADC12INCH_0;// ADC12SREF_0:VR+= AVcc+且 VR-= AVss;ADC12INCH_0:通道 A0
    ADC12MCTL1 |= ADC12SREF_0 | ADC12INCH_1 | ADC12EOS;// ADC12INCH_1:通道 A1;ADC12EOS:fin Secuencia canales
    _delay_cycles (30);//在 voltaje 举行的会议上进行讨论
    ADC12CTL0 |= ADC12ENC;// ADC12ENC:Habilitamos conversión;
    ADC12IE |= BIT1;// Habitilitamos ADC12IFG.1

    void main (void){
    uint8_t cont;//可变矩迭代 a sobre las posiciones del array
    uint16_t value1、value2;
    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
    Inicializacion_Relojes();
    iniciacion_LEDs();
    TimerA0_PWM ();
    ConfiguracionadC();
    __enable_interrupt ();// Habilitimos interruptiones generales
    while (1){
    ADC12CTL0 |= ADC12SC;// ADC12SC:empieza conversión
    while (buffer_lleno = 0);// Esperamos hasta que est é listo el Dato
    if (buffer_lleno = 1){
    对于(CONT=0;CONT<8;CONT++){
    valor_promedio_A0 += ADC_A0[续];
    valor_promedio_A1 += ADC_A1[CONT];

    valor_promedio_A0 >=3;// Para dividir entre 8 y obener el valor promedio
    valor_promedio_A1 >>= 3;
    Value1 =(TA0CCR0*((unsigned long) valor_promedio_A0))/(4096);
    TA0CCR1 = Value1;
    value2 =(TA0CCR0*(unsigned long) valor_promedio_A1))/(4096);
    TA0CCR2 =值2;
    valor_promedio_A0 = 0;// Reseteamos el valor de A0
    valor_promedio_A1 = 0;// Reseteamos el valor de A1
    Buffer_lleno = 0;


    #pragma vector=ADC12_vector
    _interrupt void ADC12ISR (void)

    静态无符号 int 索引= 0;
    switch (__evo_in_range (ADC12IV、34))

    情况0:中断;//向量0:无中断
    情况2:中断;//矢量2:ADC 溢出
    情况4:中断;//矢量4:ADC 时序溢出
    案例6:中断;
    案例8://向量8:ADC12IFG1
    ADC_A0[索引]= ADC12MEM0;
    ADC_A1[索引]= ADC12MEM1;
    索引++;
    if (index =8){
    Buffer_lleno = 1;
    索引= 0;
    ADC12CTL0 &=~ADC12ENC;

    情况10:中断;//向量10:ADC12IFG2
    情况12:中断;//向量12:ADC12IFG3
    案例14:中断;//矢量14:ADC12IFG4
    情况16:中断;//向量16:ADC12IFG5
    情况18:中断;//向量18:ADC12IFG6
    情况20:中断;//向量20:ADC12IFG7
    情况22:中断;//向量22:ADC12IFG8
    情况24:中断;//向量24:ADC12IFG9
    情况26:中断;//向量26:ADC12IFG10
    情况28:中断;//向量28:ADC12IFG11
    情况30:中断;//向量30:ADC12IFG12
    情况32:中断;//向量32:ADC12IFG13
    案例34:中断;//矢量34:ADC12IFG14
    默认值:break;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    一种可能是 ADC 的停止时间比我们想象的要长;我没有进行算术运算、但我看到有许多分频器在使用中、并且在 CONSEQ=3时、它必须完成整个序列。 [参考用户指南(SLAU208Q)第28.2.7.6节]。 尝试等待它停止、然后再重新启动它。 该序列可能类似于:

    > while (ADC12CTL1 & ADCBUSY)/* empty*/;//等待序列完成

    >索引= 0;  //开始时重新启动

    > buffer_lleno = 0;

    > ADC12CTL0 |= ADC12SC;// ADC12SC:empieza conversión