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.

[参考译文] MSP430G2553:ADC10转换在之前执行 LCD 显示屏的配置代码(由 I2C 控制)时永不结束

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/624147/msp430g2553-adc10-conversion-never-ends-when-configuration-code-of-an-lcd-display-controlled-by-i2c-is-previously-executed

器件型号:MSP430G2553

您好!

该代码测量电源电压电平、然后在 P1.4 (A4)上进行16次测量、并且工作正常。 问题在于配置 LCD 的两种方法(由 I2C 控制)未添加注释(LCDConfigure  和  LCDBackLight)。 在这种情况下、LCD 配置正确完成、功率电平测量也正确完成、但当在 A4引脚上执行电压电平测量时、线程保持在环路中锁定、同时 (while (!(ADC10CTL0 & ADC10IFG));) 我找不到问题、因为 LCD 和 I2C 设置不使用 ADC10。 有什么想法吗? 提前感谢。

代码为

#include 
#include "LCDDisplay.h"

int ADC[16]={0};
int avgADC = 0;

void getA4Voltage (void);
float getBatteryLevel (void);

float batt;

int main (void){

WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
BCSCTL1 = CALBC1_1MHz;//将 DCO 设置为1MHz
DCOCTL = CALDCO_1MHz;//将 DCO 设置为1MHz

//LCDConfigure();
//LCDBacklight (75);

BATT = getBatteryLevel ()/1000;

getA4Voltage();

while (1){}



}float getBatteryLevel (void)
{
ADC10CTL0 = SREF_1 + REFON + REF2_5V + ADC10ON + ADC10SHT_3;//使用内部基准、打开2.5V 基准、设置 SAMP 时间= 64个周期
ADC10CTL1 = INCH_11;
_delay_cycles (1000); //使内部基准稳定
ADC10CTL0 |= ENC + ADC10SC; //启用转换
while (!(ADC10CTL0和 ADC10IFG); //转换完成?
长温度=(ADC10MEM * 5000l); //将原始 ADC 值转换为毫伏
返回((float)(temp / 1024l));
}


void getA4Voltage (void){

ADC10CTL0 = 0x00;
ADC10CTL0 = SREF_1 + REF2_5V + REFON + ADC10SHT_1 + MSC + ADC10ON + ADC10IE;//采样保持时间+ ADC10打开+中断使能
ADC10CTL1 = CONSEQ_2 + INCH_4; //重复单通道,A4
ADC10DTC1 = 0x10; // 16次转换
ADC10AE0 |= BIT4;

ADC10CTL0 &=~ENC; //禁用转换
while (ADC10CTL1 & BUSY); //如果 ADC10忙则等待
ADC10SA =(int) ADC; //将数据传输到下一个数组
ADC10CTL0 |= ENC + ADC10SC; //启用并开始转换
while (!(ADC10CTL0和 ADC10IFG); //转换完成?
avgADC =((ADC[0]+ADC[1]+ADC[2]+ADC[3]+ADC[4]+ADC[5]+ADC[6]+ADC[7]+)
ADC[8]+ADC[9]+ADC[10]+ADC[11]+ADC[12]+ADC[13]+ADC[14]+ADC[15])>> 4);

}

这是两种方法的代码

void LCDConfigure (void)
{
i2cConfigure();

i2cTx (地址、TxData、10);

/*将计时器 A 配置为脉宽调制器*/
TA1CCR0 = 1000-1; //设置最大计数值以确定 PWM 频率= SMCLK/TACCR0 (1MHz/1000 = 1kHz)
TA1CCR2 = 100; //初始化计数器比较值1以控制占空比= TACCR1/TACCR0 (500/1000 = 50%)
TA1CCTL2 = OUTMOD_7; //当计数器复位时将输出设置为 on,当计数器等于 TACCR1时将输出设置为 off。 正常 PWM。
TA1CTL = tassel_2 + MC_1; //使用 SMCLK 为计数器计时并设置为递增计数模式

P2DIR |=背光; //将 P2.4设置为输出
P2SEL |=背光; //选择输出 P2.4作为 TA1.2
P2SEL2 &=~背光; //选择输出 P2.4作为 TA1.2

}

void LCDBackLight (int level)
{
TA1CCR2 =电平; //初始化计数器比较值1以控制占空比= TACCR1/TACCR0 (500/1000 = 50%)
}

void i2cConfigure (void)
{

UCB0CTL1 |= UCSWRST;//启用 SW 复位
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;//I2C 主器件、同步模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用 SMCLK、保持软件复位
P1SEL |= BIT6 + BIT7;//设置 I2C 引脚
P1SEL2|= BIT6 + BIT7;
UCB0BR0 = 12;//fSCL = SMCLK/12 =~100kHz
UCB0BR1 = 0;

UCB0CTL1 &=~Ω UCSWRST;//清除 SW 复位、恢复运行
IE2 |= UCB0TXIE;//启用 TX 中断
IE2 |= UCB0RXIE;//启用 RX 中断
} 

此致、
弗兰·马丁

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    > ADC10CTL0 = SREF_1 + REF2_5V + REFON + ADC10SHT_1 + MSC + ADC10ON + ADC10IE;//采样保持时间+ ADC10打开+中断使能

    您正在启用 ADC10中断、但我看不到它的 ISR。 尝试:
    > ADC10CTL0 = SREF_1 + REF2_5V + REFON + ADC10SHT_1 + MSC + ADC10ON;//采样保持时间+ ADC10开启+中断使能
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Bruce、

    事实上,问题已经通过你的修正得到解决,非常感谢。 为了尝试从这个错误中汲取教训、我想能够理解它为什么在对 LCDConfigure 和 LCDBackLight 方法进行注释时起作用 、这是因为没有用于处理 ADC10 ISR 的代码。 再次感谢。

    此致、

    弗兰·马丁。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您没有显示 i2cTx()的源,但由于 i2cConfigure()设置 Tx/Rx IEs,因此 i2cTx()是中断驱动的,即它设置 GIE,这似乎是一个安全的选择。 (最好选择中断驱动、因为它几乎始终是使用 I2C 单元的最简单方法。)