一、RFM69C
RFM69C是一款收发模块,能够工作在较宽的频率范围内,包括315,433,868和915MHz免许可证ISM(工业科学和医疗)频段。全主流射频通信参数是可编程的,大部分参数都可以动态集RFM69C提供了独特的窄带和宽频带可编程的优点RFM69C是针对低同时提供高射频输出功率和信道化操作。符合ETSI和FCC规定。
无线收发模块RFM69C基本特征:
● 最大+13dBm —发射发射功率
● 高灵敏度: -120 dBm @ 1.2 kbps
● 高灵敏度:16个FIR信道滤波器
● 抑制前端:IIP3 = -18 dBm,IIP2 = +35 dBm,80 dB阻断免疫,无镜像频率响应
● 低电流:接收状态时16 mA,寄存器保存状态下时100nA
● 可调功率范围:-18~+13dBm/1dB 步进
● 模块电压范围内射频性能稳定
● FSK速率高达300 kb/秒
● 高度集成的频率合成器,分辨率为61 Hz
● FSK, GFSK, MSK, GMSK及OOK解调
● 内置同位器,可实现Clock Recovery
● 同步字自动识别
● 115 dB+动态范围RSSI
● 超快AFC,自动射频侦测应
● 支持CRC,AES-128加密及66字节FIFO
● 内置温度传感器
● 模块尺寸:16*16mm
●模块采样SPI通信
二、TC1508S
TC1508S是一款双通道直流马达驱动器,常用于玩具电机驱动。
TC1508S基本特征:
● 双通道内置功率MOS全桥驱动
●驱动前进、后退、停止及刹车功能
● 超低的待机电流和工作电流
● 低导通电阻(1欧)
●最大连续输出电流可达1.8A/每通道,峰值2.5A
● 宽电压工作范围
● 采用SOP-16封装形式
三、程序
RFM69C头文件
#ifndef _RFM69_H_
#define _RFM69_H_
#include "gd32f10x.h"
#define RFM69_GPIO_CS_RCC RCU_GPIOD
#define RFM69_GPIO_CS_PORT GPIOD
#define RFM69_GPIO_CS_PIN GPIO_PIN_2
#define RFM69_GPIO_RESET_RCC RCU_GPIOB
#define RFM69_GPIO_RESET_PORT GPIOB
#define RFM69_GPIO_RESET_PIN GPIO_PIN_6
#define RFM69_GPIO_DIO0_RCC RCU_GPIOC
#define RFM69_GPIO_DIO0_PORT GPIOC
#define RFM69_GPIO_DIO0_PIN GPIO_PIN_12
#define RFM69_CS_L gpio_bit_reset(RFM69_GPIO_CS_PORT,RFM69_GPIO_CS_PIN)
#define RFM69_CS_H gpio_bit_set(RFM69_GPIO_CS_PORT,RFM69_GPIO_CS_PIN)
#define RFM69_RESET_L gpio_bit_reset(RFM69_GPIO_RESET_PORT,RFM69_GPIO_RESET_PIN)
#define RFM69_RESET_H gpio_bit_set(RFM69_GPIO_RESET_PORT,RFM69_GPIO_RESET_PIN)
#define RFM69_ReadDIO0Pin() gpio_input_bit_get(RFM69_GPIO_DIO0_PORT,RFM69_GPIO_DIO0_PIN)
#define RFM69_FSTEP 61.03515625 // Step width of synthesizer [Hz]
enum {
REG_FIFO = 0x00,
REG_OPMODE = 0x01,
REG_FRFMSB = 0x07,
REG_PALEVEL = 0x11,
REG_LNAVALUE = 0x18,
REG_AFCMSB = 0x1F,
REG_AFCLSB = 0x20,
REG_FEIMSB = 0x21,
REG_FEILSB = 0x22,
REG_RSSIVALUE = 0x24,
REG_IRQFLAGS1 = 0x27,
REG_IRQFLAGS2 = 0x28,
REG_SYNCVALUE1 = 0x2F,
REG_SYNCVALUE2 = 0x30,
REG_NODEADDR = 0x39,
REG_BCASTADDR = 0x3A,
REG_FIFOTHRESH = 0x3C,
REG_PKTCONFIG2 = 0x3D,
REG_AESKEYMSB = 0x3E,
REG_FRFMID = 0x08,
REG_FRFLSB = 0x09,
MODE_SLEEP = 0 << 2,
MODE_STANDBY = 1 << 2,
MODE_TRANSMIT = 3 << 2,
MODE_RECEIVE = 4 << 2,
IRQ1_MODEREADY = 1 << 7,
IRQ1_RXREADY = 1 << 6,
IRQ1_SYNADDRMATCH = 1 << 0,
IRQ2_FIFONOTEMPTY = 1 << 6,
IRQ2_PACKETSENT = 1 << 3,
IRQ2_PAYLOADREADY = 1 << 2,
};
static const uint8_t configRegs [] = {
0x02, 0x00, // 设置包模式,FSK
0x03, 0x02, // 设置比特率高位, data rate = 49,261 bits/s
0x04, 0x8A, // 设置比特率低位, divider = 32 MHz / 650
0x04, 0x8A, // BitRateLsb, divider = 32 MHz / 650
0x05, 0x02, // FdevMsb = 45 kHz
0x06, 0xE1, // FdevLsb = 45 kHz
0x0B, 0x20, // Low M
0x11, 0x99, // OutputPower = +7 dBm - was default = max = +13 dBm
0x19, 0x4A, // RxBw 100 kHz
0x1A, 0x42, // AfcBw 125 kHz
0x1E, 0x0C, // AfcAutoclearOn, AfcAutoOn
//0x25, 0x40, //0x80, // DioMapping1 = SyncAddress (Rx)
0x26, 0x07, // disable clkout
0x29, 0xA0, // RssiThresh -80 dB
0x2D, 0x05, // PreambleSize = 5
0x2E, 0x88, // SyncConfig = sync on, sync size = 2
0x2F, 0x2D, // SyncValue1 = 0x2D
0x37, 0xD0, // PacketConfig1 = variable, white, no filtering
0x38, 0x42, // PayloadLength = 0, unlimited
0x3C, 0x8F, // FifoThresh, not empty, level 15
0x3D, 0x12, // 0x10, // PacketConfig2, interpkt = 1, autorxrestart off
0x6F, 0x20, // TestDagc ...
0x71, 0x02, // RegTestAfc
0
};
extern uint8_t rssi;
void RFM69_Init(uint8_t id, uint8_t group, int freq);
void RFM69_Encrypt(const char* key);
int8_t RFM69_Receive (void* ptr,uint8_t len);
void RFM69_Send(const void* ptr,int len);
uint32_t Get_Frequency(void);
#endif
RFM69C源文件(移植的时候只需要修改对应的引脚与SPI驱动)
#include "rfm69.h"
#include "stdio.h"
#include "systick.h"
#include "bsp_spi.h"
uint8_t mode;
uint8_t myId;
uint8_t parity;
uint8_t lna; //增益系数
uint8_t afc; //自动频率控制
uint8_t rssi; //信号强度
static void RFM69_RST(void)
{
RFM69_RESET_H;
delay_ms(10);
RFM69_RESET_L;
delay_ms(10);
}
static void RFM69_GPIO_Config(void)
{
rcu_periph_clock_enable(RFM69_GPIO_CS_RCC);
rcu_periph_clock_enable(RFM69_GPIO_RESET_RCC);
rcu_periph_clock_enable(RFM69_GPIO_DIO0_RCC);
gpio_init(RFM69_GPIO_CS_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, RFM69_GPIO_CS_PIN);
gpio_init(RFM69_GPIO_RESET_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, RFM69_GPIO_RESET_PIN);
gpio_init(RFM69_GPIO_DIO0_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, RFM69_GPIO_DIO0_PIN);
spi_config();
RFM69_CS_H;
RFM69_RST();
}
static void RFM69_Select()
{
RFM69_CS_L;
}
static void RFM69_Unselect()
{
RFM69_CS_H;
}
static uint8_t readReg(uint8_t reg)
{
uint8_t regval;
RFM69_Select();
spi_read_write_byte(reg & 0x7F);
regval = spi_read_write_byte(0);
RFM69_Unselect();
return regval;
}
static void writeReg(uint8_t reg,uint8_t value)
{
RFM69_Select();
spi_read_write_byte(reg | 0x80);
spi_read_write_byte(value);
RFM69_Unselect();
}
static void RFM69_SetMode(uint8_t newMode)
{
mode = newMode;
writeReg(REG_OPMODE,(readReg(REG_OPMODE) & 0xE3) | newMode);
while((readReg(REG_IRQFLAGS1) & IRQ1_MODEREADY) == 0);
}
//315MHz 433MHz 868MHz 915MHz
static void RFM69_Set_Frequency(uint32_t hz)
{
uint32_t frf;
while(hz < 100000000)
{
hz *= 10;
}
frf = (hz << 2) / (32000000L >> 11);
writeReg(REG_FRFMSB, frf >> 10);
writeReg(REG_FRFMSB + 1, frf >> 2);
writeReg(REG_FRFMSB + 2, frf << 6);
}
static void RFM69_Configure(const uint8_t* p)
{
uint8_t cmd;
while(1)
{
cmd = p[0];
if (cmd == 0)
{
break;
}
writeReg(cmd, p[1]);
p += 2;
}
}
static void Set_Address(uint8_t addr)
{
writeReg(REG_NODEADDR, addr);
}
static void Set_Network(uint8_t networkID)
{
writeReg(REG_SYNCVALUE2, networkID);
}
static void RFM69_Tx_Power(uint8_t level)
{
writeReg(REG_PALEVEL,(readReg(REG_PALEVEL) & ~0x1F) | level);
}
static void RFM69_Sleep(void)
{
RFM69_SetMode(MODE_SLEEP);
}
uint32_t Get_Frequency(void)
{
return RFM69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16)
+ ((uint16_t) readReg(REG_FRFMID) << 8)+ readReg(REG_FRFLSB));
}
void RFM69_Init(uint8_t id, uint8_t group, int freq)
{
RFM69_GPIO_Config();
myId = id;
parity = group ^ (group << 4);
parity = (parity ^ (parity << 2)) & 0xC0;
do
{
writeReg(REG_SYNCVALUE1, 0xAA);
}while(readReg(REG_SYNCVALUE1) != 0xAA);
do
{
writeReg(REG_SYNCVALUE1, 0x55);
} while(readReg(REG_SYNCVALUE1) != 0x55);
RFM69_Configure(configRegs);
RFM69_Configure(configRegs);
RFM69_Set_Frequency(freq);
RFM69_Tx_Power(31);
Set_Address(id);
writeReg(REG_SYNCVALUE2, group);
}
//加密
void RFM69_Encrypt(const char* key)
{
uint8_t i;
uint8_t cfg;
cfg = readReg(REG_PKTCONFIG2) & ~0x01;
if(key)
{
for(i = 0;i < 16;i++)
{
writeReg(REG_AESKEYMSB + i,*key);
if(*key != 0)
{
key++;
}
}
cfg |= 0x01;
}
writeReg(REG_PKTCONFIG2,cfg);
}
int8_t RFM69_Receive(void* ptr, uint8_t len)
{
uint8_t i;
uint8_t value;
uint8_t count;
uint8_t dest;
uint8_t destId;
static uint8_t lastFlag;
if(mode != MODE_RECEIVE)
{
RFM69_SetMode(MODE_RECEIVE);
}
else
{
if((readReg(REG_IRQFLAGS1) & IRQ1_RXREADY) != lastFlag)
{
lastFlag ^= IRQ1_RXREADY;
if (lastFlag)
{
lna = (readReg(REG_LNAVALUE) >> 3) & 0x7;
afc = readReg(REG_AFCMSB) << 8;
afc |= readReg(REG_AFCLSB);
}
}
if(readReg(REG_IRQFLAGS2) & IRQ2_PAYLOADREADY)
{
rssi = readReg(REG_RSSIVALUE);
count = readReg(REG_FIFO);
for (i = 0;i < count;i++)
{
value = readReg(REG_FIFO);
if(i < len)
{
((uint8_t*) ptr)[i] = value;
}
}
dest = *(uint8_t*) ptr;
if(dest == parity)
{
destId = dest;
if(destId == myId || destId == 0 || myId == 63)
{
return count;
}
}
}
}
return -1;
}
void RFM69_Send(const void* ptr,int len)
{
uint8_t i;
RFM69_SetMode(MODE_SLEEP);
writeReg(REG_FIFO,len + 2);
writeReg(REG_FIFO,parity); //网络ID
writeReg(REG_FIFO,myId);
for(i = 0;i < len;i++)
{
writeReg(REG_FIFO,((const uint8_t*) ptr)[i]);
}
RFM69_SetMode(MODE_TRANSMIT);
while((readReg(REG_IRQFLAGS2) & IRQ2_PACKETSENT) == 0);
RFM69_SetMode(MODE_STANDBY);
}
TC1508S头文件
#ifndef _DEVICE_H_
#define _DEVICE_H_
#include "gd32f10x.h"
#define MODULE_EN_RCC RCU_GPIOC
#define MODULE_EN_PORT GPIOC
#define MODULE_EN_PIN GPIO_PIN_5
#define DC_MODE_nEN_RCC RCU_GPIOC
#define DC_MODE_nEN_PORT GPIOC
#define DC_MODE_nEN_PIN GPIO_PIN_4
#define DRIVER_EN_RCC RCU_GPIOB
#define DRIVER_EN_PORT GPIOB
#define DRIVER_EN_PIN GPIO_PIN_1
//TC1508
#define MOTOR_INA_RCC RCU_GPIOA
#define MOTOR_INA_PORT GPIOA
#define MOTOR_INA_PIN GPIO_PIN_4
#define MOTOR_INB_RCC RCU_GPIOA
#define MOTOR_INB_PORT GPIOA
#define MOTOR_INB_PIN GPIO_PIN_5
#define MOTOR_INC_RCC RCU_GPIOA
#define MOTOR_INC_PORT GPIOA
#define MOTOR_INC_PIN GPIO_PIN_6
#define MOTOR_IND_RCC RCU_GPIOA
#define MOTOR_IND_PORT GPIOA
#define MOTOR_IND_PIN GPIO_PIN_7
#define MODULE_EN_H gpio_bit_set(MODULE_EN_PORT,MODULE_EN_PIN)
#define MODULE_EN_L gpio_bit_reset(MODULE_EN_PORT,MODULE_EN_PIN)
#define DC_MODE_nEN_H gpio_bit_set(DC_MODE_nEN_PORT,DC_MODE_nEN_PIN)
#define DC_MODE_nEN_L gpio_bit_reset(DC_MODE_nEN_PORT,DC_MODE_nEN_PIN)
#define DRIVER_EN_H gpio_bit_set(DRIVER_EN_PORT,DRIVER_EN_PIN)
#define DRIVER_EN_L gpio_bit_reset(DRIVER_EN_PORT,DRIVER_EN_PIN)
#define MOTOR_INA_H {gpio_bit_set(MOTOR_INA_PORT,MOTOR_INA_PIN);}
#define MOTOR_INA_L {gpio_bit_reset(MOTOR_INA_PORT,MOTOR_INA_PIN);}
#define MOTOR_INB_H {gpio_bit_set(MOTOR_INB_PORT,MOTOR_INB_PIN);}
#define MOTOR_INB_L {gpio_bit_reset(MOTOR_INB_PORT,MOTOR_INB_PIN);}
#define MOTOR_INC_H {gpio_bit_set(MOTOR_INC_PORT,MOTOR_INC_PIN);}
#define MOTOR_INC_L {gpio_bit_reset(MOTOR_INC_PORT,MOTOR_INC_PIN);}
#define MOTOR_IND_H {gpio_bit_set(MOTOR_IND_PORT,MOTOR_IND_PIN);}
#define MOTOR_IND_L {gpio_bit_reset(MOTOR_IND_PORT,MOTOR_IND_PIN);}
//刹车
#define CAR_BRAKE \
MOTOR_INA_H\
MOTOR_INB_H\
MOTOR_INC_H\
MOTOR_IND_H
//前进
#define CAR_ADVANCE \
MOTOR_INA_H\
MOTOR_INB_L\
MOTOR_INC_H\
MOTOR_IND_H
//后退
#define CAR_RETREAT \
MOTOR_INA_L\
MOTOR_INB_H\
MOTOR_INC_H\
MOTOR_IND_H
//左转
#define CAR_LEFT_TURN \
MOTOR_INC_H\
MOTOR_IND_L\
MOTOR_INA_H\
MOTOR_INB_H
//右转
#define CAR_RIGHT_TURN \
MOTOR_INC_L\
MOTOR_IND_H\
MOTOR_INA_H\
MOTOR_INB_H
//前进左转
#define CAR_ABVANCE_AND_LEFT_TURN \
MOTOR_INA_H\
MOTOR_INB_L\
MOTOR_INC_H\
MOTOR_IND_L
//前进右转
#define CAR_ABVANCE_AND_RIGHT_TURN \
MOTOR_INA_H\
MOTOR_INB_L\
MOTOR_INC_L\
MOTOR_IND_H
//后退左转
#define CAR_RETREAT_AND_LEFT_TURN \
MOTOR_INA_L\
MOTOR_INB_H\
MOTOR_INC_H\
MOTOR_IND_L
//后退右转
#define CAR_RETREAT_AND_RIGHT_TURN \
MOTOR_INA_L\
MOTOR_INB_H\
MOTOR_INC_L\
MOTOR_IND_H
#define STOP 0x00
#define ABVANCE 0x01
#define RETREAT 0x02
#define LEFT_TURN 0x04
#define RIGHT_TURN 0x08
#define ABVANCE_AND_LEFT_TURN 0X05
#define ABVANCE_AND_RIGHT_TURN 0X09
#define RETREAT_AND_LEFT_TURN 0X06
#define RETREAT_AND_RIGHT_TURN 0x0A
void Device_Init(void);
void Set_Motor(uint8_t state);
#endif
TC1508S源文件
#include "device.h"
#include "bsp_led.h"
void Device_Init(void)
{
rcu_periph_clock_enable(MODULE_EN_RCC | DC_MODE_nEN_RCC);
rcu_periph_clock_enable(DRIVER_EN_RCC);
rcu_periph_clock_enable(MOTOR_INA_RCC | MOTOR_INB_RCC
| MOTOR_INC_RCC | MOTOR_IND_RCC);
gpio_init(DC_MODE_nEN_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, DC_MODE_nEN_PIN);
gpio_init(MODULE_EN_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, MODULE_EN_PIN);
gpio_init(DRIVER_EN_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, DRIVER_EN_PIN);
gpio_init(MOTOR_INA_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, MOTOR_INA_PIN);
gpio_init(MOTOR_INB_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, MOTOR_INB_PIN);
gpio_init(MOTOR_INC_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, MOTOR_INC_PIN);
gpio_init(MOTOR_IND_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, MOTOR_IND_PIN);
DC_MODE_nEN_L;
MODULE_EN_H;
DRIVER_EN_H;
MOTOR_INA_L;
MOTOR_INB_L;
MOTOR_INC_L;
MOTOR_IND_L;
}
void Set_Motor(uint8_t state)
{
switch(state)
{
case ABVANCE:
{
CAR_ADVANCE;
}break;
case RETREAT:
{
CAR_RETREAT;
}break;
case LEFT_TURN:
{
CAR_LEFT_TURN;
}break;
case RIGHT_TURN:
{
CAR_RIGHT_TURN;
}break;
case ABVANCE_AND_LEFT_TURN:
{
CAR_ABVANCE_AND_LEFT_TURN;
}break;
case ABVANCE_AND_RIGHT_TURN:
{
CAR_ABVANCE_AND_RIGHT_TURN;
}break;
case RETREAT_AND_LEFT_TURN:
{
CAR_RETREAT_AND_LEFT_TURN;
}break;
case RETREAT_AND_RIGHT_TURN:
{
CAR_RETREAT_AND_RIGHT_TURN;
}break;
case STOP:
default:
{
CAR_BRAKE;
DEBUG_LED_OFF;
}break;
}
}
四、总结
遥控距离有两百米左右,目前存在的问题是前进电机一工作就干扰到遥控信号的接收。
工程源码,提取码:tqa3https://pan.baidu.com/s/1dlI6vGBFRWRRc5OyH_lSCQ