[分享] 基于FDC2214传感器的手势识别装置(MSP430)

火辣西米秀   2020-10-7 19:34 楼主

江苏省电赛手势识别装置(D题)

装置使用MSP430F5529开发板,TI的FDC2214电容传感器,外设使用4*4矩阵按键进行功能切换、数码管显示传感器数值、LED灯显示手势状态。

image.png

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;
            }
        }
    }
}
 

 

回复评论 (3)

这场比赛是我们当年的那一场,我选的不是这个题目,因为元件有限,所以我选择了另一个题目,不过当时他们设计的也不错。

点赞 (1) 2020-10-13 12:00

非常不错

点赞  2021-1-13 02:43
fdc2214芯片手册fdc2214芯片手册
点赞  2021-10-30 20:45
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复