⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 str30.c

📁 实现无线端机(msp430和STR30组合使用)通信
💻 C
字号:
//*********************************************************************************************
//  149+STR-30点对点通信测试
//
//  硬件说明: STR-30的SLEEP功能打开.
//
//  程序说明: MASTER的TimerA隔1秒中断一次, 通过STR-30发送一次'M'(波特率9.6Kbps), 并操作D4闪动.
//            MASTER在平时进入LPM0休眠状态. 同时UART1的接收中断功能打开, 当接收到SLAVE发来的'S'
//            就操作D5闪动.
//            SLAVE平时处于LPM0休眠状态, UART1的接收中断打开, 如果收到M发来的'M', 就发送'S'
//            给M, 并操作D5闪动.
//
//  测试操作: 打开MASTER的电源, 红灯D3亮, D4隔1秒闪动一次表示正在发送'M', 亮了发送一个, 灭了
//            又发送一个. 如果, 绿灯D5闪动, 表示接收到了SLAVE发来的'S'信息, 表示通信链路互通.
 //           打开SLAVE的电源, 红灯D3亮, 如果绿灯D5闪动, 表示接收到了M发来的'M', 表示链路互通.
//
//  测试结果: 见"149+STR-30点对点通信测试结果"文档.
//
//  Wu Wenquan
//  June 2007
//  Built with IAR Embedded Workbench Version: 3.42A
//*********************************************************************************************

#define MASTER
//#define SLAVE

//#define STEP_DEBUG

#include  <msp430x14x.h>

void CLKInit(void);

void UART1Init(void); // to STR-30, TTL
void UART1TransOneByte(unsigned char c);

void InitLed(void);                   //LED相关内容
void OpenD3(void);
void OpenD4(void);
void OpenD5(void);
void OpenD6(void);
void CloseD3(void);
void CloseD4(void);
void CloseD5(void);
void CloseD6(void);

void InitSTR30(void);                     //初始化STR30
void OpenSTR30(void);                    //打开STR30             
void CloseSTR30(void);                   //关闭STR30    
void ResetSTR30(void);                  //从置STR30  

//----------------------------------------------------------------------------------------
#ifdef MASTER

void main(void)
{
  
  WDTCTL = WDTPW + WDTHOLD; // Stop WDT
  CLKInit();
  InitLed();
  OpenD3();
  UART1Init();
  
  InitSTR30();
  OpenSTR30();
  
#ifdef STEP_DEBUG
// 以下程序单步调试执行
  int i;
  for(i=10;i>0;i--)
  {
    UART1TransOneByte('M');
  }
  
  CloseSTR30();
  for(i=10;i>0;i--)
  {
    UART1TransOneByte('M');
  }
  
  OpenSTR30();
  for(i=10;i>0;i--)
  {
    UART1TransOneByte('M');
  }
#endif//对应#ifdef STEP_DEBUG

  CCTL0 = CCIE; // CCR0 interrupt enabled
                // 打开TA(TimerA)的中断
                // CCTL0即TACCTL0, CCIE置位(置1)
  CCR0 = 32768; // CCR0即TACCR0, timeSet的值装入TACCR0
                // 由于TA的CLK为ACLK, 为时钟晶体, 所以, 给CCR0赋值32768, TA的中断周期是1秒
  TACTL = TASSEL_1 + MC_1;  // 设置TA的时钟为ACLK, upmode
  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
}

// UART1 RX ISR
// 当M接收到S发来的'S', 触发该中断服务程序, 操作绿灯亮或灭
#pragma vector=UART1RX_VECTOR
__interrupt void usart1_rx (void)
{
  if (RXBUF1 == 'S')   // S发来的'S' received?
  {
    P1OUT ^= 0x40;  // Toggle P1.6, 绿灯D5
  }
}

// TimerA ISR
// 通过UART1往STR发送'M'
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
  P1OUT ^= 0x80; // Toggle P1.7, 绿灯D4
  UART1TransOneByte('M');
}

#endif  // to #ifdef MASTER//这些条件编译的对应结束是在程序执行之前已经定义了#define MASTER。如果是#define SLAVE,则这些都没有影响的
//------------------------------------------------------------------------------


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#ifdef SLAVE//这是和上面的#ifdef MASTER形成条件编译的程序(说白了就是在MASTER中嵌套定义了一个条件编译)

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop WDT
  CLKInit();
  InitLed();
  OpenD3();
  UART1Init();
  
  InitSTR30();
  OpenSTR30();
  
  _BIS_SR(LPM0_bits + GIE);   // Enter LPM0 w/ interrupt
}

// UART1 RX ISR
// 当接收到Master发来的'M', 操作绿灯亮或灭, 并发送'S'给Master
#pragma vector=UART1RX_VECTOR
__interrupt void usart1_rx (void)
{
  if (RXBUF1 == 'M')   // 'M' received?
  {
    P1OUT ^= 0x40;  // Toggle P1.6, 绿灯D5
    TXBUF1 = 'S';
  }
}
#endif  // to #ifdef SLAVE//对应#ifdef SLAVE//这些一一对应的关系不能够搞错
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


