博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【龙芯1c库】封装硬件pwm接口和使用示例
阅读量:2361 次
发布时间:2019-05-10

本文共 17557 字,大约阅读时间需要 58 分钟。

龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,类似于STM32库。Git地址:https://gitee.com/caogos/OpenLoongsonLib1c

本文通过“龙芯1c库”中提供的PWM接口,实现了在4路pwm的输出连续的pwm脉冲和单个脉冲。

在讲解了pwm接口之后,才开始详细介绍寄存器,以及怎样使用这些寄存器来封装接口,最后给出了封装的pwm接口代码清单。
 

龙芯1c库中pwm接口使用示例

PWM接口简介

提供三个接口函数,分别是

 

void pwm_init(pwm_info_t *pwm_info);void pwm_disable(pwm_info_t *pwm_info);void pwm_enable(pwm_info_t *pwm_info);

其中函数pwm_init()是最核心的接口,调用后会立刻在指定引脚上产生需要的波形。初始化之后,可以在需要的时候调用pwm_disable()停止输出pwm波形,在disable后还可以调用pwm_enable()重新使能,指定引脚上又继续输出pwm波形。

这三个接口都是一了相同的入参,这个入参到底长啥样,马上揭晓。

// 硬件pwm信息typedef struct{    unsigned int gpio;                      // PWMn所在的gpio    unsigned int mode;                      // 工作模式(单脉冲、连续脉冲)    float duty;                             // pwm的占空比    unsigned long period_ns;                // pwm周期(单位ns)}pwm_info_t;

我想这个应该一看就知道说的是啥。

这里重点解释一下为什么这里是gpio,而不是PWMn。因为每路pwm都可以复用到至少另外的一个引脚上,却不存在一个引脚可能发生支持多个PWM复用的情况,这里直接传入gpio,代码中会自动根据gpio判断是使用那个PWM,是否需要使用复用,如果需要复用,自动复用。
除了gpio之外,还有工作模式为啥还有个单脉冲模式。当工作在单脉冲模式时,调用一次pwm_init()产生一个脉冲。这对于常用于步进电机的控制,比如我之前做的3D打印机(龙印)就用到了,通过控制脉冲个数,达到控制步进电机行走距离的目的。

龙芯1C300B支持FPU(硬件浮点运算单元),并且龙芯1c库中已经默认开启了FPU,所以这里直接采用浮点数形式的占空比。

据此,构造了三个测试用例:

用例一,测试PWM正常模式(连续输出PWM)。
通过调用pwm_init()产生连续单脉冲,然后调用pwm_disable()停止输出脉冲,最后调用pwm_enable()又继续输出连续脉冲。为了便于使用示波器观察,禁止输出一会后,又使能,再禁止,再使能,反复不停的循环。
用例二,测试PWM单脉冲模式(每次只输出一个脉冲)
通过调用pwm_init()产生一个脉冲,再延时一会之后(延时时间必须大于等于pwm周期),再调用pwm_init(),再延时一会,再调用pwm_init(),再延时,再输出一定数量的脉冲之后停止输出。通用为了便于用示波器观察,可以将上述过程反复重复。
用例三。将pwm默认的引脚作用普通GPIO,同时复用其它引脚来用作pwm。
PWM0的默认引脚GPIO06用作普通gpio,而GPIO04上输出pwm波形,

 

硬件资源

龙芯1c有4路pwm,每路都可以复用。但只有pwm0和pwm1才有默认引脚(当然也可以复用其它引脚),pwm2和pwm3都需要复用。这里每路选取了两个引脚,如下

 

// pwm引脚定义#define LS1C_PWM0_GPIO06                    (6)         // gpio06用作pwm0#define LS1C_PWM0_GPIO04                    (4)         // gpio04复用为pwm0#define LS1C_PWM1_GPIO92                    (92)        // gpio92用作pwm1#define LS1C_PWM1_GPIO05                    (5)         // gpio05复用为pwm1#define LS1C_PWM2_GPIO52                    (52)        // gpio52复用为pwm2#define LS1C_PWM2_GPIO46                    (46)        // gpio46复用为pwm2#define LS1C_PWM3_GPIO47                    (47)        // gpio47复用为pwm3#define LS1C_PWM3_GPIO53                    (53)        // gpio53复用为pwm3

每个引脚都可以输出连续pwm脉冲和单个脉冲。

 

测试用例1——产生连续脉冲

代码清单

 

// 测试硬件pwm产生连续的pwm波形void test_pwm_normal(void){    pwm_info_t pwm_info;    int i;    pwm_info.gpio = LS1C_PWM0_GPIO06;               // pwm引脚位gpio06//    pwm_info.gpio = LS1C_PWM0_GPIO04;    pwm_info.mode = PWM_MODE_NORMAL;                // 正常模式--连续输出pwm波形    pwm_info.duty = 0.25;                           // pwm占空比    pwm_info.period_ns = 5*1000*1000;               // pwm周期5ms    // pwm初始化,初始化后立即产生pwm波形    pwm_init(&pwm_info);    while (1)    {        // 延时100ms        for (i=0; i<100; i++)        {            delay_1ms();        }        // 禁止pwm        pwm_disable(&pwm_info);        // 延时100ms        for (i=0; i<100; i++)        {            delay_1ms();        }        // 使能pwm        pwm_enable(&pwm_info);    }    return ;}

 

 

 

测试效果

从图上可以看出,有脉冲和没脉冲的时间都是100ms,与代码相符。下面放大了再来看看连续脉冲的详细信息,如下

占空比为0.25,pwm周期为5ms,与代码相符。

测试用例2——产生单脉冲

代码清单

 

// 测试硬件pwm产生pwm脉冲void test_pwm_pulse(void){    int i;    pwm_info_t pwm_info;    pwm_info.gpio = LS1C_PWM0_GPIO06;               // 输出pwm波形的引脚    pwm_info.mode = PWM_MODE_PULSE;                 // 单脉冲模式,每次调用只发送一个脉冲,调用间隔必须大于pwm周期    pwm_info.duty = 0.25;                           // pwm占空比    pwm_info.period_ns = 1*1000*1000;               // pwm周期1ms    // 为了便于用示波器观察,这里选择每个1s就发送10个脉冲    while (1)    {        // 发送10个脉冲        for (i=0; i<10; i++)        {            pwm_init(&pwm_info);            delay_1ms();            delay_1ms();        }        // 延时10ms        for (i=0; i<10; i++)        {            delay_1ms();        }    }    return ;}

 

 

 

测试效果

连续发了10个,然后延时10ms,再发,与代码相符。再来看看每个脉冲的详细情况,如下

每个脉冲周期为2ms与延时的时间相同,大于初始化时的1ms。这是对的,与代码相符。

测试用例3——PWM的默认引脚用作普通GPIO,而复用其它引脚输出PWM波形

但是当把gpio92用于pwm输出时(PWM1的默认引脚就是GPIO92),只有gpio92引脚有pwm波形,而gpio05引脚没有。

把gpio05复用为pwm1,而pwm1默认的引脚gpio92处于上电默认状态(未操作引脚相应寄存器)时,gpio05引脚和gpio92引脚都会出现相同的pwm波形。

PWM0也有类似情况,当把gpio04复用为PWM0时,也会出现gpio04和gpio06都出现相同的pwm波形。

代码清单

 

/* * 测试gpio04复用为pwm,gpio06作为普通gpio使用 * PWM0的默认引脚位GPIO06,但也可以复用为GPIO04 * 当gpio06还是保持默认为pwm时,复用gpio04为pwm0,那么会同时在两个引脚输出相同的pwm波形 * 本函数旨在证明可以在gpio04复用为pwm0时,还可以将(默认作为pwm0的)gpio06作为普通gpio使用 */void test_pwm_gpio04_gpio06(void){    pwm_info_t pwm_info;    unsigned int gpio = 6;    // 在gpio04引脚输出pwm波形    pwm_info.gpio = LS1C_PWM0_GPIO04;           // gpio04引脚作为pwm使用    pwm_info.mode = PWM_MODE_NORMAL;            // 输出连续的pwm波形    pwm_info.duty = 0.25;                       // 占空比0.25    pwm_info.period_ns = 1*1000*1000;           // pwm周期1ms    pwm_init(&pwm_info);    // gpio06引脚作为普通gpio使用    gpio_init(gpio, gpio_mode_output);    gpio_set(gpio, gpio_level_low);    while (1)        ;    return ;}

 

测试效果

Gpio06输出低电平

Gpio04输出pwm波形

 

 

测试用的完整代码清单

test_pwm.h

 

// 测试硬件pwm的测试用例头文件#ifndef __OPENLOONGSON_TEST_PWM_H#define __OPENLOONGSON_TEST_PWM_H// 测试硬件pwm产生连续的pwm波形void test_pwm_normal(void);// 测试硬件pwm产生pwm脉冲void test_pwm_pulse(void);/* * 测试gpio04复用为pwm,gpio06作为普通gpio使用 * PWM0的默认引脚位GPIO06,但也可以复用为GPIO04 * 当gpio06还是保持默认为pwm时,复用gpio04为pwm0,那么会同时在两个引脚输出相同的pwm波形 * 本函数旨在证明可以在gpio04复用为pwm0时,还可以将(默认作为pwm0的)gpio06作为普通gpio使用 */void test_pwm_gpio04_gpio06(void);#endif

 

 

 

test_pwm.c

 

// 测试硬件pwm的测试用例源文件#include "../lib/public.h"#include "../lib/gpio.h"#include "../lib/ls1c_regs.h"#include "../lib/sys_tick.h"#include "../lib/pwm.h"// 测试硬件pwm产生连续的pwm波形void test_pwm_normal(void){    pwm_info_t pwm_info;    int i;    pwm_info.gpio = LS1C_PWM0_GPIO06;               // pwm引脚位gpio06//    pwm_info.gpio = LS1C_PWM0_GPIO04;    pwm_info.mode = PWM_MODE_NORMAL;                // 正常模式--连续输出pwm波形    pwm_info.duty = 0.25;                           // pwm占空比    pwm_info.period_ns = 5*1000*1000;               // pwm周期5ms    // pwm初始化,初始化后立即产生pwm波形    pwm_init(&pwm_info);    while (1)    {        // 延时100ms        for (i=0; i<100; i++)        {            delay_1ms();        }        // 禁止pwm        pwm_disable(&pwm_info);        // 延时100ms        for (i=0; i<100; i++)        {            delay_1ms();        }        // 使能pwm        pwm_enable(&pwm_info);    }    return ;}// 测试硬件pwm产生pwm脉冲void test_pwm_pulse(void){    int i;    pwm_info_t pwm_info;    pwm_info.gpio = LS1C_PWM0_GPIO06;               // 输出pwm波形的引脚    pwm_info.mode = PWM_MODE_PULSE;                 // 单脉冲模式,每次调用只发送一个脉冲,调用间隔必须大于pwm周期    pwm_info.duty = 0.25;                           // pwm占空比    pwm_info.period_ns = 1*1000*1000;               // pwm周期1ms    // 为了便于用示波器观察,这里选择每个1s就发送10个脉冲    while (1)    {        // 发送10个脉冲        for (i=0; i<10; i++)        {            pwm_init(&pwm_info);            delay_1ms();            delay_1ms();        }        // 延时10ms        for (i=0; i<10; i++)        {            delay_1ms();        }    }    return ;}/* * 测试gpio04复用为pwm,gpio06作为普通gpio使用 * PWM0的默认引脚位GPIO06,但也可以复用为GPIO04 * 当gpio06还是保持默认为pwm时,复用gpio04为pwm0,那么会同时在两个引脚输出相同的pwm波形 * 本函数旨在证明可以在gpio04复用为pwm0时,还可以将(默认作为pwm0的)gpio06作为普通gpio使用 */void test_pwm_gpio04_gpio06(void){    pwm_info_t pwm_info;    unsigned int gpio = 6;    // 在gpio04引脚输出pwm波形    pwm_info.gpio = LS1C_PWM0_GPIO04;           // gpio04引脚作为pwm使用    pwm_info.mode = PWM_MODE_NORMAL;            // 输出连续的pwm波形    pwm_info.duty = 0.25;                       // 占空比0.25    pwm_info.period_ns = 1*1000*1000;           // pwm周期1ms    pwm_init(&pwm_info);    // gpio06引脚作为普通gpio使用    gpio_init(gpio, gpio_mode_output);    gpio_set(gpio, gpio_level_low);    while (1)        ;    return ;}

 

 

 

main.c

 

#include 
#include
#include
#include "../lib/ls1c_public.h"#include "../lib/ls1c_irq.h"#include "../lib/ls1c_gpio.h"#include "../lib/ls1c_delay.h"#include "../lib/ls1c_mipsregs.h"#include "../lib/ls1c_uart.h"#include "../lib/ls1c_sys_tick.h"#include "../lib/ls1c_clock.h"#include "../example/test_gpio.h"#include "../example/test_pwm.h"#include "../example/test_delay.h"#include "../example/test_simulate_i2c.h"#include "../example/test_timer.h"#include "../example/test_fpu.h"#include "../example/test_i2c.h"#include "../example/test_uart.h"#include "../example/test_sys_tick.h"#include "../example/test_spi.h"// 硬浮点初始化void fpu_init(void){ unsigned int c0_status = 0; unsigned int c1_status = 0; // 使能协处理器1--FPU c0_status = read_c0_status(); c0_status |= (ST0_CU1 | ST0_FR); write_c0_status(c0_status); // 配置FPU c1_status = read_c1_status(); c1_status |= (FPU_CSR_FS | FPU_CSR_FO | FPU_CSR_FN); // set FS, FO, FN c1_status &= ~(FPU_CSR_ALL_E); // disable exception c1_status = (c1_status & (~FPU_CSR_RM)) | FPU_CSR_RN; // set RN write_c1_status(c1_status); return ;}void bsp_init(void){ // 初始化调试串口 uart2_init(); // 硬浮点初始化 fpu_init(); // 初始化异常 exception_init(); // 显示时钟信息 clk_print_all(); return ;}int main(void){ bsp_init(); // 注意内存的大小,在文件sdram_cfg.h中配置内存大小, // 源文件中已经有8M和32M的代码,只需要 “#if 0” 或者 “#if 1” 来选择 // -------------------------测试gpio---------------------- /* * 测试库中gpio作为输出时的相关接口 * led闪烁10次 */// test_gpio_output(); /* * 测试库中gpio作为输入时的相关接口 * 按键按下时,指示灯点亮,否则,熄灭 */// test_gpio_input(); /* * 测试库中外部中断(gpio输入中断)的相关接口 * 按键被按下后,会产生一个中断 */// test_gpio_key_irq(); // ------------------------测试串口----------------------- // 通过串口2打印helloworld// test_uart2_print_helloworld(); // 测试串口2的收发功能是否正常// test_uart2_send_recv(); // 测试串口2的收发功能是否正常// test_uart1_send_recv(); // 测试串口3的收发功能是否正常// test_uart3_send_recv(); // 测试串口8的收发功能是否正常,注意龙芯1C300A没有串口8,龙芯1C300B才有串口5到串口11这几个串口// test_uart8_send_recv(); // 测试printf()函数// test_printf(); // ------------------------测试PWM-------------------------------- // 测试硬件pwm产生连续的pwm波形 test_pwm_normal(); // 测试硬件pwm产生pwm脉冲// test_pwm_pulse(); /* * 测试gpio04复用为pwm,gpio06作为普通gpio使用 * PWM0的默认引脚位GPIO06,但也可以复用为GPIO04 * 当gpio06还是保持默认为pwm时,复用gpio04为pwm0,那么会同时在两个引脚输出相同的pwm波形 * 本函数旨在证明可以在gpio04复用为pwm0时,还可以将(默认作为pwm0的)gpio06作为普通gpio使用 */// test_pwm_gpio04_gpio06(); // ------------------------测试软件延时-------------------------------- // 测试延时函数delay_1ms()// test_delay_1ms(); // 测试延时函数delay_1us()// test_delay_1us(); // 测试延时函数delay_1s()// test_delay_1s(); // ------------------------测试模拟I2C------------------------------ // 测试模拟I2C// test_simulate_i2c_am2320(); // ------------------------测试硬件I2C--------------------------- // 用温湿度传感器测试硬件i2c// test_i2c_am2320(); // ------------------------测试硬件定时器--------------------------- // 测试硬件定时器的定时功能(读取中断状态位的方式判断是否超时)// test_timer_poll_time_out(); // 测试硬件定时器的中断// test_timer_irq(); // 测试硬件定时器的计时// test_timer_get_time(); // ------------------------测试硬浮点(FPU)--------------------------- // 测试使用硬浮点进行浮点数的加减乘除// test_fpu(); // ------------------------测试滴答定时器--------------------------- // 通过获取当前tick值来测试滴答定时器,默认已经使能了滴答定时器,每秒1000个tick// test_sys_tick(); // ------------------------测试硬件SPI--------------------------- // 用tm7705测试硬件SPI // 具体为tm7705+ntc热敏电阻实现温度测量(3d打印机就可以采用此方案测量温度)// test_spi_tm7705(); // ------------------------测试CAN--------------------------- // 详情请参考文件test_can.c while (1) ; return(0);}

 

 

 

龙芯1C的PWM模块简介

相关寄存器

我认为芯片手册中,对PWM的介绍已经非常详细,编程也足够了,下面一起来读芯片手册

4路PWM,每路的工作和控制方式都一样。代码中也是使用一样的代码,只需要改变PWM寄存器基地址就可以切换在几路PWM中来回切换。

计数器CNTR、HRC和LRC都是24位的,这也就限定了计数器的最大值为0xFFFFFF,也就限定了最大PWM周期。

芯片手册说有三种工作模式,我想应该是指连续脉冲,单脉冲和定时器这三种吧。这里只考虑输出连续脉冲和单脉冲,定时器另外单独用一篇文章来讨论。

这里先不考虑中断,只是输出波形。

封装PWM接口

接口要点

其实PWM原理很清楚,首先需要设置相应引脚为PWM功能,而非普通GPIO。然后就是清零主计数器,写高低电平计数器,最后就是根据工作模式,是否需要中断等将控制信息吸入控制寄存器。

代码清单

pwm.h

 

#ifndef __OPENLOONGSON_PWM_H#define __OPENLOONGSON_PWM_H// pwm引脚定义#define LS1C_PWM0_GPIO06                    (6)         // gpio06用作pwm0#define LS1C_PWM0_GPIO04                    (4)         // gpio04复用为pwm0#define LS1C_PWM1_GPIO92                    (92)        // gpio92用作pwm1#define LS1C_PWM1_GPIO05                    (5)         // gpio05复用为pwm1#define LS1C_PWM2_GPIO52                    (52)        // gpio52复用为pwm2#define LS1C_PWM2_GPIO46                    (46)        // gpio46复用为pwm2#define LS1C_PWM3_GPIO47                    (47)        // gpio47复用为pwm3#define LS1C_PWM3_GPIO53                    (53)        // gpio53复用为pwm3// ...还有一些gpio可以复用为gpio的,有需要可以自己添加// pwm控制寄存器的每个bit#define LS1C_PWM_INT_LRC_EN                 (11)        // 低脉冲计数器中断使能#define LS1C_PWM_INT_HRC_EN                 (10)        // 高脉冲计数器中断使能#define LS1C_PWM_CNTR_RST                   (7)         // 使能CNTR计数器清零#define LS1C_PWM_INT_SR                     (6)         // 中断状态位#define LS1C_PWM_INTEN                      (5)         // 中断使能位#define LS1C_PWM_SINGLE                     (4)         // 单脉冲控制位#define LS1C_PWM_OE                         (3)         // 脉冲输出使能#define LS1C_PWM_CNT_EN                     (0)         // 主计数器使能// 硬件pwm工作模式enum{    // 正常模式--连续输出pwm波形    PWM_MODE_NORMAL = 0,        // 单脉冲模式,每次调用只发送一个脉冲,调用间隔必须大于pwm周期    PWM_MODE_PULSE};// 硬件pwm信息typedef struct{    unsigned int gpio;                      // PWMn所在的gpio    unsigned int mode;                      // 工作模式(单脉冲、连续脉冲)    float duty;                             // pwm的占空比    unsigned long period_ns;                // pwm周期(单位ns)}pwm_info_t;/* * 初始化PWMn * @pwm_info PWMn的详细信息 */void pwm_init(pwm_info_t *pwm_info);/* * 禁止pwm * @pwm_info PWMn的详细信息 */void pwm_disable(pwm_info_t *pwm_info);/* * 使能PWM * @pwm_info PWMn的详细信息 */void pwm_enable(pwm_info_t *pwm_info);#endif

 

pwm.c

 

// 封装硬件pwm接口#include "public.h"#include "pin.h"#include "pwm.h"#include "clock.h"#include "ls1c_regs.h"#include "sys_tick.h"// pwm的最大周期#define PWM_MAX_PERIOD                  (0xFFFFFF)      // 计数器的值/* * 根据gpio获取相应pwm的基地址 * @gpio pwm引脚 * @ret pwm基地址 */unsigned int pwm_get_reg_base(unsigned int gpio){    unsigned int reg_base = 0;        switch (gpio)    {        case LS1C_PWM0_GPIO06:        case LS1C_PWM0_GPIO04:            reg_base = LS1C_REG_BASE_PWM0;            break;        case LS1C_PWM1_GPIO92:        case LS1C_PWM1_GPIO05:            reg_base = LS1C_REG_BASE_PWM1;            break;        case LS1C_PWM2_GPIO52:        case LS1C_PWM2_GPIO46:            reg_base = LS1C_REG_BASE_PWM2;            break;        case LS1C_PWM3_GPIO47:        case LS1C_PWM3_GPIO53:            reg_base = LS1C_REG_BASE_PWM3;            break;    }    return reg_base;}/* * 禁止pwm * @pwm_info PWMn的详细信息 */void pwm_disable(pwm_info_t *pwm_info){    unsigned int pwm_reg_base = 0;        // 检查入参    if (NULL == pwm_info)    {        return ;    }    pwm_reg_base = pwm_get_reg_base(pwm_info->gpio);    reg_write_32(0, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CTRL));    return ;}/* * 使能PWM * @pwm_info PWMn的详细信息 */void pwm_enable(pwm_info_t *pwm_info){    unsigned int pwm_reg_base = 0;    unsigned int ctrl = 0;    // 检查入参    if (NULL == pwm_info)    {        return ;    }    // 获取基地址    pwm_reg_base = pwm_get_reg_base(pwm_info->gpio);    // 清零计数器    reg_write_32(0, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CNTR));    // 设置控制寄存器    ctrl = (0 << LS1C_PWM_INT_LRC_EN)           | (0 << LS1C_PWM_INT_HRC_EN)           | (0 << LS1C_PWM_CNTR_RST)           | (0 << LS1C_PWM_INT_SR)           | (0 << LS1C_PWM_INTEN)           | (0 << LS1C_PWM_OE)           | (1 << LS1C_PWM_CNT_EN);    if (PWM_MODE_PULSE == pwm_info->mode)     // 单脉冲    {        ctrl |= (1 << LS1C_PWM_SINGLE);    }    else                            // 连续脉冲    {        ctrl &= ~(1 << LS1C_PWM_SINGLE);    }    reg_write_32(ctrl, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CTRL));        return ;}/* * 初始化PWMn * @pwm_info PWMn的详细信息 */void pwm_init(pwm_info_t *pwm_info){    unsigned int gpio;    unsigned int mode;    unsigned long pwm_clk = 0;          // pwm模块的时钟频率    unsigned long tmp = 0;    unsigned int pwm_reg_base = 0;    unsigned long period = 0;        // 判断入参    if (NULL == pwm_info)    {        // 入参非法,则直接返回        return ;    }    gpio = pwm_info->gpio;    mode = pwm_info->mode;    // 配置相应引脚用作pwm,而非gpio    pin_set_purpose(gpio, PIN_PURPOSE_OTHER);    // 复用    switch (gpio)    {        // 不需要复用        case LS1C_PWM0_GPIO06:        case LS1C_PWM1_GPIO92:            break;        case LS1C_PWM0_GPIO04:          // gpio04的第三复用            pin_set_remap(LS1C_PWM0_GPIO04, PIN_REMAP_THIRD);            break;        case LS1C_PWM1_GPIO05:          // gpio05的第三复用            pin_set_remap(LS1C_PWM1_GPIO05, PIN_REMAP_THIRD);            break;        case LS1C_PWM2_GPIO52:          // gpio52的第四复用            pin_set_remap(LS1C_PWM2_GPIO52, PIN_REMAP_FOURTH);            break;        case LS1C_PWM2_GPIO46:          // gpio46的第四复用            pin_set_remap(LS1C_PWM2_GPIO46, PIN_REMAP_FOURTH);            break;        case LS1C_PWM3_GPIO47:          // gpio47的第四复用            pin_set_remap(LS1C_PWM3_GPIO47, PIN_REMAP_FOURTH);            break;        case LS1C_PWM3_GPIO53:          // gpio53的第四复用            pin_set_remap(LS1C_PWM3_GPIO53, PIN_REMAP_FOURTH);            break;        default:            break;    }    // 根据占空比和pwm周期计算寄存器HRC和LRC的值    // 两个64位数相乘,只能得到低32位,linux下却可以得到64位结果,    // 暂不清楚原因,用浮点运算代替    pwm_clk = clk_get_apb_rate();    period = (1.0 * pwm_clk * pwm_info->period_ns) / 1000000000;    period = MIN(period, PWM_MAX_PERIOD);       // 限制周期不能超过最大值    tmp = period - (period * pwm_info->duty);        // 写寄存器HRC和LRC    pwm_reg_base = pwm_get_reg_base(gpio);    reg_write_32(--tmp, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_HRC));    reg_write_32(--period, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_LRC));    // 写主计数器    pwm_enable(pwm_info);        return ;}

感谢能够耐心看完。

 

你可能感兴趣的文章
ROS学习笔记(1)
查看>>
lucene的中文分词器http://www.blogjava.net/dreamstone/archive/2007/06/22/125726.html
查看>>
ICTCLAS分词系统Java调用接口在Eclipse中的安装 http://blog.csdn.net/CloneIQ/archive/2006/07/20/945909.aspx
查看>>
在基于Struts构架的Java Web项目中加入ICTCLAS分词http://blog.csdn.net/CloneIQ/archive/2006/08/09/1043088.aspx
查看>>
QQ尾巴病毒的发送原理分析http://www.bitscn.com/hack/virus/200607/46309.html
查看>>
手把手教你把Vim改装成一个IDE编程环境(图文)http://blog.csdn.net/wooin/archive/2007/10/31/1858917.aspx
查看>>
Skydrive 微软1G免费网盘申请
查看>>
什么是SEO http://www.seozone.net/search-engine-optimization/what-is-seo.html
查看>>
Closure http://www.martinfowler.com/bliki/Closure.html
查看>>
闭包(Closures)在各种语言中的例子 http://blog.csdn.net/ruby_cn/archive/2004/11/23/192588.aspx
查看>>
学做网页Applet录音机
查看>>
弹出run a dll as an app对话框&amp;关机蓝屏的解决方法
查看>>
时空不是连续的
查看>>
勾股定理证明评监
查看>>
评测主流网站统计系统
查看>>
Jxta 命令 shell
查看>>
火页的窝--如何配置JXTA Shell(airclh)
查看>>
澳洲数学高手提速网络
查看>>
[图]跳过Windows,Phoenix开发内建在BIOS的小型操作系统
查看>>
奇技淫巧之避免因宏带来的名字冲突
查看>>