Firefly开源社区

标题: ROC-RK3308-CC开发实例总结——HZ711 压力传感器的使用方法 [打印本页]

作者: Demon    时间: 2019-1-27 18:17
标题: ROC-RK3308-CC开发实例总结——HZ711 压力传感器的使用方法
本帖最后由 Demon 于 2019-1-27 18:17 编辑

    最近本人调试了型号为hz711的一款压力传感器,调试过程并不算十分艰难,但也需注意此传感器的数据传输方式和获取质量的技巧。下面将本人的测试方法分享于大家,下文仅个人见解,若有不足之处,望指出,不胜感激。

1、本人的习惯是拿到传感器的第一步是查看传感器的相关资料。
    查看传感器的硬件连接图:


     由此可知SCK与DOUT连接两个gpio口作为数据传输。再看时序图:

2、对传感器工作模式已经了解之后,开始编写驱动程序!首先在DTS中添加节点。文件路径:/kernel/arch/arm64/boot/dts/rockchip/rk3308-firefly.dtsi。在此用的是 gpio1 A0 和 gpio1 A1 。

  1.         hz711_test{
  2.                 compatible = "hz711";
  3.                 sck-gpio = <&gpio1 RK_PA1 GPIO_ACTIVE_LOW>;
  4.                 dt-gpio = <&gpio1 RK_PA0 GPIO_ACTIVE_LOW>;
  5.                 flag-gpio = <&gpio1 RK_PA2 IRQ_TYPE_LEVEL_HIGH>;
  6.                 status = "okay";
  7.         };
复制代码
3、添加节点后,便在/kernel/driver/ 下创建了名为:hz711 的目录。并在目录中创建 c文件、Kconfig、Makefile ,把目录加入到 /drive 下的Kconfig与Makefile中。并完成 /hz711 下的 Kconfig、Makefile文件的编写。在此不再赘述框架搭建,进入驱动中probe的编写:
  1. static int hz711_probe(struct platform_device *pdev)
  2. {
  3.         enum of_gpio_flags dt_flag;
  4.         enum of_gpio_flags sck_flag;
  5.         hz711 = kmalloc(sizeof(struct HZ711), GFP_KERNEL);  //申请内存空间
  6.         if(!hz711)
  7.         {
  8.                 printk("hz711 kmalloc memory err!!!\n");
  9.                 return -ENODEV;
  10.         }

  11.         hz711->sck_gpio = of_get_named_gpio_flags(pdev->dev.of_node, "sck-gpio", 0, &sck_flag);  //获取sck-gpio的信息
  12.         if(!gpio_is_valid(hz711->sck_gpio))  //判断对应gpio口是否合法
  13.         {
  14.                 printk("sck-gpio is invalid!\n");
  15.                 return -ENODEV;
  16.         }
  17.         gpio_direction_output(hz711->sck_gpio, 0);  //设置为输出模式

  18.         hz711->dt_gpio = of_get_named_gpio_flags(pdev->dev.of_node, "dt-gpio", 0, &dt_flag);  // 获取dt-gpio的信息
  19.         if(!gpio_is_valid(hz711->dt_gpio))  //判断对应gpio口是否合法
  20.         {
  21.                 printk("dt-gpio is invalid!\n");
  22.                 return -ENODEV;
  23.         }
  24.         gpio_direction_input(hz711->dt_gpio);  //设置为输入模式

  25.         if(gpio_request(hz711->sck_gpio, "sck-gpio"))  //申请占用对应的gpio口
  26.         {
  27.                 printk("request sck-gpio faild!!!\n");
  28.                 gpio_free(hz711->sck_gpio);
  29.                         return -1;
  30.         }
  31.         if(gpio_request(hz711->dt_gpio, "dt-gpio"))  //申请占用对应的gpio口
  32.         {
  33.                 printk("request dt-gpio faild!!!\n");
  34.                 gpio_free(hz711->dt_gpio);
  35.                         return -1;
  36.         }

  37.         first_weight = (long)HZ711_Read();  //获取初始质量
  38.         return 0;
  39. }
复制代码
    为了获取质量,编写一个函数接口方便调用。下面进行Get_Weight()函数的编写:
  1. int Get_Weight(void)
  2. {
  3.     int Weight;
  4.     Weight = (long)HZ711_Read();  //获取质量
  5.     Weight = (long)(Weight - first_weight);  //减去初始质量,获得净重
  6.     if(Weight < 0)
  7.         Weight = (- Weight);

  8.     Weight = (int)(Weight / Gapvalue);  //除以质量系数(430),得到所需数据
  9.     return Weight;
  10. }
