打印

关于纯硬件实现可变频率可变占空比的方法

[复制链接]
2775|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lixiang69|  楼主 | 2013-10-15 16:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
关于纯硬件实现可变频率可变占空比的方法,使用DMA对TIM1_DMAR寄存器操作,进行对TIM1_ARR、TIM1_RCR、TIM1_CCR1三个寄存器进行赋值,达到一个输出可变频率可变占空比波形的目的,

但是测试发现DMA只能设置为DMA_Mode_Normal模式,只要DMA_Mode_Circular模式则TIM1_ARR、TIM1_RCR、TIM1_CCR1三个寄存器的值在进行一段输出后就乱掉了(比如对应赋给CCR1的值,结果给了ARR)。

但如果用DMA_Mode_Normal模式又没有办法进行连续的波形输出,所以请帮忙看下该如何进行设置以达到可变频率可变占空比输出的目的。谢谢!

另外,设置为DMA_Mode_Normal模式后,在传输完成后关DMA,再设置DMA计数器值,再开DMA,结果还是会乱掉,
怎么操作都是只有第一次DMA循环是正确的。不知道是不是bug
下面是初始化设置,大家帮看看是否有问题
DMA_InitTypeDef DMA_InitStructure;

//TIM1  DMA
DMA_DeInit(TIM1_DMA_Channel);
DMA_InitStructure.DMA_PeripheralBaseAddr = TIM1_DMAR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)data_buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 6*3;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(TIM1_DMA_Channel, &DMA_InitStructure);
DMA_Cmd(TIM1_DMA_Channel, ENABLE);
/* Enable DMA1 Channel6 Transfer Complete interrupt */
//DMA_ITConfig(TIM1_DMA_Channel, DMA_IT_TC, ENABLE);


//TIM1
TIM_TimeBaseStructure.TIM_Period = 4608-1;   
TIM_TimeBaseStructure.TIM_Prescaler = 0;  //72M
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 5-1;   
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM1, TIM_FLAG_Update);
//TIM_ITConfig(OSD_TIMER, TIM_IT_Update, ENABLE);
TIM_ARRPreloadConfig(TIM1, ENABLE);//DISABLE
TIM_Cmd(TIM1, ENABLE);

/* Output Compare Active Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//TIM_OCMode_Active
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period*0.073;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
//TIM_ITConfig(OSD_TIMER, TIM1_CC_IRQn, ENABLE);//
/* TIM1 DMAR Base register and DMA Burst Length Config */
TIM_DMAConfig(TIM1,TIM_DMABase_ARR , TIM_DMABurstLength_3Transfers);//
/* TIM1 Update DMA Request enable */
TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
沙发
lixiang69|  楼主 | 2013-10-15 19:25 | 只看该作者
香水城出来看看啊

使用特权

评论回复
板凳
airwill| | 2013-10-16 15:30 | 只看该作者
在进行一段输出后就乱掉了, 这种故障恐怖了.
会不会DMA 误触发了. 更精细地捕捉一下错误现成来分析吧, 可以交给香版主分析.

使用特权

评论回复
地板
香水城| | 2013-10-16 15:43 | 只看该作者
本帖最后由 香水城 于 2013-10-16 16:13 编辑

使用DMA circular模式 + TIM的burst DMA特性,连续多次更改一组寄存器的值,这个用法我用过的,没有出现乱序的问题。

一次DMA触发,传输三个数据分别给ARR、RCR、CCR1:
DMA_InitStructure.DMA_BufferSize 配置成3*6的话,对应的data_buf应该也是包含18个数据的数组。
比如:D1、D2、D3;D4、D5、D6;。。。
第一次update事件触发DMA传输,于是D1~D3被分别赋值给ARR、RCR、CCR1;
第二次update事件触发DMA传输,D4~D6被分别赋值给ARR、RCR、CCR1

按照LZ说的第二次DMA传输就乱序了的现象,则D6赋值给了ARR?

LZ是如何判断ARR没有被赋值正确的值?因为ARR反应的是TIM1的counter计数的最大值,不是一个从示波器直观看到的量,因为这里又更新了ARR,因此update事件的下一次到来的时间取决于新的ARR和新的RCR。

使用特权

评论回复
5
lixiang69|  楼主 | 2013-10-16 17:29 | 只看该作者
香水城 发表于 2013-10-16 15:43
使用DMA circular模式 + TIM的burst DMA特性,连续多次更改一组寄存器的值,这个用法我用过的,没有出现乱 ...

