搜索
bottom↓
回复: 9

求解一个定时器产生多路可调频率占空比PWM!

  [复制链接]

出0入10汤圆

发表于 2015-7-19 10:38:39 | 显示全部楼层 |阅读模式
本帖最后由 10xjzheng 于 2015-7-19 11:20 编辑

一开始看到下面这个帖子,我就觉得很好奇,然后十分想实现,即使可能然并卵。
http://www.amobbs.com/forum.php? ... 1&extra=#pid8675789
在下面回复的提醒下知道了实现的方法,就是用DMA不断地修改CRRx的值,然后进行翻转,最后还要注意下定时器触发的时基是在比较以后即可
应该用得是toggle模式,但是出来的波形甚是奇怪?求解!

下面是PWM1模式实现占空比可调而已!

程序不难
首先定义几个数组用来存放搬运到CCRx的数据
  1. #define CHANNEL1_NUM 100
  2. #define CHANNEL2_NUM 50
  3. #define CHANNEL3_NUM 10

  4. uint16_t SendBuffer1[CHANNEL1_NUM];
  5. uint16_t SendBuffer2[CHANNEL2_NUM];
  6. uint16_t SendBuffer3[CHANNEL3_NUM];
复制代码
初始化定时器引脚
  1. static void Tmr2_GPIO_Config(void)
  2. {
  3.         GPIO_InitTypeDef GPIO_InitStructure;
  4.         
  5.         
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  7.         
  8.         /* 配置PA0管脚的模式 */
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  10.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  11.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.   GPIO_Init(GPIOA,&GPIO_InitStructure);
  13.         
  14.         /* 配置PA1管脚的模式,同PA0 */
  15.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  16.         GPIO_Init(GPIOA,&GPIO_InitStructure);
  17.         
  18.         /* 配置PA2管脚的模式,同PA0 */
  19.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  20.         GPIO_Init(GPIOA,&GPIO_InitStructure);
  21. }
复制代码

