📄 rc24g.c
字号:
PCICR |= _BV(PCIE1);
PCMSK1 |= _BV(PCINT13);
DDRB &= ~_BV(PB0); // 设置ICP1口为输入
}
void Beep_ON()
{
OCR0A = 128;
TCCR0A = _BV(COM0A1) | _BV(COM0A0) | _BV(WGM02) | _BV(WGM00);
TCCR0B = _BV(CS01);
}
void Beep_OFF()
{
TCCR0A = 0x00;
TCCR0B = 0x00;
PORTD &= ~_BV(PD6);
}
//-----------------------------------------------------------------------------
// 解码时标
//
// XTAL = 8,000,000 Hz (timer input frequency), prescaler = 8
// ppmLength (uS) = Timer / TCNT_CYCLES, where TCNT_CYCLES=8
//
// Timer = 20000 uS (PPM帧长度)
// 3000 uS (同步信号长度)
// 700 uS (通道最小值脉宽长度)
// 1500 uS (通道中值脉宽长度)
// 2200 uS (通道最大值脉宽长度)
//-----------------------------------------------------------------------------
//
// 初始化PPM解码
//
void inDecoderInit(void)
{
TCCR1A = 0; // 16位计数器1,为主频的1分频
TCCR1B = _BV(ICES1) | _BV(CS11); // 普通计数模式, 上升沿触发
TCCR1C = 0;
TIFR1 |= _BV(ICF1); // 重置捕获中断标志
TIMSK1 |= _BV(ICIE1); // 使能捕获中断
}
//
// 停止PPM解码中断
//
void inDecoderStop(void)
{
TIMSK1 &= ~_BV(ICIE1); // 关闭捕获中断
TIFR1 |= _BV(ICF1); // 重置捕获中断标志
}
//
// 边沿信号捕获中断
//
SIGNAL(SIG_INPUT_CAPTURE1)
{
static uint16_t ppmData[MAX_CHANNELS]; // 临时通道数据缓冲
static unsigned char ppmChannel; // PPM通道计数
static uint16_t timerLast; // 最近捕获的定时器值
uint16_t timer; // 当前捕获的定时器值
uint16_t timerDiff; // 上述两者之差
uint16_t ppmLength; // 以uS为单位表示的PPM脉冲长度值
unsigned char i;
// 计算脉冲长度
timer = ICR1;
timerDiff = timer - timerLast;
timerLast = timer;
ppmLength = timerDiff;
// 如果发现同步信号则开始处理整个PPM信号帧,
// 否则简单地把通道信号长度保存到临时缓冲中
if (ppmLength < 6000)
{
// 捕获到下一个通道信号
if (ppmChannel < MAX_CHANNELS) ppmData[ppmChannel] = ppmLength;
ppmChannel++;
}
else
{
// 帧结束
// 将临时通道数据缓冲的值拷贝出来
if (ppmChannel)
{
// 只关心到设定的最大通道值
if (ppmChannel > MAX_CHANNELS) ppmChannel = MAX_CHANNELS;
// 拷贝每个通道值
for (i = 0; i < ppmChannel; i++)
{
// 关中断保证操作的原子性
cli();
channelData[i] = ppmData[i];
sei();
}
// 设置新数据标志为非零值 (数值=实际通道数)
newDataFound = ppmChannel;
// 准备解码下一个PPM帧
ppmChannel = 0;
}
}
}
SIGNAL(SIG_PIN_CHANGE1)
{
if (isSetting == SETTING) {
if ((PINC & _BV(PC5)) == 0) {
isSetting = SAVESETTING;
}
}
}
int main()
{
uint8_t c, pc, crc;
uint32_t tmp;
// 关闭看门狗
wdt_disable();
cli();
// 关闭模拟比较器
ACSR |= _BV(ACD);
// IO口初始化
IO_Init();
// 重置新数据标志
newDataFound = 0;
isSetting = 0;
// 初始化解码过程
inDecoderInit();
// 等待电源稳定,再进行E2PROM操作
for (c = 0; c < 10; c++)
_delay_ms(10);
// 读设置值
for (c = 0; c < MAX_CHANNELS; c++){
eeprom_busy_wait();
Min[c] = eeprom_read_word((uint16_t*)(2*c));
eeprom_busy_wait();
Max[c] = eeprom_read_word((uint16_t*)(2*c + 2*MAX_CHANNELS));
}
eeprom_busy_wait();
crc = eeprom_read_byte((uint8_t*)(4*MAX_CHANNELS));
if (crc != crc8_ibutton((uint8_t *)Min, MAX_CHANNELS)) {
isSetting = SETTING;
} else {
eeprom_busy_wait();
crc = eeprom_read_byte((uint8_t*)(4*MAX_CHANNELS + 1));
if (crc != crc8_ibutton((uint8_t *)Max, MAX_CHANNELS)) {
isSetting = SETTING;
}
}
if (((PINC & _BV(PC5)) == 0) || (isSetting == SETTING)) {
// 提示音,进入设置状态
for (c = 0; c < 3; c++) {
Beep_ON();
_delay_ms(16);
_delay_ms(16);
Beep_OFF();
for (pc = 0; pc < 24; pc ++) {
_delay_ms(16);
_delay_ms(16);
}
}
isSetting = SETTING;
for (c = 0; c < MAX_CHANNELS; c++) {
Min[c] = 0xFFFF;
Max[c] = 0x0000;
}
}
// CC2500模块初始化
SPI_Master_Init();
CC2500_Init();
sei();
// 等待PPM信号发生电路开始工作
while (newDataFound == 0);
// 重置新数据标志
newDataFound = 0;
if (isSetting == 0) {
// 提示音,设备开始工作
Beep_ON();
_delay_ms(16);
_delay_ms(16);
Beep_OFF();
// 设定开门狗周期为30mS
wdt_enable(WDTO_30MS);
}
sei();
pc = 0;
while(1){
wdt_reset(); // 喂狗
while (newDataFound == 0);
newDataFound = 0; // 重置新数据标志
if (isSetting == SETTING) {
for (c = 0; c < MAX_CHANNELS; c++) {
if (channelData[c] > Max[c])
Max[c] = channelData[c];
if (channelData[c] < Min[c])
Min[c] = channelData[c];
}
} else if (isSetting == SAVESETTING) {
isSetting = 0;
for (c = 0; c < MAX_CHANNELS; c++) {
eeprom_busy_wait();
eeprom_write_word((uint16_t*)(2*c), Min[c]);
Max[c] = Max[c] - Min[c];
eeprom_busy_wait();
eeprom_write_word((uint16_t*)(2*c + 2*MAX_CHANNELS), Max[c]);
}
// 写入crc校验字节, 先写Min数组crc字节,后写Max数组crc字节
crc = crc8_ibutton((uint8_t *)Min, MAX_CHANNELS);
eeprom_busy_wait();
eeprom_write_byte((uint8_t*)(4*MAX_CHANNELS), crc);
crc = crc8_ibutton((uint8_t *)Max, MAX_CHANNELS);
eeprom_busy_wait();
eeprom_write_byte((uint8_t*)(4*MAX_CHANNELS + 1), crc);
// 设定开门狗周期为30mS
wdt_enable(WDTO_30MS);
} else {
// 处理数据,将四通道数据,每通道10位数据组成一个数据帧
// 数据帧,CRC8检验码
// 数据帧处理
package[MAX_CHANNELS] = 0;
for (c = 0; c < MAX_CHANNELS; c++) {
if (channelData[c] < Min[c]) {
Max[c] = Max[c] + Min[c] - channelData[c];
Min[c] = channelData[c];
tmp = 0;
} else if (channelData[c] > (Min[c] + Max[c])) {
Max[c] = channelData[c] - Min[c];
tmp = 1023;
} else {
tmp = (uint32_t)(channelData[c] - Min[c]) * 1023;
tmp = tmp / Max[c];
}
package[c] = tmp >> 2;
package[MAX_CHANNELS] += (tmp & 0x0003) << (2*c);
}
// 数据累计记数器
package[PACKAGE_LEN - 1] = pc;
// 发送数据包,3次
halRfSendPacket((uint8_t *) package, PACKAGE_LEN);
_delay_ms(3);
halRfSendPacket((uint8_t *) package, PACKAGE_LEN);
_delay_ms(3);
halRfSendPacket((uint8_t *) package, PACKAGE_LEN);
// 数据包累计记数器
if (pc < 255)
pc ++;
else
pc = 0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -