493 lines
15 KiB
C
493 lines
15 KiB
C
// Haybin_Wu
|
||
// Shenitech-RD
|
||
// 2016.5
|
||
// Built with IAR Embedded Workbench v6.2
|
||
//******************************************************************************
|
||
// Modify by Qian Xianghong
|
||
// 2020.10
|
||
// 修改日志:将无线模块做成串口和RF双向透传模式。
|
||
//******************************************************************************
|
||
#include <msp430FR2433.h>
|
||
#include <stdint.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include "FR2433-RFSX.h"
|
||
#include "RF_SX1276.h"
|
||
|
||
// 射频配置参数
|
||
lora_param_t Lora_Param;
|
||
|
||
#define TRAN_BUF_SIZE (1024)
|
||
|
||
// 用UA1串口做打印输出,方便调试
|
||
char printBuf[200];
|
||
void uart_print()
|
||
{
|
||
#if 0 // 打印串口的2个引脚用作MD0、MD1模式选择
|
||
char *p = printBuf;
|
||
while(*p)
|
||
{
|
||
if(*p == '\n') // 换行前添加回车
|
||
{
|
||
while(!(UCA1IFG & UCTXIFG));
|
||
UCA1TXBUF = '\r';
|
||
}
|
||
while(!(UCA1IFG & UCTXIFG));
|
||
UCA1TXBUF = *p++;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
// 可变参数的宏定义
|
||
#define PRINTF(format, ...) \
|
||
{ \
|
||
snprintf(printBuf, sizeof(printBuf), format, ##__VA_ARGS__); \
|
||
uart_print(); \
|
||
}
|
||
|
||
// UA0接收上位机数据的buf
|
||
uint8_t UA0_RxBuf[TRAN_BUF_SIZE] = {0};
|
||
uint16_t UA0_RxBuf_Length = 0;
|
||
uint16_t UA0_RxBuf_offset = 0;
|
||
// UA0接收超时
|
||
volatile uint8_t UA0_Rx_Timeout = 1;
|
||
|
||
// RF接收数据的buf
|
||
uint8_t RF_RxBuf[TRAN_BUF_SIZE] = {0};
|
||
uint16_t RF_RxBuf_Length = 0;
|
||
uint16_t RF_RxBuf_offset = 0;
|
||
// RF接收超时标志
|
||
volatile uint8_t RF_Rx_Timeout = 1;
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// 主串口初始化
|
||
void UA0_Init(uint32_t baudrate)
|
||
{
|
||
// Configure UART
|
||
UCA0CTLW0 |=(UCSSEL__SMCLK+UCSWRST);//UCPEN+UCPAR+
|
||
// Baud Rate calculation
|
||
if(baudrate == 115200)
|
||
{
|
||
UCA0BR0 = 4; // 8000000/16/115200//这位大于16 UCOS16位要置位
|
||
UCA0BR1 = 0; // Fractional portion = 0.44444
|
||
UCA0MCTLW = 0x5500 | UCOS16 | UCBRF_5;//微调Baud Rate
|
||
}
|
||
else if(baudrate == 38400)
|
||
{
|
||
UCA0BR0 = 13; // 8000000/16/38400 /这位大于16 UCOS16位要置位
|
||
UCA0BR1 = 0; // Fractional portion = 0.33333
|
||
UCA0MCTLW = 0x8400 | UCOS16 | UCBRF_0;//微调Baud Rate
|
||
}
|
||
else
|
||
{
|
||
UCA0BR0 = 52; // 8000000/16/9600 /这位大于16 UCOS16位要置位
|
||
UCA0BR1 = 0; // Fractional portion = 0.33333
|
||
UCA0MCTLW = 0x4900 | UCOS16 | UCBRF_1;//微调Baud Rate
|
||
}
|
||
UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI
|
||
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
|
||
}
|
||
|
||
// 主串口应答(配置命令)
|
||
void UA0_Response(char *s)
|
||
{
|
||
while(*s)
|
||
{
|
||
while(!(UCA0IFG & UCTXIFG));
|
||
UCA0TXBUF = *s++;
|
||
}
|
||
// 等待发送结束
|
||
while(!(UCA0IFG & UCTXCPTIFG));
|
||
DelayMs(2);
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//主函数
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
int main(void)
|
||
{
|
||
uint8_t sendCh;
|
||
|
||
WDTCTL = (WDTPW | WDTHOLD); // Stop WDT
|
||
// Port Configuration all un-used pins to output low
|
||
P1DIR = 0xFF; P2DIR = 0xFF; P3DIR = 0xFF;
|
||
P1OUT = 0x00; P2OUT = 0x00; P3OUT = 0x00;
|
||
PM5CTL0 &= ~LOCKLPM5;//开引脚功能
|
||
|
||
// Configure DCO Clock
|
||
//外部时钟源启动
|
||
P2SEL0 |= (BIT0 | BIT1); // set XT1 pin as second function
|
||
do
|
||
{
|
||
CSCTL7 &= ~(XT1OFFG | DCOFFG); // Clear XT1 and DCO fault flag
|
||
SFRIFG1 &= ~OFIFG;
|
||
} while (SFRIFG1 & OFIFG); // Test oscillator fault flag
|
||
//上面清除标志有助于降低功耗
|
||
|
||
__bis_SR_register(SCG0); // disable FLL
|
||
CSCTL3 |= SELREF__XT1CLK; // 外部 32768hz reference source
|
||
CSCTL0 = 0; // clear DCO and MOD registers
|
||
CSCTL1 &= ~(DCORSEL_7); // Clear DCO frequency select bits first
|
||
CSCTL1 |= DCORSEL_3; //DCO=8Mhz
|
||
CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz
|
||
__delay_cycles(3);
|
||
__bic_SR_register(SCG0); // enable FLL
|
||
while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
|
||
|
||
CSCTL4 = SELREF__XT1CLK + SELMS__DCOCLKDIV;// set XT1CLK(32768Hz) as ACLK source & MCLK/SMCLK=DCO
|
||
|
||
//Timer0_A0 setup
|
||
TA0CCTL0 = CCIE; // TACCR0 interrupt enabled
|
||
TA0CCR0 = 32768 / 32; // 串口接收超时: 1000/32=31.25ms
|
||
TA0CTL = MC__STOP | TACLR; // Stop mode, Clear counter
|
||
|
||
//Timer1_A0 setup
|
||
TA1CCTL0 = CCIE; // TACCR0 interrupt enabled
|
||
TA1CCR0 = 32768 / 4; // RF接收超时: 1000/4=250ms
|
||
TA1CTL = MC__STOP | TACLR; // Stop mode, Clear counter
|
||
|
||
// 设置无线模块缺省参数
|
||
Lora_Param.sof = 0xC2;
|
||
Lora_Param.addr = 0xADF2; // 通信地址0xADF2
|
||
Lora_Param.sf = 6; // sf=12
|
||
Lora_Param.baud = 3; // 9600
|
||
Lora_Param.cr = 0; // cr=4/5
|
||
Lora_Param.ch = 9; // 479MHz
|
||
Lora_Param.power = 1; // 17dBm
|
||
Lora_Param.freqcast = 0; // freqcast off
|
||
Lora_Param.bw = 9; // 500kHz
|
||
Lora_Param.unicast = 0; // unicast off
|
||
|
||
// Configure UART pins
|
||
P1SEL1 &= ~(BIT4 | BIT5); // set 2-UART pin as second function
|
||
P1SEL0 |= (BIT4 | BIT5); // set 2-UART pin as second function
|
||
if(Lora_Param.baud == 7)
|
||
UA0_Init(115200);
|
||
else if(Lora_Param.baud == 5)
|
||
UA0_Init(38400);
|
||
else
|
||
UA0_Init(9600);
|
||
|
||
#if 0 // 配置打印串口
|
||
// Configure UART pins
|
||
P2SEL1 &= ~(BIT5 | BIT6); // set 2-UART pin as second function
|
||
P2SEL0 |= (BIT5 | BIT6); // set 2-UART pin as second function
|
||
// Configure UART
|
||
UCA1CTLW0 |=(UCSSEL__SMCLK+UCSWRST);//UCPEN+UCPAR+
|
||
// Baud Rate calculation
|
||
UCA1BR0 = 4; // 8000000/16/115200//这位大于16 UCOS16位要置位
|
||
UCA1BR1 = 0; // Fractional portion = 0.44444
|
||
UCA1MCTLW = 0x5500 | UCOS16 | UCBRF_5;//微调Baud Rate
|
||
UCA1CTLW0 &= ~UCSWRST; // Initialize eUSCI
|
||
UCA1IE |= UCRXIE; // Enable USCI_A0 RX interrupt
|
||
|
||
// 打印复位原因(电源引起,不包括看门狗)
|
||
PRINTF("\nModule reseted: %04X\n", PMMIFG);
|
||
|
||
#else // 配置MD0、MD1模式
|
||
P2SEL1 &= ~(BIT3 | BIT5 | BIT6); // set 2-UART pin as GPIO
|
||
P2SEL0 &= ~(BIT3 | BIT5 | BIT6); // set 2-UART pin as GPIO
|
||
P2DIR &= ~(BIT5 | BIT6); // Input
|
||
P2REN |= (BIT5 | BIT6); // enable pull
|
||
P2OUT &= ~(BIT5 | BIT6); // pull-down
|
||
|
||
P2DIR |= BIT3; // Output
|
||
P2OUT |= BIT3; // Output high
|
||
#endif
|
||
|
||
_EINT();
|
||
|
||
#if 0
|
||
// 打印复位原因(电源引起,不包括看门狗)
|
||
RF_RxBuf[0] = PMMIFG >> 8;
|
||
RF_RxBuf[1] = PMMIFG & 0xFF;
|
||
RF_RxBuf_Length = 2;
|
||
RF_RxBuf_offset = 0;
|
||
UCA0IE |= UCTXIE;
|
||
while(UCA0IE & UCTXIE);
|
||
#endif
|
||
// 读寄存器,清除复位原因
|
||
SYSRSTIV;
|
||
|
||
//无线模块初始化
|
||
uint8_t try_count = 3; //最多初始化3次
|
||
while(try_count)
|
||
{
|
||
if(SX127x_initLora(&Lora_Param) == NORMAL)
|
||
break;
|
||
try_count--;
|
||
}
|
||
if(try_count == 0) //无线初始化失败处理
|
||
{
|
||
//P3OUT ^= 0xC0;
|
||
LPM4;
|
||
}
|
||
|
||
// 初始处于接收模式
|
||
LSD_RF_RXmode(RF_PAYLOAD_LEN);
|
||
// 默认发送信道
|
||
sendCh = Lora_Param.ch;
|
||
|
||
// 开启看门狗: 超时时间为2^27/SMCLK,在8000000主频下约为16s
|
||
WDTCTL = (WDTPW | WDTCNTCL | WDTIS_1);
|
||
|
||
while(1)
|
||
{
|
||
#if 1
|
||
// TODO: 喂狗
|
||
WDTCTL = (WDTPW | WDTCNTCL | WDTIS_1);
|
||
|
||
// 配置模式
|
||
if((P2IN & (BIT5 | BIT6)) == (BIT5 | BIT6))
|
||
{
|
||
if(UA0_RxBuf_Length - UA0_RxBuf_offset >= sizeof(Lora_Param))
|
||
{
|
||
if(UA0_RxBuf[UA0_RxBuf_offset] == 0xC2)
|
||
{
|
||
// 保存参数
|
||
memmove(&Lora_Param, UA0_RxBuf + UA0_RxBuf_offset, sizeof(Lora_Param));
|
||
// 颠倒地址高低字节
|
||
Lora_Param.addr = (Lora_Param.addr << 8) | (Lora_Param.addr >> 8);
|
||
|
||
//无线模块初始化
|
||
uint8_t try_count = 3; //最多初始化3次
|
||
while(try_count)
|
||
{
|
||
// 其它参数有变化,无线模块初始化
|
||
if(SX127x_initLora(&Lora_Param) == NORMAL)
|
||
break;
|
||
try_count--;
|
||
}
|
||
if(try_count == 0) //无线初始化失败处理
|
||
{
|
||
//P3OUT ^= 0xC0;
|
||
LPM4;
|
||
}
|
||
|
||
// 默认处于接收模式
|
||
LSD_RF_RXmode(RF_PAYLOAD_LEN);
|
||
// 默认发送信道
|
||
sendCh = Lora_Param.ch;
|
||
// 应答配置命令
|
||
UA0_Response("OK\r\n");
|
||
|
||
// 改变串口波特率
|
||
if(Lora_Param.baud == 7)
|
||
UA0_Init(115200);
|
||
else if(Lora_Param.baud == 5)
|
||
UA0_Init(38400);
|
||
else
|
||
UA0_Init(9600);
|
||
}
|
||
|
||
UA0_RxBuf_offset = UA0_RxBuf_Length;
|
||
}
|
||
}
|
||
// 透传模式
|
||
else if((P2IN & (BIT5 | BIT6)) == 0)
|
||
#endif
|
||
{
|
||
if(UA0_RxBuf_Length > UA0_RxBuf_offset)
|
||
{
|
||
// 定点传输,指定目标地址和信道发送
|
||
if(Lora_Param.unicast) // 定点发送
|
||
{
|
||
if(UA0_RxBuf_offset == 0 && UA0_RxBuf_Length > 3)
|
||
sendCh = UA0_RxBuf[2];
|
||
}
|
||
else if(Lora_Param.freqcast) // 指定信道发送
|
||
{
|
||
if(UA0_RxBuf_offset == 0 && UA0_RxBuf_Length > 1)
|
||
{
|
||
sendCh = UA0_RxBuf[0];
|
||
Lora_Param.ch= UA0_RxBuf[1];
|
||
UA0_RxBuf_offset = 2; // 不发送第1发个字节
|
||
}
|
||
}
|
||
|
||
if(UA0_RxBuf_Length - UA0_RxBuf_offset >= RF_PAYLOAD_LEN)
|
||
{
|
||
LSD_RF_FreqSet(sendCh);
|
||
LSD_RF_SendPacket(UA0_RxBuf + UA0_RxBuf_offset, RF_PAYLOAD_LEN);
|
||
UA0_RxBuf_offset += RF_PAYLOAD_LEN;
|
||
PRINTF("Send packet\n");
|
||
|
||
// 切换到接收模式
|
||
LSD_RF_FreqSet(Lora_Param.ch);
|
||
LSD_RF_RXmode(RF_PAYLOAD_LEN);
|
||
|
||
}
|
||
else if(UA0_Rx_Timeout)
|
||
{
|
||
LSD_RF_FreqSet(sendCh);
|
||
LSD_RF_SendPacket(UA0_RxBuf + UA0_RxBuf_offset, UA0_RxBuf_Length - UA0_RxBuf_offset);
|
||
UA0_RxBuf_offset = UA0_RxBuf_Length;
|
||
PRINTF("Send packet\n");
|
||
|
||
// 切换到接收模式
|
||
LSD_RF_FreqSet(Lora_Param.ch);
|
||
LSD_RF_RXmode(RF_PAYLOAD_LEN);
|
||
}
|
||
}
|
||
}
|
||
|
||
if(UA0_Rx_Timeout && UA0_RxBuf_offset == UA0_RxBuf_Length)
|
||
P2OUT |= BIT3; // Output high
|
||
}
|
||
}
|
||
|
||
// Port 1 interrupt service routine
|
||
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
|
||
#pragma vector=PORT1_VECTOR
|
||
__interrupt void Port_1(void)
|
||
#elif defined(__GNUC__)
|
||
void __attribute__ ((interrupt(PORT1_VECTOR))) Port_1 (void)
|
||
#else
|
||
#error Compiler not supported!
|
||
#endif
|
||
{
|
||
uint8_t offset = 0;
|
||
uint8_t len[1] = {0};
|
||
uint8_t buf[RF_PAYLOAD_LEN];
|
||
if(DIO0_IFG&DIO0_BIT) //数据传输中断处理
|
||
{
|
||
// 清中断
|
||
DIO0_IFG &= ~DIO0_BIT;
|
||
|
||
// 读取RF数据
|
||
LSD_RF_RxVariPacket(buf, len); //接收可变数据包,如果速率为大速率,只能用接收固定数据包长度
|
||
|
||
if(len[0] == 0)
|
||
return;
|
||
|
||
TA1CTL = MC__STOP | TACLR; // 停止定时器,复位计数器
|
||
TA1CTL = TASSEL__ACLK | MC__UP; // 重新开始计时
|
||
|
||
offset = 0;
|
||
if(RF_Rx_Timeout) // 新的一组数据到来
|
||
{
|
||
RF_Rx_Timeout = 0;
|
||
|
||
// 复位缓冲区
|
||
RF_RxBuf_Length = 0;
|
||
RF_RxBuf_offset = 0;
|
||
|
||
if(Lora_Param.unicast)
|
||
{
|
||
// 定点传输,地址和信道校验失败
|
||
if(len[0] <= 3 || buf[2] != Lora_Param.ch || ((buf[0] << 8) | buf[1]) != Lora_Param.addr)
|
||
return;
|
||
// 前3个字符丢掉
|
||
offset = 3;
|
||
len[0] -= offset;
|
||
}
|
||
}
|
||
|
||
PRINTF("Recv packet\n");
|
||
|
||
// 透传模式
|
||
if((P2IN & (BIT5 | BIT6)) == 0)
|
||
{
|
||
if(RF_RxBuf_Length + len[0] <= TRAN_BUF_SIZE)
|
||
{
|
||
memmove(RF_RxBuf + RF_RxBuf_Length, buf + offset, len[0]);
|
||
// 中断方式向串口转发
|
||
RF_RxBuf_Length += len[0];
|
||
UCA0IE |= UCTXIE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Timer0 A0 interrupt service routine
|
||
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
|
||
#pragma vector = TIMER0_A0_VECTOR
|
||
__interrupt void Timer0_A0_ISR(void)
|
||
#elif defined(__GNUC__)
|
||
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer0_A0_ISR (void)
|
||
#else
|
||
#error Compiler not supported!
|
||
#endif
|
||
{
|
||
// 停止定时器,复位计数器
|
||
TA0CTL = MC__STOP | TACLR;
|
||
// 串口接收超时
|
||
UA0_Rx_Timeout = 1;
|
||
}
|
||
|
||
// Timer1 A0 interrupt service routine
|
||
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
|
||
#pragma vector = TIMER1_A0_VECTOR
|
||
__interrupt void Timer1_A0_ISR(void)
|
||
#elif defined(__GNUC__)
|
||
void __attribute__ ((interrupt(TIMER1_A0_VECTOR))) Timer1_A0_ISR (void)
|
||
#else
|
||
#error Compiler not supported!
|
||
#endif
|
||
{
|
||
// 停止定时器,复位计数器
|
||
TA1CTL = MC__STOP | TACLR;
|
||
// RF接收超时
|
||
RF_Rx_Timeout = 1;
|
||
}
|
||
|
||
// UAR0 interrupt service routine
|
||
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
|
||
#pragma vector=USCI_A0_VECTOR
|
||
__interrupt void USCI_A0_ISR(void)
|
||
#elif defined(__GNUC__)
|
||
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
|
||
#else
|
||
#error Compiler not supported!
|
||
#endif
|
||
{
|
||
// 接收中断
|
||
if((UCA0IE & UCRXIE) && (UCA0IFG & UCRXIFG))
|
||
{
|
||
uint8_t c = UCA0RXBUF;
|
||
|
||
TA0CTL = MC__STOP | TACLR; // 停止定时器,复位计数器
|
||
TA0CTL = TASSEL__ACLK | MC__UP; // 重新开始计时
|
||
|
||
if(UA0_Rx_Timeout) // 新的一组数据到来
|
||
{
|
||
UA0_Rx_Timeout = 0;
|
||
// 复位缓冲区
|
||
UA0_RxBuf_Length = 0;
|
||
UA0_RxBuf_offset = 0;
|
||
}
|
||
|
||
if(UA0_RxBuf_Length < TRAN_BUF_SIZE)
|
||
{
|
||
#if 1
|
||
// 配置模式
|
||
if((P2IN & (BIT5 | BIT6)) == (BIT5 | BIT6))
|
||
{
|
||
// 第1个字符必须为0xC2
|
||
if(UA0_RxBuf_Length > 0 || c == 0xC2)
|
||
UA0_RxBuf[UA0_RxBuf_Length++] = c;
|
||
}
|
||
// 透传模式
|
||
else if((P2IN & (BIT5 | BIT6)) == 0)
|
||
#endif
|
||
{
|
||
// 主函数透传
|
||
UA0_RxBuf[UA0_RxBuf_Length++] = c;
|
||
}
|
||
|
||
P2OUT &= ~BIT3; // Output low
|
||
}
|
||
}
|
||
|
||
// 发送中断
|
||
if((UCA0IE & UCTXIE) && (UCA0IFG & UCTXIFG))
|
||
{
|
||
UCA0TXBUF = RF_RxBuf[RF_RxBuf_offset++]; // 发送字符
|
||
if(RF_RxBuf_offset >= RF_RxBuf_Length) // 全部发送完
|
||
{
|
||
// 禁止中断
|
||
UCA0IE &= ~UCTXIE;
|
||
}
|
||
}
|
||
}
|