香主说的“连续多次更改一组寄存器的值”,不知道DMA是DMA_Mode_Circular模式,还是DMA_Mode_Normal模式。如果是DMA_Mode_Normal模式只是传输了N多次后,数组传输完就结束了,那我测试的也是没问题的;
就是只有当DMA设置为DMA_Mode_Circular模式后,数组传输完然后DMA重新从数组的首位再开始继续传,这个时候ARR、RCR、CCR1三个寄存器的值就乱了

判断乱的依据是:1.示波器里没有波形输出了固定为一个电平  2.硬件仿真里看TIM_CNT寄存器不再计数
3.ARR的寄存器值变为1了(或者其他数据,反正不是真正要赋值给ARR的数,而且一般都是要赋值给RCR的给了ARR),RCR的值可能得到了CCR1的值,CCR1的可能得到了ARR的值

使用特权

评论回复
6
lixiang69|  楼主 | 2013-10-16 17:34 | 只看该作者
airwill 发表于 2013-10-16 15:30
在进行一段输出后就乱掉了, 这种故障恐怖了.
会不会DMA 误触发了. 更精细地捕捉一下错误现成来分析吧, 可以 ...

是根本没发用了
DMA不能单步仿真,这种DMA错误还真不好捕捉

使用特权

评论回复
7
huzi2099| | 2013-10-16 17:38 | 只看该作者
pwm最好把预装载打开,这要波形才不会乱.
circular模式肯定不行的,更新寄存器不受信号控制.
个人觉得dma方式没有必要.

使用特权

评论回复
8
airwill| | 2013-10-16 17:56 | 只看该作者
虽然香主没有出现乱序的问题, 也不保证所有应用都不会出现问题。

真要捕捉的话, 最好做个完整的测试程序.
比如: 赋值给ARR、RCR、CCR1 的值都有特别的特征, 可以是某些特定位的不同.
然后由主程序来循环读取和检测寄存器的值.
希望看到进一步的验证和测试结果.

使用特权

评论回复
9
香水城| | 2013-10-16 17:58 | 只看该作者
lixiang69 发表于 2013-10-16 17:29
香主说的“连续多次更改一组寄存器的值”,不知道DMA是DMA_Mode_Circular模式,还是DMA_Mode_Normal模式 ...

用的是DMA_Mode_Cicular模式,没有碰到乱序。

使用特权

评论回复
10
lixiang69|  楼主 | 2013-10-16 18:13 | 只看该作者
香水城 发表于 2013-10-16 17:58
用的是DMA_Mode_Cicular模式,没有碰到乱序。

那请问下香主使用DMAR寄存器这种模式有没有需要特殊设置的地方?比如是否需要把TIM的更新中断打开,或者DMA的中断打开等等
帮我看下1楼的DMA和TIM的初始化是否正确?
或者发下你的初始化部分大家参考下

使用特权

评论回复
11
lixiang69|  楼主 | 2013-10-16 18:14 | 只看该作者
另外说明,预装载肯定都是开的

使用特权

评论回复
12
lixiang69|  楼主 | 2013-10-16 18:15 | 只看该作者
airwill 发表于 2013-10-16 17:56
虽然香主没有出现乱序的问题, 也不保证所有应用都不会出现问题。

真要捕捉的话, 最好做个完整的测试程序.

有时间是可以试试这种验证方法

使用特权

评论回复
13
trumpxp| | 2013-10-16 20:47 | 只看该作者
到底是什么问题呢  楼主   怎么解决的呢

使用特权

评论回复
14
90chinazhu| | 2014-4-12 16:45 | 只看该作者
mark,关注TIM的burst DMA特性

使用特权

评论回复
15
90chinazhu| | 2014-4-12 17:37 | 只看该作者
mark

使用特权

评论回复
16
myxiaonia| | 2014-4-13 08:29 | 只看该作者
lixiang69 发表于 2013-10-16 18:15
有时间是可以试试这种验证方法

可以使用双缓冲的做法,这也是香主在起博文提到的,具体方法就是开两个缓冲区,轮流传递值,还有种方法是dma循环模式和半传输和完成中断,这种方法类似环形队列,可靠性更好

使用特权

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

本版积分规则

60

主题

317

帖子

3

粉丝