ShipCentralControl/RF-AP/20201203烧录版本/RF-Module.c

492 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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];
UA0_RxBuf_offset = 1; // 不发送第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;
}
}
}