江苏省电赛手势识别装置(D题)
装置使用MSP430F5529开发板,TI的FDC2214电容传感器,外设使用4*4矩阵按键进行功能切换、数码管显示传感器数值、LED灯显示手势状态。
FDC2214是4路输入电容传感器,我们使用覆铜板平均分成八分,构成四路差分结构,识别结果比较稳定。
以下是实现代码:
#include "bsp.h"
#define delaytime 250 //检测到手势后延时检测比较时间 毫秒
#define Stable 10 //稳定后数值变化范围
//#define scissors 500 //手势剪刀分界
#define num0_1 400 //开始判断的分界
#define rock 1900 //手势剪刀石头的分界
#define paper 2900 //手势石头布的分界
#define num1_2 800 //手势数值1和2的分界
#define num2_3 1150 //手势数值2和3的分界
#define num3_4 1450 //手势数值3和4的分界
#define num4_5 1950 //手势数值4_5的分界
#define ratio 6 //读数右移位数
#define s1 0.67 //第1通道系数
#define s2 1 //第2通道系数
#define s3 1 //第3通道系数
#define s4 0.82 //第4通道系数
#define numfun5 50 //功能5 灯开始亮分界
#define Led0_off P3OUT |=BIT0
#define Led1_off P3OUT |=BIT1
#define Led2_off P3OUT |=BIT2
#define Led3_off P3OUT |=BIT3
#define Led4_off P3OUT |=BIT4
#define Led5_off P3OUT |=BIT5
#define Led6_off P3OUT |=BIT6
#define Led7_off P3OUT |=BIT7
#define Led0_on P3OUT &=~BIT0
#define Led1_on P3OUT &=~BIT1
#define Led2_on P3OUT &=~BIT2
#define Led3_on P3OUT &=~BIT3
#define Led4_on P3OUT &=~BIT4
#define Led5_on P3OUT &=~BIT5
#define Led6_on P3OUT &=~BIT6
#define Led7_on P3OUT &=~BIT7
#define buzzer_off P2OUT |=BIT0
#define buzzer_on P2OUT &=~BIT0
unsigned long int temp0_zero, temp1_zero, temp2_zero, temp3_zero;
unsigned char numf = 0, numf1 = 0;
unsigned char key1_f = 0, key2_f = 0, key3_f = 0, key4_f = 0, key5_f = 0;
unsigned char key6_f = 0, key7_f = 0, key8_f = 0, key9_f = 0, key10_f = 0;
unsigned char key11_f = 0, key12_f = 0, key13_f = 0, key14_f = 0, key15_f = 0;
unsigned char key16_f = 0, key3_f_x = 1, key4_f_x = 1;
unsigned char delayf = 1, ms_f = 0;
unsigned int rock_p, paper_p;
unsigned int num1_2_p, num2_3_p, num3_4_p, num4_5_p;
unsigned int scissors_s, rock_s, paper_s;
unsigned int num0_1_s, num1_2_s, num2_3_s, num3_4_s, num4_5_s;
float temp_f;
int main(void)
{
unsigned int temp, temp0_h, temp0_l, temp1_h, temp1_l, temp2_h, temp2_l, temp3_h, temp3_l;
unsigned long int temp0, temp1, temp2, temp3;
unsigned int temp_pr = 0, Difference = 0;
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
P3DIR = 0xff;
P2DIR = 0xff;
buzzer_off;
P3OUT = 0xff;
bsp_Init();
Init_Keypad();
_EINT();
Initdisplay();
delay_ms(500);
delay_ms(500);
//开机清零
temp0_h = ReadRegfdc2214(0x00); //读取第1通道的值
temp0_l = ReadRegfdc2214(0x01); //读取第1通道的值
temp0 = temp0_h;
temp0 = (temp0 << 16) + temp0_l;
temp0_zero = temp0;
temp1_h = ReadRegfdc2214(0x02); //读取第2通道的值
temp1_l = ReadRegfdc2214(0x03); //读取第2通道的值
temp1 = temp1_h;
temp1 = (temp1 << 16) + temp1_l;
temp1_zero = temp1;
temp2_h = ReadRegfdc2214(0x04); //读取第3通道的值
temp2_l = ReadRegfdc2214(0x05); //读取第3通道的值
temp2 = temp2_h;
temp2 = (temp2 << 16) + temp2_l;
temp2_zero = temp2;
temp3_h = ReadRegfdc2214(0x06); //读取第4通道的值
temp3_l = ReadRegfdc2214(0x07); //读取第4通道的值
temp3 = temp3_h;
temp3 = (temp3 << 16) + temp3_l;
temp3_zero = temp3;
while (1)
{
//读取4通道数据
temp0_h = ReadRegfdc2214(0x00); //读取第1通道的值
temp0_l = ReadRegfdc2214(0x01); //读取第1通道的值
temp0 = temp0_h;
temp0 = (temp0 << 16) + temp0_l;
if (temp0_zero > temp0)
temp0 = temp0_zero - temp0;
else
temp0 = 0;
temp0 = temp0 >> ratio;
temp1_h = ReadRegfdc2214(0x02); //读取第2通道的值
temp1_l = ReadRegfdc2214(0x03); //读取第2通道的值
temp1 = temp1_h;
temp1 = (temp1 << 16) + temp1_l;
if (temp1_zero > temp1)
temp1 = temp1_zero - temp1;
else
temp1 = 0;
temp1 = temp1 >> ratio;
temp2_h = ReadRegfdc2214(0x04); //读取第3通道的值
temp2_l = ReadRegfdc2214(0x05); //读取第3通道的值
temp2 = temp2_h;
temp2 = (temp2 << 16) + temp2_l;
if (temp2_zero > temp2)
temp2 = temp2_zero - temp2;
else
temp2 = 0;
temp2 = temp2 >> ratio;
temp3_h = ReadRegfdc2214(0x06); //读取第4通道的值
temp3_l = ReadRegfdc2214(0x07); //读取第4通道的值
temp3 = temp3_h;
temp3 = (temp3 << 16) + temp3_l;
if (temp3_zero > temp3)
temp3 = temp3_zero - temp3;
else
temp3 = 0;
temp3 = temp3 >> ratio;
temp_f = temp0 * s1 + temp1 * s2 + temp2 * s3 + temp3 * s4; //求4通道读数之和
temp = (unsigned int )temp_f;
if(key5_f)//功能5
{
if(temp0>numfun5)Led1_on;
else Led1_off;
if(temp1>numfun5)Led3_on;
else Led3_off;
if(temp2>numfun5)Led5_on;
else Led5_off;
if(temp3>numfun5)Led7_on;
else Led7_off;
if((temp0>numfun5)&&(temp1>numfun5)){Led2_on;}//Led1_off;Led3_off;
else Led2_off;
if((temp1>numfun5)&&(temp2>numfun5)){Led4_on;}//Led3_off;Led5_off;
else Led4_off;
if((temp2>numfun5)&&(temp3>numfun5)){Led6_on;}//Led5_off;Led7_off;
else Led6_off;
}
//按键信号处理
if ((key3_f == 1) && key9_f)//功能3训练 键9 :剪刀数据保存
{
scissors_s = temp;
Led5_on;
key9_f = 0;
}
if ((key3_f == 1) && key10_f)//功能3训练 键10 :石头数据保存
{
rock_s = temp;
Led6_on;
key10_f = 0;
}
if ((key3_f == 1) && key11_f)//功能3训练 键11 :布数据保存
{
paper_s = temp;
Led7_on;
key11_f = 0;
}
if ((key3_f == 2) && (key3_f_x))//功能3工作
{
key3_f_x = 0;
key9_f = 0;
key10_f = 0;
key11_f = 0;
Led5_off;
Led6_off;
Led7_off;
paper_p = (paper_s + rock_s) / 2; //设定布和石头分界
rock_p = (rock_s + scissors_s) / 2; //设定剪刀和石头分界
}
if ((key4_f == 1) && key12_f)//功能4训练 键12 :1数据保存
{
num0_1_s = temp;
Display_l(1);
key12_f = 0;
}
if ((key4_f == 1) && key13_f)//功能4训练 键13 :2数据保存
{
num1_2_s = temp;
Display_l(2);
key13_f = 0;
}
if ((key4_f == 1) && key14_f)//功能4训练 键14 :3数据保存
{
num2_3_s = temp;
Display_l(3);
key14_f = 0;
}
if ((key4_f == 1) && key15_f)//功能4训练 键15 :4数据保存
{
num3_4_s = temp;
Display_l(4);
key15_f = 0;
}
if ((key4_f == 1) && key16_f)//功能4训练 键16 :5数据保存
{
num4_5_s = temp;
Display_l(5);
key16_f = 0;
}
if ((key4_f == 2) && (key4_f_x))//功能4工作
{
key4_f_x = 0;
key12_f = 0;
key13_f = 0;
key14_f = 0;
key15_f = 0;
key16_f = 0;
Display_l(16);
num1_2_p = (num0_1_s + num1_2_s) / 2;//设定1和2分界
num2_3_p = (num1_2_s + num2_3_s) / 2;//设定2和3分界
num3_4_p = (num2_3_s + num3_4_s) / 2;//设定3和4分界
num4_5_p = (num3_4_s + num4_5_s) / 2;//设定4和5分界
}
//4种工作状态
if ((key1_f) || (key2_f) || (key3_f == 2) || (key4_f == 2))
{
if (temp > num0_1) //如果数值大于下限,开始判别是哪个手势
{
temp_pr = temp;//记录第一次数据,延时
delay_ms(delaytime);//延时设定时间
temp0_h = ReadRegfdc2214(0x00); //读取第1通道的值
temp0_l = ReadRegfdc2214(0x01); //读取第1通道的值
temp0 = temp0_h;
temp0 = (temp0 << 16) + temp0_l;
if (temp0_zero > temp0)
temp0 = temp0_zero - temp0;
else
temp0 = 0;
temp0 = temp0 >> ratio;
temp1_h = ReadRegfdc2214(0x02); //读取第2通道的值
temp1_l = ReadRegfdc2214(0x03); //读取第2通道的值
temp1 = temp1_h;
temp1 = (temp1 << 16) + temp1_l;
if (temp1_zero > temp1)
temp1 = temp1_zero - temp1;
else
temp1 = 0;
temp1 = temp1 >> ratio;
temp2_h = ReadRegfdc2214(0x04); //读取第3通道的值
temp2_l = ReadRegfdc2214(0x05); //读取第3通道的值
temp2 = temp2_h;
temp2 = (temp2 << 16) + temp2_l;
if (temp2_zero > temp2)
temp2 = temp2_zero - temp2;
else
temp2 = 0;
temp2 = temp2 >> ratio;
temp3_h = ReadRegfdc2214(0x06); //读取第4通道的值
temp3_l = ReadRegfdc2214(0x07); //读取第4通道的值
temp3 = temp3_h;
temp3 = (temp3 << 16) + temp3_l;
if (temp3_zero > temp3)
temp3 = temp3_zero - temp3;
else
temp3 = 0;
temp3 = temp3 >> ratio;
temp_f = temp0 * s1 + temp1 * s2 + temp2 * s3 + temp3 * s4; //求4通道读数之和
temp = (unsigned int )temp_f;
if(temp > temp_pr)Difference = temp - temp_pr;//记录第二次数据,与延时前数据进行比较
else Difference = temp_pr - temp;
if(Difference < Stable) //如果延时前后两次数据相差小于设定值,则认为已经稳定,可以进行判断。
{
if ((key1_f) || (key3_f == 2))
{
if (temp > paper_p)//判定为纸
{
Led7_on;
Led6_off;
Led5_off;
numf1 = 3;
}
else if ((temp > rock_p) && (numf1 < 3))//判定为石头
{
Led5_off;
Led6_on;
Led7_off;
numf1 = 2;
}
else if (numf1 < 2)//判定为剪刀
{
Led5_on;
Led6_off;
Led7_off;
numf1 = 1;
}
}
if ((key2_f) || (key4_f == 2))
{
if (temp > num4_5_p)//判定为5
{
Display_l(5);
numf = 5;
}
else if ((temp > num3_4_p) && (numf < 5))//判定为4
{
Display_l(4);
numf = 4;
}
else if ((temp > num2_3_p) && (numf < 4))//判定为3
{
Display_l(3);
numf = 3;
}
else if ((temp > num1_2_p) && (numf < 3))//判定为2
{
Display_l(2);
numf = 2;
}
else if (numf < 2)//判定为1
{
Display_l(1);
numf = 1;
}
}
}
}
else
{//无手势,清显示
if ((key1_f) || (key3_f == 2))
{
Led5_off;
Led6_off;
Led7_off;
numf1 = 0;
}
if ((key2_f) || (key4_f == 2))
{
Display_l(0);
numf = 0;
}
}
}
//功能3、4训练状态时闪烁
if (delayf && getdelayf() == 0)
{
delayf = 0;
delaytim(300);
}
if ((delayf == 0) && getdelayf() == 0)
{
delayf = 1;
ms_f = ~ms_f;
if (key3_f == 1)
{
if (ms_f)
Led2_on;
else
Led2_off;
}
else if (key3_f == 2)
Led2_on;
else
Led2_off;
if (key4_f == 1)
{
if (ms_f)
Led3_on;
else
Led3_off;
}
else if (key4_f == 2)
Led3_on;
else
Led3_off;
}
Display_h(temp);//显示当前测量数值
Key_Event();//检测按键
if (key_Flag == 1)//如果检测到按键,进行按键标志设定。
{
key_Flag = 0;
buzzer_on;
delay_ms(50);
buzzer_off;
switch (key_val)
{
case 1:
{
//键1 功能1
key1_f = ~key1_f;
if (key1_f)
{
Led0_on;
Led2_off;
Led3_off;
Led4_off;
key3_f = 0;
key4_f = 0;
key5_f = 0;
rock_p = rock;
paper_p = paper;
}
else
Led0_off;
}
break;
case 2:
{
//键2 功能2
key2_f = ~key2_f;
if (key2_f)
{
Led1_on;
Led2_off;
Led3_off;
Led4_off;
key3_f = 0;
key4_f = 0;
key5_f = 0;
num1_2_p = num1_2;
num2_3_p = num2_3;
num3_4_p = num3_4;
num4_5_p = num4_5;
}
else
Led1_off;
}
break;
case 3:
{
//键3 功能3
Led0_off;
Led1_off;
Led2_on;
Led3_off;
Led4_off;
key1_f = 0;
key2_f = 0;
key5_f = 0;
if (key3_f < 2)
key3_f++;
else
key3_f = 0;
if (key3_f == 1)
key3_f_x = 1;
}
break;
case 4:
{
//键4 功能4
Led0_off;
Led1_off;
Led2_off;
Led3_on;
Led4_off;
key1_f = 0;
key2_f = 0;
key5_f = 0;
if (key4_f < 2)
key4_f++;
else
key4_f = 0;
}
break;
case 5:
{
//键5 功能5
Led0_off;
Led1_off;
Led2_off;
Led3_off;
Led4_on;
key1_f = 0;
key2_f = 0;
key3_f = 0;
key4_f = 0;
key5_f = 1;
}
break;
case 6:
{
//清零键
temp0_h = ReadRegfdc2214(0x00); //读取第1通道的值
temp0_l = ReadRegfdc2214(0x01); //读取第1通道的值
temp0 = temp0_h;
temp0 = (temp0 << 16) + temp0_l;
temp0_zero = temp0;
temp1_h = ReadRegfdc2214(0x02); //读取第2通道的值
temp1_l = ReadRegfdc2214(0x03); //读取第2通道的值
temp1 = temp1_h;
temp1 = (temp1 << 16) + temp1_l;
temp1_zero = temp1;
temp2_h = ReadRegfdc2214(0x04); //读取第1通道的值
temp2_l = ReadRegfdc2214(0x05); //读取第1通道的值
temp2 = temp2_h;
temp2 = (temp2 << 16) + temp2_l;
temp2_zero = temp2;
temp3_h = ReadRegfdc2214(0x06); //读取第2通道的值
temp3_l = ReadRegfdc2214(0x07); //读取第2通道的值
temp3 = temp3_h;
temp3 = (temp3 << 16) + temp3_l;
temp3_zero = temp3;
}
break;
case 7:
break;
case 8:
break;
case 9:
key9_f = 1;
key10_f = 0;
key11_f = 0;
break;
case 10:
key9_f = 0;
key10_f = 1;
key11_f = 0;
break;
case 11:
key9_f = 0;
key10_f = 0;
key11_f = 1;
break;
case 12:
key12_f = 1;
key13_f = 0;
key14_f = 0;
key15_f = 0;
key16_f = 0;
break;
case 13:
key12_f = 0;
key13_f = 1;
key14_f = 0;
key15_f = 0;
key16_f = 0;
break;
case 14:
key12_f = 0;
key13_f = 0;
key14_f = 1;
key15_f = 0;
key16_f = 0;
break;
case 15:
key12_f = 0;
key13_f = 0;
key14_f = 0;
key15_f = 1;
key16_f = 0;
break;
case 16:
key12_f = 0;
key13_f = 0;
key14_f = 0;
key15_f = 0;
key16_f = 1;
break;
default:
break;
}
}
}
}
这场比赛是我们当年的那一场,我选的不是这个题目,因为元件有限,所以我选择了另一个题目,不过当时他们设计的也不错。
非常不错