风云再起 · 2022年08月28日 · 上海市

【MM32F5270开发板试用】手势传感PAJ7620U2的智能家居应用

一、序

很高兴能参加极术社区联合灵动微电子组织的【灵动MM32F5270开发板试用】活动,MM32F5270 是一款搭载了安谋科技 STAR-MC1 内核的 MCU 产品,其工作频率可达 120MHz,内置多达 256KB Flash 和 192KB RAM,配置浮点运算单元(Floating Point Unit, FPU)、数字信号处理单元(Digital Signal Processing,DSP)、信号间互联矩阵 MindSwitch、可配置逻辑单元 CLU、三角函数加速单元 CORDIC 等算法加速单元,并集成了丰富的外设模块和充足的 I/O 端口。MM32F5270 相较于现有产品全面提升了性能、存储容量、总线架构和外设配置,旨在覆盖更广泛的工业、汽车和 IoT 应用。

二、PLUS-F5270开发板功能示意框图

PLUS-F5270开发板功能示意框图.jpg

三、产品方案设计

疫情当下,非接触性来让设备启动,应用场景越来越适应市场的需求,这次抛砖引玉,大胆地做一次尝试,一起交流学习。
产品方案设计.png

四、硬件及引脚,原理图

1、手势传感PAJ7620U2

0001.jpg
0005.png

2、MM32F5270开发板使用到的引脚

0003.png
0004.png

五、部分核心代码:

paj7620u2_iic.h文件:

#ifndef __PAJ7620U2_IIC_H
#define __PAJ7620U2_IIC_H

#include "board_init.h"

#define SDA_GPIO    GPIO_PIN_7
#define SDA_PORT    GPIOC
#define SDA_RCC     RCC_APB2Periph_GPIOB
#define SCL_GPIO    GPIO_PIN_6
#define SCL_PORT    GPIOC
#define SCL_RCC     RCC_APB2Periph_GPIOB



#define SDA_H   GPIO_WriteBit(SDA_PORT,SDA_GPIO,1u)
#define SDA_L   GPIO_WriteBit(SDA_PORT,SDA_GPIO,0u)
#define SDA_R   GPIO_ReadInDataBit(SDA_PORT,SDA_GPIO)

#define SCL_H   GPIO_WriteBit(SCL_PORT,SCL_GPIO,1u)
#define SCL_L   GPIO_WriteBit(SCL_PORT,SCL_GPIO,0u)


/*
 * Macros.
 */
#define APP_I2C_TARGET_ADDR  0x50u  /* I2C target device address. */
#define APP_I2C_BUF_LEN  16u        /* The size of I2C write and read array. */
#define APP_I2C_TIMEOUT_TIME 3000u  /* Wait for the time when the status flag appears. If exceeds time, don't wait any longer and return to timeout. */
#define APP_I2C_TX_LEN  8u          /* The number of tx data. */
#define APP_I2C_RX_LEN  7u          /* The number of rx data. */

/*
 * Variables.
 */
static uint8_t app_i2c_rx_buf[APP_I2C_BUF_LEN]; /* I2C rx buffer. */
static uint8_t app_i2c_tx_buf[APP_I2C_BUF_LEN]; /* I2C tx buffer. */
static I2C_MasterXfer_Type app_i2c_xfer;



uint8_t GS_Write_Byte(uint8_t REG_Address,uint8_t REG_data);
uint8_t GS_Read_Byte(uint8_t REG_Address);
uint8_t GS_Read_nByte(uint8_t REG_Address,uint16_t len,uint8_t *buf);
void GS_i2c_init(void);
void GS_WakeUp(void);
void IIC_SpeedCtl(unsigned short speed);
void SDA_SetGpioMode(uint8_t mode);
void SCL_SetGpioMode(uint8_t mode);
void IIC_delay(uint16_t n);

void app_delay_ms(uint32_t t);
void app_delay_us(uint32_t t);

#endif

paj7620u2_iic.c文件:

//PAJ2670 I2C初始化
void GS_i2c_init(void)
{
            /* Setup I2C initialization values. */
            I2C_Master_Init_Type i2c_init;
            i2c_init.ClockFreqHz = BOARD_I2C_FREQ;
            i2c_init.BaudRate = I2C_BaudRate_100K;

            /* Initialize I2C master. */
            I2C_InitMaster(BOARD_I2C_PORT, &i2c_init);

            /* The target device address needs to be configured before enabling. */
            I2C_SetTargetAddr(BOARD_I2C_PORT, APP_I2C_TARGET_ADDR);
            
            /* Enable I2C. */
            I2C_Enable(BOARD_I2C_PORT, true);
            
            GPIO_WriteBit(SCL_PORT,SCL_GPIO,1u);
            GPIO_WriteBit(SDA_PORT,SDA_GPIO,1u);
            
}

