Skip to content

PAJ7620手势识别模块-STM32F103标准库

原文链接:PAJ7620手势识别模块-STM32F103标准库

PAJ7620手势识别模块-STM32F103标准库

前言

因项目需要所以有了这一篇博客代码分享,本项目移植于正点原子的精英版STM32F103的开源资料。精英版为HAL库,移植后为标准库。

在这里插入图片描述

下面是需要移植的代码:

sys.h

注意:如果你的sys.h已经有了,需要在最后加上一行

#define NULL 0 

如果没有sysy.h,正常复制我的代码粘贴进去就行

#ifndef __SYS_H
#define __SYS_H	
#include "stm32f10x.h"
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板		   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/8/18
//版本:V1.7
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
////////////////////////////////////////////////////////////////////////////////// 	 

//0,不支持ucos
//1,支持ucos
#define SYSTEM_SUPPORT_OS		0		//定义系统文件夹是否支持UCOS
																	    
	 
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入



#define NULL 0

//以下为汇编函数
void WFI_SET(void);		//执行WFI指令
void INTX_DISABLE(void);//关闭所有中断
void INTX_ENABLE(void);	//开启所有中断
void MSR_MSP(u32 addr);	//设置堆栈地址

#endif

atk_ms7620.c

/**
 ****************************************************************************************************
 * @file        atk_ms7620.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2022-06-21
 * @brief       ATK-MS7620模块驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 STM32F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "atk_ms7620.h"
#include "atk_ms7620_iic.h"
#include "Delay.h"
#include "sys.h"

/* ATK-MS7620模块IIC通讯地址 */
#define ATK_MS7620_IIC_ADDR                 0x73

/* ATK-MS7620模块寄存器地址 */
#define ATK_MS7620_REG_BANK_SEL             0xEF
#define ATK_MS7620_REG_00                   0x00
#define ATK_MS7620_REG_OBJ_BRIGHTNESS       0xB0
#define ATK_MS7620_REG_OBJ_SIZE_1           0xB1
#define ATK_MS7620_REG_OBJ_SIZE_2           0xB2
#define ATK_MS7620_REG_INT_FLAG_1           0x43
#define ATK_MS7620_REG_INT_FLAG_2           0x44

/* ATK-MS7620模块手势中断标识 */
#define ATK_MS7620_GES_UP_FLAG              (1 << 0)
#define ATK_MS7620_GES_DOWN_FLAG            (1 << 1)
#define ATK_MS7620_GES_LEFT_FLAG            (1 << 2)
#define ATK_MS7620_GES_RIGHT_FLAG           (1 << 3)
#define ATK_MS7620_GES_FORWARD_FLAG         (1 << 4)
#define ATK_MS7620_GES_BACKWARD_FLAG        (1 << 5)
#define ATK_MS7620_GES_CLOCKWISE_FLAG       (1 << 6)
#define ATK_MS7620_GES_ANTICLOCKWISE_FLAG   (1 << 7)
#define ATK_MS7620_GES_WAVE_FLAG            (1 << 8)

/* ATK-MS7620模块寄存器Bank枚举 */
typedef enum
{
    ATK_MS7620_BANK0 = 0x00,
    ATK_MS7620_BANK1 = 0x01,
} atk_ms7620_bank_t;

/* 初始化配置数组 */
static uint8_t initial_register_array[][2] = {
    {0xEF, 0x00},
    {0x37, 0x07},
    {0x38, 0x17},
    {0x39, 0x06},
    {0x41, 0x00},
    {0x42, 0x00},
    {0x46, 0x2D},
    {0x47, 0x0F},
    {0x48, 0x3C},
    {0x49, 0x00},
    {0x4A, 0x1E},
    {0x4C, 0x20},
    {0x51, 0x10},
    {0x5E, 0x10},
    {0x60, 0x27},
    {0x80, 0x42},
    {0x81, 0x44},
    {0x82, 0x04},
    {0x8B, 0x01},
    {0x90, 0x06},
    {0x95, 0x0A},
    {0x96, 0x0C},
    {0x97, 0x05},
    {0x9A, 0x14},
    {0x9C, 0x3F},
    {0xA5, 0x19},
    {0xCC, 0x19},
    {0xCD, 0x0B},
    {0xCE, 0x13},
    {0xCF, 0x64},
    {0xD0, 0x21},
    {0xEF, 0x01},
    {0x02, 0x0F},
    {0x03, 0x10},
    {0x04, 0x02},
    {0x25, 0x01},
    {0x27, 0x39},
    {0x28, 0x7F},
    {0x29, 0x08},
    {0x3E, 0xFF},
    {0x5E, 0x3D},
    {0x65, 0x96},
    {0x67, 0x97},
    {0x69, 0xCD},
    {0x6A, 0x01},
    {0x6D, 0x2C},
    {0x6E, 0x01},
    {0x72, 0x01},
    {0x73, 0x35},
    {0x74, 0x00},
    {0x77, 0x01}
};

/* PS模式配置数组 */
static uint8_t change_to_proximity_register_array[][2] = {
    {0xEF, 0x00},
    {0x41, 0x00},
    {0x42, 0x00},
    {0x48, 0x3C},
    {0x49, 0x00},
    {0x51, 0x13},
    {0x83, 0x20},
    {0x84, 0x20},
    {0x85, 0x00},
    {0x86, 0x10},
    {0x87, 0x00},
    {0x88, 0x05},
    {0x89, 0x18},
    {0x8A, 0x10},
    {0x9F, 0xF8},
    {0x69, 0x96},
    {0x6A, 0x02},
    {0xEF, 0x01},
    {0x01, 0x1E},
    {0x02, 0x0F},
    {0x03, 0x10},
    {0x04, 0x02},
    {0x41, 0x50},
    {0x43, 0x34},
    {0x65, 0xCE},
    {0x66, 0x0B},
    {0x67, 0xCE},
    {0x68, 0x0B},
    {0x69, 0xE9},
    {0x6A, 0x05},
    {0x6B, 0x50},
    {0x6C, 0xC3},
    {0x6D, 0x50},
    {0x6E, 0xC3},
    {0x74, 0x05}
};

/* Gesture模式配置数组 */
static uint8_t change_to_gesture_register_array[][2] = {
    {0xEF, 0x00},
    {0x41, 0x00},
    {0x42, 0x00},
    {0xEF, 0x00},
    {0x48, 0x3C},
    {0x49, 0x00},
    {0x51, 0x10},
    {0x83, 0x20},
    {0x9F, 0xF9},
    {0xEF, 0x01},
    {0x01, 0x1E},
    {0x02, 0x0F},
    {0x03, 0x10},
    {0x04, 0x02},
    {0x41, 0x40},
    {0x43, 0x30},
    {0x65, 0x96},
    {0x66, 0x00},
    {0x67, 0x97},
    {0x68, 0x01},
    {0x69, 0xCD},
    {0x6A, 0x01},
    {0x6B, 0xB0},
    {0x6C, 0x04},
    {0x6D, 0x2C},
    {0x6E, 0x01},
    {0x74, 0x00},
    {0xEF, 0x00},
    {0x41, 0xFF},
    {0x42, 0x01}
};

/**
 * @brief       连续读取ATK-MS7620指定寄存器的值
 * @param       addr: ATK-MS7620的IIC通讯地址
 *              reg : ATK-MS7620寄存器地址
 *              len : 读取的长度
 *              dat : 存放读取到的数据的地址
 * @retval      ATK_MS7620_EOK : 函数执行成功
 *              ATK_MS7620_EACK: IIC通讯ACK错误,函数执行失败
 */
