OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7107|回复: 56

使用Toggle移相,怎么改变占空比

[复制链接]

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
发表于 2018-9-7 16:06:54 | 显示全部楼层 |阅读模式
1金钱
uint16_t TimerPerio;   //自动重装载频率
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;      
        TIM_OCInitTypeDef TIM_OCInitStructure;         
        TIM_BDTRInitTypeDef TIM_BDTRInitStructure;      

        TimerPerio = (SystemCoreClock / psc / freq);           
        Channel1Pulse = TimerPerio*0.9;
        Channel2Pulse = TimerPerio*0.85;
        Channel3Pulse = TimerPerio/2;
       
       
       
        /* TIM1,GPIOA,GPIOB*/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);   
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);

        /*channel1 ,channel2  --> PA.8,PA.9, PA.10*
        *channel1N,channel2N --> PB.13,PB.14, PB.15*/
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 |GPIO_Pin_9 | GPIO_Pin_10;   
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推完输出                                
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);           //初始化GPIOA

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14 | GPIO_Pin_15;
        GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB

        /*  ???TIM1  */
        TIM_TimeBaseStructure.TIM_Period            = TimerPerio-1;                    // 设置重装载周期值      
        TIM_TimeBaseStructure.TIM_Prescaler         = psc-1;                                 //设置预分频值         
        TIM_TimeBaseStructure.TIM_ClockDivision     = 0;                                           //时钟分频         
        TIM_TimeBaseStructure.TIM_CounterMode       = TIM_CounterMode_Up;  //TIM中心计数模式
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;                                                                    //重复溢出中断                 
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);                                                              //初始化定时器               

        /* Channel_1   TIM_OCMode_PWM2模式 */
        TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_Toggle;            
        TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable;  //比较输出使能   
        TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //PWM波互补输出使能   
        TIM_OCInitStructure.TIM_Pulse        = Channel1Pulse;        //占空比设置      
        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_OCNIdleState_Reset;//PWM互补输出空闲状态      
        TIM_OC1Init(TIM1, &TIM_OCInitStructure); //初始化外设TIM1 OC1
       
        /* Channel_2  TIM_OCMode_PWM2模式 */
        TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_Toggle;            
        TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable;   
        TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;     
        TIM_OCInitStructure.TIM_Pulse        = Channel2Pulse;               
        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_OCNIdleState_Reset;     
        TIM_OC2Init(TIM1, &TIM_OCInitStructure);                           

        /* Channel_3      TIM_OCMode_PWM1模式 */  
        TIM_OCInitStructure.TIM_OCMode       = TIM_OCMode_Toggle;            
        TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable;      
        TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;     
        TIM_OCInitStructure.TIM_Pulse        = Channel3Pulse;               
        TIM_OCInitStructure.TIM_OCPolarity   = TIM_OCPolarity_High;         
        TIM_OCInitStructure.TIM_OCNPolarity  = TIM_OCNPolarity_High;        
        TIM_OCInitStructure.TIM_OCIdleState  = TIM_OCIdleState_Set;         
        TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;      
        TIM_OC3Init(TIM1, &TIM_OCInitStructure);                           

        TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
//        TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);                  
        TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);                  

        /*死区和刹车功能配置*/
        TIM_BDTRInitStructure.TIM_OSSRState       = TIM_OSSRState_Enable;
        TIM_BDTRInitStructure.TIM_OSSIState       = TIM_OSSIState_Enable;
        TIM_BDTRInitStructure.TIM_LOCKLevel       = TIM_LOCKLevel_1;
        TIM_BDTRInitStructure.TIM_DeadTime        =50;                   //设置TIM1_BDTR的DTG,死区时间DTG[7:0]
        TIM_BDTRInitStructure.TIM_Break           = TIM_Break_Disable;
        TIM_BDTRInitStructure.TIM_BreakPolarity   = TIM_BreakPolarity_High;
        TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
        TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

        TIM_Cmd(TIM1, ENABLE);          //使能TIM1                                    
        TIM_CtrlPWMOutputs(TIM1,ENABLE); //PWM输出使能  

这是我的源码,可以产生50%占空比的pwm波,并可以实现任意角度移相,但是这个占空比应该怎么改变呢?望大神赐教。


IMG_20180907_160009.jpg
IMG_20180907_155711.jpg

最佳答案

