单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1457|回复: 1
收起左侧

STM32 IIC通信之PAJ7620U2手势识别模块驱动程序源码详解

[复制链接]
不知廉耻 发表于 2019-1-26 18:16 | 显示全部楼层 |阅读模式
大家好。本人小白一个,最近在自学stm32,想用手势识别模块做一点好玩的,正好借此巩固IIC 通信的内容。
很多人刚刚接触IIC、SPI、CAN等通信方式时都会有一堆的问题:为什么要学它?学它可以做什么?我该怎么去学习它呢?我就在这里和大家分享一下自己学习时的所思所感吧,若有表述不对之处,还请各位大佬指出,我好立刻改正。
话不多说,先上硬货。
一、回答上面的问题:
1、什么是IIC通信呢?简单,两条线通信同步串行总线。(在此不做更多说明)
2、为什么要学习这些看起来“根本没多大用处”的通信协议呢?大哥,你总不能永远靠串口吃饭吧,况且真正到了实际项目中,通信的方式要根据环境选择,你总不能想当然的自己决定吧,学好这些通信方式,你才敢有底气去接手一些大项目吧。
3、该怎么学呢?个人觉得,刚刚学习阶段,只要理解大概原理,然后会熟练调用函数就可以了。
二、初识IIC通信:
1、认识IIC的两根线:SCL时钟线和SDA数据线。顾名思义,时钟线,是为整个通信过程提供了时钟信号,也可以说,是作为通信时的“参照物”(后面会说明).SDA即是数据线,在每一个周期里发送0或者1,用这些0和1传输数据。
2、如何传输数据呢?
首先,要传输数据,你总的告诉“另一半”传输开始了吧,所以,开始信号是必不可少的,对应也要有结束信号咯,你的“另一半"接收到了数据,总得告诉你一声吧,所以,应答信号也是少不了的。记住啦,它一点也不难,还有,我会按照我的理解方式来描述它,不会枯燥的。
3.这些信号如何通过两根线就实现呢????
刚才提到了,时钟线SCL作为参照,对、没错,就是这个参照物起了作用。
开始信号:SCL为高电平时,SDA由高电平向低转变。传输开始。
结束信号:SCL为高电平时,SDA由低电平向高转变。传输结束。
应答信号:接收数据的IC 在接收完8个bit的数据之后,向发送数据的IC返回特定脉冲的低电平,表示数据已被签收。
放到实际实验中怎么理解呢?CPU向受控单元发送一段数据之后,等待受控单元发送一个应答信号,若未接受到应答信号,表示受控单元发生故障。这些信号中,只有开始信号时必须的。而且,只有当SCL上为低电平时,SDA上的电平才允许发生变化。(这些资源网上太多了)
这些东西通俗易懂,是必须要了解的。
三、在实战中解读IIC通信。
其实,在工程中用到的绝大部分是调用IIC相关函数。
下面就用手势识别模块举例,我用的是正点原子配套的PAJ7620U2.
首先是初始化IIC对应的引脚 (我认为硬件IIC和软件IIC所实现的功能都一样,不过模拟IIC使用的更广泛,因为方便啊,而且,stm32硬件IIC引脚很鸡肋,还不如不用)。
PAJ2670U2 I2C初始化,(SDA\SCL都被拉高,表示为空闲状态)
void GS_i2c_init(void)//
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOC, ENABLE );  
     
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;      
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_SetBits(GPIOC,GPIO_Pin_11|GPIO_Pin_12);//PB11,PB12 被拉高
   
}
开始信号:
static void GS_IIC_Start(void)
{
    GS_SDA_OUT();//
    GS_IIC_SDA=1;            
    GS_IIC_SCL=1;
    delay_us(4);
     GS_IIC_SDA=0;//START:when CLK is high,DATA change form high to low
    delay_us(4);
    GS_IIC_SCL=0;//
}
说实话,感觉这样照着程序COPY代码太土了,而且浪费大家时间。下面,重要的干货来了。
1、要明确一点,IIC是一种通信方式,不要习惯性想着IIC又该怎么配置?是否要开启对应的时钟?是否可以产生中断?等等,这些东西都是用给外设配置的,通信方式的底层函数基本是不会变的,你要做的就是基于已有的几种命令,与你的IC进行通信。
2、IIC根本不难,然而,就代表不用敲代码了吗?错,大错特错,好记性不如烂笔头,找一个IIC通信例程,敲几遍.C文件里的代码,对于以后做项目还是很有帮助的。
3.不要懒惰,学习这几种通信方式,最好是对比着学习,在接下来的几天里,我将会以这几种方式,分别呈上我对几种通信方式的理解。大牛不喜勿喷,谢谢。
我曾许下十年,只为最美的遇见。


