单片机
返回首页

【改进】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

2024-08-16 来源:cnblogs

一、使用struct pin_desc 管理按键的值

1.定义结构体

2.将前面我们申请中断时写的(void *)1修改为 &pins_desc[n]

在ioctl中,设置中断中修改

在key_release中释放中修改

3.在中断程序中利用我们定义的struc pins_desc判断并得到按键的值

4.得到按键键值后,唤醒程序,在read函数中返回键值

附上驱动源程序:


  1 /******************************

  2     linux key_query

  3  *****************************/

  4 #include

  5 #include

  6 #include

  7 #include

  8 #include

  9 #include

 10 #include

 11 #include

 12 #include

 13 #include

 14 #include

 15 #include

 16 #include //error: 'TASK_INTERRUPTIBLE' undeclared 

 17 #include

 18 

 19 #include 'mx257_gpio.h'

 20 #include 'mx25_pins.h'

 21 #include 'iomux.h'

 22 

 23 #define Driver_NAME 'key_interrupt'

 24 #define DEVICE_NAME 'key_interrupt'

 25 

 26 #define GPIO2_21    MX25_PIN_CLKO

 27 #define GPIO3_15    MX25_PIN_EXT_ARMCLK

 28 #define GPIO2_10    MX25_PIN_A24

 29 #define GPIO2_11    MX25_PIN_A25

 30 #define GPIO2_8     MX25_PIN_A22

 31 #define GPIO2_9     MX25_PIN_A23

 32 #define GPIO2_6     MX25_PIN_A20

 33 #define GPIO2_7     MX25_PIN_A21

 34 //command

 35 #define key_input     0

 36 #define version        1

 37 //定义各个按键按下的键值

 38 struct pin_desc{

 39     unsigned int pin;

 40     unsigned int key_val;

 41 };

 42 //当按键按下时,键值分别为 以下值

 43 struct pin_desc pins_desc[8] = {

 44     {GPIO2_6,    0x01},

 45     {GPIO2_7,    0x02},

 46     {GPIO2_8,    0x03},

 47     {GPIO2_9,    0x04},

 48     {GPIO2_10,    0x05},

 49     {GPIO2_11,    0x06},

 50     {GPIO2_21,    0x07},

 51     {GPIO3_15,    0x08},

 52 };

 53 //定义一个全局变量,用于保存按下的键值

 54 static unsigned int key_val;

 55 

 56 //interrupt head

 57 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);

 58 static volatile unsigned char ev_press;  

 59 

 60 static int major=0;

 61 

 62 //auto to create device node

 63 static struct class *drv_class = NULL;

 64 static struct class_device *drv_class_dev = NULL;

 65 

 66 

 67 /* 应用程序对设备文件/dev/key_query执行open(...)时,

 68  * 就会调用key_open函数*/

 69 static int key_open(struct inode *inode, struct file *file)

 70 {

 71     printk('<0>function open!nn');

 72     

 73     return 0;

 74 }

 75 

 76 /* 中断程序key_irq */

 77 static irqreturn_t key_irq(int irq, void *dev_id)

 78 {

 79     struct pin_desc * pindesc = (struct pin_desc *)dev_id;

 80     //发生了中断

 81     //printk('<0>function interrupt key_irq!nn');

 82     //获取按键键值

 83     if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){

 84         /* 按下 */

 85         key_val = pindesc->key_val;

 86     }else{

 87         key_val = 0x80 | pindesc->key_val;

 88     }

 89     printk('<0>get key 0x%x',key_val);    

 90     ev_press = 1;

 91     wake_up_interruptible(&key_interrupt_wait);

 92 

 93     return IRQ_RETVAL(IRQ_HANDLED);

 94 }

 95 

 96 

 97 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

 98 {

 99     int ret;

100     //如果按键没有按下,没有中断,休眠

101     wait_event_interruptible(key_interrupt_wait,ev_press);

102 

103     ret = copy_to_user(buff,&key_val,sizeof(key_val));

104     if(ret){

105         ;

106     }

107     ev_press = 0;

108     return sizeof(key_val);

109 

110     //int cnt=0;

111     //unsigned char key_vals[8];

112 

113     /*

114     // reading the pins value

115     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;

116     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;

117     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;

118     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;

119     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;

120     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;

121     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;

122     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;

123     

124     //printk('<0>%04d key pressed: %d %d %d %d %d %d %d %dn',cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]); 

125     */

126 }

127 

128 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)

129 {

130     printk('<0>function write!nn');

131     

132     return 1;

133 }

134 

135 static int  key_release(struct inode *inode, struct file *filp)

136 {

137     printk('<0>function release!nn');

138     //释放中断

139     free_irq(IOMUX_TO_IRQ(GPIO2_21),  &pins_desc[6]);

140     //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);

141     free_irq(IOMUX_TO_IRQ(GPIO2_11),  &pins_desc[5]);

142     free_irq(IOMUX_TO_IRQ(GPIO2_10),  &pins_desc[4]);

143     free_irq(IOMUX_TO_IRQ(GPIO2_9),   &pins_desc[3]);

144     //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);

145     free_irq(IOMUX_TO_IRQ(GPIO2_7),   &pins_desc[1]);

146     free_irq(IOMUX_TO_IRQ(GPIO2_6),   &pins_desc[0]);

147     return 0;

148 }

149 

150 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)

151 {

152     int ret;

153     printk('<0>function ioctl!nn');

154     switch (command) {

155         case key_input:    

156             //设置所有的引脚为输入

157             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));

158             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));

159             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));

160             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));

161             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));

162             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));

163             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));

164             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));

165             printk('<0>have setting all pins to gpio input mod !n');