复制代码
    在此,需要注意:一定要先获取初始质量,再用二次测量质量减去初始质量,得到净重!!再看看HZ711_Read()函数的编写:
  1. long HZ711_Read(void)
  2. {
  3.         long count = 0;
  4.         int i;
  5.         mdelay(10);  //让传感器准备就绪

  6.         gpio_set_value(hz711->sck_gpio, 0);
  7.         while(gpio_get_value(hz711->dt_gpio));  //等待DT口为低电平(开始读取数据)
  8.         for(i=0; i<24; i++)
  9.         {
  10.                 gpio_set_value(hz711->sck_gpio, 1);
  11.                 if(i != 0)
  12.                         count = count<<1;  //高位先出,在此使用位操作
  13.                 udelay(25);
  14.                 gpio_set_value(hz711->sck_gpio, 0);
  15.                 if(gpio_get_value(hz711->dt_gpio))
  16.                         count++;  //读取保存数据,0 1操作
  17.                 udelay(25);
  18.         }
  19.         gpio_set_value(hz711->sck_gpio, 1);

  20.         count=count^0x800000;  //第25个脉冲下降沿来时,转换数据
  21.         udelay(25);
  22.         gpio_set_value(hz711->sck_gpio, 0);

  23.         return count;
  24. }
复制代码
    在此,编写代码时可参照时序图加以理解,对照时序图进行IO操作即可得到数据。

4、得到数据后,需将数据传输到应用层,在此定义一个设备节点以方便上层打开查看,具体如下:
  1. ssize_t hz711_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos)
  2. {
  3.         int ret;
  4.         char Weight_buf[20] = {0};

  5.         Weight = Get_Weight();  //调用接口,获取质量
  6.         if(Weight >= 5000)  //超重提示并返回!
  7.         {
  8.                 ret = copy_to_user(buf, "Overweight!(5000g)", sizeof("Overweight!(5000g)"));  //发送信息到设备节点
  9.                 return ret;
  10.         }
  11.         sprintf(Weight_buf, "%d", Weight);  //将整型数据转换成字符串类型
  12.         ret = copy_to_user(buf, Weight_buf, 10);   //发送信息到设备节点
  13.         return ret;
  14. }
  15. static struct file_operations hz711_fops = {
  16.         .owner = THIS_MODULE,
  17.         .open  = hz711_open,
  18.         .release = hz711_release,
  19.         .read  = hz711_read,
  20. };
  21. static struct miscdevice hz711_miscdev = {
  22.         .minor = MISC_DYNAMIC_MINOR,
  23.         .name  = "HZ711",  //设备节点的名称
  24.         .fops  = &hz711_fops,  //设备节点的信息内容
  25. };
复制代码
5、到此,内核的驱动程序已经编写完成,具体细节可下载附件中的源代码查看。是时候测试所写程序的效果了,本人在此编写了一个简单的应用层测试程序:
  1. int main (int argc, char argv[])
  2. {
  3.     char buff[10] = {0};
  4.     int fd, ret;
  5.    
  6.     fd = open("/dev/HZ711", O_RDONLY);
  7.     if(fd < 0)
  8.     {
  9.         printf("open /dev/HZ711 faild!!\n");
  10.         return -1;
  11.     }
  12.     ret = read(fd, buff, 10);
  13.     if(ret < 0)
  14.     {
  15.         printf("read fd faild!!\n");
  16.         return -1;
  17.     }
  18.     printf("the weight is %s g\n", buff);
  19.     close(fd);
  20.     return 0;
  21. }
复制代码
   在此,先前所写的设备节点是在:/dev目录下。打开设备进行read(),即可拿到copy_to_user()的信息数据。
6、把写好的内核驱动程序及测试程序编译、烧录入板子。一切工作都已经准备就绪,现在就可开始运行程序查看效果啦!!



(此文仅个人见解,若有不足之处,望指出,不胜感激)

HZ711源码及资料.tar.gz (209.69 KB, 下载次数: 26, 售价: 3 灯泡)




作者: 15920514550    时间: 2019-2-19 10:56
感谢
作者: Demon    时间: 2019-2-21 20:40
15920514550 发表于 2019-2-19 10:56
感谢

不用客气,相互学习
作者: SilverMirror    时间: 2019-4-12 11:36
good
作者: Demon    时间: 2019-4-13 09:27
SilverMirror 发表于 2019-4-12 11:36
good

相互学习!!
作者: 忘却    时间: 2019-6-3 10:03
不错看看先
作者: zcq    时间: 2019-6-6 07:42
不错
作者: Demon    时间: 2019-6-6 09:28
忘却 发表于 2019-6-3 10:03
不错看看先

相互学习!!
作者: Demon    时间: 2019-6-6 09:31
zcq 发表于 2019-6-6 07:42
不错

相互学习!!
作者: humhh575    时间: 2019-7-17 10:28
kankan
作者: 18899714881    时间: 2019-10-17 17:43
水一下
作者: fjptcym    时间: 2022-3-27 17:35
谢谢

作者: wx_柴_pb4    时间: 2022-5-1 17:27
水一下

作者: wx_柴_pb4    时间: 2022-5-1 17:41
点赞





欢迎光临 Firefly开源社区 (https://dev.t-firefly.com/) Powered by Discuz! X3.1