|
这阵子闲着没事,正好手中有个FC手柄,便想着玩玩,控制什么的。。。
第一步:找资料
百度搜下“FC手柄原理”,资料不是很多,但有个贴吧里讲得挺全的“http://tieba.baidu.com/p/1389586189”,果断学了下
FC的内部电路有5根线,分别为GND、Latch、CLK、Data、Vcc,5v供电,至于对应哪根线就不好说了(至少我的手柄情况是这样),我按照上面的颜色定义接好线,然后通电,发现芯片好烫。。。仔细检查,发现电路板上的“GND”(我猜的,因为对应电路板各个按键的一极,类似单片机的独立按键。。。)与我查的原理图上的地不对应,而“VCC”(也是猜的,一是线宽,二是靠GND最远)居然是接原理图上的GND,所以赶紧把引线改了回来。。。然后就不烫了。。。所以,要改装一个FC手柄的话,一定要仔细观察电路板的接线顺序,不要全信资料上说的。。。
至于FC的通信协议,很简单,跟读一个芯片内部寄存器数据差不多,先通过Latch给一个脉冲,资料说1-10us,我给的是3us;然后芯片就会将当前手柄按键值记录并锁存,其数据值在CLK的下降沿,通过Data依次传出来,总共8位也就一字节,传输时低位在前。8位数据对应手柄上“上”“下”“左”“右”“选择”“开始”“A”“B”,至于连发A和B,虽然没数据位对应,其实断断续续的发送A或B信号。。。所以,不按任何键时,收到的数据是0xff,全按下就是0x00,按下“上”键就是0x10。。。依次类推。。。
第二步就是写程序了
在这之前首先就是因为线序的不确定,到底哪根线对应Latch、CLK和Data,有点纠结。。。但也好办,程序写好后,枚举法,123、132、213、231、312、321,三根线,最多也就6次嘛。。。
用MDK,MCU是stm32f103rc,其实51也行。。。
用到了三个GPIO口,两个输出(Latch(初始状态低电平)、CLK(初始状态高电平)),一个输入(Data(初始状态低电平))。。。由于是必须时刻知道按键值,所以需不停地读取手柄芯片寄存器,为此开了个定时器,1ms中断一次,然后给Latch脉冲,给CLK下降沿,数据位移位,读取Data值,循环8次。。。便获得了一个按键值。。。
为了方便观察有没有获得手柄按键值,开了8个GPIO口,对应LED,在中断里,得到一个FC_Data便直接显示出来。。。
void TIM2_IRQHandler(void)//定时器2中断服务函数
{
uint8_t counter;
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检测定时器2中断
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志
FC_LATCH_H(); //给Latch高电平,
delay_us(3); //3us的脉冲
FC_LATCH_L(); //拉低Latch
for(counter=0;counter<8;counter++) //循环8次
{
FC_CLK_L(); //CLK下降沿
FC_Data>>=1; //数据位右移
if(FC_DATA_H) //判断Data是否为高电平
FC_Data|=0x80; //数据位置1 如果Data为低电平就不管
FC_CLK_H(); //拉高CLK
delay_us(1); //延时1us
}
}
GPIO_Write(GPIOC,FC_Data); //显示当前按键值
}
其中FC_Data为全局变量,在main里面想怎么用就怎么用了。。。
第三步,就是控制舵机
由于网上买一个两自由度的云台舵机要近100大洋,搞不起,就直接拿了两个10多块的SG90舵机,拼成了可以上下左右转动各180°的平台(跟云台差不多吧),放一个5V激光头,用A键控制亮灭。。。感觉还不错。。。
至程序控制,先配置两路PWM波,频率50Hz,然后再在主函数里面根据按键值改变PWM的TIMx->CCRx值就可以控制舵机转角了。。。
int main(void)
{
uint16_t Motor_Pulse1=1200,Motor_Pulse2=1200;
delay_init(72);
LED_Configuration(); //配置LED
Laser_Configuration(); //配置激光头
FC_Init(); //FC手柄初始化
servomotor_Configuration(); //舵机配置
while (1)
{
if(FC_Data&0x10) //FC“上”键检测
{
Motor_Pulse1+=1;
delay_ms(1);
if(Motor_Pulse1>=2500)
Motor_Pulse1=2500;
}
if(FC_Data&0x20) //FC“下”键检测
{
Motor_Pulse1-=1;
delay_ms(1);
if(Motor_Pulse1<=500)
Motor_Pulse1=500;
}
if(FC_Data&0x80) //FC“左”键检测
{
Motor_Pulse2+=1;
delay_ms(1);
if(Motor_Pulse2>=2500)
Motor_Pulse2=2500;
}
if(FC_Data&0x40) //FC“右”键检测
{
Motor_Pulse2-=1;
delay_ms(1);
if(Motor_Pulse2<=500)
Motor_Pulse2=500;
}
if(FC_Data&0x02)
Laser_OFF();
else
Laser_ON();
TIM5->CCR1 = Motor_Pulse1;
TIM5->CCR2 = Motor_Pulse2;
}
}
至此,具体内容都讲完了。。。
附图几张。。。有问题的可以回帖。。。{:soso_e113:}
|
-
FC手柄接口 串口母口
-
舵机1
-
舵机与接口
-
实际控制
-
舵机2
-
整体效果
|