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, ®00);
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;
}
}
}
}
}
