应用层程序控制数码管显示数字
实现代码
设备树
&spi4{
pinctrl-names = "default", "sleep";
pinctrl-0 = <&spi4_pins_b>;
pinctrl-1 = <&spi4_sleep_pins_b>;
cs-gpios = <&gpioe 11 0>;//代表片选线
status = "okay";
m74hc595@0 {//0表示是SPI总线上的第0个设备
compatible = "hqyj,m74hc595";
reg = <0>;
spi-max-frequency = <10000000>;//SPI总线速率
};
m74hc595.h
#ifndef __M74HC595_H__
#define __M74HC595_H__
#define one _IOR('m',1,int)
#define two _IOR('m',2,int)
#define three _IOR('m',3,int)
#define four _IOR('m',4,int)
#endif
demo.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include "m74hc595.h"
int major;
struct class *cls;
struct device *dev;
struct i2c_client *cli;
char buf[2]={};
struct spi_device *spi1;
int m74hc595_open(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)
{
int num;
int ret;
ret = copy_from_user(&num, (void *)arg, sizeof(int));
if (ret)
{
printk("给用户拷贝数据失败\n");
return -EINVAL;
}
if (num == 0)
buf[1] = 0x3f;
else if (num == 1)
buf[1] = 0x06;
else if (num == 2)
buf[1] = 0x5b;
else if (num == 3)
buf[1] = 0x4f;
else if (num == 4)
buf[1] = 0x66;
else if (num == 5)
buf[1] = 0x6d;
else if (num == 6)
buf[1] = 0x7d;
else if (num == 7)
buf[1] = 0x07;
else if (num == 8)
buf[1] = 0x6f;
else if (num == 9)
buf[1] = 0x7f;
switch (cmd)
{
case one:
buf[0] = 0x1;
break;
case two:
buf[0] = 0x2;
break;
case three:
buf[0] = 0x4;
break;
case four:
buf[0] = 0x8;
break;
}
spi_write(spi1, buf, sizeof(buf));
return 0;
}
int m74hc595_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
return 0;
}
//定义操作方法结构体
struct file_operations fops = {
.open = m74hc595_open,
.unlocked_ioctl = m74hc595_ioctl,
.release = m74hc595_close,
};
int m74hc595_probe(struct spi_device *spi)
{
spi1=spi;
//注册字符设备
major = register_chrdev(0, "m74hc595", &fops);
if (major < 0)
{
printk("注册字符设备驱动失败\n");
return major;
}
printk("注册字符设备驱动成功\n");
//自动创建设备节点
//向上提交目录
cls = class_create(THIS_MODULE, "m74hc595");
if (IS_ERR(cls))
{
printk("向上提交目录失败\n");
return PTR_ERR(cls);
}
printk("向上提交目录成功\n");
//向上提交节点信息
dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "m74hc595");
if (IS_ERR(dev))
{
printk("向上提交节点信息失败\n");
return PTR_ERR(dev);
}
printk("向上提交节点成功\n");
printk("%s:%d\n", __FILE__, __LINE__);
return 0;
}
int m74hc595_remove(struct spi_device *spi)
{
printk("%s:%d\n", __FILE__, __LINE__);
return 0;
}
//设备树匹配表
struct of_device_id of_table[] = {
{.compatible = "hqyj,m74hc595"},
{},
};
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/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include "m74hc595.h"
int main(int argc, char const *argv[])
{
char buf[2] = {};
int fd = open("/dev/m74hc595", O_RDWR);
int which;
if (fd < 0)
{
printf("打开设备文件失败\n");
exit(-1);
}
printf("设备文件打开成功\n");
int w, n;
//在终端输入
while (1)
{
printf("请输入数码管编号:\n");
scanf("%d", &w);
printf("请输入显示的数字:\n");
scanf("%d", &n);
if (w == 1)
ioctl(fd, one, &n);
else if (w == 2)
ioctl(fd, two, &n);
else if (w == 3)
ioctl(fd, three, &n);
else if (w == 4)
ioctl(fd, four, &n);
}
close(fd);
return 0;
}
运行结果
终端运行make modname=demo arch=arm,生成demo.ko
终端运行arm-linux-gnueabihf-gcc test.c,生成a.out
将这两个文件复制到~/nfs/rootfs/下
在串口工具中下载驱动并运行a.out