实验目的:
    学习ATK-PAJ7620U2手势识别模块的使用,实现9个手势识别(GS)和接近距离(PS)的检测功能,输出结果显示在LCD液晶中。
   
硬件资源:
    1,DS0、DS1(连接在PA8\PD2)
    2,串口1(波特率:115200,PA9/PA10连接在板载USB转串口芯片CH340上面)
    3,ALIENTEK 2.8/3.5/4.3/7寸TFTLCD模块(通过GPIO驱动,连接关系见lcd.h)  
    4,按键KEY0(PC5)/KEY1(PA15)/WK_UP(PA0)
    5,ATK-PAJ7620U2手势识别模块一个(连接在PC11(SDA),PC12(SCL),INT未用到),可直接插在板上ATK-MODULE的接口。
   
实验现象:
        本实验功能简介:本实验用于测试ATK-PAJ7620U2手势识别模块,包含两个测试:
   
    1,手势识别(GS)测试-通过KEY1按键进入此项测试。实现PAJ7620U2自带9个手势识别的检测,向上(Up)、向下(Dowm)、
          向左(Left)、向右(Right)、向前(Forward)、向后(Backward)、顺时针(Clockwise)、逆时针(Counterclockwise)、
          和挥动(Wave)。当识别到正确的手势,DS1灯会闪烁,同时手势结果显示在LCD屏幕上,并且串口输出。DS0灯闪烁提示程序正在
          运行,按下KEY_UP按键,可返回主菜单页面。
        2,接近检测(PS)测试-通过KEY0按键进入此项测试。实现读取PAJ7620U2接近物体的体积大小和亮度的传感器数据,显示在LCD屏幕上,并串口输出。
           同时DS0灯闪烁,提示程序正在运行,当按下KEY_UP按键,可返回主菜单页面。
        
       另外,本例程将PAJ7620U2的读写操作函数加入USMART控制,我们可以通过USMART对PAJ7620U2进行控制。
   
注意事项:
    1,4.3寸和7寸屏需要比较大电流,USB供电可能不足,请用外部电源适配器(推荐外接12V 1A电源).
    2,本例程在LCD_Init函数里面(在lcd.c),用到了printf,如果不初始化串口1,将导致液晶无法显示!!  
        3,模块是属于光学器件,传感器表层的不洁净,会容易导致测量不佳。所以模块在使用前,保持传感器表层的清洁度,工作时请勿用手去触摸,以免导致模块工作不正常。

