社区饮水机控制系统 项目

目录

项目要求

实现

驱动层代码

应用层代码

Makefile


项目要求

设计一个社区饮水机控制系统
功能概述:
 模拟饮水机按键控制开始停止功能,并根据时间控制出水量(红灯表示出水状态,绿灯表示停止状态)。应用层程序模拟刷卡或者扫码计费,如应用层(向驱动)传递数据3那么就表示付费3元。
 详情:
  应用层检测终端输入数据(最好有包头包尾的数据处理功能),输入格式(包头ID金额包尾 eg(0X550X010X020XFF)表示包头0X55 ID 0x01 金额2元包尾0XFF),应用层本地保存用户数据,保存个文本就行(谁消费多少),之后传递金额数据给驱动。
  驱动层上点红灯闪烁(蓝灯亮),当检测到应用层安装以后绿灯常亮,当应用层传来消费金额以后根据金额(注意识别包头包尾),倒计时并亮红灯表示放水,倒计时结束亮绿灯并且蜂鸣器响一段时间表示水停。

实现

驱动层代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <asm/io.h>
#include <linux/uaccess.h>
 
irqreturn_t handler(int irqno, void *dev);
void timer_function(unsigned long data);
void timer_function2(unsigned long data);
void timer_function3(unsigned long data);
void timer_function4(unsigned long data);
void timer_function5(unsigned long data);
 
#define MODNAME "qd"     //驱动文件名字
unsigned int major=0;               //主设备号
 
 
#define GPIONO(m, n) m * 32 + n
#define GPIO_B8 (GPIONO(1, 8))
#define GPIO_B16 (GPIONO(1, 16))
int gpiono[] = {GPIO_B8, GPIO_B16};
char *name[] = {"gpio_it_8", "gpio_it_16"};
#define RED 0XC001A000
#define GREEN 0XC001E000
#define BLUE 0XC001B000
unsigned int *red_base = NULL;
unsigned int *green_base = NULL;
unsigned int *blue_base = NULL;
 
#define BEEP 0XC001C000
unsigned int *beep_base = NULL;
 
 
struct timer_list mytimer; //按键
struct timer_list mytimer2; //扣费
struct timer_list mytimer3; //闪灯
struct timer_list mytimer4; //蜂鸣器
struct timer_list mytimer5; //无操作检测
 
//******************************读写操作函数**************
 
int copy_size = 0;
char kbuf[128] = {0};
 
ssize_t mycdv_read(struct file *file, char __user *ubuf, size_t len, loff_t *loff)
{
  if (len > sizeof(kbuf))    //len是用户需要的,有可能大于内核传的
    {
        len = sizeof(kbuf);    //大于的时候,有多少就给它多少
    }
    copy_size = copy_to_user(ubuf, kbuf, len);
    if (copy_size)
    {
        printk(KERN_ERR "copy_to_user error\n");
        return copy_size;
    }
 
    return 0;
}
 
ssize_t mycdv_write(struct file *file, const char __user *ubuf, size_t len, loff_t *lo)
{
    if (len > sizeof(kbuf))
    {
        len = sizeof(kbuf);
    }
 
    copy_size = copy_from_user(kbuf, ubuf, len);
    if (copy_size)
    {
        printk(KERN_ERR "copy_from_user error\n");
        return copy_size;
    }
 
    if( kbuf[0] != 0x55 || kbuf[3] != 0xff)                    //判断数据格式是否正确
    {
      printk(KERN_ERR "数据格式错误,请重新输入\n");
      return 0;
    }
    kbuf[4]=0xff;
    printk(KERN_ERR "等待灌装......\n");
 
 
      
    return 0;
}
int mycdv_open(struct inode *inode, struct file *file)
{
    printk(KERN_ERR "mycdv open ok\n");
 
    del_timer(&mytimer3);          //***********停止闪烁
    *(red_base) &= ~(1 << 28);    //**关红灯
    *(green_base) |= 1 << 13;       //****开绿灯
    return 0;
}
int mycdv_release(struct inode *inode, struct file *file)
{
    printk(KERN_ERR "mycdv release ok\n");
 
    *(green_base) &=~(1 << 13);    //****************关绿灯
    mytimer3.expires = jiffies + 10;          //****************再闪红灯
    mytimer3.function = timer_function3;
    mytimer3.data = 0;
    init_timer(&mytimer3);  	
    add_timer(&mytimer3);   
 
    return 0;
}
 
 
const struct file_operations fops=
{
   .read = mycdv_read,
   .write = mycdv_write,
   .open = mycdv_open,
   .release = mycdv_release,
};
 
struct class *cls;
struct device *dev;
 
