stm32mp157a linux驱动实现灯,风扇,蜂鸣器,马达的控制

驱动层: mychrdev.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/device.h>
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"

unsigned int major;
char kbuf[128] = {0};
gpio_t* vir_led1;
gpio_t* vir_led2;
gpio_t* vir_led3;
gpio_t* vir_fan; //风扇 gpioe9
gpio_t* vir_beep;//蜂鸣器 gpiob6
gpio_t* vir_motor;//马达 gpiof6
rcc_t*  vir_rcc;
struct class *cls;
struct device *dev;
int mychrdev_open (struct inode *inode, struct file *file)
{
    printk ("%s:%s:%d\n",__FILE__, __func__, __LINE__);
    return 0;
}
ssize_t mychrdev_read (struct file *file, char  *ubuf, size_t size, loff_t *lof)
{
 
    printk ("%s:%s:%d\n",__FILE__, __func__, __LINE__);
    unsigned long ret;
    //向内核空间拷贝数据
    if(size > sizeof(kbuf)) //    
    {
        size = sizeof(kbuf);
    }
    ret = copy_to_user(ubuf,kbuf,size);
    if(ret)
    {
        printk ("copy to user failed\n");
        return ret;
    }
    return 0;
}
ssize_t mychrdev_write (struct file *file, const char *ubuf, size_t size, loff_t *lof)
{ 
    unsigned long ret;
    //从用户空间读取数据
    if(size > sizeof(kbuf)) //    
    {
        size = sizeof(kbuf);
    }
    ret = copy_from_user(kbuf,ubuf,size);
    if(ret)
    {
        printk ("copy from user failed\n");
        return ret;
    }
    printk ("%s:%s:%d\n",__FILE__, __func__, __LINE__);
    switch(kbuf[0])
    {
        case '1':
            if ('1' == kbuf[1]) 
            {
                //(*vir_odr) &= (0x1<<10);
                (vir_led1->ODR) |= (1<<10);
                printk("%s\n","LED1 on by kernel");
            } else if ('0' == kbuf[1])
            {
                //(*vir_odr) &= (~(0x1<<10));
                (vir_led1->ODR) &= (~(1<<10));
                printk("%s\n","LED1 off by kernel");
            }
            break;
        case '2':
            if ('1' == kbuf[1]) 
            {
                //(*vir_odr) &= (0x1<<10);
                (vir_led2->ODR) |= (1<<10);
                printk("%s\n","LED2 on by kernel");
            } else if ('0' == kbuf[1])
            {
                //(*vir_odr) &= (~(0x1<<10));
                (vir_led2->ODR) &= (~(1<<10));
                printk("%s\n","LED2 off by kernel");
            }
            break;
        case '3':
            if ('1' == kbuf[1]) 
            {
                //(*vir_odr) &= (0x1<<10);
                (vir_led1->ODR) |= (1<<8);
                printk("%s\n","LED3 on by kernel");
            } else if ('0' == kbuf[1])
            {
                //(*vir_odr) &= (~(0x1<<10));
                (vir_led1->ODR) &= (~(1<<8));
                printk("%s\n","LED3 off by kernel");
            }
            break;
        case '4':
            if ('1' == kbuf[1]) 
            {
                (vir_fan->ODR) |= (1<<9);
                printk("%s\n","fan on by kernel");
            } else if ('0' == kbuf[1])
            {
               (vir_fan->ODR) &= (~(1<<9));
                printk("%s\n","fan off by kernel");
            }
            break;
        case '5':
            if ('1' == kbuf[1]) 
            {
                (vir_beep->ODR) |= (1<<6);
                printk("%s\n","beep on by kernel");
            } else if ('0' == kbuf[1])
            {
                (vir_beep->ODR) &= (~(1<<6));
                printk("%s\n","beep off by kernel");
            }
            break;
        case '6':
            if ('1' == kbuf[1]) 
            {
                (vir_motor->ODR) |= (1<<6);
                printk("%s\n","motor on by kernel");
            } else if ('0' == kbuf[1])
            {
                (vir_motor->ODR) &= (~(1<<6));
                printk("%s\n","motor off by kernel");
            }
            break;
        default:
            break;
    } 
    return 0;
}