单片机源程序如下:
  1. #include "paj7620u2.h"
  2. #include "paj7620u2_cfg.h"
  3. #include "delay.h"
  4. #include "usart.h"
  5. #include "led.h"
  6. #include "lcd.h"
  7. #include "key.h"


  8. //选择PAJ7620U2 BANK区域
  9. void paj7620u2_selectBank(bank_e bank)
  10. {
  11.         switch(bank)
  12.         {
  13.                 case BANK0: GS_Write_Byte(PAJ_REGITER_BANK_SEL,PAJ_BANK0);break;//BANK0寄存器区域
  14.                 case BANK1: GS_Write_Byte(PAJ_REGITER_BANK_SEL,PAJ_BANK1);break;//BANK1寄存器区域
  15.         }
  16.                         
  17. }

  18. //PAJ7620U2唤醒
  19. u8 paj7620u2_wakeup(void)
  20. {
  21.         u8 data=0x0a;
  22.         GS_WakeUp();//唤醒PAJ7620U2
  23.         delay_ms(5);//唤醒时间>400us
  24.         GS_WakeUp();//唤醒PAJ7620U2
  25.         delay_ms(5);//唤醒时间>400us
  26.         paj7620u2_selectBank(BANK0);//进入BANK0寄存器区域
  27.         data = GS_Read_Byte(0x00);//读取状态
  28.         if(data!=0x20) return 0; //唤醒失败
  29.         
  30.         return 1;
  31. }

  32. //PAJ7620U2初始化
  33. //返回值:0:失败 1:成功
  34. u8 paj7620u2_init(void)
  35. {
  36.         u8 i;
  37.         u8 status;
  38.         
  39.         GS_i2c_init();//IIC初始化
  40.     status = paj7620u2_wakeup();//唤醒PAJ7620U2
  41.         if(!status) return 0;
  42.         paj7620u2_selectBank(BANK0);//进入BANK0寄存器区域
  43.         for(i=0;i<INIT_SIZE;i++)
  44.         {
  45.                 GS_Write_Byte(init_Array[i][0],init_Array[i][1]);//初始化PAJ7620U2
  46.         }
  47.     paj7620u2_selectBank(BANK0);//切换回BANK0寄存器区域
  48.         
  49.         return 1;
  50. }

  51. //主菜单
  52. void paj7620u2_test_ui(void)
  53. {
  54.         POINT_COLOR=BLUE;//设置字体为蓝色
  55.         LCD_Fill(30,170,300,300,WHITE);
  56.         LCD_ShowString(30,170,200,16,16,"KEY1:   Gesture test");//手势识别测试
  57.         LCD_ShowString(30,190,200,16,16,"KEY0:   Ps test     ");//接近距离测试
  58.         
  59. }

  60. //手势识别测试
  61. void Gesture_test(void)
  62. {
  63.         u8 i;
  64.     u8 status;
  65.         u8 key;
  66.         u8 data[2]={0x00};
  67.         u16 gesture_data;
  68.         u8 ledflash=0;
  69.         paj7620u2_selectBank(BANK0);//进入BANK0寄存器区域
  70.         for(i=0;i<GESTURE_SIZE;i++)
  71.         {
  72.                 GS_Write_Byte(gesture_arry[i][0],gesture_arry[i][1]);//手势识别模式初始化
  73.         }
  74.         paj7620u2_selectBank(BANK0);//切换回BANK0寄存器区域
  75.         i=0;
  76.         POINT_COLOR=BLUE;//设置字体为蓝色
  77.         LCD_Fill(30,170,300,300,WHITE);
  78.         LCD_ShowString(30,180,200,16,16,"KEY_UP: Exit the test");
  79.         LCD_ShowString(30,210,200,16,16,"Gesture test");
  80.         POINT_COLOR=RED;//设置字体为蓝色
  81.         while(1)
  82.         {
  83.         key = KEY_Scan(0);
  84.                 if(key==WKUP_PRES)
  85.                 {
  86.                         GS_Write_Byte(PAJ_SET_INT_FLAG1,0X00);//关闭手势识别中断输出
  87.                         GS_Write_Byte(PAJ_SET_INT_FLAG2,0X00);
  88.                         break;
  89.                 }               
  90.         status = GS_Read_nByte(PAJ_GET_INT_FLAG1,2,&data[0]);//读取手势状态                        
  91.                 if(!status)
  92.                 {   
  93.                         gesture_data =(u16)data[1]<<8 | data[0];
  94.                         if(gesture_data)
  95.                         {
  96.                                 switch(gesture_data)
  97.                                 {
  98.                                         case GES_UP:               LCD_ShowString(110,250,200,16,24,"UP          ");
  99.                                                                    printf("Up\r\n");            ledflash=1;      break; //向上
  100.                                         case GES_DOWM:             LCD_ShowString(100,250,200,16,24,"Dowm        ");      
  101.                                                                           printf("Dowm\r\n");          ledflash=1;      break; //向下
  102.                                         case GES_LEFT:             LCD_ShowString(100,250,200,16,24,"Left        ");           
  103.                                                                          printf("Left\r\n");          ledflash=1;      break; //向左
  104.                                         case GES_RIGHT:            LCD_ShowString(100,250,200,16,24,"Right       ");      
  105.                                                                        printf("Right\r\n");         ledflash=1;      break; //向右
  106.                                         case GES_FORWARD:          LCD_ShowString(80,250,200,16,24,"Forward     ");        
  107.                                                                        printf("Forward\r\n");       ledflash=1;      break; //向前
  108.                                         case GES_BACKWARD:         LCD_ShowString(80,250,200,16,24,"Backward    ");   
  109.                                                                        printf("Backward\r\n");      ledflash=1;      break; //向后
  110.                                         case GES_CLOCKWISE:        LCD_ShowString(70,250,200,16,24,"Clockwise   ");     
  111.                                                                        printf("Clockwise\r\n");     ledflash=1;      break; //顺时针
  112.                                         case GES_COUNT_CLOCKWISE:  LCD_ShowString(50,250,200,16,24,"AntiClockwise");  
  113.                                                                           printf("AntiClockwise\r\n"); ledflash=1;      break; //逆时针
  114.                                         case GES_WAVE:             LCD_ShowString(100,250,200,16,24,"Wave         ");   
  115.                                                                        printf("Wave\r\n");          ledflash=1;      break; //挥动
  116.                                         default:  ledflash=0; break;
  117.                                        
  118.                                 }        
  119.                 if(ledflash)//DS1闪烁
  120.                                 {   
  121.                                         LED1=0;delay_ms(80);LED1=1;delay_ms(80);
  122.                                         LED1=0;delay_ms(80);LED1=1;delay_ms(80);
  123.                                         LCD_ShowString(40,250,200,16,24,"                        ");
  124.                                         ledflash=0;
  125.                                 }                                                
  126.                         }
  127.                         
  128.                 }
  129.                 delay_ms(50);
  130.                 i++;
  131.                 if(i==5)
  132.                 {
  133.                         LED0=!LED0;//提示系统正在运行        
  134.                         i=0;
  135.                 }                  
  136.         }
  137. }

  138. //接近检测测试
  139. void Ps_test(void)
  140. {
  141.     u8 i;
  142.         u8 key;
  143.         u8 data[2]={0x00};
  144.         u8 obj_brightness=0;
  145.         u16 obj_size=0;
  146.         
  147.         paj7620u2_selectBank(BANK0);//进入BANK0寄存器区域
  148.         for(i=0;i<PROXIM_SIZE;i++)
  149.         {
  150.                 GS_Write_Byte(proximity_arry[i][0],proximity_arry[i][1]);//接近检测模式初始化
  151.         }
  152.         paj7620u2_selectBank(BANK0);//返回BANK0寄存器区域
  153.         i=0;
  154.         POINT_COLOR=BLUE;//设置字体为蓝色
  155.         LCD_Fill(30,170,300,300,WHITE);
  156.         LCD_ShowString(30,180,200,16,16,"KEY_UP: Exit the test");
  157.         LCD_ShowString(30,210,200,16,16,"Ps test");
  158.         LCD_ShowString(30,240,200,16,16,"Brightness");
  159.         LCD_ShowString(160,240,200,16,16,"Size");
  160.         POINT_COLOR=RED;//设置字体为蓝色        
  161.         
  162.         while(1)
  163.         {        
  164.                 key = KEY_Scan(0);
  165.                 if(key==WKUP_PRES) break;
  166.                
  167.                 obj_brightness = GS_Read_Byte(PAJ_GET_OBJECT_BRIGHTNESS);//读取物体亮度
  168.                 data[0] = GS_Read_Byte(PAJ_GET_OBJECT_SIZE_1);//读取物体大小
  169.                 data[1] = GS_Read_Byte(PAJ_GET_OBJECT_SIZE_2);
  170.                 obj_size = ((u16)data[1] & 0x0f)<<8 | data[0];
  171.                 LCD_ShowxNum(50,270,obj_brightness,3,24,0);
  172.                 LCD_ShowxNum(152,270,obj_size,3,24,0);
  173.                 printf("obj_brightness: %d\r\n",obj_brightness);
  174.         printf("obj_size: %d\r\n",obj_size);
  175.                
  176.                 delay_ms(100);
  177.                 i++;
  178.                 if(i==5)
  179.                 {
  180.                     LED0=!LED0;//提示系统正在运行        
  181.                         i=0;
  182.                 }
  183.         }
  184.         
  185. }
  186. //PAJ7620U2传感器测试
  187. void paj7620u2_sensor_test(void)
  188. {   
  189.          u8 i=0;
  190.          u8 key;
  191.         
  192.      paj7620u2_test_ui();//主菜单显示
  193.          while(1)
  194.          {
  195.                  key = KEY_Scan(0);//按键扫描
  196.                  if(key)
  197.                  {
  198.                          switch(key)
  199.                          {
  200.                                  case KEY1_PRES:  Gesture_test();   break;//手势检测模式
  201.                                  case KEY0_PRES:  Ps_test();        break;//接近检测模式  
  202.                          }
  203.                          paj7620u2_test_ui();
  204.                  }
  205.                 delay_ms(50);
  206.                 i++;
  207.                 if(i==5)
  208.                 {
  209.                     LED0=!LED0;//提示系统正在运行        
  210.                         i=0;
  211.                 }
  212.                  
  213.          }
  214. }
