通过ioctl函数选择不同硬件的控制,LED 蜂鸣器 马达 风扇
实验现象
head.h
# ifndef __HEAD_H__
# define __HEAD_H__
typedef struct {
volatile unsigned int MODER;
volatile unsigned int OTYPER;
volatile unsigned int OSPEEDR;
volatile unsigned int PUPDR;
volatile unsigned int IDR;
volatile unsigned int ODR;
volatile unsigned int BSRR;
volatile unsigned int LCKR;
volatile unsigned int AFRL;
volatile unsigned int AFRH;
volatile unsigned int BRR;
volatile unsigned int res;
volatile unsigned int SECCFGR;
} gpio_t ;
# define PHY_LED1_ADDR 0X50006000
# define PHY_LED2_ADDR 0X50007000
# define PHY_LED3_ADDR 0X50006000
# define PHY_RCC_ADDR 0X50000A28
# define GPIOB 0X50003000
# define GPIOE 0X50006000
# define GPIOF 0X50007000
# define LED_ON _IOW ( 'l' , 1 , int )
# define LED_OFF _IOW ( 'l' , 0 , int )
# define FAN_ON _IO ( 'f' , 1 )
# define FAN_OFF _IO ( 'f' , 0 )
# define MOTOR_ON _IO ( 'm' , 1 )
# define MOTOR_OFF _IO ( 'm' , 0 )
# define BEE_ON _IO ( 'b' , 1 )
# define BEE_OFF _IO ( 'b' , 0 )
# endif
test.c
# include <stdlib.h>
# include <stdio.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
# include <string.h>
# include <sys/ioctl.h>
# include "head.h"
int main ( int argc, char const * argv[ ] )
{
int a, b;
char buf[ 128 ] = { 0 } ;
char ch[ 128 ] = { 0 } ;
printf ( "请输入要控制的硬件:LED(LED) fan(风扇) motor(马达) bee(蜂鸣器)>>>" ) ;
scanf ( "%s" , ch) ;
getchar ( ) ;
if ( ! strcmp ( ch, "LED" ) )
{
int fd = open ( "/dev/led0" , O_RDWR) ;
if ( fd < 0 )
{
printf ( "打开led设备文件失败\n" ) ;
exit ( - 1 ) ;
}
while ( 1 )
{
printf ( "请选择要实现的功能\n" ) ;
printf ( "0(关灯) 1(开灯)>>>" ) ;
scanf ( "%d" , & a) ;
printf ( "请输入要控制的灯\n" ) ;
printf ( "1(LED1) 2(LED2) 3(LED3)>>>" ) ;
scanf ( "%d" , & b) ;
if ( a == 1 )
{
ioctl ( fd, LED_ON, & b) ;
}
else if ( a == 0 )
{
ioctl ( fd, LED_OFF, & b) ;
}
}
close ( fd) ;
}
else if ( ! strcmp ( ch, "fan" ) )
{
int fd_fan = open ( "/dev/fan" , O_RDWR) ;
if ( fd_fan < 0 )
{
printf ( "打开fan设备文件失败\n" ) ;
exit ( - 1 ) ;
}
while ( 1 )
{
printf ( "请输入要实现的功能\n" ) ;
printf ( "0(关闭风扇) 1(开启风扇)>>>" ) ;
scanf ( "%d" , & a) ;
if ( a == 1 )
{
ioctl ( fd_fan, FAN_ON) ;
}
else if ( a == 0 )
{
ioctl ( fd_fan, FAN_OFF) ;
}
}
close ( fd_fan) ;
}
else if ( ! strcmp ( ch, "motor" ) )
{
int fd_motor = open ( "/dev/motor" , O_RDWR) ;
if ( fd_motor < 0 )
{
printf ( "打开motor设备文件失败\n" ) ;
exit ( - 1 ) ;
}
while ( 1 )
{
printf ( "请输入要实现的功能\n" ) ;
printf ( "0(关闭马达) 1(开启马达)>>>" ) ;
scanf ( "%d" , & a) ;
if ( a == 1 )
{
ioctl ( fd_motor, MOTOR_ON) ;
}
else if ( a == 0 )
{
ioctl ( fd_motor, MOTOR_OFF) ;
}
}
close ( fd_motor) ;
}
else if ( ! strcmp ( ch, "bee" ) )
{
int fd_bee = open ( "/dev/bee" , O_RDWR) ;
if ( fd_bee < 0 )
{
printf ( "打开bee设备文件失败\n" ) ;
exit ( - 1 ) ;
}
while ( 1 )
{
printf ( "请输入要实现的功能\n" ) ;
printf ( "0(关闭蜂鸣器) 1(开启蜂鸣器)>>>" ) ;
scanf ( "%d" , & a) ;
if ( a == 1 )
{
ioctl ( fd_bee, BEE_ON) ;
}
else if ( a == 0 )
{
ioctl ( fd_bee, BEE_OFF) ;
}
}
close ( fd_bee) ;
}
else
printf ( "输入有误!\n" ) ;
return 0 ;
}
led.c
# include <linux/init.h>
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/io.h>
# include <linux/device.h>
# include "head.h"
struct class * cls;
struct device * dev;
int major;
char kbuf[ 128 ] = { 0 } ;
gpio_t * vir_led1;
gpio_t * vir_led2;
gpio_t * vir_led3;
unsigned int * vir_rcc;
int mycdev_open ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
long mycdev_ioctl ( struct file * file, unsigned int cmd, unsigned long arg)
{
int which;
int ret= copy_from_user ( & which, ( void * ) arg, 4 ) ;
if ( ret)
{
printk ( "拷贝用户空间数据失败\n" ) ;
return - EIO;
}
switch ( cmd)
{
case LED_ON:
switch ( which)
{
case 1 :
vir_led1-> ODR |= ( 0x1 << 10 ) ;
break ;
case 2 :
vir_led2-> ODR |= ( 0x1 << 10 ) ;
break ;
case 3 :
vir_led3-> ODR |= ( 0x1 << 8 ) ;
break ;
}
break ;
case LED_OFF:
switch ( which)
{
case 1 :
vir_led1-> ODR &= ( ~ ( 0X1 << 10 ) ) ;
break ;
case 2 :
vir_led2-> ODR &= ( ~ ( 0X1 << 10 ) ) ;
break ;
case 3 :
vir_led3-> ODR &= ( ~ ( 0X1 << 8 ) ) ;
break ;
}
break ;
}
return 0 ;
}
int mycdev_close ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
struct file_operations fops = {
. open = mycdev_open,
. unlocked_ioctl = mycdev_ioctl,
. release = mycdev_close,
} ;
int all_led_init ( void )
{
vir_led1 = ioremap ( PHY_LED1_ADDR, sizeof ( gpio_t ) ) ;
if ( vir_led1 == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
vir_led2 = ioremap ( PHY_LED2_ADDR, sizeof ( gpio_t ) ) ;
if ( vir_led2 == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
vir_led3 = vir_led1;
vir_rcc = ioremap ( PHY_RCC_ADDR, 4 ) ;
if ( vir_rcc == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
printk ( "物理地址映射成功\n" ) ;
( * vir_rcc) |= ( 3 << 4 ) ;
vir_led1-> MODER &= ( ~ ( 3 << 20 ) ) ;
vir_led1-> MODER |= ( 1 << 20 ) ;
vir_led1-> ODR &= ( ~ ( 1 << 10 ) ) ;
vir_led2-> MODER &= ( ~ ( 3 << 20 ) ) ;
vir_led2-> MODER |= ( 1 << 20 ) ;
vir_led2-> ODR &= ( ~ ( 1 << 10 ) ) ;
vir_led3-> MODER &= ( ~ ( 3 << 16 ) ) ;
vir_led1-> MODER |= ( 1 << 16 ) ;
vir_led1-> ODR &= ( ~ ( 1 << 8 ) ) ;
printk ( "寄存器初始化成功\n" ) ;
return 0 ;
}
static int __init mycdev_init ( void )
{
int i;
major = register_chrdev ( 0 , "mychrdev" , & fops) ;
if ( major < 0 )
{
printk ( "字符设备驱动注册失败\n" ) ;
return major;
}
printk ( "字符设备驱动注册成功:major=%d\n" , major) ;
cls = class_create ( THIS_MODULE, "mychrdev" ) ;
if ( IS_ERR ( cls) )
{
printk ( "向上提交目录失败\n" ) ;
return - PTR_ERR ( cls) ;
}
for ( i = 0 ; i < 3 ; i++ )
{
dev = device_create ( cls, NULL , MKDEV ( major, i) , NULL , "led%d" , i) ;
if ( IS_ERR ( dev) )
{
printk ( "向上提交设备节点信息失败\n" ) ;
return - PTR_ERR ( dev) ;
}
}
all_led_init ( ) ;
return 0 ;
}
static void __exit mycdev_exit ( void )
{
int i;
iounmap ( vir_led1) ;
iounmap ( vir_led2) ;
iounmap ( vir_rcc) ;
for ( i = 0 ; i < 3 ; i++ )
{
device_destroy ( cls, MKDEV ( major, i) ) ;
}
class_destroy ( cls) ;
unregister_chrdev ( major, "mychrdev" ) ;
}
module_init ( mycdev_init) ;
module_exit ( mycdev_exit) ;
MODULE_LICENSE ( "GPL" ) ;
fan.c
# include <linux/init.h>
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/io.h>
# include <linux/device.h>
# include "head.h"
struct class * cls;
struct device * dev;
gpio_t * vir_gpioe;
int major;
char kbuf[ 128 ] = { 0 } ;
unsigned int * vir_rcc;
int mycdev_open ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
long mycdev_ioctl ( struct file * file, unsigned int cmd, unsigned long arg)
{
switch ( cmd)
{
case FAN_ON:
vir_gpioe-> ODR |= ( 0x1 << 9 ) ;
break ;
case FAN_OFF:
vir_gpioe-> ODR &= ( ~ ( 0X1 << 9 ) ) ;
break ;
}
return 0 ;
}
int mycdev_close ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
struct file_operations fops = {
. open = mycdev_open,
. unlocked_ioctl = mycdev_ioctl,
. release = mycdev_close,
} ;
int all_fan_init ( void )
{
vir_gpioe = ioremap ( GPIOE, sizeof ( gpio_t ) ) ;
if ( vir_gpioe == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
vir_rcc = ioremap ( PHY_RCC_ADDR, 4 ) ;
if ( vir_rcc == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
printk ( "物理地址映射成功\n" ) ;
( * vir_rcc) |= ( 0x3 << 4 ) ;
vir_gpioe-> MODER &= ( ~ ( 0x3 << 18 ) ) ;
vir_gpioe-> MODER |= ( 0x1 << 18 ) ;
vir_gpioe-> ODR &= ( ~ ( 0x1 << 9 ) ) ;
printk ( "寄存器初始化成功\n" ) ;
return 0 ;
}
static int __init mycdev_init ( void )
{
major = register_chrdev ( 0 , "fan" , & fops) ;
if ( major < 0 )
{
printk ( "字符设备驱动注册失败\n" ) ;
return major;
}
printk ( "字符设备驱动注册成功:major=%d\n" , major) ;
cls = class_create ( THIS_MODULE, "fan" ) ;
if ( IS_ERR ( cls) )
{
printk ( "向上提交目录失败\n" ) ;
return - PTR_ERR ( cls) ;
}
dev = device_create ( cls, NULL , MKDEV ( major, 0 ) , NULL , "fan" ) ;
if ( IS_ERR ( dev) )
{
printk ( "向上提交设备节点信息失败\n" ) ;
return - PTR_ERR ( dev) ;
}
all_fan_init ( ) ;
return 0 ;
}
static void __exit mycdev_exit ( void )
{
iounmap ( vir_gpioe) ;
iounmap ( vir_rcc) ;
device_destroy ( cls, MKDEV ( major, 0 ) ) ;
class_destroy ( cls) ;
unregister_chrdev ( major, "fan" ) ;
}
module_init ( mycdev_init) ;
module_exit ( mycdev_exit) ;
MODULE_LICENSE ( "GPL" ) ;
motor.c
# include <linux/init.h>
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/io.h>
# include <linux/device.h>
# include "head.h"
struct class * cls;
struct device * dev;
gpio_t * vir_gpiof;
int major;
char kbuf[ 128 ] = { 0 } ;
unsigned int * vir_rcc;
int mycdev_open ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
long mycdev_ioctl ( struct file * file, unsigned int cmd, unsigned long arg)
{
switch ( cmd)
{
case MOTOR_ON:
vir_gpiof-> ODR |= ( 0x1 << 6 ) ;
break ;
case MOTOR_OFF:
vir_gpiof-> ODR &= ( ~ ( 0X1 << 6 ) ) ;
break ;
}
return 0 ;
}
int mycdev_close ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
struct file_operations fops = {
. open = mycdev_open,
. unlocked_ioctl = mycdev_ioctl,
. release = mycdev_close,
} ;
int all_motor_init ( void )
{
vir_gpiof = ioremap ( GPIOB, sizeof ( gpio_t ) ) ;
if ( vir_gpiof == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
vir_rcc = ioremap ( PHY_RCC_ADDR, 4 ) ;
if ( vir_rcc == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
printk ( "物理地址映射成功\n" ) ;
( * vir_rcc) |= ( 0x3 << 4 ) ;
vir_gpiof-> MODER &= ( ~ ( 0x3 << 12 ) ) ;
vir_gpiof-> MODER |= ( 0x1 << 12 ) ;
vir_gpiof-> ODR &= ( ~ ( 0x1 << 6 ) ) ;
printk ( "寄存器初始化成功\n" ) ;
return 0 ;
}
static int __init mycdev_init ( void )
{
major = register_chrdev ( 0 , "bee" , & fops) ;
if ( major < 0 )
{
printk ( "字符设备驱动注册失败\n" ) ;
return major;
}
printk ( "字符设备驱动注册成功:major=%d\n" , major) ;
cls = class_create ( THIS_MODULE, "bee" ) ;
if ( IS_ERR ( cls) )
{
printk ( "向上提交目录失败\n" ) ;
return - PTR_ERR ( cls) ;
}
dev = device_create ( cls, NULL , MKDEV ( major, 0 ) , NULL , "bee" ) ;
if ( IS_ERR ( dev) )
{
printk ( "向上提交设备节点信息失败\n" ) ;
return - PTR_ERR ( dev) ;
}
all_motor_init ( ) ;
return 0 ;
}
static void __exit mycdev_exit ( void )
{
iounmap ( vir_gpiof) ;
iounmap ( vir_rcc) ;
device_destroy ( cls, MKDEV ( major, 0 ) ) ;
class_destroy ( cls) ;
unregister_chrdev ( major, "bee" ) ;
}
module_init ( mycdev_init) ;
module_exit ( mycdev_exit) ;
MODULE_LICENSE ( "GPL" ) ;
bee.c
# include <linux/init.h>
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/io.h>
# include <linux/device.h>
# include "head.h"
struct class * cls;
struct device * dev;
gpio_t * vir_gpiob;
int major;
char kbuf[ 128 ] = { 0 } ;
unsigned int * vir_rcc;
int mycdev_open ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
long mycdev_ioctl ( struct file * file, unsigned int cmd, unsigned long arg)
{
switch ( cmd)
{
case BEE_ON:
vir_gpiob-> ODR |= ( 0x1 << 6 ) ;
break ;
case BEE_OFF:
vir_gpiob-> ODR &= ( ~ ( 0X1 << 6 ) ) ;
break ;
}
return 0 ;
}
int mycdev_close ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
struct file_operations fops = {
. open = mycdev_open,
. unlocked_ioctl = mycdev_ioctl,
. release = mycdev_close,
} ;
int all_motor_init ( void )
{
vir_gpiob = ioremap ( GPIOB, sizeof ( gpio_t ) ) ;
if ( vir_gpiob == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
vir_rcc = ioremap ( PHY_RCC_ADDR, 4 ) ;
if ( vir_rcc == NULL )
{
printk ( "ioremap filed:%d\n" , __LINE__ ) ;
return - ENOMEM;
}
printk ( "物理地址映射成功\n" ) ;
( * vir_rcc) |= ( 0x1 << 1 ) ;
vir_gpiob-> MODER &= ( ~ ( 0x3 << 12 ) ) ;
vir_gpiob-> MODER |= ( 0x1 << 12 ) ;
vir_gpiob-> ODR &= ( ~ ( 0x1 << 6 ) ) ;
printk ( "寄存器初始化成功\n" ) ;
return 0 ;
}
static int __init mycdev_init ( void )
{
major = register_chrdev ( 0 , "bee" , & fops) ;
if ( major < 0 )
{
printk ( "字符设备驱动注册失败\n" ) ;
return major;
}
printk ( "字符设备驱动注册成功:major=%d\n" , major) ;
cls = class_create ( THIS_MODULE, "bee" ) ;
if ( IS_ERR ( cls) )
{
printk ( "向上提交目录失败\n" ) ;
return - PTR_ERR ( cls) ;
}
dev = device_create ( cls, NULL , MKDEV ( major, 0 ) , NULL , "bee" ) ;
if ( IS_ERR ( dev) )
{
printk ( "向上提交设备节点信息失败\n" ) ;
return - PTR_ERR ( dev) ;
}
all_motor_init ( ) ;
return 0 ;
}
static void __exit mycdev_exit ( void )
{
iounmap ( vir_gpiob) ;
iounmap ( vir_rcc) ;
device_destroy ( cls, MKDEV ( major, 0 ) ) ;
class_destroy ( cls) ;
unregister_chrdev ( major, "bee" ) ;
}
module_init ( mycdev_init) ;
module_exit ( mycdev_exit) ;
MODULE_LICENSE ( "GPL" ) ;