zoukankan      html  css  js  c++  java
  • 05day02pwm

      1 /*
      2 pwm  硬件手册24章
      3 蜂鸣器   GPD0_0  配置成  tout0  pwm0的输出
      4 
      5 从硬件手册P446页 查出  总线的频率是100Mhz
      6 
      7 TCFG0  配置一级分频  0-7位  配置timer0~1的预分频
      8 8~15  配置timer2 3 4预分频
      9 TCFG1  设置5个timer的二级分频
     10 TCON  pwm定时器的控制寄存器
     11 [0]  定时器0的开关
     12 [1]   将TCNTB0和TCMPB0的值分别写入定时器0内部
     13 注意一点,写入的操是瞬间完成,写完之后要立即把该位清0
     14 否则,写入的操作将会连续不断的持续进行,那么定时器就无法计数
     15 [2]  输出电平的极性,参照1300 ,该值会影响到占空比的计算
     16 [3]  单次开启还是连续开启  (每个计数周期结束之后会自动将TCMB0写入计数器中,开始新的周期)
     17 
     18 TINT_CSTAT  使能和清除,对应的中断
     19 
     20 
     21 linux 内核  设备和设备分离
     22 
     23 */  
     24 #include <linux/module.h>
     25 #include <linux/init.h>
     26 #include <linux/kernel.h> //printk
     27 
     28 #include <linux/miscdevice.h> //misc_register....
     29 #include <linux/fs.h> //file_operations
     30 #include <mach/regs-gpio.h> //S5P_VA_GPIO2
     31 #include <linux/ioport.h> //request_mem_region
     32 
     33 #include <linux/io.h>
     34 
     35 #include "pwm_ctl.h"
     36 
     37 #define DEVNAME "ldm"
     38 
     39 
     40 #define TCFG0   (*(volatile u32 *)ioremap(0x139d0000, 4))
     41 #define TCFG1    (*(volatile u32 *)ioremap(0x139d0004, 4))
     42 #define TCON    (*(volatile u32 *)ioremap(0x139d0008, 4))
     43 #define TCNTB0  (*(volatile u32 *)ioremap(0x139d000c, 4))
     44 #define TCMPB0  (*(volatile u32 *)ioremap(0x139d0010, 4))
     45 #define TINT_CSTAT  (*(volatile u32 *)ioremap(0x139d0044, 4))
     46 
     47 #define GPD0CON    (*(volatile u32 *)ioremap(0x114000a0, 4))
     48 
     49 struct   ldm_info 
     50 {
     51     struct miscdevice dev;
     52     struct file_operations  ops;
     53 };
     54 
     55 struct ldm_info ldm;
     56 
     57 //跟时钟配置相关
     58 
     59 
     60 // int pwm_init()
     61 // {
     62 //     //GPD0CON 配置成复用模式
     63 
     64 //     //设置频率
     65 
     66 //     //设置TCNTB0  TCMPB0  两个寄存器
     67 //     //提供应用层相关的接口
     68 
     69 //     //把TCNTB0  和  TCMPB0  加载到 定时器中
     70 //     TCON  |=   1 << 1;
     71 //     TCON  &= ~(1 << 1);
     72 
     73 //     //打开定时器,开启连续触发的模式
     74 
     75 
     76 //     //加入到misc 子系统中 以提供给用户层访问
     77 
     78 
     79 static inline void timer0_cout_set(u32  cmp, u32  cnt)
     80 {
     81     TCNTB0 = cnt;
     82     TCMPB0 = cmp;
     83 
     84     TCON  |=   1 << 1;
     85     TCON  &= ~(1 << 1);
     86 }
     87 
     88 long ldm_ioctl(struct file *  file, unsigned int  cmd, unsigned long arg)
     89 {
     90 
     91     switch(cmd) {
     92         case SET_CMP:
     93             timer0_cout_set(arg, TIMER0_KHZ /2);
     94             break;
     95         default:
     96             break;
     97     }
     98     return 0;
     99 }
    100 
    101 static int ldm_init(void)
    102 {
    103     int ret = 0;
    104     printk("%s:%s, %d
    ", __FILE__, __FUNCTION__, __LINE__);
    105 
    106     ////GPD0CON 配置成复用模式
    107     GPD0CON = (GPD0CON & ~0xf) | 0x2;
    108 
    109     //设置频率
    110     TCFG0 = (TCFG0 & ~0xff) | PWM_PRESCALER0;
    111     TCFG1 = (TCFG1 & ~0xf) | DIV;
    112 
    113     //占空比为50%
    114     timer0_cout_set(TIMER0_KHZ/4, TIMER0_KHZ /2);
    115 
    116     //把TCNTB0  和  TCMPB0  加载到 定时器中
    117     TCON  |=   1 << 1;
    118     TCON  &= ~(1 << 1);
    119 
    120     //打开定时器,选择连续触发模式
    121     TCON &= ~(1 << 2);
    122     TCON |=  1<< 3 | 1;
    123 
    124     //给应用层提供接口
    125     ldm.dev.minor =  MISC_DYNAMIC_MINOR;
    126     ldm.dev.name  = DEVNAME;
    127     ldm.dev.fops = &ldm.ops;
    128     ldm.ops.unlocked_ioctl = ldm_ioctl;
    129 
    130     ret = misc_register(&ldm.dev);
    131     if(ret < 0) {
    132         printk("misc_register  failed
    ");
    133         goto err_misc_register;
    134     }
    135 
    136     return 0;
    137 err_misc_register:
    138     return -1;
    139 
    140 }
    141 
    142 static void ldm_exit(void)
    143 {
    144     printk("%s:%s, %d
    ", __FILE__, __FUNCTION__, __LINE__);
    145     misc_deregister(&ldm.dev);
    146 }
    147 
    148 
    149 
    150 module_init(ldm_init);
    151 module_exit(ldm_exit);
    152 MODULE_LICENSE("GPL");

    .h

     1 #pragma once
     2 
     3 #include <linux/ioctl.h>
     4 //参考下内核文档 linux/linux-3.5/Documentation/ioctl
     5 //ioctl-decoding.txt  和 ioctl-number.txt
     6 //例如 实现  控制LED灯
     7 /*
     8 _IO (魔数, 基数);
     9 • _IOR (魔数, 基数, 变量型)
    10 • _IOW (魔数, 基数, 变量型)
    11 • _IOWR (魔数, 基数,变量型 )
    12 */
    13 
    14 enum 
    15 {    
    16     //4412  P446  100MHZ
    17     PCLK_PERIL = 100000000,
    18     PWM_PRESCALER0 = 99,
    19     DIV =  4,
    20 
    21     TIMER0_HZ = PCLK_PERIL / (PWM_PRESCALER0 + 1) / 16,
    22     TIMER0_KHZ  = TIMER0_HZ /1000,
    23 };
    24 
    25 //
    26 #define  SET_CMP   _IOW('l', 1, unsigned int)
    27 //底层的驱动生成的一系列 命令  这个头文件同样也需要提供给应用层
    28 
    29 #define DUTY_0   TIMER0_KHZ/2
    30 //#define DUTY_25 
    31 #define DUTY_50    TIMER0_KHZ/4
    32 //#define DUTY_75
    33 #define DUTY_100   0

    .app

    //应用层
    #include <stdio.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    
    #include "pwm_ctl.h"
    
    
    int main(int argc, char const *argv[])
    {
    
    
        int fd = open("/dev/ldm", O_RDWR);
        if(fd < 0) {
               perror("open");
               goto err_open;
        }
    
    
    
        //ioctl(fd, LED_STATUS, led_status);
        //ioctl(fd, LED1_ON);
        ioctl(fd, SET_CMP, DUTY_100);
    
        close(fd);
    
        return 0;
    
    err_open:
        return -1;
    }
  • 相关阅读:
    mybatis :xml文件中传入参数和if标签结合使用时要点
    mysql:查询数据库版本的几种方式
    http post 方法传递参数的2种方式
    深入理解mybatis参数
    Mybatis:动态sql
    Mybatis:传入参数方式以及#{}与${}的区别
    [GLSL]着色器周记02——火焰特效 【转】
    OpenGL ES入门09-GLSL实现常见特效 [转]
    RenderMonkey 练习 第五天 【OpenGL NormalMapping】
    反射向量 及 向量投影
  • 原文地址:https://www.cnblogs.com/baoshulin/p/6477014.html
Copyright © 2011-2022 走看看