2018年电子设计大赛省赛题制作方案改进,变成基于手势识别控制舵机
可用于实现开关锁之类的小活动
剪刀模拟识别开锁
石头关锁
其他功能详见代码
单片机源程序如下:
- #include "stm32f10x.h" // Device header
- #include "delay.h"
- #include "key.h"
- #include "sys.h"
- #include "usart.h"
- #include "myiic.h"
- #include "FDC2X2X_CMD.h"
- #include "FDC2214.h"
- #include "DataScope_DP.h"
- #include "OLED.h"
- #include "IMG.h"
- #include "TIM.h"
- #include "LED.h"
- #define VOLUME 1000
- //接线方式:
- //ch0:拇指
- //ch1:手掌
- //ch2:食指
- //ch3:中指
- //ch4:无名指
- //ch5:小指
- u8 STA;
- u8 pwm;
- u8 STA_num;
- u8 STA_num_1;
- #define HAND_FORMS_ONE 0x06
- #define HAND_FORMS_TWO 0x0e
- #define HAND_FORMS_THREE 0x1e
- #define HAND_FORMS_FOUR 0x3e
- #define HAND_FORMS_FIVE 0x3f
- #define HAND_FORMS_SIX 0x23
- #define HAND_FORMS_SIVEN 0x0f
- #define HAND_FORMS_EIGHT 0x07
- #define HAND_FORMS_NINE 0x03
- #define HAND_FORMS_TEN 0x02
- #define HAND_FORMS_JD 0x0e
- #define HAND_FORMS_ST 0x02
- #define HAND_FORMS_B 0x3f
- #define FINGER_PIANO_1 ((0x03) &0xfd)
- #define FINGER_PIANO_2 ((0x06) &0xfd)
- #define FINGER_PIANO_3 ((0x0a) &0xfd)
- #define FINGER_PIANO_4 ((0x12) &0xfd)
- #define FINGER_PIANO_5 ((0x22) &0xfd)
-
- //**特别注意:使用时SDA、SCL要接4.7K上拉电阻,地址线接地**//
- //**寄存器值的读取及电容的计算具体在 FDC2214_read_CHx() 中**/
- float i;//for循环专用变量
- u8 s[100];//sprintf
- void Data_BackUp()
- {
- BKP->DR1=(u32)FDC_CH0.Threshold;
- BKP->DR2=((u32)FDC_CH0.Threshold>>16);
- BKP->DR3=(u32)FDC_CH1.Threshold;
- BKP->DR4=((u32)FDC_CH1.Threshold>>16);
- BKP->DR5=(u32)FDC_CH2.Threshold;
- BKP->DR6=((u32)FDC_CH2.Threshold>>16);
- BKP->DR7=(u32)FDC_CH3.Threshold;
- BKP->DR8=((u32)FDC_CH3.Threshold>>16);
- BKP->DR9=(u32)FDC_CH4.Threshold;
- BKP->DR10=((u32)FDC_CH4.Threshold>>16);
- BKP->DR11=(u32)FDC_CH5.Threshold;
- BKP->DR12=((u32)FDC_CH5.Threshold>>16);
- }
- void Data_Load()
- {
- FDC_CH0.Threshold = (float)(BKP->DR1 | (BKP->DR2<<16) );
- FDC_CH1.Threshold = (float)(BKP->DR3 | (BKP->DR4<<16) );
- FDC_CH2.Threshold = (float)(BKP->DR5 | (BKP->DR6<<16) );
- FDC_CH3.Threshold = (float)(BKP->DR7 | (BKP->DR8<<16) );
- FDC_CH4.Threshold = (float)(BKP->DR9 | (BKP->DR10<<16) );
- FDC_CH5.Threshold = (float)(BKP->DR11| (BKP->DR12<<16) );
- }
- int main(void)
- {
- pwm=190;
- delay_init(); //延时函数初始化
- OLED_Init();
- OLED_ShowString(10,32,"Loading...");OLED_Refresh_Gram();
- NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
- uart_init(256000); //串口初始化为9600
- uart5_init(9600);
- KEY_Init();
- LED_Init();
- //开启后备寄存器
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启后备电源
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//开启后备寄存器
- PWR->CR|=0x00100;//取消后备寄存器的写保护
- FDC2214_Init();
- FDC2214_Init_2();
- // Read_REG();
- // Read_REG_2();
-
-
- TIM_1_PWM_Init(7199,0);//不分频。PWM频率=72000/(7199+1)=10Khz
- TIM2_PWM_Init(199,7199);//不分频。PWM频率=72000/(7199+1)/(199+1)=50hz
- TIM1->CCR4=0;//比较值,音量设置
- TIM1->PSC=0; //预分频系数,频率设置
- // delay_ms(10000);
- while(1)
- {
- static int timer=19;
- static u8 step=3;
- static u8 mode=0;//0:划拳//1:猜拳//2:手指琴//3:划拳(扩充)
- static u8 mode_1=5;
- static u8 key_sta;
- delay_ms(10);
-
- Date_Back(0);//刷新数据并上传给上位机
-
- switch(STA)
- {
- case HAND_FORMS_ONE : STA_num=1; break;
- case HAND_FORMS_TWO : STA_num=2; break;
- case HAND_FORMS_THREE: STA_num=3; break;
- case HAND_FORMS_FOUR : STA_num=4; break;
- case HAND_FORMS_FIVE : STA_num=5; break;
- case HAND_FORMS_SIX : STA_num=6; break;
- case HAND_FORMS_SIVEN: STA_num=7; break;
- case HAND_FORMS_EIGHT: STA_num=8; break;
- case HAND_FORMS_NINE : STA_num=9; break;
- case HAND_FORMS_TEN : STA_num=10; break;
- default : STA_num=0; break;
- }
-
- // if( (STA_num_1 != STA_num) || (mode_1 != mode) )
- // {
- while((UART5->SR&0X40)==0);//循环发送,直到发送完毕
- UART5->DR = (u8)'*';
- while((UART5->SR&0X40)==0);//循环发送,直到发送完毕
- UART5->DR = (u8) mode;
- while((UART5->SR&0X40)==0);//循环发送,直到发送完毕
- UART5->DR = (u8) STA_num;
- while((UART5->SR&0X40)==0);//循环发送,直到发送完毕
- UART5->DR = (u8) '#';
- // }
- STA_num_1=STA_num;
- mode_1=mode;
-
- switch(step)
- {
- case 0://校准Normal值
-
- if(timer<=0)//倒计时时间到
- {
- FDC_CH0.Normal=From_History_Get_Average(FDC_CH0.History,10);
- FDC_CH1.Normal=From_History_Get_Average(FDC_CH1.History,10);
- FDC_CH2.Normal=From_History_Get_Average(FDC_CH2.History,10);
- FDC_CH3.Normal=From_History_Get_Average(FDC_CH3.History,10);
- FDC_CH4.Normal=From_History_Get_Average(FDC_CH4.History,10);
- FDC_CH5.Normal=From_History_Get_Average(FDC_CH5.History,10);
- OLED_Clear();OLED_Refresh_Gram();
- step=1;timer=39;
- }
- else //倒计时未到
- {
- timer--;
- OLED_SHOW_Imag(0,0,32,32,(u8*)gImage_qing,2,0);
- OLED_SHOW_Imag(32,0,32,32,(u8*)gImage_wu,2,0);
- OLED_SHOW_Imag(64,0,32,32,(u8*)gImage_chu,2,0);
- OLED_SHOW_Imag(96,0,32,32,(u8*)gImage_peng,2,0);
- OLED_SHOW_Imag(0,32,24,24,(u8*)gImage_xun,2,0);
- OLED_SHOW_Imag(24,32,24,24,(u8*)gImage_lian,2,0);
- OLED_Refresh_Gram();
- }
- break;
- case 1://校准Put值
- if(timer<=0)//倒计时时间到
- {
- FDC_CH0.Put=From_History_Get_Average(FDC_CH0.History,10);
- FDC_CH1.Put=From_History_Get_Average(FDC_CH1.History,10);
- FDC_CH2.Put=From_History_Get_Average(FDC_CH2.History,10);
- FDC_CH3.Put=From_History_Get_Average(FDC_CH3.History,10);
- FDC_CH4.Put=From_History_Get_Average(FDC_CH4.History,10);
- FDC_CH5.Put=From_History_Get_Average(FDC_CH5.History,10);
- step=2;timer=39;
- }
- else //倒计时时间未到
- {
- timer--;
- OLED_SHOW_Imag(0,0,32,32,(u8*)gImage_fang,2,0);
- OLED_SHOW_Imag(32,0,32,32,(u8*)gImage_zhi,2,0);
- OLED_SHOW_Imag(64,0,32,32,(u8*)gImage_shou,2,0);
- OLED_SHOW_Imag(96,0,32,32,(u8*)gImage_zhang,2,0);
- sprintf((char *)s,"Counter:%d",timer/10);
- OLED_ShowString(0,32,s);
- OLED_Refresh_Gram();
- }
- break;
- case 2://计算阈值
- FDC_CH0.Threshold=(FDC_CH0.Put+FDC_CH0.Normal)/2;
- FDC_CH1.Threshold=(FDC_CH1.Put+FDC_CH1.Normal)/2;
- FDC_CH2.Threshold=(FDC_CH2.Put+FDC_CH2.Normal)/2;
- FDC_CH3.Threshold=(FDC_CH3.Put+FDC_CH3.Normal)/2;
- FDC_CH4.Threshold=(FDC_CH4.Put+FDC_CH4.Normal)/2;
- FDC_CH5.Threshold=(FDC_CH5.Put+FDC_CH5.Normal)/2;
- Data_BackUp();
- OLED_Clear();
- step=4;
- break;
- case 3://读取数据
- Data_Load();
- step=4;
- break;
- case 4://清屏
- OLED_Clear();
- step=5;
- break;
- case 5://状态解算
- FDC_CH0.STA<<=1;
- FDC_CH1.STA<<=1;
- FDC_CH2.STA<<=1;
- FDC_CH3.STA<<=1;
- FDC_CH4.STA<<=1;
- FDC_CH5.STA<<=1;
-
- if( FDC_CH0.Now < FDC_CH0.Threshold )
- FDC_CH0.STA|=0x01;
- else
- FDC_CH0.STA&=0xfe;
- if( FDC_CH1.Now < FDC_CH1.Threshold )
- FDC_CH1.STA|=0x01;
- else
- FDC_CH1.STA&=0xfe;
- if( FDC_CH2.Now < FDC_CH2.Threshold )
- FDC_CH2.STA|=0x01;
- else
- FDC_CH2.STA&=0xfe;
- if( FDC_CH3.Now < FDC_CH3.Threshold )
- FDC_CH3.STA|=0x01;
- else
- FDC_CH3.STA&=0xfe;
- if( FDC_CH4.Now < FDC_CH4.Threshold )
- FDC_CH4.STA|=0x01;
- else
- FDC_CH4.STA&=0xfe;
- if( FDC_CH5.Now < FDC_CH5.Threshold )
- FDC_CH5.STA|=0x01;
- else
- FDC_CH5.STA&=0xfe;
-
- STA = ((FDC_CH5.STA&0x01)<<5) | ((FDC_CH4.STA&0x01)<<4) | ((FDC_CH3.STA&0x01)<<3) | ((FDC_CH2.STA&0x01)<<2) | ((FDC_CH1.STA&0x01)<<1) | (FDC_CH0.STA&0x01);
-
- key_sta = KEY_Scan(0);
- if(key_sta != 0)
- OLED_Clear(),timer=19;
- if( key_sta == KEY0_PRES)//换模式
- mode=!mode;
- if( key_sta == WKUP_PRES)//换模式,附加模式
- {
- if(mode == 2)
- mode=3;
- else
- mode=2;
- }
-
- switch(mode)
- {
- case 0:step=7;break;
- case 1:step=8;break;
- case 2:step=9;break;
- case 3:step=10;break;
- }
-
- if(key_sta == KEY1_PRES)//去校准
- {
- step=0;
- timer=19;
- }
-
-
- break;
- case 7://猜拳
- if(timer>0)//倒计时时间未到
- {
- timer--;
- OLED_SHOW_Imag(60,16,16,16,(u8*)cai,2,0),OLED_SHOW_Imag(76,16,16,16,(u8*)quan,2,0);
- OLED_Refresh_Gram();
- }
- else //倒计时到
- {
- switch(STA)
- {
- case HAND_FORMS_JD:
- OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_jiandao,1,0);
- if(pwm>60)
- {
- TIM_SetCompare3(TIM2,pwm--);
- delay_ms(10);
- }
- OLED_Refresh_Gram();
- break;
- case HAND_FORMS_ST:
- OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_shitou,1,0);
- if(pwm==60|pwm<190)
- {
- // pwm=190;
- TIM_SetCompare3(TIM2,pwm++);
- delay_ms(10);}
- OLED_Refresh_Gram();
- break;
- case HAND_FORMS_B:
- OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_bu,1,0);
- // TIM_SetCompare3(TIM2,0);
- OLED_Refresh_Gram();
- break;
- default:
- OLED_Fill(30,0,94,64,0);OLED_Refresh_Gram();
- break;
-
- }
- step=5;
- }
- break;
- case 8://划拳
- if(timer>0)//倒计时时间未到
- {
- timer--;
- OLED_SHOW_Imag(60,16,16,16,(u8*)hua,2,0),OLED_SHOW_Imag(76,16,16,16,(u8*)quan,2,0);
- OLED_Refresh_Gram();
- }
- else //倒计时到
- {
-
- switch(STA)
- {
- case HAND_FORMS_ONE:
- OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_one,1,0);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_TWO:
- OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_two,1,0);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_THREE:
- OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_three,1,0);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_FOUR:
- OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_foul,1,0);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_FIVE:
- OLED_SHOW_Imag(30,0,64,64,(u8 *)gImage_five,1,0);OLED_Refresh_Gram();
- break;
- default:
- OLED_Fill(30,0,94,64,0);OLED_Refresh_Gram();
- break;
- }
- step=5;
- }
- break;
- case 9://手指琴
- if(timer>0)//倒计时时间未到
- {
- timer--;
- OLED_ShowString(15,16,(u8*)"Finger Piano");
- OLED_Refresh_Gram();
- }
- else //倒计时到
- {
-
- switch(STA)
- {
- case FINGER_PIANO_1: TIM1->PSC=7;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_2: TIM1->PSC=6;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_3: TIM1->PSC=5;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_4: TIM1->PSC=4;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_5: TIM1->PSC=3;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_1|FINGER_PIANO_2: TIM1->PSC=13;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_1|FINGER_PIANO_3: TIM1->PSC=12;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_1|FINGER_PIANO_4: TIM1->PSC=11;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_1|FINGER_PIANO_5: TIM1->PSC=10;TIM1->CCR4=VOLUME; break;
- case FINGER_PIANO_2|FINGER_PIANO_3: TIM1->PSC=9;TIM1->CCR4=VOLUME; break;
- default :TIM1->CCR4=0;//比较值,音量设置
- break;
- }
- //
- step=5;
- }
- break;
- case 10://划拳(扩充)
- if(timer>0)//倒计时时间未到
- {
- timer--;
- OLED_SHOW_Imag(60,16,16,16,(u8*)hua,2,0),OLED_SHOW_Imag(76,16,16,16,(u8*)quan,2,0);
- OLED_ShowString(60,32,(u8*)"plus");
- OLED_Refresh_Gram();
- }
- else //倒计时到
- {
-
- switch(STA)
- {
- case HAND_FORMS_ONE:OLED_Fill(64,0,128,64,0);
- OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_1,1,1);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_TWO:OLED_Fill(64,0,128,64,0);
- OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_2,1,1);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_THREE:OLED_Fill(64,0,128,64,0);
- OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_3,1,1);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_FOUR:OLED_Fill(64,0,128,64,0);
- OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_4,1,1);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_FIVE:OLED_Fill(64,0,128,64,0);
- OLED_SHOW_Imag(0,0,64,64,(u8 *)gImage_5,1,1);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_SIX:
- OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_6,1,0);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_SIVEN:
- OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_7,1,0);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_EIGHT:
- OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_8,1,1);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_NINE:
- OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_9,1,1);OLED_Refresh_Gram();
- break;
- case HAND_FORMS_TEN:
- OLED_SHOW_Imag(0,0,96,64,(u8 *)gImage_10,1,1);OLED_Refresh_Gram();
- break;
- default:
- OLED_Clear();OLED_Refresh_Gram();
- break;
- }
- step=5;
- }
- break;
- default:
- OLED_Fill(0,0,128,64,1);OLED_Refresh_Gram();delay_ms(10000);
- break;
-
- }
- }
- }
复制代码
所有资料51hei提供下载:
fingers.rar
(363.18 KB, 下载次数: 35)
|