int mychrdev_close (struct inode *inode, struct file *file)
{

    printk ("%s:%s:%d\n",__FILE__, __func__, __LINE__);
    return 0;
}

const struct file_operations fops = 
{
    .open = mychrdev_open,
    .read =mychrdev_read,
    .write =mychrdev_write,
    .release =mychrdev_close,
};

int led_init(void)
{
    //寄存器地址映射
     //LED1 
     vir_led1 = ioremap(GPIOE,sizeof(gpio_t));
     if (vir_led1 == NULL)
     {
         printk("ioremap failed:%d\n",__LINE__);
         return -ENOMEM;
     }
     vir_led2 = ioremap(GPIOF,sizeof(gpio_t));
     if (vir_led2 == NULL)
     {
         printk("ioremap failed:%d\n",__LINE__);
         return -ENOMEM;
     }
     vir_beep = ioremap(GPIOB,sizeof(gpio_t));
     if (vir_beep == NULL)
     {
         printk("ioremap failed:%d\n",__LINE__);
         return -ENOMEM;
     }
    vir_led3 = vir_led1;
    vir_fan = vir_led1;
    vir_motor = vir_led2;
   

    vir_rcc = ioremap(RCC,sizeof(rcc_t));
    if (vir_rcc == NULL)
    {
        printk("ioremap failed:%d\n",__LINE__);
        return -ENOMEM;
    }
    printk("physical address mapping succeeded\n");

    //寄存器初始化
    // (*vir_rcc) |= (0x1<<4);
    // (*vir_moder) &= (~(0x3<<20));
    // (*vir_moder) |= (~(0x1<<20));
    //GPIOE使能
    (vir_rcc->MP_AHB4ENSETR) |= (1<<4);
    //GPIOF使能
    (vir_rcc->MP_AHB4ENSETR) |= (1<<5);
    //GPIOB使能
    (vir_rcc->MP_AHB4ENSETR) |= (1<<1);

    //LED1 moder 
    (vir_led1->MODER) &= (~(3<<20));
    (vir_led1->MODER) |= (1<<20);

    //LED2 moder
    (vir_led2->MODER) &= (~(3<<20));
    (vir_led2->MODER) |= (1<<20);

    //LED3 moder
    (vir_led3->MODER) &= (~(3<<16));
    (vir_led3->MODER) |= (1<<16);

    //LED1 odr输出低电平
    //(*vir_odr) &= (~(0x1<<10));
    (vir_led1->ODR) &= (~(1<<10));

    //LED2 odr输出低电平
    (vir_led2->ODR) &= (~(1<<10));

    //LED3 odr输出低电平
    (vir_led3->ODR) &= (~(1<<8));

    /*****风扇 蜂鸣器 马达 部分*****/
    //风扇 gpioe9
    vir_fan->MODER &= (~(3<<18));
    vir_fan->MODER |= (1<<18);
    vir_fan->ODR &= (~(1<<9));
    //蜂鸣器 gpiob6
    vir_beep->MODER &= (~(3<<12));
    vir_beep->MODER |= (1<<12);
    vir_beep->ODR &= (~(1<<6));
    //马达 gpiof6
    vir_motor->MODER &= (~(3<<12));
    vir_motor->MODER |= (1<<12);
    vir_motor->ODR &= (~(1<<6));
    printk("register init succeeded\n");
    return 0;
}

static int __init mychrdev_init(void)
{
    //字符设备驱动注册
    major = register_chrdev(0,"mychrdev",&fops);
    if (major < 0)
    {
        printk(" register_chrdev failed\n");
        return major;
    }
     printk("register_chrdev succeeded:major=%d\n",major);

     //向上提交目录
    cls = class_create(THIS_MODULE,"mychrdev");
    if (IS_ERR(cls))
    {
        printk(" 向上提交目录失败\n");
        return PTR_ERR(cls);
    }
    printk(" 向上提交目录成功\n");

    //向上提交设备信息
    dev = device_create(cls,NULL,MKDEV(major,0),NULL,"mychrdev");
    if (IS_ERR(dev))
    {
        printk(" 向上提交设备信息失败\n");
        return PTR_ERR(dev);
    }
    printk(" 向上提交设备信息成功\n");

     

    led_init();
    
    return 0;
}

static void __exit mychrdev_exit(void)
{
    //取消地址映射
    iounmap(vir_led1);
    iounmap(vir_led2);
    iounmap(vir_led3);
    iounmap(vir_rcc);
    //销毁设备信息
    device_destroy(cls,MKDEV(major,0));
    //销毁目录
    class_destroy(cls);
    //注销字符设备驱动
    unregister_chrdev(major,"mychrdev");
    
}


module_init(mychrdev_init);
module_exit(mychrdev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Satoshi Nakamoto");

应用层: 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 <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
char buf[128] = {0};
void horse_led(int fd);
void telegram_beep(int fd);
int main(int argc, char *argv[])
{
    int fd = open("/dev/mychrdev",O_RDWR);
    if (fd < 0)
    {
        printf("open failed\n");
        return -1;
    }
    while (1)
    {
        printf("请输入两个字符:\n");
        printf("第一个字符:1(LED1),2(LED2),3(LED3),4(风扇),5(蜂鸣器),6(马达)\n");
        printf("第二个字符:0(关),1(开)\n");
        printf("输入horse实现跑马灯\n");
        printf("输入quit退出\n");
        fgets(buf,sizeof(buf),stdin);
        buf[strlen(buf)-1] = '\0'; //替换\n
        if (!strcmp(buf,"quit"))
        {
            break;
        }
        if (!strcmp(buf,"horse"))
        {
            horse_led(fd);
        }
        if (!strcmp(buf,"telegram"))
        {
            telegram_beep(fd);
        }
        //向设备中写
        write(fd,buf,sizeof(buf));
        //从设备文件中读取
        memset(buf,0,sizeof(buf));
        read(fd,buf,sizeof(buf));

        printf("buf returned from kernel==>%s\n",buf);
    }
    
    
    

    return 0;
}

void horse_led(int fd)
{
    
    while (1)
    {
    strcpy(buf,"11");
    write(fd,buf,sizeof(buf));
    sleep(1);
    strcpy(buf,"10");
    write(fd,buf,sizeof(buf));
    sleep(1);
    strcpy(buf,"21");
    write(fd,buf,sizeof(buf));
    sleep(1);
    strcpy(buf,"20");
    write(fd,buf,sizeof(buf));
    sleep(1);
    strcpy(buf,"31");
    write(fd,buf,sizeof(buf));
    sleep(1);
    strcpy(buf,"30");
    write(fd,buf,sizeof(buf));
    sleep(1);
    }
}

void telegram_beep(int fd)
{
    while (1)
    {
        strcpy(buf,"51");
        write(fd,buf,sizeof(buf));
        sleep(0.5);
        strcpy(buf,"51");
        write(fd,buf,sizeof(buf));
        sleep(0.5);
        strcpy(buf,"51");
        write(fd,buf,sizeof(buf));
        sleep(0.5);
        strcpy(buf,"50");
        write(fd,buf,sizeof(buf));
        sleep(0.5);
        strcpy(buf,"50");
        write(fd,buf,sizeof(buf));
        sleep(0.5);
        strcpy(buf,"50");
        write(fd,buf,sizeof(buf));
        sleep(0.5);
    }
    
}

现象:

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值