📄 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 + -