控制蜂鸣器根据不同音符发出不同声音
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;
}