1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
前言
上面一个文章配置了普通的GPIO口。然后根据在单片机的经验,尝试配置CS1237驱动。 CS1237是一款高精度、低功耗模数转换芯片,一路差分输入通道,内置温度传感器和高精度振荡器。通过 2线SPI接口 通信。 在单片机中是使用模拟IO口的方式实现SPI通信。在Android里也是一样。 实现 1.首先还是配置DTS设备树,修改kernel/arch/arm/boot/dts/qcom/msm8909-mtp.dtsi。 cs1237 { compatible = "cs1237"; //这是一个enable的pin cs1237,gpio0 = <&msm_gpio 0 0>; //SDA pin cs1237,gpio68 = <&msm_gpio 68 0>; //SCL pin cs1237,gpio69 = <&msm_gpio 69 0>; label = "cs1237"; }; 2.在 kernel/drivers/misc 下添加 cs1237.c文件 (1)IO口函数操作定义 void CLK_H(void){gpio_set_value(CLK_PIN, GPIO_HIGH);} void CLK_L(void){gpio_set_value(CLK_PIN, GPIO_LOW);} void SDA_H(void){gpio_set_value(SDA_PIN, GPIO_HIGH);} void SDA_L(void){gpio_set_value(SDA_PIN, GPIO_LOW);} int SDA_Read(void){return gpio_get_value(SDA_PIN);} void SDA_OUT(void){gpio_direction_output(SDA_PIN, 1);} void SDA_IN(void){gpio_direction_input(SDA_PIN);} (2)cs1237配置初始化,读取配置函数 unsigned char cs1237_init_config(void) { int count_i = 0; //溢出计时器 int i = 0; unsigned char dat = PGA_2 | SPEED_640 | REF_ON; SDA_OUT();//SDA_H(); SDA_IN(); CLK_L(); while(SDA_Read() == 1) { //等待CS237准备好 mdelay(5); count_i++; if(count_i > 300) { SDA_OUT(); //SDA_H(); // OUT引脚拉高 CLK_H(); // CLK引脚拉高 return -1;//超时,则直接退出程序 } } for(i = 0; i < 29; i++) { // 1 - 29 CLK_H();udelay(1);CLK_L();udelay(1); } SDA_OUT(); CLK_H();udelay(1);SDA_H();CLK_L();udelay(1);//30 CLK_H();udelay(1);SDA_H();CLK_L();udelay(1);//31 CLK_H();udelay(1);SDA_L();CLK_L();udelay(1);//32 CLK_H();udelay(1);SDA_L();CLK_L();udelay(1);//33 CLK_H();udelay(1);SDA_H();CLK_L();udelay(1);//34 CLK_H();udelay(1);SDA_L();CLK_L();udelay(1);//35 CLK_H();udelay(1);SDA_H();CLK_L();udelay(1);//36 CLK_H();udelay(1);CLK_L();udelay(1); //37 写入了0x65 for(i = 0; i < 8; i++) { // 38 - 45个脉冲了,写8位数据 CLK_H(); udelay(1); if(dat & 0x80) SDA_H(); else SDA_L(); dat <<= 1; CLK_L(); udelay(1); } SDA_H(); CLK_H();udelay(1);CLK_L();udelay(1); return 0; } // 读取芯片的配置数据 unsigned char Read_Config(void) { unsigned char i; unsigned char dat = 0; //读取到的数据 unsigned int count_i = 0; //溢出计时器 SDA_OUT(); //SDA_H(); SDA_IN(); CLK_L();//时钟拉低 while(SDA_Read() == 1) { //等待芯片准备好数据 mdelay(1); count_i++; if(count_i > 300) { SDA_OUT(); CLK_H(); // CLK=1; //SDA_H(); // OUT=1; return -1;//超时,则直接退出程序 } } //CLK引脚拉高拉低即为一个时钟 for(i = 0; i < 29; i++) { // 产生第1到29个时钟 CLK_H(); udelay(1);CLK_L();udelay(1); } SDA_OUT(); CLK_H();udelay(1);SDA_H();CLK_L();udelay(1);//30 CLK_H();udelay(1);SDA_L();CLK_L();udelay(1);//31 CLK_H();udelay(1);SDA_H();CLK_L();udelay(1);//32 CLK_H();udelay(1);SDA_L();CLK_L();udelay(1);//33 CLK_H();udelay(1);SDA_H();CLK_L();udelay(1);//34 CLK_H();udelay(1);SDA_H();CLK_L();udelay(1);//35 CLK_H();udelay(1);SDA_L();CLK_L();udelay(1);//36 SDA_H(); CLK_H();udelay(1);CLK_L();udelay(1);//37 写入0x56 即读命令 dat = 0; SDA_IN(); for(i = 0; i < 8; i++) { // 第38 - 45个脉冲了,读取数据 CLK_H();udelay(1);CLK_L();udelay(1); dat <<= 1; if(SDA_Read()) dat++; } //第46个脉冲 CLK_H();udelay(1);CLK_L();udelay(1); SDA_OUT(); //SDA_H(); //OUT引脚拉高 return dat; } (3)probe函数中添加 static int gpio_probe(struct platform_device *pdev) { int ret = 0; printk("*************cs1237 probe *************n"); cs1237_class = class_create(THIS_MODULE, "cs1237"); if(IS_ERR(cs1237_class)) { ret = PTR_ERR(cs1237_class); pr_err("Failed to create class.n"); return ret; } cs1237_dev = device_create(cs1237_class, NULL, 0, NULL, "cs1237"); if (IS_ERR(cs1237_dev)) { ret = PTR_ERR(cs1237_class); pr_err("Failed to create device(cs1237)!n"); return ret; } ret = device_create_file(cs1237_dev, &cs1237_dev_attr); if(ret) { pr_err("%s: cs1237 creat sysfs failedn",__func__); return ret; } ret = device_create_file(cs1237_dev, &cs1237_config_attr); if(ret) { pr_err("%s: cs1237 creat sysfs failedn",__func__); return ret; } ret = device_create_file(cs1237_dev, &cs1237_init_attr); if(ret) { pr_err("%s: cs1237 creat sysfs failedn",__func__); return ret; } //寻找设备树dts下的 "cs1237,gpio0" 名称对应的GPIO口 ENABLE_PIN = of_get_named_gpio(pdev->dev.of_node, "cs1237,gpio0", 0); if (ENABLE_PIN < 0) printk( "ENABLE_PIN is not available n"); //对应修改的dts的 label ret = gpio_request(ENABLE_PIN, "cs1237"); if(0 != ret) { printk( "gpio request %d failed.", CLK_PIN); return -EIO; } gpio_direction_output(ENABLE_PIN, 1); gpio_set_value(ENABLE_PIN, GPIO_HIGH); SDA_PIN = of_get_named_gpio(pdev->dev.of_node, "cs1237,gpio68", 0); if (SDA_PIN < 0) printk( "SDA_PIN is not available n"); //对应修改的dts的 label ret = gpio_request(SDA_PIN, "cs1237"); if(0 != ret) { printk( "gpio request %d failed.", SDA_PIN); return -EIO; } gpio_direction_output(SDA_PIN, 1); CLK_PIN = of_get_named_gpio(pdev->dev.of_node, "cs1237,gpio69", 0); if (CLK_PIN < 0) printk( "CLK_PIN is not available n"); //对应修改的dts的 label ret = gpio_request(CLK_PIN, "cs1237"); if(0 != ret) { printk( "gpio request %d failed.", CLK_PIN); return -EIO; } gpio_direction_output(CLK_PIN, 1); CLK_H(); cs1237_init_config(); CONFIG = Read_Config(); if(CONFIG == 36){ printk("cs1237_probe ok , config is %dn",ret); } else{ printk("cs1237_probe failed, config is %dn",ret); } return 0; } (4)读取CS1237数值 //读取ADC数据,返回的是一个有符号数据 int Read_CS1237(void) { unsigned char i; uint32_t dat = 0; //读取到的数据 unsigned int count_i = 0; //溢出计时器 int temp; SDA_OUT(); //SDA_H(); //OUT引脚拉高 SDA_IN(); CLK_L();//时钟拉低 while(SDA_Read()) { //等待芯片准备好数据 mdelay(1); count_i++; if(count_i > 300) { SDA_OUT(); CLK_H(); // CLK=1; //SDA_H(); // OUT=1; return -1;//超时,则直接退出程序 } } dat = 0; for(i = 0; i < 24; i++) { //获取24位有效转换 CLK_H(); udelay(1); dat <<= 1; if(SDA_Read()) dat++; CLK_L(); udelay(1); } for(i = 0; i < 3; i++) { //接着前面的时钟 再来3个时钟 CLK_H();udelay(1);CLK_L();udelay(1); } SDA_OUT(); //SDA_H(); if(dat == 0x00800000) return -1; if(dat & 0x00800000) { // 判断是负数 最高位24位是符号位 temp = (((~dat) & 0x007FFFFF) + 1); // 补码变源码 } else temp = dat; // 正数的补码就是源码 return temp; } 3.修改 kernel/drivers/misc 下 Makefile 和 Kconfig 文件(和上篇文章普通IO口配置一样) 4. 修改 kernel/arch/arm/configs 下的 msm8909-1gb_defconfig 文件(和上篇文章普通IO口配置一样) 5. 执行编译、烧录 make bootimage -j6 6. 测试驱动 系统启动后,用adb命令进入系统 可以看到在 /sys/class/ 目录下生成了 cs1237 文件夹,里面有个 cs1237 文件夹。 下面我们就可以控制 value 文件,去读取cs1237读数。 7.java层获取PT100温度数值 jni层调用cat命令获取cs1237读数 char path[DIRECTION_MAX]; char value_str[10]; int fd; snprintf(path, DIRECTION_MAX, "/sys/class/cs1237/cs1237/value"); fd = open(path, O_RDONLY); if (fd < 0) { LOGE("failed to open gpio value for reading!n"); return 1003; } if (read(fd, value_str, 10) < 0) { LOGE("failed to read value!n"); return 1003; } close(fd); return (atoi(value_str)); java层调用jni函数,将读数转成温度数值 public static float getTemp() { //获取得到AD数值 int data = JNIhardware.getTempure(); //Log.e("Temp","temp ad data =>"+data); //根据电路图,将AD数值转成电压 float vo = (float)data/(float)0x800000 * 3.3f / 2.0f; vo = vo/2; //将电压转换成pt100电阻值 float pt100 = 3000 * vo / (3.3f - vo); //根据pt100电阻特性,得到温度。offset_tem表示误差 float tempdat = ( pt100 - 100) / 0.39f + offset_tem; Log.e("Temp","temp => "+tempdat); return tempdat; } |
|
|
|
只有小组成员才能发言,加入小组>>
3310 浏览 9 评论
2991 浏览 16 评论
3492 浏览 1 评论
9055 浏览 16 评论
4086 浏览 18 评论
1174浏览 3评论
603浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
596浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2333浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1894浏览 2评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 17:17 , Processed in 1.121962 second(s), Total 78, Slave 59 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号