int ret;
int i;
 
 
//入口  申请资源
static int __init hello_init(void)
{
  //***********************  创建字符设备*************
 
    major = register_chrdev(major, MODNAME, &fops);       //注册字符设备
    if(major<0)
	{
 		printk(KERN_ERR "register chrdev error\n");
		return major;
	}
 
    cls = class_create(THIS_MODULE, MODNAME);    //创建一个class类型的对象,向用户空间提交目录信息(内核目录的创建)
    if(IS_ERR(cls))
    {
        return PTR_ERR(cls);
    }
 
    dev = device_create(cls, NULL,MKDEV(major,0), NULL,MODNAME );    //向用户空间提交文件信息
    if(IS_ERR(dev ))
  {
    return PTR_ERR(dev);
  }
  //****************************初始化定时器***************
 
    mytimer.expires = jiffies + 10;
    mytimer.function = timer_function;
    mytimer.data = 0;
    init_timer(&mytimer);  //内核帮你填充你未填充的对象	
    add_timer(&mytimer);    //开启一次定时器
 
    mytimer3.expires = jiffies + 10;
    mytimer3.function = timer_function3;
    mytimer3.data = 0;
    init_timer(&mytimer3);  //内核帮你填充你未填充的对象	
    add_timer(&mytimer3);    //开启一次定时器
 
      mytimer4.expires = jiffies + 10;
      mytimer4.function = timer_function4;
      mytimer4.data = 0;
      init_timer(&mytimer4);  	
      add_timer(&mytimer4);  
 
 
    //***************************开启按键中断************
 
      for (i = 0; i < sizeof(gpiono) / sizeof(int); i++)
    {
        ret = request_irq(gpio_to_irq(gpiono[i]), handler, IRQF_TRIGGER_FALLING, name[i], NULL);
        if (ret != 0)
        {
            printk(KERN_ERR "%s request irq err\n", name[i]);
            return ret;
        }
    }
 
  //***************************初始化LED、蜂鸣器******
 
    red_base = ioremap(RED, 40);              //关闭红灯
    if (NULL == red_base)
    {
        printk("RED ioremap err\n");
    }
    *(red_base) &= ~(1 << 28);
    *(red_base + 1) |= 1 << 28;
    *(red_base + 9) &= ~(3 << 24);
    blue_base = ioremap(BLUE,40);    //关闭蓝灯
    if (NULL == blue_base)
    {
        printk("BLUE ioremap err\n");
    }
    *(blue_base) &= ~(1<<12);
    *(blue_base+1) |= 1<<12;
    *(blue_base+8) |= 2<<24;
    green_base = ioremap(GREEN, 40);   //关绿灯
    if (NULL == green_base)
    {
        printk("GREEN ioremap err\n");
    }
    *(green_base) &=~(1 << 13);
    *(green_base + 1) |= 1 << 13;
    *(green_base + 8) &= ~(3 << 26);
    beep_base = ioremap(BEEP,40);  //关蜂鸣器
    if (NULL == beep_base)
    {
        printk("BEEP ioremap err\n");
    }
    *(beep_base)  &= ~ (1<<14) ;
    *(beep_base+1) |= 1<<14;
    *(beep_base+8) |= 1<<28;
    return 0;
}
 
//出口  释放资源
static void __exit hello_exit(void)
{
  //********************还原LED、蜂鸣器************
 
  *(red_base) |= (1 << 28);
  *(green_base) |= 1<<13;
  *(blue_base) |=(1<<12);
  *(beep_base)  &= ~ (1<<14) ;
  iounmap(red_base);
  iounmap(green_base);
   iounmap(blue_base);
  iounmap(beep_base);
 
//*********************关闭按键、定时器中断***********
 
  for (i = 0; i < sizeof(gpiono) / sizeof(int); i++)
    {
        free_irq(gpio_to_irq(gpiono[i]), NULL);
    }
 
  del_timer(&mytimer);
  del_timer(&mytimer2);
  del_timer(&mytimer3);
  del_timer(&mytimer4);
  del_timer(&mytimer5);
 
 
  //*******************************注销字符设备*****************
    device_destroy(cls, MKDEV(major, 0));         
    class_destroy(cls);                                                 
    unregister_chrdev(major, MODNAME);         
 
}
 
module_init(hello_init);    //入口
module_exit(hello_exit);    //出口
MODULE_LICENSE("GPL");      //许可证
 
 
 
//*****************按键中断处理函数***********
 
irqreturn_t handler(int irqno, void *dev)
{
    mod_timer(&mytimer,jiffies + 30);
    return IRQ_HANDLED;
}
 
//*****************定时器中断处理函数********
 