查看完整内容[请看2#楼]

那就Toggle+DMA burst, 去ST官网找一份应用笔记是讲TIMER的, 里面有例程 然后你用Update做触发, DMA burst 帮你从buffer里更新CCR1~CCR4的内容
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-7 16:06:55 | 显示全部楼层
PearlH 发表于 2018-9-7 18:39
但是pwm模式不可以移相的呀

那就Toggle+DMA burst, 去ST官网找一份应用笔记是讲TIMER的, 里面有例程
然后你用Update做触发, DMA burst 帮你从buffer里更新CCR1~CCR4的内容
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-7 17:39:46 | 显示全部楼层
在不改变频率的情况下, 用toggle是改不了占空比的
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-7 18:05:21 | 显示全部楼层
edmund1234 发表于 2018-9-7 17:39
在不改变频率的情况下, 用toggle是改不了占空比的

那如果想改变占空比应该怎么做呢?还要保证任意角度移相。
回复

使用道具 举报

64

主题

446

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1032
金钱
1032
注册时间
2017-7-26
在线时间
275 小时
发表于 2018-9-7 18:32:27 | 显示全部楼层
利用中断,中断中更改CCR的值。
这种方法需要MCU进行处理,可靠性相对较低,且消耗资源。

可以尝试定时器从模式触发,或者一个定时器定时启动2个定时器。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-7 18:37:27 | 显示全部楼层
PearlH 发表于 2018-9-7 18:05
那如果想改变占空比应该怎么做呢?还要保证任意角度移相。

PWM模式
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-7 18:38:35 | 显示全部楼层
a3748622 发表于 2018-9-7 18:32
利用中断,中断中更改CCR的值。
这种方法需要MCU进行处理,可靠性相对较低,且消耗资源。

一个定时器定时启动2个定时器这个方法可以说一下吗?
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-7 18:39:34 | 显示全部楼层

但是pwm模式不可以移相的呀
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-8 10:16:07 | 显示全部楼层
本帖最后由 PearlH 于 2018-9-9 15:37 编辑

。。。。
回复

使用道具 举报

3

主题

238

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1366
金钱
1366
注册时间
2016-5-26
在线时间
1698 小时
发表于 2018-9-8 11:00:01 | 显示全部楼层
淘汰人的从来是工具而不是年龄
嵌入式的冷知识屋 blog.csdn.net/k_o_carnivist
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-8 12:16:33 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-8 12:38 编辑

这是我以前用m0做的项目, 用到DMA BURST的初始代码, 两通道的, 输入读占空比的, 可供参考

        //--------------------        TIM3_CH3 & TIM3_CH4
        TimTbX.TIM_ClockDivision = TIM_CKD_DIV1;
        TimTbX.TIM_CounterMode = TIM_CounterMode_Up;
        TimTbX.TIM_Period = 0xFFFF;                        
        TimTbX.TIM_Prescaler = 0x00;
        TIM_TimeBaseInit(TIM3, &TimTbX);

        TimIC.TIM_Channel = TIM_Channel_3;
        TimIC.TIM_ICPolarity = TIM_ICPolarity_Rising;
        TimIC.TIM_ICSelection = TIM_ICSelection_IndirectTI;
        TimIC.TIM_ICPrescaler = TIM_ICPSC_DIV1;
        TimIC.TIM_ICFilter = 0x03;
        TIM_ICInit(TIM3, &TimIC);

        TimIC.TIM_Channel = TIM_Channel_4;
        TimIC.TIM_ICPolarity = TIM_ICPolarity_Falling;
        TimIC.TIM_ICSelection = TIM_ICSelection_DirectTI;
        TimIC.TIM_ICPrescaler = TIM_ICPSC_DIV1;
        TimIC.TIM_ICFilter = 0x03;
        TIM_ICInit(TIM3, &TimIC);

        TIM_DMAConfig(TIM3,TIM_DMABase_CCR3, TIM_DMABurstLength_2Transfers);
//        TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
        TIM_DMACmd(TIM3, TIM_DMA_CC4, ENABLE);

        //--------------------------        DMA1_CH3
        DMA_DeInit(DIN_DMA);
//        Dma.DMA_PeripheralBaseAddr = ( uint32_t ) ( &TIM3->CCR4 );
        Dma.DMA_PeripheralBaseAddr = ( uint32_t ) ( &TIM3->DMAR );
        Dma.DMA_MemoryBaseAddr = ( uint32_t ) Rx_buf;
        Dma.DMA_DIR = DMA_DIR_PeripheralSRC;
        Dma.DMA_BufferSize = RxBufSize;
        Dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        Dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
        Dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        Dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        Dma.DMA_Mode = DMA_Mode_Circular;
        Dma.DMA_Priority = DMA_Priority_High;
        Dma.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DIN_DMA, &Dma);
//        DMA_RemapConfig(DMA1, DMA1_CH4_TIM3_CH1);
        DMA1->RMPCR &= ~(u32)0xF00;
        DMA1->RMPCR |= 0x600;
//        DMA_Cmd(DMA1_Channel4, ENABLE);        
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-8 12:41:15 | 显示全部楼层
这是官方DMA Burst的例程(都是在库里有的, 不明白你为何找不到)

DMABurst.zip

13.6 KB, 下载次数: 47

回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 14:37:10 | 显示全部楼层
edmund1234 发表于 2018-9-8 12:41
这是官方DMA Burst的例程(都是在库里有的, 不明白你为何找不到)

[mw_shl_code=cpp,true]#define TIM1_DMAR_ADDRESS ((uint32_t)0x40012C4C) /* TIM ARR (Auto Reload Register) address */
#define NumTIM_CH    3
#define NumTIM_DATA  9
uint16_t SRC_Buffer[NumTIM_CH*NumTIM_DATA] = {1000,2,900,1000,1,800,1000,0,700,
                                                                                                                                                                                        1000,2,600,1000,1,500,1000,0,400,
                                                                                                                                                                                        1000,2,300,1000,1,200,1000,0,100,
};
void DMA_TIM1_Burst(void) ;

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup TIM_DMABurst
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/



/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  DMA_TIM1_Burst();
       
  while(1)
  {
               
  }
}

void DMA_TIM1_Burst(void)         
{  
        /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */   
   GPIO_InitTypeDef         GPIO_InitStructure;
   DMA_InitTypeDef          DMA_InitStructure;
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
   TIM_OCInitTypeDef        TIM_OCInitStructure;       
         TIM_BDTRInitTypeDef      TIM_BDTRInitStructure;      
      
  /* TIM1 and GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB, ENABLE);

       
  /* DMA clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  
        /*channel1 ,channel2  --> PA.8,PA.9, PA.10*
        *channel1N,channel2N --> PB.13,PB.14, PB.15*/
  /* GPIOA Configuration: Channel 1 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14 | GPIO_Pin_15;
        GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB
       
  /* TIM1 DeInit */
  TIM_DeInit(TIM1);

  /* DMA1 Channel5 Config */
  DMA_DeInit(DMA1_Channel5);

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM1_DMAR_ADDRESS;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SRC_Buffer;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = NumTIM_CH*NumTIM_DATA;
  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_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel5, &DMA_InitStructure);
  
  /* Time base configuration */
  /* -----------------------------------------------------------------------
    TIM1 Configuration: generate 1 PWM signal using the DMA burst mode:
    The TIM1CLK frequency is set to SystemCoreClock (Hz), to get TIM1 counter
    clock at 24 MHz the Prescaler is computed as following:
     - Prescaler = (TIM1CLK / TIM1 counter clock) - 1
    SystemCoreClock is set to 72 MHz for Low-density, Medium-density, High-density
    and Connectivity line devices and to 24 MHz for Low-Density Value line and
    Medium-Density Value line devices

    The TIM1 period is 5.8 KHz: TIM1 Frequency = TIM1 counter clock/(ARR + 1)
                                               = 24 MHz / 4096 = 5.8KHz KHz
    TIM1 Channel1 duty cycle = (TIM1_CCR1/ TIM1_ARR)* 100 = 33.33%
  ----------------------------------------------------------------------- */  
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;         
  TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 24000000) - 1;      
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;   
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  /* TIM Configuration in PWM Mode */
  TIM_OCInitStructure.TIM_OCMode =  TIM_OCMode_PWM1;   
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   
        TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 0xFFF;  
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
        TIM_OC2Init(TIM1, &TIM_OCInitStructure);
        TIM_OC3Init(TIM1, &TIM_OCInitStructure);

  /* TIM1 DMAR Base register and DMA Burst Length Config */
  TIM_DMAConfig(TIM1, TIM_DMABase_ARR, TIM_DMABurstLength_3Transfers);

  /* TIM1 DMA Update enable */
  TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
       
       
        /*死区和刹车功能配置*/
        TIM_BDTRInitStructure.TIM_OSSRState       = TIM_OSSRState_Enable;
        TIM_BDTRInitStructure.TIM_OSSIState       = TIM_OSSIState_Enable;
        TIM_BDTRInitStructure.TIM_LOCKLevel       = TIM_LOCKLevel_1;
        TIM_BDTRInitStructure.TIM_DeadTime        =50;                   //设置TIM1_BDTR的DTG,死区时间DTG[7:0]
        TIM_BDTRInitStructure.TIM_Break           = TIM_Break_Disable;
        TIM_BDTRInitStructure.TIM_BreakPolarity   = TIM_BreakPolarity_High;
        TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
        TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

  /* TIM1 enable */
  TIM_Cmd(TIM1, ENABLE);
  
  /* TIM1 PWM Outputs Enable */
  TIM_CtrlPWMOutputs(TIM1, ENABLE);

  /* DMA1 Channel5 enable */
  DMA_Cmd(DMA1_Channel5, ENABLE);

  /* Wait until DMA1 Channel5 end of Transfer */
  while (!DMA_GetFlagStatus(DMA1_FLAG_TC5))
  {
  }

  /* Infinite loop */                                 
}[/mw_shl_code]



这个实现了一个通道的,多个通道的代码也加上去了,但是其他通道的波形没有出来,大神可以指导一下吗?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 14:44:30 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-9 15:03 编辑
PearlH 发表于 2018-9-9 14:37
[mw_shl_code=cpp,true]#define TIM1_DMAR_ADDRESS ((uint32_t)0x40012C4C) /* TIM ARR (Auto Reload Reg ...

没看出有什么问题呢
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 15:05:17 | 显示全部楼层
edmund1234 发表于 2018-9-9 14:44
没看出有什么问题呢

刚开始波形出来了,后来我改了一开始的那个数组和buffer_size,就没波形了,没找到错误。
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 15:09:48 | 显示全部楼层
本帖最后由 PearlH 于 2018-9-9 15:41 编辑
edmund1234 发表于 2018-9-9 14:44
没看出有什么问题呢

#define NumTIM_CH    3
#define NumTIM_DATA  9
uint16_t SRC_Buffer[NumTIM_CH*NumTIM_DATA] = {1000,2,900,1000,1,800,1000,0,700,
                                              1000,2,600,1000,1,500,1000,0,400,
                                              1000,2,300,1000,1,200,1000,0,100,
};
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 15:38:32 | 显示全部楼层
PearlH 发表于 2018-9-9 15:09
也不是没有波形,就只有高低电平。

你的数组长度是多少?值是怎样设的?
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 15:38:59 | 显示全部楼层
K.O.Carnivist 发表于 2018-9-8 11:00
http://openedv.com/forum.php?mod=viewthread&tid=85109#pid484479

原理应该类似吧

大神,可以麻烦帮我看一下我新贴出的代码吗?单通道的已经可以的,想写多通道,但是其他通道只能直接输出高低电平。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 15:42:51 | 显示全部楼层
PearlH 发表于 2018-9-9 15:09
也不是没有波形,就只有高低电平。

buf数组的长度应该是6, 前面的3个是决定相移的角度, 不变的
后面3个是调占空比的
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 15:45:08 | 显示全部楼层
edmund1234 发表于 2018-9-9 15:42
buf数组的长度应该是6, 前面的3个是决定相移的角度, 不变的
后面3个是调占空比的

那其他通道怎么和buffer扯上关系呢
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 17:49:55 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-9 18:09 编辑

不好意思, 我想清楚你的问题, 是不能用DMA burst做得到的, 因为没有任何一点能作为共同触发DMA, 原因是各通道的占空比都不是固定的
只能是用三个DMA通道, 分别更新CCR1~3, 每个buffer只大小是2


