[STM8] STM8硬件I2C与PAJ7620U2手势识别芯片调试分享

[复制链接]
3345|28
 楼主| henangongda123 发表于 2020-10-26 14:44 | 显示全部楼层 |阅读模式
这两天因为工作需要,用STM8单片机调试了一下PAJ7620U2手势识别芯片,网上几乎所有的资料都是STM32的,STM8或者8位单片机控制PAJ7620U2的例子不多,几乎没有,虽然STM32应用广泛,但实际上我们这些做小电子设备产品的暂时还用不上。调试了四五天,中途有个坑,被坑的很惨,大家有需要的可以参考一下,免得掉坑里。
 楼主| henangongda123 发表于 2020-10-26 14:47 | 显示全部楼层
硬件电路很简单,PAJ7620U2我是某宝上买的现成的模块,基本上都大同小异,就是2个LEDO和上拉电阻,因为PAJ7620U2的发射二极管功率较大,所以需要单独供电。电路参考如下:
PAJ7620U2模块.png
 楼主| henangongda123 发表于 2020-10-26 14:50 | 显示全部楼层
然后就是PAJ7620U2的I2C接口和STM8S207的硬件I2C接口对接即可:
STM8S207硬件I2C接口.png
 楼主| henangongda123 发表于 2020-10-26 14:54 | 显示全部楼层
最后说坑!这里面有2个坑,一个STM8S硬件I2C,这个坑在我之前做电子台历的时候,调试DS3231SN芯片已解决,大家有兴趣的可以去看一下我之前的帖子。这个坑的程序代码如下:
/******** PAJ7620手势识别IC驱动及相关数据处理操作 *********/
/***********************************************************
函数名: PAJ7620_Read()
功  能: STM8S207 MCU通过硬件I2C通信读取PAJ7620内多个寄存器数据
参  数: reg_address --- 欲读取数据的寄存器起始地址
        data_buff   --- 从PAJ7620读取的多字节数据指针
                          data_len    --- 从PAJ7620读取的多字节数据长度
返回值: 无
***********************************************************/
void PAJ7620_Read(uchar reg_address,uchar *data_buff,uchar data_len)
{         
        uchar temp;                 //定义一下,读取MCU状态寄存器用
        uchar i;                    //定义一下,供循环使用
        uint time;                  //定义一下,供等待延时用
        //以下程序为I2C通信防锁死操作,非常重要!
        if((PE_IDR&0x04) == 0x00)  //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
        {
                I2C_CR1 &= 0xFE;         //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
                PE_DDR |= 0x02;           //设置SCL端口为输出
                PE_CR1 |= 0x02;           //上拉输出
                for(i=0;i<9;i++)         //SCL端口发出9个时钟脉冲,让从设备DS3231释放总线(恢复SDA=1)
                {
                        PE_ODR &= 0xFD;         //SCL=0;
                        delay_us(50);           //延时(I2C通信频率10KHz)
                  PE_ODR |= 0x02;         //SCL=1
                  delay_us(50);           //延时(I2C通信频率10KHz)
                }
                time = 500;               //变量赋值,准备延迟等待500次
                while(!(PE_IDR&0x04))     //等待数据线SDA=1
                {
                  if(!--time)             //变量自减
                  return;                 //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
          }
                PE_DDR &= 0xFD;           //SCL端口恢复输入方式
                PE_CR1 &= 0xFD;           //浮空输入
                PE_ODR &= 0xFD;           //清零输出寄存器
                I2C_CR1 |= 0x01;         //重新启动硬件I2C模块,接管SCL、SDA端口
                return;                  //退出函数,放弃本次数据读取操作
        }
        //以上程序为I2C通信防锁死操作,非常重要!
        //以下程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
        if((I2C_SR3&0x02) == 0x02) //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
        {
                I2C_CR2 |= 0x80;         //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
          I2C_CR2 &= 0x7F;         //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
                I2C_FREQR = 0x02;         //配置I2C外设时钟2MHz
                I2C_CCRH = 0x00;          //配置I2C为标准模式及速率
                I2C_CCRL = 0x64;          //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
          I2C_TRISER = 0x03;        //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
                I2C_CR1 |= 0x01;          //启动I2C硬件模块
                return;                  //退出函数,放弃本次数据读取操作
        }
        //以上程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
       
        /****** 第一步: 发送写指令(器件地址) ******/
        time = 500;                 //变量赋值,准备延迟等待500次
        while(I2C_SR3&0x02)         //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))     //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = PAJ7620_ID;        //发送PAJ7620写指令(器件地址)
       
        /****** 第二步: 写入欲读取的寄存器首地址 ******/
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;            //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_DR = reg_address;       //发送欲读取数据的寄存器首地址
       
        /****** 第三步: 发送读指令(器件地址|0x01) ******/
  time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        I2C_CR2 |= 0x01;            //重复发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))     //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = PAJ7620_ID|0x01;   //发送PAJ7620读指令

  /****** 第四步: 读取数据 ******/
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;            //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_CR2        |= 0x04;           //使能ACK应答(置位I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后返回应答)
        while(data_len)             //循环读取数据
        {
                if(data_len == 1)        //如果是接收最后一位数据(特殊处理)
                {
                        I2C_CR2 &= 0xFB;       //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
                        I2C_CR2 |= 0x02;        //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
                }
                if(I2C_SR1 & 0x40)        //数据寄存器为满(I2C_SR1状态寄存器RxNE位为1时,表示接收寄存器数据非空)
                {
                        *data_buff = I2C_DR;   //读取数据寄存器内数值,同时清除BTF位
                        data_buff++;            //准备接收下一字节数据
                        data_len--;
                }
        }
       
        /****** 第五步: 收尾 ******/
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        temp = I2C_DR;              //清除I2C_SR1中BFT位
}