void timer_function(unsigned long data)          //***********检测按键
{
    int B8 = gpio_get_value(GPIO_B8);
    int B16 = gpio_get_value(GPIO_B16);
 
    if (B8 == 0)     //****************暂停按键按下
    {
      if(kbuf[4]!=0xff)
      {
        printk(KERN_ERR "请先刷卡缴费\n");
        return;
      }
      printk(KERN_ERR "暂停\n");
 
       *(green_base) |=1 << 13;    //****************开绿灯
      *(red_base) &= ~(1 << 28);//********关红灯
      mytimer5.expires = jiffies + 10000;                //****开启无操作检测10s
      mytimer5.function = timer_function5;
      mytimer5.data = 0;
      init_timer(&mytimer5);  	
      add_timer(&mytimer5); 
      
      del_timer(&mytimer2);
    }
    if (B16 == 0)              //*****************开始按键按下
    {
      if(kbuf[4]!=0xff)
      {
        printk(KERN_ERR "请先刷卡缴费\n");
        return;
      }
      printk(KERN_ERR "开始\n");
      del_timer(&mytimer5);   //**********关闭无操作检测
 
      *(green_base) &=~(1 << 13);    //****************关绿灯
      *(red_base) |= 1 << 28;  //********开红灯
 
      printk(KERN_ERR "当前余额:%d\n",kbuf[2]);
 
      mytimer2.expires = jiffies + 1000;
      mytimer2.function = timer_function2;
      mytimer2.data = 0;
      init_timer(&mytimer2);  //内核帮你填充你未填充的对象	
      add_timer(&mytimer2);    //开启一次定时器
    }
}
 
void timer_function2(unsigned long data) //***********按秒扣费
{
    if(kbuf[2]==0)
  {
      del_timer(&mytimer2);
      printk(KERN_ERR "灌水结束\n");
 
     *(green_base) |=1 << 13;    //****************开绿灯
      *(red_base) &= ~(1 << 28);  //********关红灯
      kbuf[4]=0x00;  //**********结束标志
 
      *(beep_base)  |= 1<<14 ;//******开蜂鸣器
      mod_timer(&mytimer4,jiffies + 1000);//*****1s后关闭
 
      return;
  }
  kbuf[2]=kbuf[2]-0.5;
  printk(KERN_ERR "当前余额:%.2f\n",kbuf[2]);
 
  mod_timer(&mytimer2,jiffies + 1000);
}
int led_flag=0;
void timer_function3(unsigned long data) //***********闪红灯 0.3s
{
  led_flag++;
  if(led_flag==2)
    led_flag=0;
  if(led_flag==0)
    *(red_base) &= ~(1 << 28);
  if(led_flag==1)
    *(red_base) |= 1 << 28;
  mod_timer(&mytimer3,jiffies + 300);
}
 
void timer_function4(unsigned long data) //***********关蜂鸣器
{
  *(beep_base)  &= ~ (1<<14) ;
}
 
void timer_function5(unsigned long data) //***********长时间无操作
{
  printk(KERN_ERR "售水结束,余额:%d\n",kbuf[2]);
  kbuf[4]=0x00;
}

应用层代码

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
 
char buf[128]={0};
char history[128]={0};
int main(int argc, char const *argv[])
{
    int fd;
    int fd_history;
    fd = open("/dev/qd",O_RDWR);   //打开驱动文件
    if(fd<0)
    {
        perror("open err");
        return -1;
    }
 
    fd_history = open("History.txt",O_WRONLY | O_APPEND | O_CREAT ,0777 );   //打开历史记录文件
    if(fd_history<0)
    {
        perror("open err");
        return -1;
    }
    int old,new;
    while (1)
    {
        printf("请输入ID和金额     eg:(0X55 0X01 0X02 0XFF) 表示包头 0X55 ID 0x01 金额 2元0X02  包尾 0XFF)\n");
        scanf("%x %x %x %x",&buf[0],&buf[1],&buf[2],&buf[3]);
        old=buf[2];
        write(fd,buf,sizeof(buf));   //向驱动写入数据
        memset(buf,0,sizeof(buf));    
        do{
            read(fd,buf,sizeof(buf));    //等待售水结束
        }while (buf[4]!=0x00);
        new=buf[2];
        sprintf(history,"ID:0x%02hx    consumption: %d\n",buf[1],old-new);  //拼接历史记消息,写入History.txt
        write(fd_history, history, strlen(history));
        
    }
    
    close(fd_history);
    close(fd);
    return 0;
}

Makefile

KERNELDIR:=/home/hq/kernel/kernel-3.4.39/
#KERNELDIR:=/lib/modules/$(shell uname -r)/build/
PWD:=$(shell pwd)
all:
	make -C $(KERNELDIR) M=$(PWD) modules
	arm-none-linux-gnueabi-gcc yy.c 
	cp *.ko a.out /opt/6818/rootfs/rootfs 
clean:
	make -C $(KERNELDIR) M=$(PWD) clean
obj-m :=qd.o
#obj-m:=qd.o

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值