回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 19:22:15 | 显示全部楼层
edmund1234 发表于 2018-9-9 17:49
不好意思, 我想清楚你的问题, 是不能用DMA burst做得到的, 因为没有任何一点能作为共同触发DMA, 原因是 ...

那我应该怎么写另外那几个通道呢,比如DMA1的5通道和TIM1的1通道是通过什么确定联系的。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 19:56:18 | 显示全部楼层
PearlH 发表于 2018-9-9 19:22
那我应该怎么写另外那几个通道呢,比如DMA1的5通道和TIM1的1通道是通过什么确定联系的。

你的芯片是103吗? 每个通道都要互补吗?
如果是103只能做到有2个通道有互补
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 19:57:21 | 显示全部楼层
edmund1234 发表于 2018-9-9 19:56
你的芯片是103吗? 每个通道都要互补吗?
如果是103只能做到有2个通道有互补

两个通道够了
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 20:00:20 | 显示全部楼层
如果说不要互补的话, 你可以用这个, 用了CH1, CH3, CH4(因为CH2没有DMA功能)


u16 Ch1_buf[2];
u16 Ch2_buf[2];
u16 Ch3_buf[2];
const u16 ArrVal=0x1000;

void setMBRatio(float mbR1, float mbR2, float mbR3);

int main(void)
{

        GPIO_InitTypeDef                        Gpio;
        DMA_InitTypeDef                    Dma;
        TIM_TimeBaseInitTypeDef            Tim;
        TIM_OCInitTypeDef                        TimOc;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_TIM1 , ENABLE);
        //------------------------ GPIO
        //------------------------ PA8, 10, 11 (CH1, 3, 4)
        Gpio.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_11;       
        Gpio.GPIO_Mode = GPIO_Mode_AF_PP;
        Gpio.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &Gpio);       
        //------------------------ PB13,14,15 (CHN1~3)
        Gpio.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;       
        GPIO_Init(GPIOB, &Gpio);               
       
        //------------------------ TIM1 TimeBase
        TIM_TimeBaseStructInit(&Tim);
        Tim.TIM_Period = ArrVal-1;                // 2us
        Tim.TIM_Prescaler = 0x01;
        Tim.TIM_ClockDivision = 0x0;
        Tim.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM1, &Tim);
        //------------------------ TIM1 OC
        TimOc.TIM_OCMode = TIM_OCMode_Toggle;
        TimOc.TIM_OutputState = TIM_OutputState_Enable;
        TimOc.TIM_OutputNState = TIM_OutputNState_Enable;
        TimOc.TIM_Pulse = 0xFFF;
        TimOc.TIM_OCPolarity = TIM_OCPolarity_Low;
        TimOc.TIM_OCNPolarity = TIM_OCNPolarity_High;
        TimOc.TIM_OCIdleState = TIM_OCIdleState_Reset;
        TimOc.TIM_OCNIdleState = TIM_OCNIdleState_Set;

        TIM_OC1Init(TIM1, &TimOc);
        TimOc.TIM_Pulse = 0;       
        TIM_OC3Init(TIM1, &TimOc);
        TimOc.TIM_Pulse = 0x800;       
    TIM_OC4Init(TIM1, &TimOc);
       
        TIM_DMACmd(TIM1, TIM_DMA_CC1|TIM_DMA_CC3|TIM_DMA_CC4, ENABLE);       
        //------------------------ DMA1 - Ch2, Ch4, Ch6
        DMA_DeInit(DMA1_Channel2);

        Dma.DMA_PeripheralBaseAddr = (u32)&(TIM1->CCR1);          
        Dma.DMA_MemoryBaseAddr = ( u32) Ch1_buf;
        Dma.DMA_DIR = DMA_DIR_PeripheralDST;
        Dma.DMA_BufferSize = 2;
        Dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        Dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
        Dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        Dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        Dma.DMA_Mode = DMA_Mode_Circular;
        Dma.DMA_Priority = DMA_Priority_High;
        Dma.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel2, &Dma);

        DMA_DeInit(DMA1_Channel6);
        Dma.DMA_PeripheralBaseAddr = (u32)&(TIM1->CCR3);                  
        Dma.DMA_MemoryBaseAddr = ( u32) Ch2_buf;
        DMA_Init(DMA1_Channel6, &Dma);

        DMA_DeInit(DMA1_Channel4);
        Dma.DMA_PeripheralBaseAddr = (u32)&(TIM1->CCR4);                  
        Dma.DMA_MemoryBaseAddr = ( u32) Ch3_buf;
        DMA_Init(DMA1_Channel4, &Dma);
        //------------------------------        Buf Init
        Ch1_buf[0] = (u16)(0.333 * 0x1000)-1;
        Ch2_buf[0] = (u16)(0.666 * 0x1000)-1;
        Ch3_buf[0] = (u16)(0.999 * 0x1000)-1;
       

        setMBRatio(37.5, 22.5, 81.3);
        //------------------------------        Start
        DMA_Cmd(DMA1_Channel2,ENABLE);
        DMA_Cmd(DMA1_Channel6,ENABLE);
        DMA_Cmd(DMA1_Channel4,ENABLE);
        TIM_Cmd(TIM1, ENABLE);
        TIM_CtrlPWMOutputs(TIM1, ENABLE);

        while (1)
                __nop();
}