一定要注意上面的I2C通信防锁死操作和防BUSY锁死操作,非常重要!
 楼主| henangongda123 发表于 2020-10-26 14:56 | 显示全部楼层
最后,还有一个坑就是PAJ7620U2连续写操作之间要加延时,一定要延时,10ms左右,不能太短,否则初始化数组写不成功的,这个坑搞了我好几天!代码如下:
/***********************************************************
函数名: PAJ7620_Init()
功  能: PAJ7620U2手势识别芯片初始化操作
参  数: 无
返回值: 无
***********************************************************/
void PAJ7620_Init(void)
{
  uchar i,PAJ7620_R1_Data1[1]={0x00}; //定义保存子函数临时使用数据
        do                          //执行唤醒操作
        {
          PAJ7620_WakeUp();         //唤醒PAJ7620
          delay_ms(5);              //延时等待(最低700us)
          PAJ7620_WakeUp();         //再次唤醒PAJ7620
          delay_ms(5);              //延时等待(最低700us)
          PAJ7620_SelectBank(0);    //选择BANK0寄存器区域
    PAJ7620_Read(0x00,PAJ7620_R1_Data1,1);//读取0x00寄存器数值,判断是否唤醒正确
        }
        while(PAJ7620_R1_Data1[0]==0x20);//直到正确唤醒
        PAJ7620_SelectBank(0);      //选择BANK0寄存器区域
        for(i=0;i<INIT_SIZE;i++)    //准备写入上电初始化初始化寄存器数据
        {
                PAJ7620_Write(Init_Array[i][0],Init_Array[i][1]); //上电初始化PAJ7620U2寄存器配置
                delay_ms(10);            //延时(此步非常重要,PAJ7620连续写操作需要间隔一段时间,否则不能正常写完)
        }
        PAJ7620_SelectBank(0);      //选择Bank0区域寄存器
        for(i=0;i<GESTURE_SIZE;i++) //准备写入手势模式初始化寄存器数据
        {
                PAJ7620_Write(Gesture_Arry[i][0],Gesture_Arry[i][1]); //初始化PAJ7620U2手势模式
                delay_ms(10);            //延时(此步非常重要,PAJ7620连续写操作需要间隔一段时间,否则不能正常写完)
        }
}
goyhuan 发表于 2020-10-26 15:53 | 显示全部楼层
谢谢分享
氧化二氢 发表于 2020-10-26 22:54 | 显示全部楼层
谢谢分享 请问你用的是8位的哪个板子
 楼主| henangongda123 发表于 2020-10-27 11:18 | 显示全部楼层
氧化二氢 发表于 2020-10-26 22:54
谢谢分享 请问你用的是8位的哪个板子

STM8S207CB主控板
奔牛滚滚 发表于 2020-10-27 13:39 来自手机 | 显示全部楼层
感觉用硬件的模块比用io模拟的还复杂
 楼主| henangongda123 发表于 2020-10-27 17:04 | 显示全部楼层
奔牛滚滚 发表于 2020-10-27 13:39
感觉用硬件的模块比用io模拟的还复杂

貌似是,IO模拟的多
hjl2832 发表于 2020-10-27 20:49 | 显示全部楼层
这个好,谢谢分享,手势识别芯片编程。
 楼主| henangongda123 发表于 2020-10-28 15:49 | 显示全部楼层