/***************************************************************************************************************
*switch SDA GPIO input or output
****************************************************************************************************************/
void SDA_SetGpioMode(uint8_t mode)
{
      GPIO_Init_Type gpio_init;
        gpio_init.Pins  = SDA_GPIO;
    
        if(mode==1)
    {
            gpio_init.PinMode  = GPIO_PinMode_Out_PushPull;
            gpio_init.Speed = GPIO_Speed_50MHz;
        }
        else
            gpio_init.PinMode  = GPIO_PinMode_In_PullUp;
    GPIO_Init(SDA_PORT, &gpio_init);
    GPIO_PinAFConf(SDA_PORT, gpio_init.Pins, GPIO_AF_4);
    
}

void SCL_SetGpioMode(uint8_t mode)
{
      GPIO_Init_Type gpio_init;
        gpio_init.Pins  = SCL_GPIO;
    
        if(mode==1)
    {
            gpio_init.PinMode  = GPIO_PinMode_Out_PushPull;
            gpio_init.Speed = GPIO_Speed_50MHz;
        }
        else
            gpio_init.PinMode  = GPIO_PinMode_In_PullUp;
    GPIO_Init(SCL_PORT, &gpio_init);
    GPIO_PinAFConf(SCL_PORT, gpio_init.Pins, GPIO_AF_4);    
    
}

//产生IIC起始信号
static void GS_IIC_Start(void)
{
    SDA_SetGpioMode(1);
    SDA_H;
    SCL_H;
        app_delay_us(4);
    SDA_L;
      app_delay_us(4);
    SCL_L;
}

//产生IIC停止信号
static void GS_IIC_Stop(void)
{
    SDA_SetGpioMode(1);//sda线输出
    SCL_L;
    SDA_L;
      app_delay_us(4);
    SCL_H;
    SDA_H;
      app_delay_us(4);
}

//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
static uint8_t GS_IIC_Wait_Ack(void)
{
    uint8_t ucErrTime=0;
    SDA_SetGpioMode(0);  //SDA设置为输入
    SDA_H;
    app_delay_us(3);
    SCL_H;
    app_delay_us(3);
    while(SDA_R)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            GS_IIC_Stop();
            return 1;
        }
    }
    SCL_L;
    return 0;
}

//产生ACK应答
static void GS_IIC_Ack(void)
{
    SCL_L;
    SDA_SetGpioMode(1);
    SDA_L;
      app_delay_us(3);
    SCL_H;
      app_delay_us(3);
    SCL_L;
}

//不产生ACK应答            
static void GS_IIC_NAck(void)
{
    SCL_L;
    SDA_SetGpioMode(1);
    SDA_H;
        app_delay_us(2);
    SCL_H;
        app_delay_us(2);
    SCL_L;
}

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答              
static void GS_IIC_Send_Byte(uint8_t txd)
{
    uint8_t t;
    SDA_SetGpioMode(1);
    SCL_L;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {
      if((txd&0x80)>>7)
          SDA_H;
      else
          SDA_L;
      txd<<=1;
          app_delay_us(5);
      SCL_H;
          app_delay_us(5);
      SCL_L;
          app_delay_us(5);
    }
} 

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
static uint8_t GS_IIC_Read_Byte(uint8_t ack)
{
    uint8_t i,receive=0;
    SDA_SetGpioMode(0);//SDA设置为输入
    for(i=0;i<8;i++ )
    {
        SCL_L;
            app_delay_us(4);
        SCL_H;
        receive<<=1;
        if(SDA_R)receive++;
            app_delay_us(4);
    }
    if (!ack)
        GS_IIC_NAck();//发送nACK
    else
        GS_IIC_Ack(); //发送ACK
    return receive;
}

//PAJ7620U2写一个字节数据
uint8_t GS_Write_Byte(uint8_t REG_Address,uint8_t REG_data)
{
    GS_IIC_Start();
    GS_IIC_Send_Byte(PAJ7620_ID);
    if(GS_IIC_Wait_Ack())
    {
        GS_IIC_Stop();//释放总线
        return 1;//没应答则退出

    }
    GS_IIC_Send_Byte(REG_Address);
    GS_IIC_Wait_Ack();    
    GS_IIC_Send_Byte(REG_data);
    GS_IIC_Wait_Ack();    
    GS_IIC_Stop();

    return 0;
}