void setMBRatio(float mbR1, float mbR2, float mbR3){
       
//        mbR1 = 0.1~99.9 %
        u16 vv;
       
        vv=(u16)((float)mbR1*0x1000/100.0);
        if (!vv) vv=1;
        if (vv>=0xFFF) vv=0xFFE;
        Ch1_buf[1] = (Ch1_buf[0] + vv) % 0x1000;
       
        vv=(u16)((float)mbR2*0x1000/100.0);
        if (!vv) vv=1;
        if (vv>=0xFFF) vv=0xFFE;       
        Ch2_buf[1] = (Ch2_buf[0] + vv) % 0x1000;
       
        vv=(u16)((float)mbR3*0x1000/100.0);
        if (!vv) vv=1;
        if (vv>=0xFFF) vv=0xFFE;       
        Ch3_buf[1] = (Ch3_buf[0] + vv) % 0x1000;
}

103只有CHN1~CHN3, 没有CHN4, 所以做不到互补
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 20:03:04 | 显示全部楼层
edmund1234 发表于 2018-9-9 20:00
如果说不要互补的话, 你可以用这个, 用了CH1, CH3, CH4(因为CH2没有DMA功能)

我用两个互补通道就可以了
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 20:09:25 | 显示全部楼层
如果一定要互补, 就改回用CH1~CH3, CH1 & CH3 用DMA自动更新, 而CH2, 用中断更新CCR2
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 20:21:11 | 显示全部楼层
这是用中断更新CCR2的

u16 Ch1_buf[2];
u16 Ch2_buf[2];
u16 Ch3_buf[2];
u16 TIM1_CCR2_Val;
const u16 ArrVal=0x1000;

void setMBRatio(float mbR1, float mbR2, float mbR3);

int main(void)
{

        GPIO_InitTypeDef                        Gpio;
        DMA_InitTypeDef                    Dma;
        TIM_TimeBaseInitTypeDef            Tim;
        TIM_OCInitTypeDef                        TimOc;
        NVIC_InitTypeDef                        Nvic;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_TIM1 , ENABLE);
        //------------------------ GPIO
        //------------------------ PA8, 9, 10 (CH1, 2, 3)
        Gpio.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;       
        Gpio.GPIO_Mode = GPIO_Mode_AF_PP;
        Gpio.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &Gpio);       
        //------------------------ PB13,14,15 (CHN1~3)
        Gpio.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;       
        GPIO_Init(GPIOB, &Gpio);               
       
        //------------------------ TIM1 TimeBase
        TIM_TimeBaseStructInit(&Tim);
        Tim.TIM_Period = ArrVal-1;                // 2us
        Tim.TIM_Prescaler = 0x01;
        Tim.TIM_ClockDivision = 0x0;
        Tim.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM1, &Tim);
        //------------------------ TIM1 OC
        TimOc.TIM_OCMode = TIM_OCMode_Toggle;
        TimOc.TIM_OutputState = TIM_OutputState_Enable;
        TimOc.TIM_OutputNState = TIM_OutputNState_Enable;
        TimOc.TIM_Pulse = 0xFFF;
        TimOc.TIM_OCPolarity = TIM_OCPolarity_Low;
        TimOc.TIM_OCNPolarity = TIM_OCNPolarity_Low;
        TimOc.TIM_OCIdleState = TIM_OCIdleState_Reset;
        TimOc.TIM_OCNIdleState = TIM_OCNIdleState_Set;

        TIM_OC1Init(TIM1, &TimOc);
        TimOc.TIM_Pulse = 0;       
        TIM_OC2Init(TIM1, &TimOc);
        TimOc.TIM_Pulse = 0x800;       
    TIM_OC3Init(TIM1, &TimOc);
       
        TIM_DMACmd(TIM1, TIM_DMA_CC1|TIM_DMA_CC3, ENABLE);       
        TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
        //------------------------ DMA1 - Ch2, Ch4
        DMA_DeInit(DMA1_Channel2);

        Dma.DMA_PeripheralBaseAddr = (u32)&(TIM1->CCR1);          
        Dma.DMA_MemoryBaseAddr = ( u32) Ch1_buf;
        Dma.DMA_DIR = DMA_DIR_PeripheralDST;
        Dma.DMA_BufferSize = 2;
        Dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        Dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
        Dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        Dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        Dma.DMA_Mode = DMA_Mode_Circular;
        Dma.DMA_Priority = DMA_Priority_High;
        Dma.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel2, &Dma);

        DMA_DeInit(DMA1_Channel6);
        Dma.DMA_PeripheralBaseAddr = (u32)&(TIM1->CCR3);                  
        Dma.DMA_MemoryBaseAddr = ( u32) Ch2_buf;
        DMA_Init(DMA1_Channel6, &Dma);
        //------------------------------        Nvic Init
        Nvic.NVIC_IRQChannel = TIM1_CC_IRQn;
        Nvic.NVIC_IRQChannelPreemptionPriority = 0x0F;
        Nvic.NVIC_IRQChannelSubPriority = 0x0F;
        Nvic.NVIC_IRQChannelCmd = ENABLE;

        NVIC_Init(&Nvic);
        //------------------------------        Buf Init
        Ch1_buf[0] = (u16)(0.333 * 0x1000)-1;
        Ch2_buf[0] = (u16)(0.666 * 0x1000)-1;
        Ch3_buf[0] = (u16)(0.999 * 0x1000)-1;
       

        setMBRatio(37.5, 22.5, 81.3);
        //------------------------------        Start
        DMA_Cmd(DMA1_Channel2,ENABLE);        // TIM1_CH1
        DMA_Cmd(DMA1_Channel6,ENABLE);        // TIM1_CH3
        TIM_Cmd(TIM1, ENABLE);
        TIM_CtrlPWMOutputs(TIM1, ENABLE);

        while (1)
                __nop();
}