接着配置定时器和DMA
  1. void Tmr2_Config(void)
  2. {
  3.         TIM_TimeBaseInitTypeDef  TIM_TmrBaseInitStructure;
  4.         TIM_OCInitTypeDef        TIM_OCInitStructure;
  5.   DMA_InitTypeDef          DMA_InitStructure;
  6.   int i;
  7.         
  8.         for(i=0;i<CHANNEL1_NUM;i++)
  9.         {
  10.                 SendBuffer1[i]=i*10;
  11.         }
  12.         
  13.         for(i=0;i<CHANNEL2_NUM;i++)
  14.         {
  15.                 SendBuffer2[i]=i*20;
  16.         }
  17.         
  18.         for(i=0;i<CHANNEL3_NUM;i++)
  19.         {
  20.                 SendBuffer3[i]=i*100;
  21.         }
  22.         
  23.         Tmr2_GPIO_Config();
  24.         
  25.   /* 开启定时器2的时钟 */
  26.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  27.         
  28.         /* 为定时器2设置内部时钟为计数源 */
  29.         TIM_InternalClockConfig(TIM2);
  30.                
  31.         /* 定时器设置为向上计数模式 */
  32.         TIM_TmrBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  33.         /* 定时器的周期设置 */
  34.         TIM_TmrBaseInitStructure.TIM_Period = 1000-1;
  35.         /* 分频系数为7200 */
  36.         TIM_TmrBaseInitStructure.TIM_Prescaler =  7200-1;
  37.         /* 设置定时器2时基 */
  38.         TIM_TimeBaseInit(TIM2,&TIM_TmrBaseInitStructure);
  39.         
  40.   /* 通道1输出设置为PWM1模式 */
  41.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  42.         /* 输出通道极性是高 */
  43.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  44.         /* 允许输出 */
  45.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  46.         /* 设置PWM翻转时比较的值 */
  47.         TIM_OCInitStructure.TIM_Pulse = 0;
  48.         /* 设置定时器2的通道1 */
  49.   TIM_OC1Init(TIM2,&TIM_OCInitStructure);

  50.         /* 设置定时器2的通道2 */
  51.   TIM_OC2Init(TIM2,&TIM_OCInitStructure);

  52.         /* 设置定时器2的通道3 */
  53.   TIM_OC3Init(TIM2,&TIM_OCInitStructure);

  54.         /* 设置定时器2的通道4 */
  55.   TIM_OC4Init(TIM2,&TIM_OCInitStructure);

  56.         TIM_SelectCCDMA(TIM2,ENABLE);
  57.         TIM_DMACmd(TIM2,TIM_DMA_CC1|TIM_DMA_CC2|TIM_DMA_CC3,ENABLE);
  58.         
  59. //开启DMA外设时钟
  60.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  61.         
  62.         /* DMA数据传输数量        */
  63.         DMA_InitStructure.DMA_BufferSize = CHANNEL1_NUM;
  64.         /* DMA数据传输方向,从内存到外设 */
  65.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  66.         /* 禁止从内存到内存进行传输,即禁止一直触发DMA进行传输 */
  67.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  68.         /* DMA内存基地址 */
  69.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuffer1;
  70.         /* 每次发送16位的数据 */
  71.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  72.         /* 内存的地址增加 */
  73.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  74.         /* 循环传输 */
  75.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  76.         /* 定时器1的比较寄存器为要发送的数组的首地址 */
  77.         DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM2->CCR1);
  78.         /* 外设每次接收16位的数据 */
  79.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  80.         /* CCR1的地址不自增 */
  81.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  82.         /* DMA优先级设置为最高 */
  83.         DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  84.         /* DMA1通道2进行配置 */
  85.         DMA_Init(DMA1_Channel5,&DMA_InitStructure);
  86.         /* 使能DMA1通道5 */
  87.         DMA_Cmd(DMA1_Channel5,ENABLE);
  88.         
  89.         DMA_InitStructure.DMA_BufferSize = CHANNEL2_NUM;
  90.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuffer2;
  91.         DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM2->CCR2);
  92.         DMA_Init(DMA1_Channel7,&DMA_InitStructure);
  93.         DMA_Cmd(DMA1_Channel7,ENABLE);
  94.         
  95.         DMA_InitStructure.DMA_BufferSize = CHANNEL3_NUM;
  96.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuffer3;
  97.         DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM2->CCR3);
  98.         DMA_Init(DMA1_Channel1,&DMA_InitStructure);
  99.         DMA_Cmd(DMA1_Channel1,ENABLE);
  100.         
  101.         /* 开启定时器2 */
  102.         TIM_Cmd(TIM2,ENABLE);
  103. }
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入10汤圆

 楼主| 发表于 2015-7-19 11:06:41 | 显示全部楼层
突然发现自己好像搞错了,这是占空比可调而已

出0入10汤圆

 楼主| 发表于 2015-7-28 15:59:20 | 显示全部楼层
上面的程序去掉TIM_SelectCCDMA(TIM2,ENABLE);就可以实现了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-7-31 18:18:30 | 显示全部楼层
赞!干得漂亮

出0入10汤圆

 楼主| 发表于 2015-7-31 22:55:44 | 显示全部楼层

小意思,只不过还是需要一点空间来存放比较值

出0入0汤圆

发表于 2016-4-3 16:42:49 | 显示全部楼层
真的漂亮!也试试,不过可以做到各个通道随意更改频率以及起停吗?不过16位计数器是不是频率也受限制?

出0入0汤圆

发表于 2016-5-26 13:44:13 | 显示全部楼层
我能说我是路过打酱油的不。。。。。

出0入0汤圆

发表于 2017-7-6 13:43:44 | 显示全部楼层
我是路过打酱油的

出0入0汤圆

发表于 2017-8-30 13:44:18 | 显示全部楼层
mark                  

出0入0汤圆

发表于 2017-11-19 17:23:25 | 显示全部楼层
mark!!!!!!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-7 18:33

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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