166             //设置GPIO引脚为上拉模式

167             mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

168             mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

169             //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

170             mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

171             mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

172             mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

173             mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

174             //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

175 

176             //设置GPIO引脚中断  ,下降沿触发

177             request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_6', &pins_desc[0]);

178             request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_7', &pins_desc[1]);

179             request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_9', &pins_desc[3]);

180             request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_10', &pins_desc[4]);

181             request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_11', &pins_desc[5]);

182             request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_21', &pins_desc[6]);

183             //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO3_15', &pins_desc[7]);

184             //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_8', &pins_desc[2]);

185             printk('<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !n');

186 

187             break;

188         case version:

189             printk('<0>hello,the version is 0.1.0nn');

190             break;

191         default:

192               printk('<0>command error n');

193             printk('<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;n');

194             printk('<0>command: nn');

195             return -1;

196     }

197     return 0;    

198 }

199 

200 /* 这个结构是字符设备驱动程序的核心

201  * 当应用程序操作设备文件时所调用的open、read、write等函数,

202  * 最终会调用这个结构中指定的对应函数

203  */

204 static struct file_operations key_fops = {

205     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */

206     .open   =   key_open,     

207     .read    =    key_read,       

208     .write    =    key_write,       

209     .release=   key_release,

210     .ioctl  =   key_ioctl,    

211 };

212     

213 /*

214  * 执行insmod命令时就会调用这个函数 

215  */

216 static int __init  key_irq_init(void)

217 {

218     printk('<0>nHello,this is %s module!nn',Driver_NAME);

219     //register and mknod

220     major = register_chrdev(0,Driver_NAME,&key_fops);

221     drv_class = class_create(THIS_MODULE,Driver_NAME);

222     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);    /*/dev/key_query*/

223 

224     //set all pins to GPIO mod  ALF5

225     mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);

226     mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);

227       mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);

228        mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);

229     mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);

230     mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);

231     mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);

232     mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);

233     //request IOMUX GPIO

234     gpio_request(IOMUX_TO_GPIO(GPIO2_21), 'GPIO2_21');

235      gpio_request(IOMUX_TO_GPIO(GPIO3_15), 'GPIO3_15');

236      gpio_request(IOMUX_TO_GPIO(GPIO2_10), 'GPIO2_10');

237        gpio_request(IOMUX_TO_GPIO(GPIO2_11), 'GPIO2_11');

238     gpio_request(IOMUX_TO_GPIO(GPIO2_8), 'GPIO2_8');

239      gpio_request(IOMUX_TO_GPIO(GPIO2_9), 'GPIO2_9');

240       gpio_request(IOMUX_TO_GPIO(GPIO2_6), 'GPIO2_6');

241     gpio_request(IOMUX_TO_GPIO(GPIO2_7), 'GPIO2_7');

242     

243     return 0;

244 }

245 

246 /*

247  * 执行rmmod命令时就会调用这个函数 

248  */

249 static void __exit key_irq_exit(void)

250 {

251     printk('<0>nGoodbye,%s!nn',Driver_NAME);

252 

253     unregister_chrdev(major,Driver_NAME);

254     device_unregister(drv_class_dev);

255     class_destroy(drv_class);

256 

257     /* free gpios */

258     mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);

259     mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);

260     mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);

261     mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);

262     mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);

263     mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);

264     mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);

265     mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);

266 

267     gpio_free(IOMUX_TO_GPIO(GPIO2_21));

268     gpio_free(IOMUX_TO_GPIO(GPIO3_15));

269     gpio_free(IOMUX_TO_GPIO(GPIO2_10));

270     gpio_free(IOMUX_TO_GPIO(GPIO2_11));

271     gpio_free(IOMUX_TO_GPIO(GPIO2_8));

272     gpio_free(IOMUX_TO_GPIO(GPIO2_9));

273     gpio_free(IOMUX_TO_GPIO(GPIO2_6));

274     gpio_free(IOMUX_TO_GPIO(GPIO2_7));

275 

276 }

277 /* 这两行指定驱动程序的初始化函数和卸载函数 */

278 module_init(key_irq_init);

279 module_exit(key_irq_exit);

280 

281 /* 描述驱动程序的一些信息,不是必须的 */

282 MODULE_AUTHOR('Lover雪');

283 MODULE_VERSION('0.1.0');

284 MODULE_DESCRIPTION('IMX257 key Driver');

285 MODULE_LICENSE('GPL');


附上应用程序代码:


 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 #include

 8 #include

 9 #include

10 #include

11 #include

12 #include

13 

14 #include 'mx257_gpio.h'

15 

16 #define key_input     0

17 #define version       1

18 

19 

20 int main(int argc, char **argv)

21 {

22     int fd;

23     int i=0,cnt=0;

24     unsigned char key_val[1];

25     

26     fd = open('/dev/key_interrupt',O_RDWR);

27     if(fd < 0){

28         printf('can't open !!!n');

29     }

30     ioctl(fd,version,NULL);

31     ioctl(fd,key_input,NULL);

32     while(1){

33         read(fd,key_val,sizeof(key_val));

34         printf('%04d key pressed: 0x%xn',cnt++,key_val[0]);    

35     }

36     return 0;

37 }


结果如图所用 insmod key_interrupt.ko

后台运行应用程序 ./test/key_test &

查看中断 cat /proc/interrupts

ps,查看我们后台的进程号,使用kill函数时,驱动程序会自动进入release函数,释放中断号。


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 红外线探测报警器

  • 用NE555制作定时器

  • 带有短路保护系统的5V直流稳压电源电路图

  • 如何构建一个触摸传感器电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章