#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include "ads1256_spi.h"
#include <linux/unistd.h>
#define ADS1256_CNT 1
#define ADS1256_NAME "ads1256"
#define ADS1256_TRANSFORM_TIME_US 309
static int ads1256_probe(struct spi_device *spi);
static int ads1256_remove(struct spi_device *spi);
static int ads1256_open(struct inode *inode, struct file *filp);
static ssize_t ads1256_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt);
static ssize_t ads1256_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off);
static int ads1256_release(struct inode *inode, struct file *filp);
struct ads1256_dev
{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
struct device_node *nd; /* 设备节点 */
int major; /* 主设备号 */
int pdwn_gpio;
int cs_gpio; /* cs所使用的GPIO编号 */
int reset_gpio; /* reset所使用的GPIO编号 */
int drdy_gpio; /* drdy所使用的GPIO编号 */
unsigned char channels[8]; /* 采样通道,最多8个 */
unsigned char channel_num; /* 采样通道数量 */
int delay_us; /* 采样间隔时间 */
void *private_data; /* 私有数据 */
};
static struct ads1256_dev ads1256dev;
static const struct spi_device_id ads1256_id[] = {
{"alientek,ads1256", 0},
{}};
static const struct of_device_id ads1256_of_match[] = {
{.compatible = "alientek,ads1256"},
{/* Sentinel */}};
static struct spi_driver ads1256_driver = {
.probe = ads1256_probe,
.remove = ads1256_remove,
.driver = {
.owner = THIS_MODULE,
.name = "ads1256",
.of_match_table = ads1256_of_match,
},
.id_table = ads1256_id,
};
/* ads1256操作函数 */
static const struct file_operations ads1256_ops = {
.owner = THIS_MODULE,
.open = ads1256_open,
.read = ads1256_read,
.write = ads1256_write,
.release = ads1256_release,
};
static int ads1256_transfer_multibyte(struct ads1256_dev *dev, unsigned char *wbuf, unsigned char *rbuf, unsigned char len)
{
int ret = 0;
struct spi_message m;
struct spi_transfer t = {0};
struct spi_device *spi = (struct spi_device *)dev->private_data;
/* 一共发送len个字节的数据*/
t.tx_buf = wbuf; /* 要发送的数据 */
t.rx_buf = rbuf;
t.len = len; /* 传输长度 */
spi_message_init(&m); /* 初始化spi_message */
spi_message_add_tail(&t, &m); /* 将spi_transfer添加到spi_message队列 */
ret = spi_sync(spi, &m); /* 同步发送 */
return -ret;
}
static unsigned char ads1256_transfer(struct ads1256_dev *dev, unsigned char byte)
{
int ret = -1;
unsigned char txdata[1];
unsigned char rxdata[1];
struct spi_message m;
struct spi_transfer t = {0};
struct spi_device *spi = (struct spi_device *)dev->private_data;
/* 一共发送1个字节的数据,第一个字节为
寄存器首地址,一共要读取len个字节长度的数据,*/
txdata[0] = byte | 0x80; /* 写数据的时候首寄存器地址bit8要置1 */
t.tx_buf = txdata; /* 要发送的数据 */
t.rx_buf = rxdata; /* 要读取的数据 */
t.len = 1; /* 发送的长度 */
spi_message_init(&m); /* 初始化spi_message */
spi_message_add_tail(&t, &m); /* 将spi_transfer添加到spi_message队列 */
ret = spi_sync(spi, &m); /* 同步发送 */
if (ret)
{
rxdata[0] = 0;
printk("error transfer data!\r\n");
}
printk("recv transfer data! %x\r\n",rxdata[0]);
return rxdata[0];
}
static int ads1256_read_global_reg(struct ads1256_dev *dev,uint8_t index,uint8_t *dat)
{
unsigned char wbuf[8];
unsigned char rbuf[8];
/* 设置采样通道 */
gpio_set_value(dev->cs_gpio, 0);
while (gpio_get_value(dev->drdy_gpio))
;
wbuf[0] = ADS1256_CMD_RREG | (index & 0xF);
wbuf[1] = 0;
ads1256_transfer_multibyte(dev, wbuf, rbuf, 2);
dat[0] = ads1256_transfer(dev, 0xFF);
while (gpio_get_value(dev->drdy_gpio));
gpio_set_value(dev->cs_gpio, 1);
return 1;
}
static int ads1256_read_channel(struct ads1256_dev *dev, unsigned char channel)
{
unsigned char i = 0;
unsigned int r = 0;
int sum = 0;
unsigned char wbuf[8];
unsigned char rbuf[8];
/* 设置采样通道 */
gpio_set_value(dev->cs_gpio, 0);
while (gpio_get_value(dev->drdy_gpio))
;
wbuf[0] = ADS1256_CMD_WREG | (ADS1256_MUX & 0xF);
wbuf[1] = 0;
ads1256_transfer_multibyte(dev, wbuf, rbuf, 2);
wbuf[0] = channel;
ads1256_transfer_multibyte(dev, wbuf, rbuf, 1);
while (gpio_get_value(dev->drdy_gpio))
;
/* 读取转换结果 */
wbuf[0] = ADS1256_CMD_SYNC;
wbuf[1] = ADS1256_CMD_WAKEUP;
wbuf[2] = ADS1256_CMD_RDATA;
ads1256_transfer_multibyte(dev, wbuf, rbuf, 3);
wbuf[0] = 0xFF;
wbuf[1] = 0xFF;
wbuf[2] = 0xFF;
memset(rbuf, 0, 3);
ads1256_transfer_multibyte(dev, wbuf, rbuf, 3);
for (i = 0; i < 3; i++)
{
sum = sum << 8;
r = rbuf[i];
sum |= r;
}
printk("sum %x, channal %x\r\n",sum,channel);
if (sum > 0x7FFFFF)
{ // 负值转换
// sum |= ~0 << 23;
// sum = ~(sum - 1);
sum -= 0x1000000;
}
while (gpio_get_value(dev->drdy_gpio))
;
gpio_set_value(dev->cs_gpio, 1);
return sum;
}
struct write_data
{
unsigned char cmd;
unsigned char length;
unsigned char param[8]; /* 最多8个参数 */
};
static int ads1256_write_string_to_dev(struct ads1256_dev *dev, const char *buf, size_t cnt)
{
size_t index = 0;
struct write_data *data_p;
int temp;
while (index < cnt)
{
if (cnt - index < 3)
{
return index;
}
data_p = (struct write_data *)&buf[index];
switch (data_p->cmd)
{
case SET_CHANNELS:
if (data_p->length > 8 || index + 1 + data_p->length >= cnt)
{
return index;/* 参数�?误 或 剩余长度不够 */
}
dev->channel_num = data_p->length; /* 设置通道数量 */
memcpy(dev->channels, data_p->param, dev->channel_num); /* 设置通道序列 */
ads1256_read_channel(dev, dev->channels[0]);/* 重置通道 */
index = index + data_p->length + 2;
break;
case SET_FREQUENCY:
if (data_p->length != 4 || index + 1 + data_p->length >= cnt)
{
return index;/* 参数错误 或 剩余长度不够 */
}
temp = (data_p->param[0] << 24) + (data_p->param[1] << 16) + (data_p->param[2] << 8) + data_p->param[3];
temp = 1000000 / temp - ADS1256_TRANSFORM_TIME_US;
dev->delay_us = temp > 0 ? temp : 0;
index = index + data_p->length + 2;
break;
default:
return index;
}
}
return index;
}
static int ads1256_open(struct inode *inode, struct file *filp)
{
filp->private_data = &ads1256dev; /* 设置私有数据 */
return 0;
}
static ssize_t ads1256_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
int retvalue;
unsigned char *databuf;
struct ads1256_dev *dev = (struct ads1256_dev *)filp->private_data;
databuf = kzalloc(cnt, GFP_KERNEL);
if (!databuf)
{
return -ENOMEM;
}
retvalue = copy_from_user(databuf, buf, cnt);
if (retvalue < 0)
{
printk("kernel write failed!\r\n");
retvalue = -EFAULT;
goto out1;
}
retvalue = ads1256_write_string_to_dev(dev, databuf, cnt);
out1:
kfree(databuf);
return retvalue;
}
static ssize_t ads1256_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
{
int err = 0;
int *result;
int length;
int index = 1; /* 浠??开始,实际采样是从通道0开始 */
struct ads1256_dev *dev = (struct ads1256_dev *)filp->private_data;
/* 计算采样点个数 */
length = cnt / 4;
/* 开内存空间 */
result = kzalloc(length * 4, GFP_KERNEL);
if (!result)
{
return -ENOMEM;
}
udelay(dev->delay_us);
/* 采样 */
while (index < length + 1)
{
result[index - 1] = ads1256_read_channel(dev, dev->channels[index % dev->channel_num]);
index++;
udelay(dev->delay_us);
}
/* 重置通道 */
ads1256_read_channel(dev, dev->channels[0]);
err = copy_to_user(buf, result, length * 4);
kfree(result);
return len
ads1256 linux 驱动
需积分: 5 61 浏览量
2024-05-14
16:01:11
上传
评论
收藏 23KB RAR 举报
qq_28219531
- 粉丝: 102
- 资源: 2
最新资源
- 基于Typescript和PHP的编程知识储备库设计源码 - study-php
- Screenshot_2024-05-28-11-40-58-177_com.tencent.mm.jpg
- 基于Dart的Flutter小提琴调音器APP设计源码 - violinhelper
- 基于JavaScript和CSS的随寻订购网页设计源码 - web-order
- 基于MATLAB的声纹识别系统设计源码 - VoiceprintRecognition
- 基于Java的微服务插件集合设计源码 - wsy-plugins
- 基于Vue和微信小程序的监理日志系统设计源码 - supervisionLog
- 基于Java和LCN分布式事务框架的设计源码 - tx-lcn
- 基于Java和JavaScript的茶叶评级管理系统设计源码 - tea
- IMG_5680.JPG
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