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:GIE 和定时器示例有问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/670536/msp430g2553-trouble-with-gie-and-timer-examples

器件型号:MSP430G2553

支持、

我正在成功使用 ADXL345加速计。  它使用 I2C 到 ADXL 并使用 UART 打印值。

我有一个单独的项目、使用 TimerA 进行 PWM 调光、加/减、独立运行。

当我将这两者结合在一起时、它们不能协同工作。  仅当我在设置后进入 LPM0 + GIE 时、上行/下行才起作用。  ADXL 部件仅在我不启用 LPM0 + GIE 时工作?

计时器中断。

//将 ADXL345加速计与 MSP430G2553连接到 I2C 通信
//并使用 UART 将打印库连接到串行端口。
//
///|/|/|/
ADXL345 10k 10k MSP430G2xx3
//从器件||主器件
//--- |||---
//| SDA|<-|--+-|P1.7/UCB0SDA XIN|-
//|||||||
XOUT|-
//| SCL|<---- || P1.6/UCB.S.|
//|||//

对于 SparkFun ADXL345,
//*将 SDO 接地
//*将 CS 连接到 VCC
//
////原始 I2C 代码:
// Ravi Butani 教授
// Marwadi Education Foundation、Rajkot Gujarat 印度
// ravi.butani@marwadieducation.edu.in
// 


//修改:////
// Phitchaya Mangpo Phothilimthana
// mangpo@eecs.berkeley.edu

//
#include 

#define NUM_Bytes_TX 2
#define NUM_Bytes_RX 6
#define ADXL_345 0x53
#define LED

int RXByteCtr;
volatile unsigned char RxBuffer[6];//分配6字节 RAM
unsigned char * PRxData;//指向 RX DATA unsigned
char TXByteCtr 的指针、RX = 0;
unsigned char MSData[2];Insigned char I
Dec = 1
;int PWM

//用于 I2C
void Setup_TX (unsigned char)的函数;
void Setup_RX (unsigned char);
void transmitOne
(unsigned char);
void receive (void);

//用于 UART 的函数:将输出打印到串行端口
void Setup_UART (unsigned char);
void UDTSendArray (unsigned char * WDTxArray、unsigned ARTART、void WDTL)



;void WDTx (unsigned char)
;void WDTx (unsigned t) //停止 WDT

// LED
P1DIR |= BIT0;// P1.0 =红色 LED
P1OUT |= BIT0;// P1.0 =红色 LED

// UART
DCOCTL = 0;
BCSCTL1 = CALBC1_1MHz;//将 DCO 设置为1MHz
DCOCTL = CALDCO_1MHz; //将 DCO 设置为1MHz

//配置硬件 UART
P1SEL |= BIT1 + BIT2;// P1.1 = RXD、P1.2 = TXD
P1SEL2 |= BIT1 + BIT2;// P1.1 = RXD、P1.2 = TXD

// ADXL345
P1SEL |= BIT6 + BIT2;// P1.1 = RXD; //将 I2C 引脚分配给 USCI_B0、P1.6 = SCL、P1.7 = SDA
P1SEL2 ||= BIT6 + BIT7;//将 I2C 引脚分配给 USCI_B0、P1.6 = SCL、P1.7 = SDA

#ifdef LED
/***添加 LED 调光器- P2.6、通过引脚19的导线连接***/
P2DIR |= BIT6;

P2SEL &=~(BIT7);
P2SEL2 &=~(BIT6 + BIT4);

/*** Timer0_A 设置***/
TA0CCR0 |= 1000;
TA0CCR1 |= 1;
TA0CCTL1 |= OUTMOD_7;
TA0CTL |= TA0CCEL_2 + TA1MC_1;

TA1CC0|= TA1M2|TA1CC4000 |




//
如果我启用这个 LOP0 + GIE、定时器 PWM 工作、但是 ADXL 停止。
如果我删除这一行、PWM 将不起作用、但 ADXL 会起作用
//********* //

_BIS_SR (LPM0_Bits + GIE);
//_ENABLE_INTERRUPT ();
//_ bis_SR_register (GIE);

#endif

// Init sequence for ADXL345
SETUP_TX (ADXL_345);
P1DIR ^




^= BIT0;transmit (0x345、0x00、0xBCTXL);SEND