void setMBRatio(float mbR1, float mbR2, float mbR3){
       
//        mbR1 = 0.1~99.9 %
        u16 vv;
       
        vv=(u16)((float)mbR1*0x1000/100.0);
        if (!vv) vv=1;
        if (vv>=0xFFF) vv=0xFFE;
        Ch1_buf[1] = (Ch1_buf[0] + vv) % 0x1000;
       
        vv=(u16)((float)mbR2*0x1000/100.0);
        if (!vv) vv=1;
        if (vv>=0xFFF) vv=0xFFE;       
        Ch2_buf[1] = ((Ch2_buf[0] + vv) % 0x1000);       
        TIM1_CCR2_Val=Ch2_buf[0] ^ Ch2_buf[1];
       
        vv=(u16)((float)mbR3*0x1000/100.0);
        if (!vv) vv=1;
        if (vv>=0xFFF) vv=0xFFE;       
        Ch3_buf[1] = (Ch3_buf[0] + vv) % 0x1000;
       
}

extern u16 TIM1_CCR2_Val;
void TIM1_CC_IRQHandler(void){
       
        if (TIM1->SR & TIM_SR_CC2IF){
                TIM1->CCR2 ^= TIM1_CCR2_Val;
                TIM1->SR &= ~(u32)TIM_SR_CC2IF;
        }
}

回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 20:21:51 | 显示全部楼层
edmund1234 发表于 2018-9-9 20:09
如果一定要互补, 就改回用CH1~CH3, CH1 & CH3 用DMA自动更新, 而CH2, 用中断更新CCR2

我是按照这种思路写的,但是CH1和CH3都直接拉高了,我想写这两个通道的互补。[mw_shl_code=cpp,true]GPIO_InitTypeDef         GPIO_InitStructure;
   DMA_InitTypeDef          DMA_InitStructure;
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
   TIM_OCInitTypeDef        TIM_OCInitStructure;       
   TIM_BDTRInitTypeDef      TIM_BDTRInitStructure;
       
  /* TIM1 and GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB, ENABLE);

  /* DMA clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  
  /*channel1 ,channel2  --> PA.8,PA.9, PA.10*
        *channel1N,channel2N --> PB.13,PB.14, PB.15*/
  /* GPIOA Configuration: Channel 1 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14 | GPIO_Pin_15;
        GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB

  /* TIM1 DeInit */
  TIM_DeInit(TIM1);

  /* DMA1 Channel5 Config */
  DMA_DeInit(DMA1_Channel2);

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM1->CCR1);
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SRC_Buffer_CH1;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure.DMA_BufferSize = 6;
  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_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel2, &DMA_InitStructure);
       
       
        DMA_DeInit(DMA1_Channel6);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM1->CCR3);
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SRC_Buffer_CH3;
  DMA_Init(DMA1_Channel6, &DMA_InitStructure);
  /* Time base configuration */


    The TIM1 period is 5.8 KHz: TIM1 Frequency = TIM1 counter clock/(ARR + 1)
                                               = 24 MHz / 4096 = 5.8KHz KHz
    TIM1 Channel1 duty cycle = (TIM1_CCR1/ TIM1_ARR)* 100 = 33.33%
  ----------------------------------------------------------------------- */  
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;         
  TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 24000000) - 1;      
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;   
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  /* TIM Configuration in PWM Mode */
  TIM_OCInitStructure.TIM_OCMode =  TIM_OCMode_PWM1;   
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;         
  TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable;
        TIM_OCInitStructure.TIM_Pulse = 0xFFF;  
  
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
//  TIM_OC2Init(TIM1, &TIM_OCInitStructure);
  TIM_OC3Init(TIM1, &TIM_OCInitStructure);

  /* TIM1 DMAR Base register and DMA Burst Length Config */
  TIM_DMAConfig(TIM1, TIM_DMABase_ARR, TIM_DMABurstLength_3Transfers);

  /* TIM1 DMA Update enable */
  TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
       
        /*死区和刹车功能配置*/
        TIM_BDTRInitStructure.TIM_OSSRState       = TIM_OSSRState_Enable;
        TIM_BDTRInitStructure.TIM_OSSIState       = TIM_OSSIState_Enable;
        TIM_BDTRInitStructure.TIM_LOCKLevel       = TIM_LOCKLevel_1;
        TIM_BDTRInitStructure.TIM_DeadTime        =50;                   //设置TIM1_BDTR的DTG,死区时间DTG[7:0]
        TIM_BDTRInitStructure.TIM_Break           = TIM_Break_Disable;
        TIM_BDTRInitStructure.TIM_BreakPolarity   = TIM_BreakPolarity_High;
        TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
        TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

  /* TIM1 enable */
  TIM_Cmd(TIM1, ENABLE);
  
  /* TIM1 PWM Outputs Enable */
  TIM_CtrlPWMOutputs(TIM1, ENABLE);

  /* DMA1 Channel enable */
  DMA_Cmd(DMA1_Channel2, ENABLE);
  DMA_Cmd(DMA1_Channel6, ENABLE);
  /* Wait until DMA1 Channel5 end of Transfer */
  while (!DMA_GetFlagStatus(DMA1_FLAG_TC2))
  {
  }
        while (!DMA_GetFlagStatus(DMA1_FLAG_TC6))
  {
  }[/mw_shl_code]
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 20:25:18 | 显示全部楼层
PearlH 发表于 2018-9-9 20:03
我用两个互补通道就可以了

那就删了通道2的, 只用通道1,3, 中断的初始部分也可以删掉, 中断处理函数删掉, 就可以了
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 20:29:15 | 显示全部楼层
用这个


u16 Ch1_buf[2];
u16 Ch3_buf[2];
const u16 ArrVal=0x1000;