static uint8_t atk_ms7620_read(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *dat)
{
    atk_ms7620_iic_start();
    atk_ms7620_iic_send_byte((addr << 1) | 0);
    if (atk_ms7620_iic_wait_ack() == 1)
    {
        atk_ms7620_iic_stop();
        return ATK_MS7620_EACK;
    }
    atk_ms7620_iic_send_byte(reg);
    if (atk_ms7620_iic_wait_ack() == 1)
    {
        atk_ms7620_iic_stop();
        return ATK_MS7620_EACK;
    }
    atk_ms7620_iic_start();
    atk_ms7620_iic_send_byte((addr << 1) | 1);
    if (atk_ms7620_iic_wait_ack() == 1)
    {
        atk_ms7620_iic_stop();
        return ATK_MS7620_EACK;
    }
    while (len)
    {
        *dat = atk_ms7620_iic_read_byte((len > 1) ? 1 : 0);
        len--;
        dat++;
    }
    atk_ms7620_iic_stop();
    return ATK_MS7620_EOK;
}

/**
 * @brief       往ATK-MS7620的指定寄存器连续写入指定数据
 * @param       addr: ATK-MS7620的IIC通讯地址
 *              reg : ATK-MS7620寄存器地址
 *              len : 写入的长度
 *              dat : 写入的数据
 * @retval      ATK_MS7620_EOK : 函数执行成功
 *              ATK_MS7620_EACK: IIC通讯ACK错误,函数执行失败
 */
static uint8_t atk_ms7620_write(uint8_t addr,uint8_t reg, uint8_t len, uint8_t *dat)
{
    uint8_t i;
    
    atk_ms7620_iic_start();
    atk_ms7620_iic_send_byte((addr << 1) | 0);
    if (atk_ms7620_iic_wait_ack() == 1)
    {
        atk_ms7620_iic_stop();
        return ATK_MS7620_EACK;
    }
    atk_ms7620_iic_send_byte(reg);
    if (atk_ms7620_iic_wait_ack() == 1)
    {
        atk_ms7620_iic_stop();
        return ATK_MS7620_EACK;
    }
    for (i=0; i<len; i++)
    {
        atk_ms7620_iic_send_byte(dat[i]);
        if (atk_ms7620_iic_wait_ack() == 1)
        {
            atk_ms7620_iic_stop();
            return ATK_MS7620_EACK;
        }
    }
    atk_ms7620_iic_stop();
    return ATK_MS7620_EOK;
}

/**
 * @brief       读取ATK-MS7620指定寄存器的值
 * @param       addr: ATK-MS7620的IIC通讯地址
 *              reg : ATK-MS7620寄存器地址
 *              dat : 读取到的寄存器的值
 * @retval      ATK_MS7620_EOK : 函数执行成功
 *              ATK_MS7620_EACK: IIC通讯ACK错误,函数执行失败
 */
static inline uint8_t atk_ms7620_read_byte(uint8_t addr, uint8_t reg, uint8_t *dat)
{
    return atk_ms7620_read(addr, reg, 1, dat);
}

/**
 * @brief       往ATK-MS7620的指定寄存器写入一字节数据
 * @param       addr: ATK-MS7620的IIC通讯地址
 *              reg : ATK-MS7620寄存器地址
 *              dat : 写入的数据
 * @retval      ATK_MS7620_EOK : 函数执行成功
 *              ATK_MS7620_EACK: IIC通讯ACK错误,函数执行失败
 */
static inline uint8_t atk_ms7620_write_byte(uint8_t addr, uint8_t reg, uint8_t dat)
{
    return atk_ms7620_write(addr, reg, 1, &dat);
}

/**
 * @brief       切换ATK-MS7620寄存器Bank
 * @param       bank: ATK_MS7620_BANK0: 寄存器Bank0
 *                    ATK_MS7620_BANK1: 寄存器Bank1
 * @retval      无
 */
static void atk_ms7620_switch_reg_bank(atk_ms7620_bank_t bank)
{
    switch (bank)
    {
        case ATK_MS7620_BANK0:
        case ATK_MS7620_BANK1:
        {
            break;
        }
        default:
        {
            return;
        }
    }
    
    atk_ms7620_write_byte(ATK_MS7620_IIC_ADDR, ATK_MS7620_REG_BANK_SEL, bank);
}

/**
 * @brief       获取ATK-MS7620模块唤醒状态
 * @param       无
 * @retval      ATK_MS7620_EOK  : ATK-MS7620模块已唤醒
 *              ATK_MS7620_ERROR: ATK-MS7620模块未唤醒
 */