和 UCTL (UCB0X0

);SEND = UCTL (UCTL);SEND 和 UCTL (UCTL (UCTL);
发送 UST_0X2D 和 UCTL (UCTL);发送 UCTL (0x345);发送 UCTL (UCTL);发送 UCTL (0x3DIR 0X3DIR 和 UCTL);发送 UCTL (UCTL (UCTL)
while (UCB0CTL1 & UCTXSTP);//确保已发送停止条件

//取消注释下一个块以更改 ADXL345的范围
//
Setup_TX (ADXL_345);
RPT_Flag = 1;
Transmit (0x31 0x01);//在 add 0x31写入0x00表示2g (默认值)/ 0x01表示
UCTL1 & 0x01;while UCB08G (0x31) //确保发送停止条件
*/

while (1){
//发送进程
Setup_TX (ADXL_345);
TransmitOne (0x32);//从 ADXL345请求数据(2g 范围内) 10位分辨
率,同时(UCB0CTL1 & UCTXSTP);//确保发送停止条件

//接收进程
Setup_RX (ADXL_RX);
UCB0CTL1 (UCT345
);(UCTXSTPs); //确保停止条件已发送

int x =(((int) RxBuffer[1])<< 8)| RxBuffer[0];
int y =(((int) RxBuffer[3])<< 8)| RxBuffer[2];
int z =(((int) RxBuffer[5])<< 8)| RxBuffer[4);

我们现在已经读取了/z x、//。
//红色下面的 LED 亮起,如果 x 或 y 角度超过45度或小于-45度。
if ((x > 128)||(y > 128)||(x <-128)||(y <-128)){
P1OUT |= BIT0;//红色 LED 亮起
}
否则{
P1OUT &=~BIT0;//红色 LED 熄灭
}

//打印 x、y、z 至偏斜的串行端口。
Setup_UART();
UARTSendArray ("sample\n"、7);
UARTSendInt (x);
UARTSendInt (y);
UARTSendInt (z);
__delay_cycles (3000000);//延迟1秒
}
}-->---------------


// I2C
///-------------------------------------------------------
#pragma vector = USCIAB0TX_VECTOR
__INTERRUPT void USCIAB0TX_ISR (void)
{

if (RX ==1){//主机接收?
RXByteCtr --;//如果
(RXByteCtr)
{
* PRxData++= UCB0RXBUF;//将 RX 数据移动到地址 PRxData
}
否则
{
UCB0CTL1 |= UCTXSTP;//无重复开始:停止条件
* PRxData++= UCB0RXBUF};_ PRxRXBUF_REGIS_EXIT
//退出 LPM0
}
else{//主机发送
IF (TXByteCtr)//检查 TX 字节计数
器{
TXByteCtr -;//测量 TX 字节计数器
UCB0TXBUF = MSData[TXByteC1];//加载 TX 缓冲区
}
else
{
UCB0CTG2 |= UCTXSTP;// I2C_TXIFCTR1
= MSData[TXByteL1];//加载 TX 缓冲区= UCB0TXIF_TXIFT_PRU =~UCCR
= U0TXIF_TO_REF;//清除 TXIF0_TOP_FLAG;// UCB0TXIF0TXIF0TXIFG_FLAG = //退出 LPM0
}

}

void Setup_TX (unsigned char Dev_ID){
_DINT ();
RX = 0;
IE2 &=~UCA0RXIE;//禁用 USCI_A0 RX 中断(UART)
IE2 &=~UCB0RXIE;//禁用 USCI_B0 RX 中断(I2C
) while (UCB0XCTL1 &禁用 UCB0RXST 中断
);//确保已发送中断/ UCB0WCTL1 //启用 SW 复位
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;// I2C 主器件、同步模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用 SMCLK、保持 SW 复位
UCB0BR0 = 12;// fSCL = SMCLK/12 =~


~UCS0RST = UCB0kHz;// UCS0BR1 = UCB0BR0 = UCB0kHz;UCB0CCS0 = UCB0W0 = UCB0CLK/ UCB0CL1 = UCS0 = UCB0kHz;UCB0CL0 = UCB0CL1 = U //清除 SW 复位,恢复操作
IE2 |= UCB0TXIE;//启用 TX 中断
}

void Setup_RX (unsigned char Dev_ID){
_DINT ();
RX = 1;
IE2 &=~UCA0RXIE;//禁用 USCI_A0 RX 中断(UART)
IE2 &=~UCB0TXIE;//禁用 UCB0RXIE
;// UCS0 | UCB0TXI 中断 //启用 SW 复位
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;// I2C 主器件、同步模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用 SMCLK、保持 SW 复位
UCB0BR0 = 12;// fSCL = SMCLK/12 =~


~UCS0RST = UCB0kHz;// UCS0BR1 = UCB0BR0 = UCB0kHz;UCB0CCS0 = UCB0W0 = UCB0CLK/ UCB0CL1 = UCS0 = UCB0kHz;UCB0CL0 = UCB0CL1 = U //清除 SW 复位,恢复操作
IE2 |= UCB0RXIE;//启用 RX 中断
}

void transmit (unsigned char ReG_Add,unsigned char ReG_DAT){
MSData[1]= ReG_Add;
MSData[0]= ReG_DAT;
TXByteCtr = NUM_Bytes_TX;//在
(UCB0CTXCTL1 + UCTSTUCTL)发送时加载 TX 字节计数器
;//确保停止条件| UCB0CTSTCTL // I2C TX、起始条件
__bis_SR_register (CPUOFF + GIE);//输入 LPM0、带中断
}

void TransmitOne (unsigned char Reg_Add){
MSData[0]=_ADD;
TXByteCtr = 1;//在
(UCB0CTL1 & UCTXSTP)期间加载 TX 字节计数器;
|确保发送 UCB0CTL1 + UCTL 条件 // I2C TX、起始条件
__bis_SR_register (CPUOFF + GIE);//输入 LPM0、带中断
}

void Receive (void){
PRxData =(unsigned char *) RxBuffer;// RX buffer 的起始
RXByteCtr = NUM_Bytes_RX;//在
(UCB0CTL1 & UCB0CTL1)发送时加载 RX 计数器;//确保发送条件
// I2C 起始条件
__bis_SR_register (CPUOFF + GIE);//输入 LPM0,带中断
}

//---------------
// UART
///-------------------------------------------------------

void Setup_UART (){
_DINT ();
IE2 &=~UCB0RXIE;//禁用 USCI_B0 RX 中断(I2C)
IE2 &=~UCB0TXIE;//禁用 USCI_B0 TX 中断(I2C)
UCA0CTL1 |= UCSSEL_2;//使用 SMCLK UCA0TXIE

;//将数据表15.3MHz 设置为0;//将数据表设置为9600波特率设置为15.3MHz //将1MHz 时钟 UCA0MCTL
= UCBRS0时的波特率设置为9600;//调制 UCBRSx = 1
UCA0CTL1 &=~UCSWRST;//初始化 USCI 状态机
IE2 |= UCA0RXIE;//启用 USCI_A0 RX 中断
}

//打印字符数组
UARTxL (

无符号数组长度),而符号数组为*字符数组为空字符数组 ){//循环直到 StringLength = 0并且 POST 递减
while (!(IFG2 & UCA0TXIFG));//等待 TX 缓冲区为新数据做好准备
UCA0TXBUF =* TxArray;//在指定的位置写入字符指针
TxArray++; //使 TxString 指针递增以指向下一个字符
}
IFG2 &=~UCA0TXIFG;//清除 USCI_A0 int 标志
}