//PAJ7620U2读一个字节数据
uint8_t GS_Read_Byte(uint8_t REG_Address)
{
    uint8_t REG_data;
    
    GS_IIC_Start();
    GS_IIC_Send_Byte(PAJ7620_ID);//发写命令
    if(GS_IIC_Wait_Ack())
    {
         GS_IIC_Stop();//释放总线
         return 0;//没应答则退出
    }        
    GS_IIC_Send_Byte(REG_Address);
    GS_IIC_Wait_Ack();
    GS_IIC_Start(); 
    GS_IIC_Send_Byte(PAJ7620_ID|0x01);//发读命令
    GS_IIC_Wait_Ack();
    REG_data = GS_IIC_Read_Byte(0);
    GS_IIC_Stop();

    return REG_data;
}
//PAJ7620U2读n个字节数据
uint8_t GS_Read_nByte(uint8_t REG_Address,uint16_t len,uint8_t *buf)
{
    GS_IIC_Start();
    GS_IIC_Send_Byte(PAJ7620_ID);//发写命令
    if(GS_IIC_Wait_Ack()) 
    {
        GS_IIC_Stop();//释放总线
        return 1;//没应答则退出
    }
    GS_IIC_Send_Byte(REG_Address);
    GS_IIC_Wait_Ack();

    GS_IIC_Start();
    GS_IIC_Send_Byte(PAJ7620_ID|0x01);//发读命令
    GS_IIC_Wait_Ack();
    while(len)
    {
        if(len==1)
        {
            *buf = GS_IIC_Read_Byte(0);
        }
        else
        {
            *buf = GS_IIC_Read_Byte(1);
        }
        buf++;
        len--;
    }
    GS_IIC_Stop();//释放总线

    return 0;
    
}
//PAJ7620唤醒
void GS_WakeUp(void)
{
    GS_IIC_Start();
    GS_IIC_Send_Byte(PAJ7620_ID);//发写命令
    GS_IIC_Stop();//释放总线
}

paj7620u2.c文件:

//手势识别测试
void Gesture_test(void)
{
    uint8_t i;
    uint8_t status;
    uint8_t key;
    uint8_t data[2]={0x00};
    uint16_t gesture_data;
    uint8_t ledflash=0;
    
    paj7620u2_selectBank(BANK0);//进入BANK0寄存器区域
    for(i=0;i<GESTURE_SIZE;i++)
    {
        GS_Write_Byte(gesture_arry[i][0],gesture_arry[i][1]);//手势识别模式初始化
    }
    paj7620u2_selectBank(BANK0);//切换回BANK0寄存器区域
    i=0;

    printf("---  Gesture show  ---\r\n");

    while(1)
    {
        status = GS_Read_nByte(PAJ_GET_INT_FLAG1,2,&data[0]);//读取手势状态            
        if(!status)
        {   

            gesture_data =(uint16_t)data[1]<<8 | data[0];
            if(gesture_data) 
            {
                switch(gesture_data)
                {
                    case GES_UP:
                        printf("Up\r\n");
                        ledflash=1;
                    
                            GPIO_WriteBit(GPIOC,GPIO_PIN_9,1u);
                            GPIO_WriteBit(GPIOB,GPIO_PIN_14,0u);
                            GPIO_WriteBit(GPIOD,GPIO_PIN_2,0u);
                            GPIO_WriteBit(GPIOI,GPIO_PIN_0,0u);
                        break; //向上
                    case GES_DOWM:
                           printf("Dowm\r\n");
                           ledflash=1;
                            GPIO_WriteBit(GPIOC,GPIO_PIN_9,0u);
                            GPIO_WriteBit(GPIOB,GPIO_PIN_14,1u);
                            GPIO_WriteBit(GPIOD,GPIO_PIN_2,0u);
                            GPIO_WriteBit(GPIOI,GPIO_PIN_0,0u);
                           break; //向下
                    case GES_LEFT:
                          printf("Left\r\n");
                          ledflash=1;
                            GPIO_WriteBit(GPIOC,GPIO_PIN_9,0u);
                            GPIO_WriteBit(GPIOB,GPIO_PIN_14,0u);
                            GPIO_WriteBit(GPIOD,GPIO_PIN_2,1u);
                            GPIO_WriteBit(GPIOI,GPIO_PIN_0,0u);
                          break; //向左
                    case GES_RIGHT:
                        printf("Right\r\n");
                        ledflash=1;
                            GPIO_WriteBit(GPIOC,GPIO_PIN_9,0u);
                            GPIO_WriteBit(GPIOB,GPIO_PIN_14,0u);
                            GPIO_WriteBit(GPIOD,GPIO_PIN_2,0u);
                            GPIO_WriteBit(GPIOI,GPIO_PIN_0,1u);
                        break; //向右
                    default:                  
                        ledflash=0; break;
                    
                }    

        app_delay_ms(300);
        i++;
        printf("### check %d\r\n",i);
        if(i==500)
        {
            i=0;
        }           
    }
}

main.c文件:

/*
 * Functions.
 */
int main(void)
{
      uint8_t check_yn =0;

    BOARD_Init();

    printf("hello, world\r\n");
    
        app_delay_ms(500);
        printf("PAJ7620U2 test\r\n");
    
      while(!paj7620u2_init())
    {
        printf("PAJ7620U2 Error!!!\r\n");
              check_yn = 1;
    }
        if(check_yn==1)
        {
            printf("PAJ7620U2 Ok!!!\r\n");
        }

    while (1)
    {
              if(check_yn==1)
                {
                    paj7620u2_sensor_test();//PAJ7620U2传感器测试
                }
    }
}

六、最后实验输出结果:

0002.png

推荐阅读
关注数
6144
内容数
276
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息