static uint8_t atk_ms7620_get_wakeup_status(void)
{
    uint8_t reg00;
    
    atk_ms7620_switch_reg_bank(ATK_MS7620_BANK0);
    atk_ms7620_read_byte(ATK_MS7620_IIC_ADDR, ATK_MS7620_REG_00, &reg00);
    if (reg00 != 0x20)
    {
        return ATK_MS7620_ERROR;
    }
    
    return ATK_MS7620_EOK;
}

/**
 * @brief       ATK-MS7620模块初始化寄存器配置
 * @param       无
 * @retval      无
 */
static void atk_ms7620_initial_register(void)
{
    uint8_t array_index;
    
    for (array_index=0; array_index<(sizeof(initial_register_array)/sizeof(initial_register_array[0])); array_index++)
    {
        atk_ms7620_write_byte(ATK_MS7620_IIC_ADDR, initial_register_array[array_index][0], initial_register_array[array_index][1]);
    }
}

/**
 * @brief       ATK-MS7620模块初始化
 * @param       无
 * @retval      ATK_MS7620_EOK  : ATK-MS7620模块初始化成功
 *              ATK_MS7620_ERROR: ATK-MS7620模块初始化失败
 */
uint8_t atk_ms7620_init(void)
{
    uint8_t ret;
    
    Delay_ms(1);                            /* 等待至少700us */
    atk_ms7620_iic_init();                  /* 初始化IIC接口 */
    ret = atk_ms7620_get_wakeup_status();   /* 获取唤醒状态 */
    if (ret != ATK_MS7620_EOK)
    {
        return ATK_MS7620_ERROR;
    }
    atk_ms7620_initial_register();          /* 初始化寄存器配置 */
    
    return ATK_MS7620_EOK;
}

/**
 * @brief       配置ATK-MS7620模块的模式
 * @param       mode: ATK_MS7620_MODE_PS     : 接近检测模式
 *                    ATK_MS7620_MODE_GESTURE: 手势检测模式
 * @retval      ATK_MS7620_EOK   : 模式配置成功
 *              ATK_MS7620_EINVAL: 函数参数有误
 */
uint8_t atk_ms7620_mode_config(atk_ms7620_mode_t mode)
{
    uint8_t (*array)[2];
    uint8_t array_size;
    uint8_t array_index;
    
    switch (mode)
    {
        case ATK_MS7620_MODE_PS:
        {
            array = change_to_proximity_register_array;
            array_size = sizeof(change_to_proximity_register_array) / sizeof(change_to_proximity_register_array[0]);
            break;
        }
        case ATK_MS7620_MODE_GESTURE:
        {
            array = change_to_gesture_register_array;
            array_size = sizeof(change_to_gesture_register_array) / sizeof(change_to_gesture_register_array[0]);
            break;
        }
        default:
        {
            return ATK_MS7620_EINVAL;
        }
    }
    
    for (array_index=0; array_index<array_size; array_index++)
    {
        atk_ms7620_write_byte(ATK_MS7620_IIC_ADDR, array[array_index][0], array[array_index][1]);
    }
    
    return ATK_MS7620_EOK;
}

/**
 * @brief       ATK-MS7620模块获取物体亮度
 * @param       brightness: 物体亮度,范围0~255
 * @retval      ATK_MS7620_EOK   : 获取物体亮度成功
 *              ATK_MS7620_ERROR : 获取物体亮度失败
 *              ATK_MS7620_EINVAL: 函数参数有误
 */
uint8_t atk_ms7620_get_obj_brightness(uint8_t *brightness)
{
    uint8_t ret;
    uint8_t _brightness[1];
    
    if (brightness == NULL)
    {
        return ATK_MS7620_EINVAL;
    }
    
    atk_ms7620_switch_reg_bank(ATK_MS7620_BANK0);
    ret = atk_ms7620_read_byte(ATK_MS7620_IIC_ADDR, ATK_MS7620_REG_OBJ_BRIGHTNESS, _brightness);
    if (ret != ATK_MS7620_EOK)
    {
        return ATK_MS7620_ERROR;
    }
    
    *brightness = _brightness[0];
    
    return ATK_MS7620_EOK;
}