void setMBRatio(float mbR1, float mbR3);

int main(void)
{

        GPIO_InitTypeDef                        Gpio;
        DMA_InitTypeDef                    Dma;
        TIM_TimeBaseInitTypeDef            Tim;
        TIM_OCInitTypeDef                        TimOc;
        NVIC_InitTypeDef                        Nvic;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_TIM1 , ENABLE);
        //------------------------ GPIO
        //------------------------ PA8, 9, 10 (CH1, 2, 3)
        Gpio.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_10;       
        Gpio.GPIO_Mode = GPIO_Mode_AF_PP;
        Gpio.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &Gpio);       
        //------------------------ PB13,14,15 (CHN1~3)
        Gpio.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_15;       
        GPIO_Init(GPIOB, &Gpio);               
       
        //------------------------ TIM1 TimeBase
        TIM_TimeBaseStructInit(&Tim);
        Tim.TIM_Period = ArrVal-1;                // 2us
        Tim.TIM_Prescaler = 0x01;
        Tim.TIM_ClockDivision = 0x0;
        Tim.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM1, &Tim);
        //------------------------ TIM1 OC
        TimOc.TIM_OCMode = TIM_OCMode_Toggle;
        TimOc.TIM_OutputState = TIM_OutputState_Enable;
        TimOc.TIM_OutputNState = TIM_OutputNState_Enable;
        TimOc.TIM_Pulse = 0xFFF;
        TimOc.TIM_OCPolarity = TIM_OCPolarity_Low;
        TimOc.TIM_OCNPolarity = TIM_OCNPolarity_Low;
        TimOc.TIM_OCIdleState = TIM_OCIdleState_Reset;
        TimOc.TIM_OCNIdleState = TIM_OCNIdleState_Set;

        TIM_OC1Init(TIM1, &TimOc);
        TimOc.TIM_Pulse = 0x800;       
    TIM_OC3Init(TIM1, &TimOc);
       
        TIM_DMACmd(TIM1, TIM_DMA_CC1|TIM_DMA_CC3, ENABLE);       
        //------------------------ DMA1 - Ch2, Ch4
        DMA_DeInit(DMA1_Channel2);

        Dma.DMA_PeripheralBaseAddr = (u32)&(TIM1->CCR1);          
        Dma.DMA_MemoryBaseAddr = ( u32) Ch1_buf;
        Dma.DMA_DIR = DMA_DIR_PeripheralDST;
        Dma.DMA_BufferSize = 2;
        Dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        Dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
        Dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        Dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        Dma.DMA_Mode = DMA_Mode_Circular;
        Dma.DMA_Priority = DMA_Priority_High;
        Dma.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel2, &Dma);

        DMA_DeInit(DMA1_Channel6);
        Dma.DMA_PeripheralBaseAddr = (u32)&(TIM1->CCR3);                  
        Dma.DMA_MemoryBaseAddr = ( u32) Ch3_buf;
        DMA_Init(DMA1_Channel6, &Dma);
        //------------------------------        Buf Init
        Ch1_buf[0] = (u16)(0.25 * 0x1000)-1;
        Ch3_buf[0] = (u16)(0.75 * 0x1000)-1;
       

        setMBRatio(37.5, 81.3);
        //------------------------------        Start
        DMA_Cmd(DMA1_Channel2,ENABLE);        // TIM1_CH1
        DMA_Cmd(DMA1_Channel6,ENABLE);        // TIM1_CH3
        TIM_Cmd(TIM1, ENABLE);
        TIM_CtrlPWMOutputs(TIM1, ENABLE);

        while (1)
                __nop();
}

void setMBRatio(float mbR1, float mbR3){
       
//        mbR1 = 0.1~99.9 %
        u16 vv;
       
        vv=(u16)((float)mbR1*0x1000/100.0);
        if (!vv) vv=1;
        if (vv>=0xFFF) vv=0xFFE;
        Ch1_buf[1] = (Ch1_buf[0] + vv) % 0x1000;
       
       
        vv=(u16)((float)mbR3*0x1000/100.0);
        if (!vv) vv=1;
        if (vv>=0xFFF) vv=0xFFE;       
        Ch3_buf[1] = (Ch3_buf[0] + vv) % 0x1000;
       
}

回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-9 21:23:40 | 显示全部楼层

波形出来了,但是那个移相角度是通过深控制的呀?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-9 21:32:11 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-9 21:34 编辑
PearlH 发表于 2018-9-9 21:23
波形出来了,但是那个移相角度是通过深控制的呀?

Ch1_buf[0] = (u16)(0.25 * 0x1000)-1;
Ch3_buf[0] = (u16)(0.75 * 0x1000)-1;

这两个是调相移角度的 1==360度, Ch1移了0.25*360 = 90度, Ch3移了0.75*360 = 270度
随时可以改的, 但改完要马上调用setMBRation更新占空比
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-10 12:07:02 | 显示全部楼层
edmund1234 发表于 2018-9-9 21:32
Ch1_buf[0] = (u16)(0.25 * 0x1000)-1;
Ch3_buf[0] = (u16)(0.75 * 0x1000)-1;

这个效果实现了,如果是想一个周期里有多个占空比不同的脉冲应该怎么做呢?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-10 12:18:35 | 显示全部楼层
PearlH 发表于 2018-9-10 12:07
这个效果实现了,如果是想一个周期里有多个占空比不同的脉冲应该怎么做呢?

不明白你说的什么是一周期里有多个占空比
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-10 15:05:25 | 显示全部楼层
本帖最后由 PearlH 于 2018-9-10 15:08 编辑
edmund1234 发表于 2018-9-10 12:18
不明白你说的什么是一周期里有多个占空比

