SPI总线驱动实现数码管的显示
demo.h
#ifndef __M74HC595_H__
#define __M74HC595_H__
#define NUM0 _IOR('a',0,int)
#define NUM1 _IOR('a',1,int)
#define NUM2 _IOR('b',0,int)
#define NUM3 _IOR('b',1,int)
#define NUM4 _IOR('c',0,int)
#define NUM5 _IOR('c',1,int)
#define NUM6 _IOR('d',0,int)
#define NUM7 _IOR('d',1,int)
#define NUM8 _IOR('e',0,int)
#define NUM9 _IOR('e',1,int)
#endif
demo.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include<linux/slab.h>
#include "m74hc595.h"
int major;
struct class *cls;
struct device *dev;
struct spi_device *spi_m74hc595;
int m74hc595_open(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
return 0;
}
int m74hc595_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
return 0;
}
long m74hc595_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned char wh, nu;
int ret, which;
ret = copy_from_user(&which, (void *)arg, sizeof(int));
if (ret)
{
printk("copy failed\n");
return -EIO;
}
if (which == 1)
wh = 0x1;
else if (which == 2)
wh = 0x2;
else if (which == 3)
wh = 0x4;
else if (which == 4)
wh = 0x8;
switch (cmd)
{
case NUM0:
nu = 0x3F;
break;
case NUM1:
nu = 0x06;
break;
case NUM2:
nu = 0x5B;
break;
case NUM3:
nu = 0x4F;
break;
case NUM4:
nu = 0x66;
break;
case NUM5:
nu = 0x6D;
break;
case NUM6:
nu = 0x7D;
break;
case NUM7:
nu = 0x07;
break;
case NUM8:
nu = 0x7F;
break;
case NUM9:
nu = 0x6F;
break;
}
char buf[] = {wh, nu};
spi_write(spi_m74hc595, buf, sizeof(buf));
return 0;
}
struct file_operations fops = {
.open = m74hc595_open,
.unlocked_ioctl = m74hc595_ioctl,
.release = m74hc595_close,
};
int m74hc595_probe(struct spi_device *spi)
{
spi_m74hc595 = spi;
//注册字符设备
major = register_chrdev(0, "m74hc595", &fops);
if (major < 0)
{
printk("register char dev driver failed\n");
return major;
}
printk("register char dev driver success\n");
//自动创建设备节点
//向上提交目录
cls = class_create(THIS_MODULE, "m74hc595");
if (IS_ERR(cls))
{
printk("up submit dir failed\n");
return PTR_ERR(cls);
}
printk("up submit dir success\n");
//向上提交节点信息
dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "m74hc595");
if (IS_ERR(dev))
{
printk("up submit device jiedian failed\n");
return PTR_ERR(dev);
}
printk("up submit device jiedian success\n");
printk("%s:%d\n", __FILE__, __LINE__);
return 0;
}
int m74hc595_remove(struct spi_device *spi)
{
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
unregister_chrdev(major, "m74hc595");
printk("%s:%d\n", __FILE__, __LINE__);
return 0;
}
//设备树匹配表
struct of_device_id of_table[] = {
{.compatible = "hqyj,m75hc595"},
{},
};
MODULE_DEVICE_TABLE(of, of_table);
//定义SPI对象并初始化
struct spi_driver m74hc595 = {
.probe = m74hc595_probe,
.remove = m74hc595_remove,
.driver = {
.name = "m74hc595",
.of_match_table = of_table,
}};
module_spi_driver(m74hc595);
MODULE_LICENSE("GPL");
test.c
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include "m74hc595.h"
int main(int argc, const char *argv[])
{
int fd = open("/dev/m74hc595", O_RDWR);
if (fd < 0)
{
printf("open failed\n");
exit(-1);
}
printf("open success\n");
int number, which;
while (1)
{
printf("please input number(0-9)->");
scanf("%d", &number);
if (number < 0 || number > 9)
{
printf("please input again(0-9)!\n");
continue;
}
printf("please choose which(1-4)->");
scanf("%d", &which);
if (which < 1 || which > 4)
{
printf("please input again(1-4)!\n");
continue;
}
if (number == 0)
ioctl(fd, NUM0, &which);
if (number == 1)
ioctl(fd, NUM1, &which);
if (number == 2)
ioctl(fd, NUM2, &which);
if (number == 3)
ioctl(fd, NUM3, &which);
if (number == 4)
ioctl(fd, NUM4, &which);
if (number == 5)
ioctl(fd, NUM5, &which);
if (number == 6)
ioctl(fd, NUM6, &which);
if (number == 7)
ioctl(fd, NUM7, &which);
if (number == 8)
ioctl(fd, NUM8, &which);
if (number == 9)
ioctl(fd, NUM9, &which);
}
close(fd);
return 0;
}
测试结果