/**
 * @brief       ATK-MS7620模块获取物体大小
 * @param       size: 物体大小,范围0~900
 * @retval      ATK_MS7620_EOK   : 获取物体大小成功
 *              ATK_MS7620_ERROR : 获取物体大小失败
 *              ATK_MS7620_EINVAL: 函数参数有误
 */
uint8_t atk_ms7620_get_obj_size(uint16_t *size)
{
    uint8_t ret;
    uint8_t _size[2];
    
    if (size == NULL)
    {
        return ATK_MS7620_EINVAL;
    }
    
    atk_ms7620_switch_reg_bank(ATK_MS7620_BANK0);
    ret  = atk_ms7620_read_byte(ATK_MS7620_IIC_ADDR, ATK_MS7620_REG_OBJ_SIZE_1, &_size[0]);
    ret += atk_ms7620_read_byte(ATK_MS7620_IIC_ADDR, ATK_MS7620_REG_OBJ_SIZE_2, &_size[1]);
    
    if (ret != ATK_MS7620_EOK)
    {
        return ATK_MS7620_ERROR;
    }
    
    *size = (((uint16_t)_size[1] << 8) & 0x0F00) | _size[0];
    
    return ATK_MS7620_EOK;
}

/**
 * @brief       ATK-MS7620模块获取手势
 * @param       gesture: 手势
 * @retval      ATK_MS7620_EOK   : 获取手势成功
 *              ATK_MS7620_ERROR : 获取手势失败
 *              ATK_MS7620_EINVAL: 函数参数有误
 */
uint8_t atk_ms7620_get_gesture(atk_ms7620_gesture_t *gesture)
{
    uint8_t ret;
    union
    {
        uint8_t byte[2];
        uint16_t halfword;
    }_flag;
    
    if (gesture == NULL)
    {
        return ATK_MS7620_EINVAL;
    }
    
    atk_ms7620_switch_reg_bank(ATK_MS7620_BANK0);
    ret = atk_ms7620_read_byte(ATK_MS7620_IIC_ADDR, ATK_MS7620_REG_INT_FLAG_1, &_flag.byte[0]);
    ret += atk_ms7620_read_byte(ATK_MS7620_IIC_ADDR, ATK_MS7620_REG_INT_FLAG_2, &_flag.byte[1]);
    if (ret != ATK_MS7620_EOK)
    {
        return ATK_MS7620_ERROR;
    }
    
    switch (_flag.halfword)
    {
        case ATK_MS7620_GES_UP_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_UP;
            break;
        }
        case ATK_MS7620_GES_DOWN_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_DOWN;
            break;
        }
        case ATK_MS7620_GES_LEFT_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_LEFT;
            break;
        }
        case ATK_MS7620_GES_RIGHT_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_RIGHT;
            break;
        }
        case ATK_MS7620_GES_FORWARD_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_FORWARD;
            break;
        }
        case ATK_MS7620_GES_BACKWARD_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_BACKWARD;
            break;
        }
        case ATK_MS7620_GES_CLOCKWISE_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_CLOCKWISE;
            break;
        }
        case ATK_MS7620_GES_ANTICLOCKWISE_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_ANTICLOCKWISE;
            break;
        }
        case ATK_MS7620_GES_WAVE_FLAG:
        {
            *gesture = ATK_MS7620_GESTURE_WAVE;
            break;
        }
        default:
        {
            return ATK_MS7620_ERROR;
        }
    }
    
    return ATK_MS7620_EOK;
}

atk_ms7620.h

/**
 ****************************************************************************************************
 * @file        atk_ms7620.h
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2022-06-21
 * @brief       ATK-MS7620模块驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 STM32F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#ifndef __ATK_MS7620_H
#define __ATK_MS7620_H

#include "sys.h"

/* ATK-MS7620模块模式枚举 */
typedef enum
{
    ATK_MS7620_MODE_PS = 0x00,  /* 接近检测模式 */
    ATK_MS7620_MODE_GESTURE,    /* 手势检测模式 */
} atk_ms7620_mode_t;