void CLKInit(void)//需要十分清楚和十分关键的步骤
{
  unsigned int i;
    BCSCTL1 &= ~(XT2OFF+XTS);  // BCSCTL1寄存器的XT2OFF位置0,XT2 is on
                             // XTS位置0,LFXT1(即XT1)选择为低频模式,
                             // 说明XT1连接的是低频的晶体,32768Hz
                             // ACLK的时钟源只能是XT1, BCSCTL1的DIVAx位设置ACLK的分频
                             // 默认为00, 不分频
  do
  {
    IFG1 &= ~OFIFG; // IFG1寄存器的OFIFG位置0,Clear Oscillator fault interrupt flag
    for (i = 0xFF; i > 0; i--); // Time for flag to set
  }while ((IFG1 & OFIFG) != 0); // flag still set
	
  BCSCTL2 |= SELM1+SELS;  // SELM1位置1,MCLK选择为XT2,如果XT2不工作,则MCLK选XT1
                          // MSN-I的XT2接的是4MHz的晶体
                          // SELS位置1,SMCLK选择为XT2,如果XT2不工作,则SMCLK选XT1	
}

void InitLed(void)//LED的初始化
{
  P1SEL &= ~(BIT2+BIT3+BIT6+BIT7);	// 置0,P1.2,3,6,7设置为IO模式
  P1DIR |= BIT2+BIT3+BIT6+BIT7;  // 置1,P1.2,3,6,7设置为output
  P1OUT &= ~(BIT2+BIT3+BIT6+BIT7);  // P1.2,3,6,7输出低电平,初始化D3,4,5,6为关闭状态
}

void OpenD3(void)//对应LED3的操作
{
  P1OUT |= BIT2;  // P1.2输出高电平
}

void CloseD3(void)
{
  P1OUT &= ~BIT2; // P1.2输出低电平
}

void OpenD4(void)
{
  P1OUT |= BIT7;  // P1.7输出高电平
}

void CloseD4(void)
{
  P1OUT &= ~BIT7; // P1.7输出低电平
}

void OpenD5(void)
{
  P1OUT |= BIT6;  // P1.6输出高电平
}

void CloseD5(void)
{
  P1OUT &= ~BIT6; // P1.6输出低电平
}

void OpenD6(void)
{
  P1OUT |= BIT3;  // P1.3输出高电平
}

void CloseD6(void)
{
  P1OUT &= ~BIT3; // P1.3输出低电平
}

void UART1Init(void)
// UART1是与RF模块通信的串口,直接TTL电平连接
{
  UCTL1 &= ~SWRST; // SWRST为0x01,UCTL1的LSB位置0,Software reset Disabled
  UTCTL1 |= SSEL1+SSEL0;  // UTCTL1寄存器的SSEL0位和SSEL1位置1,BRCLK(波特率源CLK)选择为SMCLK
  UCTL1=0x10; // 0x10=0b00010000
              // parity disabled,no parity
              // one stop bit
              // 8-bit data
              // UART mode

  // 以下三项设置决定波特率为9600bps,波特率输入频率为4MHz,由MSP430波特率计算工具得到//十分清楚了
  UBR01=0xA0;
  UBR11=0x01;
  UMCTL1=0xC0;
       
  ME2 |= UTXE1+URXE1; // Enable UART1 TXD and RXD, 注意这里为ME2而不是ME1!//值得注意的地方,因为这是利用了USART1模式,
  IE2 |= URXIE1;  // Enable UART1 RXD Interrupt, 注意这里为ME2而不是ME1!
  
  P3SEL |= BIT6+BIT7; // 寄存器P3SEL的BIT6和BIT7置1,P3.6和P3.7选择为UART模式
  P3DIR |= BIT6;  // 设置P3.6(UTXD1)为output
  P3DIR &= ~BIT7; // 设置P3.7(URXD1)为input	
}

void UART1TransOneByte(unsigned char c)//发送指定的一个字节
{
  TXBUF1 = c;
  while((UTCTL1 & 0x01)==0);  // 判断Transmitter empty flag如果为0表示正在发送,则等待直到发送完毕
}

void InitSTR30()
//  初始化STR-30的信道, ABC设置均为0
//P2.0--STR30_JP2_C
//P2.1--STR30_JP2_B
//P2.5--STR30_JP2_A
{
  P2SEL &= ~(BIT0+BIT1+BIT5);
  P2DIR |= BIT0+BIT1+BIT5;
  P2OUT &= ~(BIT0+BIT1+BIT5); // P2.0,1,2输出低电平
}

void OpenSTR30()//选择引脚用作外部模块,选择方向和输出电平
{
  P4SEL &= ~BIT0;//用作一般的I/O口
  P4DIR |= BIT0;
  P4OUT &= ~BIT0; // P4.0输出低电平
}

void CloseSTR30()
{
  P4SEL &= ~BIT0;
  P4DIR |= BIT0;
  P4OUT |= BIT0;  // P4.0输出高电平
}

void ResetSTR30(void)
{
  unsigned int i;
  P4SEL &= ~BIT1;
  P4DIR |= BIT1;
  P4OUT &= ~BIT1; // RST高电平有效, 这里拉低电平进行复位
  for(i=25000;i>0;i--); // 一个for循环5个指令周期, MCLK=4MHz, 一个指令周期0.25us, 25000个循环,延时约31.25ms.
  P4OUT |= BIT1;  // 输出高电平, 恢复到正常工作状态
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -