打印
[技术问答]

M051 BSP 3.0代码求助

[复制链接]
2488|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
寂静的火|  楼主 | 2014-8-16 17:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这两天在看BSP代码,看到PWM.c的时候有些不懂,求大神指点
PWM_ConfigOutputChannel这个函数里面(整个函数我贴在最后)
if(pwm == PWMA)       
        u32Src = (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM01_S_Msk << (u32ChannelNum >> 1))) >> (CLK_CLKSEL1_PWM01_S_Pos << (u32ChannelNum >> 1));
    else /*pwm == PWMB*/
        u32Src = (CLK->CLKSEL2 & (CLK_CLKSEL2_PWM45_S_Msk << (u32ChannelNum >> 1))) >> (CLK_CLKSEL2_PWM45_S_Pos << (u32ChannelNum >> 1));
这里面这两句应该是要读取时钟源配置的信息吧, (u32ChannelNum >> 1)这个是不是有点问题,PWM时钟源的配置占两个位,这里就算channelnum输入3,右移一下变成1,CLK_CLKSEL1_PWM01_S_Msk也只是左移了一位,读出来的值不就错了吗

然后是这里,这句实在是看不懂了
    // set PWM to edge aligned type
    (pwm)->PCR &= ~(PWM_PCR_PWM01TYPE_Msk << (u32ChannelNum >> 1));
PCR寄存器的第28位之后是保留位,但是
#define PWM_PCR_PWM01TYPE_Pos                   30                                  /*!< PWM PCR: PWM01TYPE Position */#define PWM_PCR_PWM01TYPE_Msk                   (1ul << PWM_PCR_PWM01TYPE_Pos)      /*!< PWM PCR: PWM01TYPE Mask */
这里已经左移30位了,还得再左移n位,这样做操作的位不就是保留位了吗



完整的PWM_ConfigOutputChannel函数
uint32_t PWM_ConfigOutputChannel(PWM_T *pwm,
                                 uint32_t u32ChannelNum,
                                 uint32_t u32Frequency,
                                 uint32_t u32DutyCycle)
{
    uint32_t u32Src;
    uint32_t u32PWMClockSrc;
    uint32_t u32PWMClkTbl[4] = {__HXT, __LIRC, 0, __HIRC};
    uint32_t i;
    uint8_t  u8Divider = 1, u8Prescale = 0xFF;
    /* this table is mapping divider value to register configuration */
    uint32_t u32PWMDividerToRegTbl[17] = {NULL, 4, 0, NULL, 1, NULL, NULL, NULL, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3};
    uint16_t u16CNR = 0xFFFF;

    if(pwm == PWMA)       
        u32Src = (CLK->CLKSEL1 & (CLK_CLKSEL1_PWM01_S_Msk << (u32ChannelNum >> 1))) >> (CLK_CLKSEL1_PWM01_S_Pos << (u32ChannelNum >> 1));
    else /*pwm == PWMB*/
        u32Src = (CLK->CLKSEL2 & (CLK_CLKSEL2_PWM45_S_Msk << (u32ChannelNum >> 1))) >> (CLK_CLKSEL2_PWM45_S_Pos << (u32ChannelNum >> 1));

    if(u32Src == 2)       
    {
        SystemCoreClockUpdate();
        u32PWMClockSrc = SystemCoreClock;
    }
    else
    {
        u32PWMClockSrc = u32PWMClkTbl[u32Src];
    }

    for(; u8Divider < 17; u8Divider <<= 1)    // clk divider could only be 1, 2, 4, 8, 16 ʱÖÓÔ´·ÖƵ
    {
        i = (u32PWMClockSrc / u32Frequency) / u8Divider;               
        // If target value is larger than CNR * prescale, need to use a larger divider
        if(i > (0x10000 * 0x100))        //×î´ó¼ÆÊýÖµ*×î´óÔ¤·ÖƵֵ Èç¹û¼ÆÊýʱ¼ä³¬¹ýPWMÄ£¿é×î´óʱ¼äÔòÐèÒª¼Ó´óʱÖÓÔ´·ÖƵ
            continue;

        // CNR = 0xFFFF + 1, get a prescaler that CNR value is below 0xFFFF
        u8Prescale = (i + 0xFFFF) / 0x10000;       

        // u8Prescale must at least be 2, otherwise the output stop
        if(u8Prescale < 3)
            u8Prescale = 2;

        i /= u8Prescale;               

        if(i <= 0x10000)       
        {
            if(i == 1)
                u16CNR = 1;//Too fast, and PWM cannot generate expected frequency...
            else
                u16CNR = i;
            break;
        }
    }
    // Store return value here 'cos we're gonna change u8Divider & u8Prescale & u16CNR to the real value to fill into register
    i = u32PWMClockSrc / (u8Prescale * u8Divider * u16CNR);

    u8Prescale -= 1;       
    u16CNR -= 1;               
    // convert to real register value
    u8Divider = u32PWMDividerToRegTbl[u8Divider];

    // every two channels share a prescaler
    (pwm)->PPR = ((pwm)->PPR & ~(PWM_PPR_CP01_Msk << ((u32ChannelNum >> 1) * 8))) | (u8Prescale << ((u32ChannelNum >> 1) * 8));
    (pwm)->CSR = ((pwm)->CSR & ~(PWM_CSR_CSR0_Msk << (4 * u32ChannelNum))) | (u8Divider << (4 * u32ChannelNum));
    // set PWM to edge aligned type
    (pwm)->PCR &= ~(PWM_PCR_PWM01TYPE_Msk << (u32ChannelNum >> 1));
    (pwm)->PCR |= PWM_PCR_CH0MOD_Msk << (8 * u32ChannelNum);       
    *((__IO uint32_t *)((((uint32_t) & ((pwm)->CMR0)) + u32ChannelNum * 12))) = (u16CNR + 1) * u32DutyCycle / 100 - 1;
    *((__IO uint32_t *)((((uint32_t) & ((pwm)->CNR0)) + (u32ChannelNum) * 12))) = u16CNR;

    return(i);
}


沙发
598330983| | 2014-8-18 19:22 | 只看该作者
这么深奥的代码,我也看不懂啊,太长了。

使用特权

评论回复
板凳
mintspring| | 2014-8-18 20:17 | 只看该作者
找找例程看看。

使用特权

评论回复
地板
gaoyang9992006| | 2014-8-19 19:47 | 只看该作者
先弄懂这个程序的编程风格,以及基本句型,然后再认真读两遍

使用特权

评论回复
5
从小木丁丁| | 2014-8-19 22:04 | 只看该作者
代码太长了,直接没看

使用特权

评论回复
6
从小木丁丁| | 2014-8-19 22:04 | 只看该作者
gaoyang9992006 发表于 2014-8-19 19:47
先弄懂这个程序的编程风格,以及基本句型,然后再认真读两遍

你弄懂了没

使用特权

评论回复
7
gaoyang9992006| | 2014-8-20 13:56 | 只看该作者
从小木丁丁 发表于 2014-8-19 22:04
你弄懂了没

我没弄。你弄了》?

使用特权

评论回复
8
haolaishi| | 2014-8-20 16:27 | 只看该作者
gaoyang9992006 发表于 2014-8-20 13:56
我没弄。你弄了》?

你两搞基呢,弄过来,弄过去

使用特权

评论回复
9
haolaishi| | 2014-8-20 16:32 | 只看该作者
寄存器看的头大,楼主可以用完这个函数后,直接看寄存器,看看所需要的通道是否正确,如果正确,就是你的理解错误

使用特权

评论回复
10
haolaishi| | 2014-8-20 16:32 | 只看该作者
话说,看官方的库,纯粹找虐待,哈哈

使用特权

评论回复
11
从小木丁丁| | 2014-8-20 22:03 | 只看该作者
gaoyang9992006 发表于 2014-8-20 13:56
我没弄。你弄了》?

没弄,太长了,失去耐心了

使用特权

评论回复
12
从小木丁丁| | 2014-8-20 22:03 | 只看该作者
haolaishi 发表于 2014-8-20 16:27
你两搞基呢,弄过来,弄过去

没 ,我嫌长,没看,一般他会看的,他喜欢长的

使用特权

评论回复
13
寂静的火|  楼主 | 2014-8-22 10:23 | 只看该作者
598330983 发表于 2014-8-18 19:22
这么深奥的代码,我也看不懂啊,太长了。

这就几句话啊,还长,不过都是寄存器操作确实不对着数据手册看很难看懂

使用特权

评论回复
14
寂静的火|  楼主 | 2014-8-22 10:24 | 只看该作者
mintspring 发表于 2014-8-18 20:17
找找例程看看。

例程里面都是直接操作,没用到库文件

使用特权

评论回复
15
寂静的火|  楼主 | 2014-8-22 10:26 | 只看该作者
gaoyang9992006 发表于 2014-8-19 19:47
先弄懂这个程序的编程风格,以及基本句型,然后再认真读两遍

作为BSP,风格肯定就是严谨,也就是说考虑到各种情况,基本句型就是左移右移,然后我已经认真读了好多遍了,结果发现因为是考虑了各种情况的代码,所以觉得有问题但是不知道是不是因为要考虑什么情况才这么写的,具体到底对不对也不清楚

使用特权

评论回复
16
寂静的火|  楼主 | 2014-8-22 10:28 | 只看该作者
haolaishi 发表于 2014-8-20 16:32
话说,看官方的库,纯粹找虐待,哈哈

看了几个之后发现确实是没有细看的价值,不过这个是疑似的错误,问清楚好点,上次就有一次数据手册错了然后搞了很久,如果下次直接调用他的库,然后里面有错。。。。。。

使用特权

评论回复
17
gaoyang9992006| | 2014-8-22 11:22 | 只看该作者
寂静的火 发表于 2014-8-22 10:26
作为BSP,风格肯定就是严谨,也就是说考虑到各种情况,基本句型就是左移右移,然后我已经认真读了好多遍 ...

我也是啊,经常被官方的底层代码看的成**了。也有部分嵌入汇编的,更坑爹,还有那种许多指针操作的。

使用特权

评论回复
18
寂静的火|  楼主 | 2014-8-22 11:27 | 只看该作者
gaoyang9992006 发表于 2014-8-22 11:22
我也是啊,经常被官方的底层代码看的成**了。也有部分嵌入汇编的,更坑爹,还有那种许多指针操作的。 ...

嗯,蛋疼啊,,,这些东西,没有就一直期待有,等有了又觉得不好了

使用特权

评论回复
19
缥缈九哥| | 2014-8-22 12:48 | 只看该作者
我能看懂。你不懂我也没有办法 。

使用特权

评论回复
20
从小木丁丁| | 2014-8-22 13:01 | 只看该作者
haolaishi 发表于 2014-8-20 16:32
寄存器看的头大,楼主可以用完这个函数后,直接看寄存器,看看所需要的通道是否正确,如果正确,就是你的理 ...

用寄存器才是王道

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

110

帖子

0

粉丝