/* ATK-MS7620模块手势枚举 */
typedef enum
{
    ATK_MS7620_GESTURE_UP = 0x00,
    ATK_MS7620_GESTURE_DOWN,
    ATK_MS7620_GESTURE_LEFT,
    ATK_MS7620_GESTURE_RIGHT,
    ATK_MS7620_GESTURE_FORWARD,
    ATK_MS7620_GESTURE_BACKWARD,
    ATK_MS7620_GESTURE_CLOCKWISE,
    ATK_MS7620_GESTURE_ANTICLOCKWISE,
    ATK_MS7620_GESTURE_WAVE,
} atk_ms7620_gesture_t;

/* 函数错误代码 */
#define ATK_MS7620_EOK      0   /* 没有错误 */
#define ATK_MS7620_ERROR    1   /* 通用错误 */
#define ATK_MS7620_EINVAL   2   /* 参数错误 */
#define ATK_MS7620_EACK     3   /* IIC通讯ACK错误 */

/* 操作函数 */
uint8_t atk_ms7620_init(void);                                  /* ATK-MS7620模块初始化 */
uint8_t atk_ms7620_mode_config(atk_ms7620_mode_t mode);         /* 配置ATK-MS7620模块的模式 */
uint8_t atk_ms7620_get_obj_brightness(uint8_t *brightness);     /* ATK-MS7620模块获取物体亮度 */
uint8_t atk_ms7620_get_obj_size(uint16_t *size);                /* ATK-MS7620模块获取物体大小 */
uint8_t atk_ms7620_get_gesture(atk_ms7620_gesture_t *gesture);  /* ATK-MS7620模块获取手势 */

#endif

atk_ms7620_iic.c

/**
 ****************************************************************************************************
 * @file        atk_ms7620_iic.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2022-06-21
 * @brief       ATK-MS7620模块IIC接口驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 STM32F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "atk_ms7620_iic.h"
#include "Delay.h"


/**
 * @brief       IIC接口延时函数,用于控制IIC读写速度
 * @param       无
 * @retval      无
 */
static inline void atk_ms7620_iic_delay(void)
{
    Delay_us(2);
}

/**
 * @brief       产生IIC起始信号
 * @param       无
 * @retval      无
 */
void atk_ms7620_iic_start(void)
{
    ATK_MS7620_IIC_SDA(1);
    ATK_MS7620_IIC_SCL(1);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SDA(0);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SCL(0);
    atk_ms7620_iic_delay();
}

/**
 * @brief       产生IIC停止信号
 * @param       无
 * @retval      无
 */
void atk_ms7620_iic_stop(void)
{
    ATK_MS7620_IIC_SDA(0);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SCL(1);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SDA(1);
    atk_ms7620_iic_delay();
}

/**
 * @brief       等待IIC应答信号
 * @param       无
 * @retval      0: 应答信号接收成功
 *              1: 应答信号接收失败
 */
uint8_t atk_ms7620_iic_wait_ack(void)
{
    uint8_t waittime = 0;
    uint8_t rack = 0;
    
    ATK_MS7620_IIC_SDA(1);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SCL(1);
    atk_ms7620_iic_delay();
    
    while (ATK_MS7620_IIC_READ_SDA())
    {
        waittime++;
        
        if (waittime > 250)
        {
            atk_ms7620_iic_stop();
            rack = 1;
            break;
        }
    }
    
    ATK_MS7620_IIC_SCL(0);
    atk_ms7620_iic_delay();
    
    return rack;
}

/**
 * @brief       产生ACK应答信号
 * @param       无
 * @retval      无
 */
void atk_ms7620_iic_ack(void)
{
    ATK_MS7620_IIC_SDA(0);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SCL(1);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SCL(0);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SDA(1);
    atk_ms7620_iic_delay();
}