复制代码

主程序:
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"
  5. #include "lcd.h"
  6. #include "key.h"
  7. #include "usmart.h"
  8. #include "paj7620u2.h"

  9.            
  10. int main(void)
  11. {

  12.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
  13.         delay_init();                     //延时函数初始化         
  14.         uart_init(115200);                  //串口初始化为115200
  15.         LED_Init();                                   //初始化与LED连接的硬件接口
  16.          LCD_Init();                     //初始化LCD
  17.         KEY_Init();                                 //按键初始化
  18.     usmart_dev.init(72);          //初始化USMART                        
  19.     POINT_COLOR=RED;         //设置字体为红色
  20.     LCD_ShowString(30,50,200,16,16,"Mini STM32");        
  21.         LCD_ShowString(30,70,200,16,16,"Sensor PAJ7620U2 TEST");        
  22.         LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
  23.         LCD_ShowString(30,110,200,16,16,"2017/8/23");            
  24.         POINT_COLOR=BLUE;//设置字体为蓝色                  
  25.          while(!paj7620u2_init())//PAJ7620U2传感器初始化
  26.         {
  27.             printf("PAJ7620U2 Error!!!\r\n");
  28.                 LCD_ShowString(30,140,200,16,16,"PAJ7620U2 Error!!!");
  29.             delay_ms(500);
  30.                 LCD_ShowString(30,140,200,16,16,"                  ");
  31.                 delay_ms(500);
  32.                 LED0=!LED0;//DS0闪烁
  33.                
  34.         }
  35.     printf("PAJ7620U2 OK\r\n");
  36.         LCD_ShowString(30,140,200,16,16,"PAJ7620U2 OK");
  37.         while(1)
  38.         {
  39.                 paj7620u2_sensor_test();//PAJ7620U2传感器测试
  40.         }
  41. }
复制代码


所有资料51hei提供下载:
(标准库版本,适合MiniV3 STM32开发板)扩展实验22 ATK-PAJ7620模块实验.7z (245.78 KB, 下载次数: 11)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

curster 发表于 2019-1-29 14:38 | 显示全部楼层
#include "paj7620u2_cfg.h"
#include "key.h"
怎麼沒有這兩個副程序,上面的程序有呼叫到這兩個副程序的,煩有空補上好嗎?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51hei电子论坛2群 联系QQ:125739409;技术交流QQ群219535678

Powered by 单片机教程网

快速回复 返回顶部 返回列表