小喇叭关注了,那就贴上完整代码吧!
 楼主| henangongda123 发表于 2020-10-28 15:53 | 显示全部楼层
  1. /**********************************************************************
  2. 文件名: 基于STM8S207的PAJ7620U2手势识别测试程序
  3. 编  写: Michael Lee
  4. 单  位:
  5. 时  间: 2020年10月20日
  6. 修  改:
  7. 备  注:
  8.         1. CPU主时钟选择内部16MHz RC振荡器;
  9.                           2. 接口说明:
  10.                                    STM8S207CBT6  -----   外部设备
  11.                                    ******** 12864液晶显示器 ********
  12.                                    PD2           -----   YJ_RS
  13.                                    PD3           -----   YJ_RW
  14.                                    PD4           -----   YJ_E
  15.                                    PC1           -----   YJ_PSB
  16.                                    PB0-7         -----   YJ_DB0-7
  17.                                    ******** STM8S硬件I2C ********
  18.                                    PE1           -----   PAJ7620_SCL
  19.                                    PE2           -----   PAJ7620_SDA
  20. 声明:
  21. **********************************************************************/
  22. //加载头文件
  23. #include "stm8s207cb.h"

  24. //宏定义
  25. #define uchar unsigned char
  26. #define uint unsigned int
  27. #define ushort unsigned short
  28. #define EEP_BASE 0x4000       //STM8S大容量Data EEPROM起始地址
  29. #define EEPROM_Lock() FLASH_IAPSR&=(~0x08)  
  30. #define EEPROM_Wait_Read_Over() while(!(FLASH_IAPSR&0x04))
  31. #define EEPROM_Wrover_Clear() FLASH_IAPSR&=(~0x04)
  32. #define PAJ7620_ID 0x73<<1    //PAJ7620设备地址(写命令)

  33. //全局变量
  34. uchar Gesture_Flag=0;         //手势识别结果标志

  35. //PAJ7620初始化数据及宏定义
  36. #define INIT_SIZE sizeof(Init_Array)/2
  37. //上电初始化寄存器数组
  38. const unsigned char Init_Array[][2]=
  39. {
  40.         {0xEF,0x00},
  41.         {0x37,0x07},
  42.         {0x38,0x17},
  43.         {0x39,0x06},
  44.         {0x41,0x00},
  45.         {0x42,0x00},
  46.         {0x46,0x2D},
  47.         {0x47,0x0F},
  48.         {0x48,0x3C},
  49.         {0x49,0x00},
  50.         {0x4A,0x1E},
  51.         {0x4C,0x20},
  52.         {0x51,0x10},
  53.         {0x5E,0x10},
  54.         {0x60,0x27},
  55.         {0x80,0x42},
  56.         {0x81,0x44},
  57.         {0x82,0x04},
  58.         {0x8B,0x01},
  59.         {0x90,0x06},
  60.         {0x95,0x0A},
  61.         {0x96,0x0C},
  62.         {0x97,0x05},
  63.         {0x9A,0x14},
  64.         {0x9C,0x3F},
  65.         {0xA5,0x19},
  66.         {0xCC,0x19},
  67.         {0xCD,0x0B},
  68.         {0xCE,0x13},
  69.         {0xCF,0x64},
  70.         {0xD0,0x21},
  71.         {0xEF,0x01},
  72.         {0x02,0x0F},
  73.         {0x03,0x10},
  74.         {0x04,0x02},
  75.         {0x25,0x01},
  76.         {0x27,0x39},
  77.         {0x28,0x7F},
  78.         {0x29,0x08},
  79.         {0x3E,0xFF},
  80.         {0x5E,0x3D},
  81.         {0x65,0x96},
  82.         {0x67,0x97},
  83.         {0x69,0xCD},
  84.         {0x6A,0x01},
  85.         {0x6D,0x2C},
  86.         {0x6E,0x01},
  87.         {0x72,0x01},
  88.         {0x73,0x35},
  89.         {0x74,0x00},
  90.         {0x77,0x01},
  91. };
  92. #define GESTURE_SIZE sizeof(Gesture_Arry)/2
  93. //手势识别初始化寄存器数组
  94. const unsigned char Gesture_Arry[][2]=
  95. {
  96.         {0xEF,0x00},
  97.         {0x41,0x00},
  98.         {0x42,0x00},
  99.         {0xEF,0x00},
  100.         {0x48,0x3C},
  101.         {0x49,0x00},
  102.         {0x51,0x10},
  103.         {0x83,0x20},
  104.         {0x9F,0xF9},
  105.         {0xEF,0x01},
  106.         {0x01,0x1E},
  107.         {0x02,0x0F},
  108.         {0x03,0x10},
  109.         {0x04,0x02},
  110.         {0x41,0x40},
  111.         {0x43,0x30},
  112.         {0x65,0x96},
  113.         {0x66,0x00},
  114.         {0x67,0x97},
  115.         {0x68,0x01},
  116.         {0x69,0xCD},
  117.         {0x6A,0x01},
  118.         {0x6B,0xB0},
  119.         {0x6C,0x04},
  120.         {0x6D,0x2C},
  121.         {0x6E,0x01},
  122.         {0x74,0x00},
  123.         {0xEF,0x00},
  124.         {0x41,0xFF},
  125.         {0x42,0x01},
  126. };

  127. /********** 延时函数 ********/
  128. /***********************************************************
  129. 函数名: delay_us()、delay_ms()
  130. 功  能: 微秒级、毫秒级延时程序
  131. 参  数: us --- 欲延时微秒数
  132.         ms --- 欲延时毫秒数
  133. /**********************************************************/
  134. void delay_us(unsigned int us)
  135. {
  136. //24M 1个int us延时0.68uS
  137. //16M 1.02us
  138.         while(us--);
  139. }
  140. void delay_ms(unsigned int ms)//16MHZ 延时1ms
  141. {
  142.         unsigned int i;
  143.         while(ms--)
  144.         {
  145.                 for(i=0;i<1421;i++){}     //1421
  146.         }
  147. }

  148. /******* 系统时钟切换操作 *******/
  149. /***********************************************************
  150. 函数名: Clk_Init()
  151. 功  能: 时钟初始化
  152. 参  数: 无
  153. 返回值: 无
  154. /**********************************************************/
  155. void Clk_Init(void)
  156. {
  157.         CLK_CKDIVR = 0x00;
  158. //配置系统内部时钟分频系数为1(16M),CPU时钟分频系数为1(16M)
  159. }

  160. /********* 端口初始化操作 **********/
  161. /***********************************************************
  162. 函数名: Port_Init()
  163. 功  能: 端口初始化配置
  164. 参  数: 无
  165. 返回值: 无
  166. /**********************************************************/
  167. void Port_Init(void)
  168. {
  169. //12864液晶控制接口
  170.         PC_DDR |= 0x04;             //配置PC2为输出方式(液晶显示器背光控制端口)
  171.         PC_CR1 |= 0x04;             //配置端口推挽输出
  172.         PC_CR2 = 0x00;              //普通2M的输出摆率
  173.         PC_ODR |= 0x04;             //YJ_ON=1,选择开启液晶背光
  174.         PD_DDR |= 0x1C;             //配置PD2-4为输出方式(液晶显示器RS,RW,E端口)
  175.         PD_CR1 |= 0x1C;             //配置端口推挽输出
  176.         PD_CR2  = 0x00;             //普通2M的输出摆率
  177.         PB_DDR |= 0xFF;            //配置PB0-7输出(液晶数据DB0-7端口)
  178.         PB_CR1 |= 0xFF;             //推挽输出
  179.         PB_CR2 = 0x00;              //普通2M摆率
  180. }

  181. /******* 12864液晶(ST7920主控IC)显示器驱动及相关操作 *******/
  182. //底层驱动函数
  183. //写入一字节指令/数据
  184. /***********************************************************
  185. 函数名: lcd_w_char()
  186. 功  能: 向12864液晶写入一字节指令/数据
  187. 参  数: cd    --- 写入指令/数据选择标志(0=指令,1=数据)
  188.                           cdata --- 写入指令/数据内容
  189. 返回值: 无
  190. /**********************************************************/
  191. void lcd_w_char(uchar cd, uchar cdata)
  192. {
  193.         if(cd == 0)                 //选择写入"指令"
  194.   {
  195.                 PD_ODR &= (~0x04);        //RS=0,选择写"指令"
  196.         }
  197.         if(cd == 1)                 //选择写入"数据"
  198.         {
  199.                 PD_ODR |= 0x04;           //RS=1,选择写"数据"
  200.         }
  201.         PD_ODR &= (~0x08);          //RW=0,选择"写"操作
  202.         PB_ODR = cdata;             //加载指令/数据内容
  203.         PD_ODR |= 0x10;             //E=1,开始写入指令/数据
  204.         delay_us(1);                //延时,等待液晶端口读入指令/数据内容
  205.         PD_ODR &= (~0x10);          //E=0,写入完成
  206.         delay_us(80);               //液晶处理指令时间一般为72us
  207. }
  208. //写入一串字符数据
  209. /***********************************************************
  210. 函数名: lcd_w_word()
  211. 功  能:  向12864液晶写入一串字符数据(最长64字符: 8个汉字或16个数字/英文字符)
  212.                            (注: ST7920主控IC的12864液晶内部已集成汉字库,程序可直接写入汉字字符)
  213. 参  数: str --- 字符串内容
  214. 返回值: 无
  215. ***********************************************************/
  216. void lcd_w_word(uchar *str)
  217. {
  218.         while(*str != '\0')         //字符串未结束
  219.         {
  220.                 lcd_w_char(1,*str++);     //写入每个字符串数据内容
  221.         }
  222.         *str = 0;
  223. }
  224. //初始化函数
  225. /***********************************************************
  226. 函数名: Lcd_Init()
  227. 功  能: 12864液晶初始化
  228. 参  数: 无
  229. 返回值: 无
  230. /**********************************************************/
  231. void Lcd_Init(void)
  232. {
  233.         lcd_w_char(0,0x30);        //写入指令,选择8位界面,基本指令集,绘图显示关
  234.         lcd_w_char(0,0x0c);         //显示开,光标关闭
  235.         lcd_w_char(0,0x01);         //清屏
  236.         delay_ms(5);                //液晶处理指令时间4.6ms
  237. }

  238. /********* STM8S硬件I2C相关操作 **********/
  239. //初始化函数
  240. /***********************************************************
  241. 函数名: I2C_Init()
  242. 功  能: STM8S207 MCU硬件I2C初始化
  243.         (注: 主模式,两线连接,7位地址模式,40Kbps通信速率)
  244. 参  数: 无
  245. 返回值: 无
  246. ***********************************************************/
  247. void I2C_Init(void)
  248. {
  249.   I2C_CR1 &= 0xFE;           //PE=0,禁用硬件I2C模块(所有位置0)
  250.         CLK_PCKENR1 |= 0x01;        //使能I2C时钟
  251.         I2C_CR2 |= 0x80;           //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
  252.         I2C_CR2 &= 0x7F;           //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
  253.   I2C_FREQR = 0x02;           //配置I2C外设时钟2MHz
  254.         I2C_CCRH = 0x00;            //配置I2C为标准模式及速率
  255.         I2C_CCRL = 0x32;            //I2C通信速率半周期=((1/2)*50us=25us,速率=1/25us=40KHz
  256.         I2C_TRISER = 0x03;          //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
  257.         I2C_CR1 |= 0x01;            //启动I2C硬件模块
  258. }

  259. /******** PAJ7620手势识别IC驱动及相关数据处理操作 *********/
  260. /***********************************************************
  261. 函数名: PAJ7620_Read()
  262. 功  能: STM8S207 MCU通过硬件I2C通信读取PAJ7620内多个寄存器数据
  263. 参  数: reg_address --- 欲读取数据的寄存器起始地址
  264.         data_buff   --- 从PAJ7620读取的多字节数据指针
  265.                           data_len    --- 从PAJ7620读取的多字节数据长度
  266. 返回值: 无
  267. ***********************************************************/
  268. void PAJ7620_Read(uchar reg_address,uchar *data_buff,uchar data_len)
  269. {         
  270.         uchar temp;                 //定义一下,读取MCU状态寄存器用
  271.         uchar i;                    //定义一下,供循环使用
  272.         uint time;                  //定义一下,供等待延时用
  273.         //以下程序为I2C通信防锁死操作,非常重要!
  274.         if((PE_IDR&0x04) == 0x00)  //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
  275.         {
  276.                 I2C_CR1 &= 0xFE;         //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
  277.                 PE_DDR |= 0x02;           //设置SCL端口为输出
  278.                 PE_CR1 |= 0x02;           //上拉输出
  279.                 for(i=0;i<9;i++)         //SCL端口发出9个时钟脉冲,让从设备DS3231释放总线(恢复SDA=1)
  280.                 {
  281.                         PE_ODR &= 0xFD;         //SCL=0;
  282.                         delay_us(50);           //延时(I2C通信频率10KHz)
  283.                   PE_ODR |= 0x02;         //SCL=1
  284.                   delay_us(50);           //延时(I2C通信频率10KHz)
  285.                 }
  286.                 time = 500;               //变量赋值,准备延迟等待500次
  287.                 while(!(PE_IDR&0x04))     //等待数据线SDA=1
  288.                 {
  289.                   if(!--time)             //变量自减
  290.                   return;                 //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  291.           }
  292.                 PE_DDR &= 0xFD;           //SCL端口恢复输入方式
  293.                 PE_CR1 &= 0xFD;           //浮空输入
  294.                 PE_ODR &= 0xFD;           //清零输出寄存器
  295.                 I2C_CR1 |= 0x01;         //重新启动硬件I2C模块,接管SCL、SDA端口
  296.                 return;                  //退出函数,放弃本次数据读取操作
  297.         }
  298.         //以上程序为I2C通信防锁死操作,非常重要!
  299.         //以下程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
  300.         if((I2C_SR3&0x02) == 0x02) //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
  301.         {
  302.                 I2C_CR2 |= 0x80;         //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
  303.           I2C_CR2 &= 0x7F;         //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
  304.                 I2C_FREQR = 0x02;         //配置I2C外设时钟2MHz
  305.                 I2C_CCRH = 0x00;          //配置I2C为标准模式及速率
  306.                 I2C_CCRL = 0x64;          //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
  307.           I2C_TRISER = 0x03;        //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
  308.                 I2C_CR1 |= 0x01;          //启动I2C硬件模块
  309.                 return;                  //退出函数,放弃本次数据读取操作
  310.         }
  311.         //以上程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
  312.        
  313.         /****** 第一步: 发送写指令(器件地址) ******/
  314.         time = 500;                 //变量赋值,准备延迟等待500次
  315.         while(I2C_SR3&0x02)         //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
  316.         {
  317.                 if(!--time)               //变量自减
  318.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  319.         }
  320.         I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
  321.         time = 500;                 //变量赋值,准备延迟等待500次
  322.         while(!(I2C_SR1&0x01))     //I2C_SR1状态寄存器SB位=1表示发送成功
  323.         {
  324.                 if(!--time)               //变量自减
  325.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  326.         }
  327.         delay_us(5);                //短暂延时
  328.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
  329.         I2C_DR = PAJ7620_ID;        //发送PAJ7620写指令(器件地址)
  330.        
  331.         /****** 第二步: 写入欲读取的寄存器首地址 ******/
  332.         time = 500;                 //变量赋值,准备延迟等待500次
  333.         while(!(I2C_SR1&0x02))     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
  334.         {
  335.                 if(!--time)               //变量自减
  336.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  337.         }
  338.         delay_us(5);                //短暂延时
  339.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
  340.         temp = I2C_SR3;            //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
  341.         I2C_DR = reg_address;       //发送欲读取数据的寄存器首地址
  342.        
  343.         /****** 第三步: 发送读指令(器件地址|0x01) ******/
  344.   time = 500;                 //变量赋值,准备延迟等待500次
  345.         while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
  346.         {
  347.                 if(!--time)               //变量自减
  348.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  349.         }
  350.         I2C_CR2 |= 0x01;            //重复发起始条件(置位I2C_CR2控制寄存器START位)
  351.         time = 500;                 //变量赋值,准备延迟等待500次
  352.         while(!(I2C_SR1&0x01))     //I2C_SR1状态寄存器SB位=1表示发送成功
  353.         {
  354.                 if(!--time)               //变量自减
  355.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  356.         }
  357.         delay_us(5);                //短暂延时
  358.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
  359.         I2C_DR = PAJ7620_ID|0x01;   //发送PAJ7620读指令

  360.   /****** 第四步: 读取数据 ******/
  361.         time = 500;                 //变量赋值,准备延迟等待500次
  362.         while(!(I2C_SR1&0x02))     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
  363.         {
  364.                 if(!--time)               //变量自减
  365.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  366.         }
  367.         delay_us(5);                //短暂延时
  368.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
  369.         temp = I2C_SR3;            //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
  370.         I2C_CR2        |= 0x04;           //使能ACK应答(置位I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后返回应答)
  371.         while(data_len)             //循环读取数据
  372.         {
  373.                 if(data_len == 1)        //如果是接收最后一位数据(特殊处理)
  374.                 {
  375.                         I2C_CR2 &= 0xFB;       //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
  376.                         I2C_CR2 |= 0x02;        //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
  377.                 }
  378.                 if(I2C_SR1 & 0x40)        //数据寄存器为满(I2C_SR1状态寄存器RxNE位为1时,表示接收寄存器数据非空)
  379.                 {
  380.                         *data_buff = I2C_DR;   //读取数据寄存器内数值,同时清除BTF位
  381.                         data_buff++;            //准备接收下一字节数据
  382.                         data_len--;
  383.                 }
  384.         }
  385.        
  386.         /****** 第五步: 收尾 ******/
  387.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
  388.         temp = I2C_DR;              //清除I2C_SR1中BFT位
  389. }

 楼主| henangongda123 发表于 2020-10-28 15:54 | 显示全部楼层
  1. /***********************************************************
  2. 函数名: PAJ7620_Write()
  3. 功  能: STM8S207 MCU通过硬件I2C通信写入PAJ7620寄存器一字节数据
  4. 参  数: write_address --- 欲写入的寄存器地址
  5.                                 write_data    --- 欲写入的一字节数据
  6. 返回值: 无
  7. ***********************************************************/
  8. void PAJ7620_Write(uchar write_address,uchar write_data)
  9. {         
  10.         uchar temp;                 //定义一下,读取MCU状态寄存器用
  11.         uchar i;                    //定义一下,供循环使用
  12.         uint time;                  //定义一下,供等待延时用
  13.         //以下程序为I2C通信防锁死操作,非常重要!
  14.         if((PE_IDR&0x04) == 0x00)  //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
  15.         {
  16.                 I2C_CR1 &= 0xFE;         //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
  17.                 PE_DDR |= 0x02;           //设置SCL端口为输出
  18.                 PE_CR1 |= 0x02;           //上拉输出
  19.                 for(i=0;i<9;i++)         //SCL端口发出9个时钟脉冲,让从设备DS3231释放总线(恢复SDA=1)
  20.                 {
  21.                         PE_ODR &= 0xFD;         //SCL=0;
  22.                         delay_us(50);           //延时(I2C通信频率10KHz)
  23.                   PE_ODR |= 0x02;         //SCL=1
  24.                   delay_us(50);           //延时(I2C通信频率10KHz)
  25.                 }
  26.                 time = 500;               //变量赋值,准备延迟等待500次
  27.                 while(!(PE_IDR&0x04))     //等待数据线SDA=1
  28.                 {
  29.                   if(!--time)             //变量自减
  30.                   return;                 //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  31.           }
  32.                 PE_DDR &= 0xFD;           //SCL端口恢复输入方式
  33.                 PE_CR1 &= 0xFD;           //浮空输入
  34.                 PE_ODR &= 0xFD;           //清零输出寄存器
  35.                 I2C_CR1 |= 0x01;         //重新启动硬件I2C模块,接管SCL、SDA端口
  36.                 return;                   //退出函数,放弃本次数据写操作
  37.         }
  38.         //以上程序为I2C通信防锁死操作,非常重要!
  39.         //以下程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
  40.         if((I2C_SR3&0x02) == 0x02) //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
  41.         {
  42.                 I2C_CR2 |= 0x80;         //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
  43.           I2C_CR2 &= 0x7F;         //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
  44.                 I2C_FREQR = 0x02;         //配置I2C外设时钟2MHz
  45.                 I2C_CCRH = 0x00;          //配置I2C为标准模式及速率
  46.                 I2C_CCRL = 0x64;          //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
  47.           I2C_TRISER = 0x03;        //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
  48.                 I2C_CR1 |= 0x01;          //启动I2C硬件模块
  49.                 return;                   //退出函数,放弃本次数据写操作
  50.         }
  51.         //以上程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
  52.        
  53.         /****** 第一步: 发送写指令(器件地址) ******/
  54.         I2C_CR2 &= 0xFB;           //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
  55.         time = 500;                 //变量赋值,准备延迟等待500次
  56.         while(I2C_SR3&0x02)         //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
  57.         {
  58.                 if(!--time)               //变量自减
  59.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  60.         }
  61.         I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
  62.         time = 500;                 //变量赋值,准备延迟等待500次
  63.         while(!(I2C_SR1&0x01))     //I2C_SR1状态寄存器SB位=1表示发送成功
  64.         {
  65.                 if(!--time)               //变量自减
  66.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  67.         }
  68.         delay_us(5);                //短暂延时
  69.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
  70.         I2C_DR = PAJ7620_ID;        //发送PAJ7620写指令(器件地址)
  71.        
  72.         /****** 第二步: 写入欲写入数据的寄存器首地址 ******/
  73.         time = 500;                 //变量赋值,准备延迟等待500次
  74.         while(!(I2C_SR1&0x02))      //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
  75.         {
  76.                 if(!--time)               //变量自减
  77.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  78.         }
  79.         delay_us(5);                //短暂延时
  80.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
  81.         temp = I2C_SR3;            //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
  82.         I2C_DR = write_address;       //发送欲写入数据的寄存器首地址
  83.        
  84.         /****** 第三步: 写入一字节数据 ******/
  85.         time = 500;                 //变量赋值,准备延迟等待500次
  86.         while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
  87.         {
  88.                 if(!--time)               //变量自减
  89.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  90.         }
  91.         I2C_DR = write_data;        //发送一字节数据
  92.         while(!(I2C_SR1&0x84));   //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
  93.        
  94.         /****** 第四步: 收尾 ******/
  95.         I2C_CR2 |= 0x02;            //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
  96. }

  97. /***********************************************************
  98. 函数名: PAJ7620_SelectBank
  99. 功  能: STM8S207 MCU通过硬件I2C通信选择操作寄存器区域
  100. 参  数: 无
  101. 返回值: 无
  102. ***********************************************************/
  103. void PAJ7620_SelectBank(uchar bank)
  104. {
  105.         switch(bank)
  106.         {
  107.                 case 0: PAJ7620_Write(0xEF,0x00);//选择BANK0寄存器区域
  108.                                                 break;
  109.                 case 1: PAJ7620_Write(0xEF,0x01);//选择BANK1寄存器区域
  110.                                                 break;
  111.                 default: break;
  112.         }
  113. }

  114. /***********************************************************
  115. 函数名: PAJ7620_WakeUp()
  116. 功  能: STM8S207 MCU通过硬件I2C通信唤醒PAJ7620
  117. 参  数: 无
  118. 返回值: 无
  119. ***********************************************************/
  120. void PAJ7620_WakeUp(void)
  121. {
  122.         uchar temp;                 //定义一下,读取MCU状态寄存器用
  123.         uchar i;                    //定义一下,供循环使用
  124.         uint time;                  //定义一下,供等待延时用
  125.         //以下程序为I2C通信防锁死操作,非常重要!
  126.         if((PE_IDR&0x04) == 0x00)  //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
  127.         {
  128.                 I2C_CR1 &= 0xFE;         //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
  129.                 PE_DDR |= 0x02;           //设置SCL端口为输出
  130.                 PE_CR1 |= 0x02;           //上拉输出
  131.                 for(i=0;i<9;i++)         //SCL端口发出9个时钟脉冲,让从设备PAJ7620释放总线(恢复SDA=1)
  132.                 {
  133.                         PE_ODR &= 0xFD;         //SCL=0;
  134.                         delay_us(50);           //延时(I2C通信频率10KHz)
  135.                   PE_ODR |= 0x02;         //SCL=1
  136.                   delay_us(50);           //延时(I2C通信频率10KHz)
  137.                 }
  138.                 time = 500;               //变量赋值,准备延迟等待500次
  139.                 while(!(PE_IDR&0x04))     //等待数据线SDA=1
  140.                 {
  141.                   if(!--time)             //变量自减
  142.                   return;                 //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  143.           }
  144.                 PE_DDR &= 0xFD;           //SCL端口恢复输入方式
  145.                 PE_CR1 &= 0xFD;           //浮空输入
  146.                 PE_ODR &= 0xFD;           //清零输出寄存器
  147.                 I2C_CR1 |= 0x01;         //重新启动硬件I2C模块,接管SCL、SDA端口
  148.                 return;                   //退出函数,放弃本次数据写操作
  149.         }
  150.         //以上程序为I2C通信防锁死操作,非常重要!
  151.         //以下程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
  152.         if((I2C_SR3&0x02) == 0x02) //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
  153.         {
  154.                 I2C_CR2 |= 0x80;         //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
  155.           I2C_CR2 &= 0x7F;         //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
  156.                 I2C_FREQR = 0x02;         //配置I2C外设时钟2MHz
  157.                 I2C_CCRH = 0x00;          //配置I2C为标准模式及速率
  158.                 I2C_CCRL = 0x64;          //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
  159.           I2C_TRISER = 0x03;        //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
  160.                 I2C_CR1 |= 0x01;          //启动I2C硬件模块
  161.                 return;                   //退出函数,放弃本次数据写操作
  162.         }
  163.         //以上程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
  164.        
  165.         /****** 第一步: 发送写指令(器件地址) ******/
  166.         I2C_CR2 &= 0xFB;           //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
  167.         time = 500;                 //变量赋值,准备延迟等待500次
  168.         while(I2C_SR3&0x02)         //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
  169.         {
  170.                 if(!--time)               //变量自减
  171.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  172.         }
  173.         I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
  174.         time = 500;                 //变量赋值,准备延迟等待500次
  175.         while(!(I2C_SR1&0x01))     //I2C_SR1状态寄存器SB位=1表示发送成功
  176.         {
  177.                 if(!--time)               //变量自减
  178.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  179.         }
  180.         delay_us(5);                //短暂延时
  181.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
  182.         I2C_DR = PAJ7620_ID;        //发送PAJ7620写指令(器件地址)
  183.        
  184.         /****** 第二步: 等待发送完毕 ******/
  185.         while(!(I2C_SR1&0x02))     //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
  186.         {
  187.                 if(!--time)               //变量自减
  188.                 return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
  189.         }
  190.         delay_us(5);                //短暂延时
  191.         temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
  192.         temp = I2C_SR3;            //清除状态寄存器I2C_SR1中ADDR标志位(地址命令已发送结束)
  193.        
  194.         /****** 第三步: 收尾 ******/
  195.         I2C_CR2 |= 0x02;            //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
  196. }

  197. /***********************************************************
  198. 函数名: PAJ7620_Init()
  199. 功  能: PAJ7620U2手势识别芯片初始化操作
  200. 参  数: 无
  201. 返回值: 无
  202. ***********************************************************/
  203. void PAJ7620_Init(void)
  204. {
  205.   uchar i,PAJ7620_R1_Data1[1]={0x00}; //定义保存子函数临时使用数据
  206.         do                          //执行唤醒操作
  207.         {
  208.           PAJ7620_WakeUp();         //唤醒PAJ7620
  209.           delay_ms(5);              //延时等待(最低700us)
  210.           PAJ7620_WakeUp();         //再次唤醒PAJ7620
  211.           delay_ms(5);              //延时等待(最低700us)
  212.           PAJ7620_SelectBank(0);    //选择BANK0寄存器区域
  213.     PAJ7620_Read(0x00,PAJ7620_R1_Data1,1);//读取0x00寄存器数值,判断是否唤醒正确
  214.         }
  215.         while(PAJ7620_R1_Data1[0]==0x20);//直到正确唤醒
  216.         PAJ7620_SelectBank(0);      //选择BANK0寄存器区域
  217.         for(i=0;i<INIT_SIZE;i++)    //准备写入上电初始化初始化寄存器数据
  218.         {
  219.                 PAJ7620_Write(Init_Array[i][0],Init_Array[i][1]); //上电初始化PAJ7620U2寄存器配置
  220.                 delay_ms(10);            //延时(此步非常重要,PAJ7620连续写操作需要间隔一段时间,否则不能正常写完)
  221.         }
  222.         PAJ7620_SelectBank(0);      //选择Bank0区域寄存器
  223.         for(i=0;i<GESTURE_SIZE;i++) //准备写入手势模式初始化寄存器数据
  224.         {
  225.                 PAJ7620_Write(Gesture_Arry[i][0],Gesture_Arry[i][1]); //初始化PAJ7620U2手势模式
  226.                 delay_ms(10);            //延时(此步非常重要,PAJ7620连续写操作需要间隔一段时间,否则不能正常写完)
  227.         }
  228. }

  229. /***********************************************************
  230. 函数名: Gesture_Get()
  231. 功  能: 获取当前手势识别结果
  232. 参  数: 无
  233. 返回值: 无
  234. ***********************************************************/
  235. void Gesture_Get(void)
  236. {
  237.         uchar PAJ7620_R2_Data1[2]={0x00,0x00};//定义保存临时数据
  238.         PAJ7620_SelectBank(0);      //选择Bank0区域寄存器
  239.         PAJ7620_Read(0x43,PAJ7620_R2_Data1,2); //读取PAJ7620手势结果(Bank0区域0x43、0x44中断标志寄存器)
  240.   if((PAJ7620_R2_Data1[0]&0x01)==0x01)
  241.         {
  242.                 Gesture_Flag=1;           //Up
  243.         }
  244.         else if((PAJ7620_R2_Data1[0]&0x02)==0x02)
  245.         {
  246.                 Gesture_Flag=2;           //Down
  247.         }
  248.         else if((PAJ7620_R2_Data1[0]&0x04)==0x04)
  249.         {
  250.                 Gesture_Flag=3;           //Left
  251.         }
  252.         else if((PAJ7620_R2_Data1[0]&0x08)==0x08)
  253.         {
  254.                 Gesture_Flag=4;           //Right
  255.         }
  256.         else if((PAJ7620_R2_Data1[0]&0x10)==0x10)
  257.         {
  258.                 Gesture_Flag=5;           //Forward
  259.         }
  260.         else if((PAJ7620_R2_Data1[0]&0x20)==0x20)
  261.         {
  262.                 Gesture_Flag=6;           //Backward
  263.         }
  264.         else if((PAJ7620_R2_Data1[0]&0x40)==0x40)
  265.         {
  266.                 Gesture_Flag=7;           //Clockwise
  267.         }
  268.         else if((PAJ7620_R2_Data1[0]&0x80)==0x80)
  269.         {
  270.                 Gesture_Flag=8;           //Counter Clockwise
  271.         }
  272.         else if((PAJ7620_R2_Data1[1]&0x01)==0x01)
  273.         {
  274.                 Gesture_Flag=9;           //Wave
  275.         }
  276. }

  277. /***********************************************************
  278. 函数名: Display()
  279. 功  能: 12864液晶显示屏主屏显示手势测试结果
  280. 参  数: 无
  281. 返回值: 无
  282. ***********************************************************/
  283. void Display(void)
  284. {
  285.         lcd_w_char(0,0x80);         //第一行显示起始地址
  286.         lcd_w_word("  手势识别测试  ");//"手势识别测试"
  287.         lcd_w_char(0,0x90);         //第二行显示起始地址
  288.         lcd_w_word("测试结果:      ");//"测试结果:"
  289.         lcd_w_char(0,0x88);         //第一行显示起始地址
  290.         switch(Gesture_Flag)
  291.         {
  292.                 case 1: lcd_w_word("      向上      ");break; //向上
  293.                 case 2: lcd_w_word("      向下      ");break; //向下
  294.                 case 3: lcd_w_word("      向左      ");break; //向左
  295.                 case 4: lcd_w_word("      向右      ");break; //向右
  296.                 case 5: lcd_w_word("      前进      ");break; //前进
  297.                 case 6: lcd_w_word("      后退      ");break; //后退
  298.                 case 7: lcd_w_word("    顺时针      ");break; //顺时针
  299.                 case 8: lcd_w_word("    逆时针      ");break; //逆时针
  300.           case 9: lcd_w_word("      挥动      ");break; //挥动
  301.                 default: lcd_w_word("    未测出      ");break; //逆时针
  302.         }
  303.         lcd_w_char(0,0x98);         //第二行显示起始地址
  304.         lcd_w_word("        爱上电子");//爱上电子
  305. }

  306. //主函数
  307. void main()
  308. {
  309.         Clk_Init();                 //系统时钟初始化
  310.         Port_Init();                //端口初始化
  311.         I2C_Init();                 //硬件I2C初始化
  312.         delay_ms(200);              //等待软硬件系统稳定
  313.         PAJ7620_Init();             //PAJ7620初始化
  314.         Lcd_Init();                 //12864液晶初始化
  315.         while(1)
  316.         {
  317.                 Gesture_Get();
  318.                 Display();                //12864液晶主屏显示
  319.                 delay_ms(200);            //200ms扫描检测一次(可用定时器定时中断操作)
  320.         }
  321. }


无法去污粉 发表于 2020-10-28 23:28 | 显示全部楼层
请问,调试DS3231SN芯片的帖子在哪里?不太会找你之前的帖子。或者帖子叫什么?我搜一下。
打扰,楼主分享很棒!
 楼主| henangongda123 发表于 2020-10-29 09:04 | 显示全部楼层
无法去污粉 发表于 2020-10-28 23:28
请问,调试DS3231SN芯片的帖子在哪里?不太会找你之前的帖子。或者帖子叫什么?我搜一下。
...

https://bbs.21ic.com/icview-2527734-1-1.html
这个贴里面有源代码
不想画板子 发表于 2020-10-29 10:25 | 显示全部楼层
谢谢分享
xiaoqizi 发表于 2020-11-13 12:36 | 显示全部楼层
手势识别的原理是什么啊
木木guainv 发表于 2020-11-13 12:38 | 显示全部楼层
这个识别芯片大概多少钱啊
磨砂 发表于 2020-11-13 12:40 | 显示全部楼层
调试过程顺利吗  遇到什么问题过吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

2115

帖子

19

粉丝
快速回复 在线客服 返回列表 返回顶部