fs4412控制蜂鸣器根据不同音符发出不同声音 7.17

控制蜂鸣器根据不同音符发出不同声音

pwm

驱动程序

/*===============================================
 *   文件名称:mod.c
 *   创 建 者: memories
 *   创建日期:2023年07月06日
 *   描    述:have a nice day
 ================================================*/
//1.header
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/of.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include "cmd.h"
#define MA 300
#define MI 0

static dev_t no = 0;
static unsigned count = 1;
static const char *name = "mydev";
static struct cdev mydev;
static char mbuf[32]={0};
static int *gpd0con=NULL,*tcfg0=NULL,*tcfg1=NULL,*tcntb0=NULL,*tcmpb0=NULL,*tcon=NULL;



void addr_map(void)
{

    gpd0con = ioremap(GPD0CON,4);
    tcfg0   = ioremap(TCFG0,4);
    tcfg1   = ioremap(TCFG1,4);
    tcntb0  = ioremap(TCNTB0,4);
    tcmpb0  = ioremap(TCMPB0,4);
    tcon    = ioremap(TCON,4);
}
void addr_unmap(void)
{
    iounmap(gpd0con);
    iounmap(tcfg0);
    iounmap(tcfg1);
    iounmap(tcntb0);
    iounmap(tcmpb0);
    iounmap(tcon);
}

void dev_init(void)
{
    writel(((readl(gpd0con)) & ~(0xf)) | (0x2),gpd0con);
    writel(((readl(tcfg1)) & ~(0xf)) | (0x2),tcfg1);
    writel((readl(tcfg0)) |(0xff),tcfg0);
    writel(3000,tcntb0);
    writel(1500,tcmpb0);
    writel(((readl(tcon)) |(1<<1) | (1<<3) | (0x3<<2)),tcon);
    writel(((readl(tcon)) & ~(1<<1)),tcon);
}

void pwm_on(void)
{
    printk("pwm on\n");
    writel((readl(tcon)| (0x1)),tcon);
}
void pwm_off(void)
{
    printk("pwm off\n");
    writel((readl(tcon) & ~(0x1)),tcon);
}
int myopen(struct inode *pi,struct file *pf)
{
    printk("kernel open\n");
    return 0;
}

int myrelease(struct inode *pi,struct file *pf)
{
    printk("kernel close\n");
    return 0;
}
ssize_t myread (struct file *pf, char __user *ubuf, size_t len, loff_t *poff)
{
    int ret = 0;
    ret = copy_to_user(ubuf,mbuf,len);
    if(ret != 0)
        return -1;
    printk("mmmm\n");   
    return len;
}
ssize_t mywrite (struct file *pf, const char __user *ubuf, size_t len, loff_t *poff)
{
    int ret = 0;
    ret = copy_from_user(mbuf,ubuf,len);
    if(ret != 0)
        return -1;
    printk("now write\n");    
    return len;
}

void pwm_set(unsigned int arg)
{
    unsigned int n = 100000000/256/4/arg;
    printk("n=%d\n",n);
    writel(n,tcntb0);
    writel(n/2,tcmpb0);
    //writel(3000,tcntb0);
    //writel(1500,tcmpb0);
}
long myioctl (struct file *pf, unsigned int cmd, unsigned long arg)
{
    switch(cmd)
    {
        case PWM_ON:
            pwm_on();
            break;
        case PWM_OFF:
            pwm_off();
            break;
        case PWM_SET:
            pwm_set(arg);
            break;
    };
    return 0;
}

static const struct file_operations myfops={
    .release = myrelease,
    .open = myopen,
    .read = myread,
    .write = mywrite,
    .unlocked_ioctl = myioctl,

};//文件操作集
//2.init/exit fun
static int myinit(void)
{
    int ret = 1;
    //up: kernel
    //1.registed 把设备对象注册到系统中
    no = MKDEV(MA,MI);//组合主次设备号
    ret = register_chrdev_region(no,count,name);
    if(ret != 0)
    {
        printk("reg is error\n");
        return -1;
    }
    //2.init    设备初始化,抽象出来一个对象
    cdev_init(&mydev,&myfops);
    //3.add     添加设备
    ret = cdev_add(&mydev,no,count);
    if(ret != 0)
    {
        unregister_chrdev_region(no,count);
        return -1;
    }
    //down:hardware
    printk("myinit ok\n");
    //1.映射,内核的物理地址转换为虚拟地址paddr-->vaddr
    printk("121212\n");
    addr_map();
    //2.dev init
    dev_init();
    return 0;
}
static void myexit(void)
{
    //和内核相关
    cdev_del(&mydev);
    unregister_chrdev_region(no,count);
    printk("myexit ok\n");
    //和硬件相关
    //1.解除映射
    addr_unmap();
    return ;
}
//3.reg kernel
module_init(myinit);
module_exit(myexit);

//模块信息描述
//4.mod info
MODULE_LICENSE("GPL");

应用程序

/*===============================================
 *   文件名称:mainopen.c
 *   创 建 者: memories
 *   创建日期:2023年07月06日
 *   描    述:have a nice day
 ================================================*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include "cmd.h"

#define DO  523
#define RE  597
#define MII 659

struct node{
 int y;
 int t;
};

struct node tiggers[]={
    {DO,1},{RE,1},{MII,1},{DO,1},
        {DO,1},{RE,1},{MII,1},{DO,1},
};

int main(int argc, char *argv[])
{ 
    int n = 0;
    char *start;
    char wbuf[20]="12122122142";
    char rbuf[32]={0};
    int ret = 0;
    int fd = open("/dev/mydev",O_RDWR);
    if(fd < 0)
    {
        printf("open failed fd is %d\n",fd);
        return -1;
    }
    ioctl(fd,PWM_ON);
    for(n = 0;n<sizeof(tiggers)/sizeof(struct node);n++)
    {
        ioctl(fd,PWM_SET,tiggers[n].y);
        usleep(tiggers[n].t*400000);
    }
    ioctl(fd,PWM_OFF);
    close(fd);
    return 0;
} 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独memories

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值