C:\Users\Administrator.WIN7-1710311227\Desktop
IMG_20180909_143609.jpg
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-10 16:46:21 | 显示全部楼层

这个只是每个周期变更一次占空比, 你应该可以自己懂得怎样做的
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-14 17:11:00 | 显示全部楼层
edmund1234 发表于 2018-9-10 16:46
这个只是每个周期变更一次占空比, 你应该可以自己懂得怎样做的

可以设置一个占空比数组,然后通过数组来改变,但是怎么让数组循环呢?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-14 17:25:35 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-14 17:27 编辑
PearlH 发表于 2018-9-14 17:11
可以设置一个占空比数组,然后通过数组来改变,但是怎么让数组循环呢?

DMA有标志位显示传送了buffer的一半, 或整个buffer都传送完



比如说你的是buffer[16], 当HTIFx是1的时候,更新buffer[0..7], 当TCIFx是1的时候, 更新buffer[8..15], 记得看标志位要清
Capture.PNG
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-16 09:53:37 | 显示全部楼层
本帖最后由 PearlH 于 2018-9-16 11:45 编辑
edmund1234 发表于 2018-9-14 17:25
DMA有标志位显示传送了buffer的一半, 或整个buffer都传送完

大神,想要这个波形,那个中断的两个标志位是在哪里设置的呢?就是ISR标准库对应的是哪条语句啊?
IMG20180902204415.jpg
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-16 13:26:07 | 显示全部楼层
PearlH 发表于 2018-9-16 09:53
大神,想要这个波形,那个中断的两个标志位是在哪里设置的呢?就是ISR标准库对应的是哪条语句啊?

这波形用之前的方法是可以做到的
我只提供方法或原理, 不直接给答案
自己动手才有答案
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-16 14:56:07 | 显示全部楼层
edmund1234 发表于 2018-9-16 13:26
这波形用之前的方法是可以做到的
我只提供方法或原理, 不直接给答案
自己动手才有答案

你上一个回答我懂了一半,就是怎么在那个函数里面更新中断标志位呢?应该是交错的吧,也就是要不就是HTIF1或者HCIF1为1,那这个标志位通过什么修改呢?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-16 16:27:53 | 显示全部楼层
PearlH 发表于 2018-9-16 14:56
你上一个回答我懂了一半,就是怎么在那个函数里面更新中断标志位呢?应该是交错的吧,也就是要不就是HTIF ...

DMA会根据把它写为"1"
你读完后, 用DMA1->IFCR=(1<<x);来清零x位
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-16 18:14:38 | 显示全部楼层
edmund1234 发表于 2018-9-16 16:27
DMA会根据把它写为"1"
你读完后, 用DMA1->IFCR=(1

我理解得意思就是在中断中更改占空比,是这个意思吗?但是更改之后它就一直保持在中断中更新的那个占空比的值了。还是不是我想要的那种。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-16 18:29:22 | 显示全部楼层
PearlH 发表于 2018-9-16 18:14
我理解得意思就是在中断中更改占空比,是这个意思吗?但是更改之后它就一直保持在中断中更新的那个占空比 ...

这些标志位可以配置产生中断, 不配置为中断你也可以在main的while里查看
配不配置为中断都不影响, 都是可以做到这效果
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-16 18:47:07 | 显示全部楼层
edmund1234 发表于 2018-9-16 18:29
这些标志位可以配置产生中断, 不配置为中断你也可以在main的while里查看
配不配置为中断都不影响, 都 ...

可以改变占空比,但是改变之后就固定在中断里面的占空比了。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-16 18:56:37 | 显示全部楼层
PearlH 发表于 2018-9-16 18:47
可以改变占空比,但是改变之后就固定在中断里面的占空比了。

你要不停的改变占空被, 就要不断的在中断里改变buffer里占空比的值啊, STM32总不能猜你想要什么占空比而帮你设吧
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-16 19:02:28 | 显示全部楼层
edmund1234 发表于 2018-9-16 18:56
你要不停的改变占空被, 就要不断的在中断里改变buffer里占空比的值啊, STM32总不能猜你想要什么占空比 ...

void TIM1_CC_IRQHandler(void)
        {
                i++;
                if(i % 2==0)
                {
        if (TIM1->SR & TIM_SR_CC1IF)
                                {
                TIM1->CCR1 ^= 200;
                TIM1->SR &= ~(u32)TIM_SR_CC1IF;
        }
                }
               
                else
                {
        if (TIM1->SR & TIM_SR_CC1IF)
                                {
                TIM1->CCR1 ^= 500;
                TIM1->SR &= ~(u32)TIM_SR_CC1IF;
        }
                }
}
然后波形是颤抖的
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-16 19:09:27 | 显示全部楼层
PearlH 发表于 2018-9-16 19:02
void TIM1_CC_IRQHandler(void)
        {
                i++;

应该用DMA的HT及TC中断, 而不是TIM
回复

使用道具 举报

3

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2018-7-6
在线时间
22 小时
 楼主| 发表于 2018-9-16 19:44:39 | 显示全部楼层
edmund1234 发表于 2018-9-16 19:09
应该用DMA的HT及TC中断, 而不是TIM

有两个问题请教一下大神。
1.buffer数组通过两个标志位控制传入的是前一半还是后一半占空比,我们之前程序里的bufffer数组是通过计算得到的数据,后一半占空比也应该通过算式计算得到吗?
2.然后通过DMA的DMA1_Channel2_IRQHandler这个中断函数,然后在中断里面需要更新的是占空比还有哪些标志位呀?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 20:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表