/**
 * @brief       不产生ACK应答信号
 * @param       无
 * @retval      无
 */
void atk_ms7620_iic_nack(void)
{
    ATK_MS7620_IIC_SDA(1);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SCL(1);
    atk_ms7620_iic_delay();
    ATK_MS7620_IIC_SCL(0);
    atk_ms7620_iic_delay();
}

/**
 * @brief       IIC发送一个字节
 * @param       dat: 要发送的数据
 * @retval      无
 */
void atk_ms7620_iic_send_byte(uint8_t dat)
{
    uint8_t t;
    
    for (t=0; t<8; t++)
    {
        ATK_MS7620_IIC_SDA((dat & 0x80) >> 7);
        atk_ms7620_iic_delay();
        ATK_MS7620_IIC_SCL(1);
        atk_ms7620_iic_delay();
        ATK_MS7620_IIC_SCL(0);
        dat <<= 1;
    }
    ATK_MS7620_IIC_SDA(1);
}

/**
 * @brief       IIC接收一个字节
 * @param       ack: ack=1时,发送ack; ack=0时,发送nack
 * @retval      接收到的数据
 */
uint8_t atk_ms7620_iic_read_byte(uint8_t ack)
{
    uint8_t i;
    uint8_t dat = 0;
    
    for (i = 0; i < 8; i++ )
    {
        dat <<= 1;
        ATK_MS7620_IIC_SCL(1);
        atk_ms7620_iic_delay();
        
        if (ATK_MS7620_IIC_READ_SDA())
        {
            dat++;
        }
        
        ATK_MS7620_IIC_SCL(0);
        atk_ms7620_iic_delay();
    }
    
    if (ack == 0)
    {
        atk_ms7620_iic_nack();
    }
    else
    {
        atk_ms7620_iic_ack();
    }

    return dat;
}

/**
 * @brief       初始化IIC接口
 * @param       无
 * @retval      无
 */
void atk_ms7620_iic_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
    
    /* 使能SCL、SDA引脚GPIO的时钟 */
    ATK_MS7620_IIC_SCL_GPIO_CLK_ENABLE();
    ATK_MS7620_IIC_SDA_GPIO_CLK_ENABLE();
    
	
	/* 初始化SCL引脚 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = ATK_MS7620_IIC_SCL_GPIO_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(ATK_MS7620_IIC_SCL_GPIO_PORT, &GPIO_InitStructure);
	
	/* 初始化SDA引脚 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Pin = ATK_MS7620_IIC_SDA_GPIO_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(ATK_MS7620_IIC_SDA_GPIO_PORT, &GPIO_InitStructure);
	
    
    atk_ms7620_iic_stop();
}

atk_ms7620_iic.h

/**
 ****************************************************************************************************
 * @file        atk_ms7620_iic.h
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2022-06-21
 * @brief       ATK-MS7620模块IIC接口驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 STM32F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#ifndef __ATK_MS7620_IIC_H
#define __ATK_MS7620_IIC_H

#include "sys.h"

/* 引脚定义 */
#define ATK_MS7620_IIC_SCL_GPIO_PORT            GPIOB
#define ATK_MS7620_IIC_SCL_GPIO_PIN             GPIO_Pin_10
#define ATK_MS7620_IIC_SCL_GPIO_CLK_ENABLE()    do{ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); }while(0)
#define ATK_MS7620_IIC_SDA_GPIO_PORT            GPIOB
#define ATK_MS7620_IIC_SDA_GPIO_PIN             GPIO_Pin_11
#define ATK_MS7620_IIC_SDA_GPIO_CLK_ENABLE()    do{ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);}while(0)

/* IO操作 */
#define ATK_MS7620_IIC_SCL(x)                   do{ x ?                                                                                             \
                                                    GPIO_SetBits(ATK_MS7620_IIC_SCL_GPIO_PORT, ATK_MS7620_IIC_SCL_GPIO_PIN) :    \
                                                    GPIO_ResetBits(ATK_MS7620_IIC_SCL_GPIO_PORT, ATK_MS7620_IIC_SCL_GPIO_PIN);   \
                                                }while(0)

#define ATK_MS7620_IIC_SDA(x)                   do{ x ?                                                                                             \
                                                    GPIO_SetBits(ATK_MS7620_IIC_SDA_GPIO_PORT, ATK_MS7620_IIC_SDA_GPIO_PIN) :    \
                                                    GPIO_ResetBits(ATK_MS7620_IIC_SDA_GPIO_PORT, ATK_MS7620_IIC_SDA_GPIO_PIN);   \
                                                }while(0)

#define ATK_MS7620_IIC_READ_SDA()               GPIO_ReadInputDataBit(ATK_MS7620_IIC_SDA_GPIO_PORT, ATK_MS7620_IIC_SDA_GPIO_PIN)

/* 操作函数 */
void atk_ms7620_iic_start(void);                /* 产生IIC起始信号 */
void atk_ms7620_iic_stop(void);                 /* 产生IIC停止信号 */
uint8_t atk_ms7620_iic_wait_ack(void);          /* 等待IIC应答信号 */
void atk_ms7620_iic_ack(void);                  /* 产生ACK应答信号 */
void atk_ms7620_iic_nack(void);                 /* 不产生ACK应答信号 */
void atk_ms7620_iic_send_byte(uint8_t dat);     /* IIC发送一个字节 */
uint8_t atk_ms7620_iic_read_byte(uint8_t ack);  /* IIC接收一个字节 */
void atk_ms7620_iic_init(void);                 /* 初始化IIC接口 */

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Serial.h"
#include "atk_ms7620.h"
#include "sys.h"


//手势识别相关测试代码
int main(void)
{
    uint8_t ret;
    atk_ms7620_gesture_t gesture;
	Serial_Init();
	
	Serial_SendString("hello\r\n");
    
    /* 初始化ATK-MS7620模块 */
    ret = atk_ms7620_init();
    if (ret != 0)
    {
        Serial_SendString("ATK-MS7620 init failed!\r\n");
        while (1)
        {
            Delay_ms(200);
        }
    }
    
    /* 配置ATK-MS7620模块为手势检测模式 */
    ret = atk_ms7620_mode_config(ATK_MS7620_MODE_GESTURE);
    if (ret != 0)
    {
        Serial_SendString("ATK_MS7620 config failed!\r\n");
        while (1)
        {
            Delay_ms(200);
        }
    }
    
    Serial_SendString("ATK-MS7620 config succedded!\r\n");
    
    while (1)
    {
        /* 获取手势 */
        ret = atk_ms7620_get_gesture(&gesture);
        if (ret == ATK_MS7620_EOK)
        {
            switch (gesture)
            {
                case ATK_MS7620_GESTURE_UP:
                {
                    Serial_SendString("Gesture: Up\r\n");
                    break;
                }
                case ATK_MS7620_GESTURE_DOWN:
                {
                    Serial_SendString("Gesture: Down\r\n");
                    break;
                }
                case ATK_MS7620_GESTURE_LEFT:
                {
                    Serial_SendString("Gesture: Left\r\n");
                    break;
                }
                case ATK_MS7620_GESTURE_RIGHT:
                {
                    Serial_SendString("Gesture: Right\r\n");
                    break;
                }
                case ATK_MS7620_GESTURE_FORWARD:
                {
                    Serial_SendString("Gesture: Forward\r\n");
                    break;
                }
                case ATK_MS7620_GESTURE_BACKWARD:
                {
                    Serial_SendString("Gesture: Backward\r\n");
                    break;
                }
                case ATK_MS7620_GESTURE_CLOCKWISE:
                {
                    Serial_SendString("Gesture: Clockwise\r\n");
                    break;
                }
                case ATK_MS7620_GESTURE_ANTICLOCKWISE:
                {
                    Serial_SendString("Gesture: Anticlockwise\r\n");
                    break;
                }
                case ATK_MS7620_GESTURE_WAVE:
                {
                    Serial_SendString("Gesture: Wave\r\n");
                    break;
                }
                default:
                {
                    break;
                }
            }
        }
    }
}
最近更新