//以十六进
制形式打印 int void UARTSendInt (unsigned int x){
unsigned char buy[10];

unsigned char data[10];unsigned char index = 0、i = 0;

while (x > 0){
unsigned char val = x % 16;
if (val < 10)
buff [索引]= 48+val;
else
buff [索引]= 97+ver-10;
index++;
x /= 16;
}
buff [索引]='\n';

while (索引> 0){
index--
;data[i]=[index ]= 0];



if '+


=[i+= 0];'+='data';if '=[i+= 0'}

UARTSendArray (data、i+1);
}

#ifdef LED
/*** LED 调光器***/
#pragma vector=Timer1_A0_vector
__interrupt void Timer1_A0 (void)
{
TA0CCR1 += IncDec_PWM*2;

if (TA0CCR1 > 998 || TA0CCR1 < 2)
enDec_PWM =-Incdec
;#incf}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您未显示任何可将故障归咎于 GIE 的分析。

    如果我想猜测一下、您的问题是代码的阻塞性质。

    那么、从那里开始。

    至于可变调光、您可以尝试以下方法:设置两个翻转相同输出引脚的 ISR。 如果这两个 ISR 有轻微的关闭周期,例如一个 ISR 以1000个周期运行,另一个 ISR 以1001个周期运行,则该输出引脚将经历一个占空比,从0%变为100%,然后是0%再变为100%......

    正是您尝试执行的操作、但不会阻塞。 如果您有创意、则可以使用一个计时器+两个输出比较通道来完成此操作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Pathfinder、
    问题在于:
    对于未注释的代码、您永远不会从计时器中断中从 LPM0唤醒、因此您永远不会访问 UART 代码。 如果是注释代码,则会进入 UART,但 setup_UART()会禁用中断,除发送和接收之外,似乎没有任何可重发的中断。 因此、您在禁用中断的情况下花费大量时间、从而导致 PWM 发生故障。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    金马伦
    感谢您的回答。 我知道。 是否有任何关于如何纠正我的问题的建议? 可能将 UART 代码移入 ISR?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好极了。 我还会在延迟1秒之前重新启用中断。 我怀疑这正是导致 PWM 出现大部分问题的原因。